]> Pileus Git - ~andy/gtk/commitdiff
New font private structures, related to fontsets.
authorTor Lillqvist <tml@iki.fi>
Mon, 8 Nov 1999 00:09:29 +0000 (00:09 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Mon, 8 Nov 1999 00:09:29 +0000 (00:09 +0000)
1999-11-07  Tor Lillqvist  <tml@iki.fi>

* gdk/win32/gdkprivate.h: New font private structures, related to
fontsets.

* gdk/win32/gdkfont.c: New functions gdk_font_list_new() and
gdk_font_list_free(). On X11, will just be wrappers to
XListFonts() and XFreeFontNames(). On Win32, the code previously
in gtkfontsel.c is now here.

New function gdk_font_xlfd_create(). On X11 will get the FONT
property of the font (for GDK_FONT_FONTs), or call
XBaseFontNameListOfFontSet (for GDK_FONT_FONTSETs), on Win32
builds a XLFD style name from the font information in the LOGFONT
struct(s).

New function gdk_font_xlfd_free(), which correspondingly frees the
string returned by gdk_font_xlfd_create().

Implement fontsets on Win32. Add a function that iterates over a
wide char string and calls a callback function for each substring
of wide chars from the same Unicode subrange (and thus probably
available in the same real font).

Improve the XLFD emulation a bit.

* gdk/win32/gdkim.c (gdk_nmbstowchar_ts): Small bugfix.

* gdk/win32/gdkevents.c: Workaround for suspected bug on Win2k
Beta3, WM_IME_CHAR messages don't seem to contain the composed
multi-byte char as with the Active IMM on Win9x. Oh well, handle
WM_IME_COMPOSITION with GCS_RESULTSTR instead, use
ImmGetCompositionStringW() to get the composed Unicode chars.

* gdk/win32/gdkgc.c
* gdk/win32/gdkdraw.c: Changes needed because of the font private
struct changes.

* gdk/win32/gdk.def: Add the new functions.

29 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
gdk/win32/gdk-win32.def
gdk/win32/gdk.c
gdk/win32/gdk.def
gdk/win32/gdkconfig.h
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/gdkmain-win32.c
gdk/win32/gdkprivate-win32.h
gdk/win32/gdkprivate.h
gdk/win32/gdkwin32.h
gdk/win32/gdkx.h
po/makefile.cygwin

index 608f6d7582204eec6e0dba17b7c7d082116a3f56..d7b557e905a641d5156bd26662dd37df7e09dc5c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+1999-11-07  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: New font private structures, related to
+       fontsets.
+
+       * gdk/win32/gdkfont.c: New functions gdk_font_list_new() and
+       gdk_font_list_free(). On X11, will just be wrappers to
+       XListFonts() and XFreeFontNames(). On Win32, the code previously
+       in gtkfontsel.c is now here.
+
+       New function gdk_font_xlfd_create(). On X11 will get the FONT
+       property of the font (for GDK_FONT_FONTs), or call
+       XBaseFontNameListOfFontSet (for GDK_FONT_FONTSETs), on Win32
+       builds a XLFD style name from the font information in the LOGFONT
+       struct(s).
+
+       New function gdk_font_xlfd_free(), which correspondingly frees the
+       string returned by gdk_font_xlfd_create().
+
+       Implement fontsets on Win32. Add a function that iterates over a
+       wide char string and calls a callback function for each substring
+       of wide chars from the same Unicode subrange (and thus probably
+       available in the same real font).
+
+       Improve the XLFD emulation a bit.
+
+       * gdk/win32/gdkim.c (gdk_nmbstowchar_ts): Small bugfix.
+
+       * gdk/win32/gdkevents.c: Workaround for suspected bug on Win2k
+       Beta3, WM_IME_CHAR messages don't seem to contain the composed
+       multi-byte char as with the Active IMM on Win9x. Oh well, handle
+       WM_IME_COMPOSITION with GCS_RESULTSTR instead, use
+       ImmGetCompositionStringW() to get the composed Unicode chars.
+
+       * gdk/win32/gdkgc.c
+       * gdk/win32/gdkdraw.c: Changes needed because of the font private
+       struct changes.
+
+       * gdk/win32/gdk.def: Add the new functions.
+
 1999-11-04  Tor Lillqvist  <tml@iki.fi>
 
        * config.h.win32: Don't define HAVE_DIMM_H if MSC, as you have to
index 608f6d7582204eec6e0dba17b7c7d082116a3f56..d7b557e905a641d5156bd26662dd37df7e09dc5c 100644 (file)
@@ -1,3 +1,43 @@
+1999-11-07  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: New font private structures, related to
+       fontsets.
+
+       * gdk/win32/gdkfont.c: New functions gdk_font_list_new() and
+       gdk_font_list_free(). On X11, will just be wrappers to
+       XListFonts() and XFreeFontNames(). On Win32, the code previously
+       in gtkfontsel.c is now here.
+
+       New function gdk_font_xlfd_create(). On X11 will get the FONT
+       property of the font (for GDK_FONT_FONTs), or call
+       XBaseFontNameListOfFontSet (for GDK_FONT_FONTSETs), on Win32
+       builds a XLFD style name from the font information in the LOGFONT
+       struct(s).
+
+       New function gdk_font_xlfd_free(), which correspondingly frees the
+       string returned by gdk_font_xlfd_create().
+
+       Implement fontsets on Win32. Add a function that iterates over a
+       wide char string and calls a callback function for each substring
+       of wide chars from the same Unicode subrange (and thus probably
+       available in the same real font).
+
+       Improve the XLFD emulation a bit.
+
+       * gdk/win32/gdkim.c (gdk_nmbstowchar_ts): Small bugfix.
+
+       * gdk/win32/gdkevents.c: Workaround for suspected bug on Win2k
+       Beta3, WM_IME_CHAR messages don't seem to contain the composed
+       multi-byte char as with the Active IMM on Win9x. Oh well, handle
+       WM_IME_COMPOSITION with GCS_RESULTSTR instead, use
+       ImmGetCompositionStringW() to get the composed Unicode chars.
+
+       * gdk/win32/gdkgc.c
+       * gdk/win32/gdkdraw.c: Changes needed because of the font private
+       struct changes.
+
+       * gdk/win32/gdk.def: Add the new functions.
+
 1999-11-04  Tor Lillqvist  <tml@iki.fi>
 
        * config.h.win32: Don't define HAVE_DIMM_H if MSC, as you have to
index 608f6d7582204eec6e0dba17b7c7d082116a3f56..d7b557e905a641d5156bd26662dd37df7e09dc5c 100644 (file)
@@ -1,3 +1,43 @@
+1999-11-07  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: New font private structures, related to
+       fontsets.
+
+       * gdk/win32/gdkfont.c: New functions gdk_font_list_new() and
+       gdk_font_list_free(). On X11, will just be wrappers to
+       XListFonts() and XFreeFontNames(). On Win32, the code previously
+       in gtkfontsel.c is now here.
+
+       New function gdk_font_xlfd_create(). On X11 will get the FONT
+       property of the font (for GDK_FONT_FONTs), or call
+       XBaseFontNameListOfFontSet (for GDK_FONT_FONTSETs), on Win32
+       builds a XLFD style name from the font information in the LOGFONT
+       struct(s).
+
+       New function gdk_font_xlfd_free(), which correspondingly frees the
+       string returned by gdk_font_xlfd_create().
+
+       Implement fontsets on Win32. Add a function that iterates over a
+       wide char string and calls a callback function for each substring
+       of wide chars from the same Unicode subrange (and thus probably
+       available in the same real font).
+
+       Improve the XLFD emulation a bit.
+
+       * gdk/win32/gdkim.c (gdk_nmbstowchar_ts): Small bugfix.
+
+       * gdk/win32/gdkevents.c: Workaround for suspected bug on Win2k
+       Beta3, WM_IME_CHAR messages don't seem to contain the composed
+       multi-byte char as with the Active IMM on Win9x. Oh well, handle
+       WM_IME_COMPOSITION with GCS_RESULTSTR instead, use
+       ImmGetCompositionStringW() to get the composed Unicode chars.
+
+       * gdk/win32/gdkgc.c
+       * gdk/win32/gdkdraw.c: Changes needed because of the font private
+       struct changes.
+
+       * gdk/win32/gdk.def: Add the new functions.
+
 1999-11-04  Tor Lillqvist  <tml@iki.fi>
 
        * config.h.win32: Don't define HAVE_DIMM_H if MSC, as you have to
index 608f6d7582204eec6e0dba17b7c7d082116a3f56..d7b557e905a641d5156bd26662dd37df7e09dc5c 100644 (file)
@@ -1,3 +1,43 @@
+1999-11-07  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: New font private structures, related to
+       fontsets.
+
+       * gdk/win32/gdkfont.c: New functions gdk_font_list_new() and
+       gdk_font_list_free(). On X11, will just be wrappers to
+       XListFonts() and XFreeFontNames(). On Win32, the code previously
+       in gtkfontsel.c is now here.
+
+       New function gdk_font_xlfd_create(). On X11 will get the FONT
+       property of the font (for GDK_FONT_FONTs), or call
+       XBaseFontNameListOfFontSet (for GDK_FONT_FONTSETs), on Win32
+       builds a XLFD style name from the font information in the LOGFONT
+       struct(s).
+
+       New function gdk_font_xlfd_free(), which correspondingly frees the
+       string returned by gdk_font_xlfd_create().
+
+       Implement fontsets on Win32. Add a function that iterates over a
+       wide char string and calls a callback function for each substring
+       of wide chars from the same Unicode subrange (and thus probably
+       available in the same real font).
+
+       Improve the XLFD emulation a bit.
+
+       * gdk/win32/gdkim.c (gdk_nmbstowchar_ts): Small bugfix.
+
+       * gdk/win32/gdkevents.c: Workaround for suspected bug on Win2k
+       Beta3, WM_IME_CHAR messages don't seem to contain the composed
+       multi-byte char as with the Active IMM on Win9x. Oh well, handle
+       WM_IME_COMPOSITION with GCS_RESULTSTR instead, use
+       ImmGetCompositionStringW() to get the composed Unicode chars.
+
+       * gdk/win32/gdkgc.c
+       * gdk/win32/gdkdraw.c: Changes needed because of the font private
+       struct changes.
+
+       * gdk/win32/gdk.def: Add the new functions.
+
 1999-11-04  Tor Lillqvist  <tml@iki.fi>
 
        * config.h.win32: Don't define HAVE_DIMM_H if MSC, as you have to
index 608f6d7582204eec6e0dba17b7c7d082116a3f56..d7b557e905a641d5156bd26662dd37df7e09dc5c 100644 (file)
@@ -1,3 +1,43 @@
+1999-11-07  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: New font private structures, related to
+       fontsets.
+
+       * gdk/win32/gdkfont.c: New functions gdk_font_list_new() and
+       gdk_font_list_free(). On X11, will just be wrappers to
+       XListFonts() and XFreeFontNames(). On Win32, the code previously
+       in gtkfontsel.c is now here.
+
+       New function gdk_font_xlfd_create(). On X11 will get the FONT
+       property of the font (for GDK_FONT_FONTs), or call
+       XBaseFontNameListOfFontSet (for GDK_FONT_FONTSETs), on Win32
+       builds a XLFD style name from the font information in the LOGFONT
+       struct(s).
+
+       New function gdk_font_xlfd_free(), which correspondingly frees the
+       string returned by gdk_font_xlfd_create().
+
+       Implement fontsets on Win32. Add a function that iterates over a
+       wide char string and calls a callback function for each substring
+       of wide chars from the same Unicode subrange (and thus probably
+       available in the same real font).
+
+       Improve the XLFD emulation a bit.
+
+       * gdk/win32/gdkim.c (gdk_nmbstowchar_ts): Small bugfix.
+
+       * gdk/win32/gdkevents.c: Workaround for suspected bug on Win2k
+       Beta3, WM_IME_CHAR messages don't seem to contain the composed
+       multi-byte char as with the Active IMM on Win9x. Oh well, handle
+       WM_IME_COMPOSITION with GCS_RESULTSTR instead, use
+       ImmGetCompositionStringW() to get the composed Unicode chars.
+
+       * gdk/win32/gdkgc.c
+       * gdk/win32/gdkdraw.c: Changes needed because of the font private
+       struct changes.
+
+       * gdk/win32/gdk.def: Add the new functions.
+
 1999-11-04  Tor Lillqvist  <tml@iki.fi>
 
        * config.h.win32: Don't define HAVE_DIMM_H if MSC, as you have to
index 608f6d7582204eec6e0dba17b7c7d082116a3f56..d7b557e905a641d5156bd26662dd37df7e09dc5c 100644 (file)
@@ -1,3 +1,43 @@
+1999-11-07  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: New font private structures, related to
+       fontsets.
+
+       * gdk/win32/gdkfont.c: New functions gdk_font_list_new() and
+       gdk_font_list_free(). On X11, will just be wrappers to
+       XListFonts() and XFreeFontNames(). On Win32, the code previously
+       in gtkfontsel.c is now here.
+
+       New function gdk_font_xlfd_create(). On X11 will get the FONT
+       property of the font (for GDK_FONT_FONTs), or call
+       XBaseFontNameListOfFontSet (for GDK_FONT_FONTSETs), on Win32
+       builds a XLFD style name from the font information in the LOGFONT
+       struct(s).
+
+       New function gdk_font_xlfd_free(), which correspondingly frees the
+       string returned by gdk_font_xlfd_create().
+
+       Implement fontsets on Win32. Add a function that iterates over a
+       wide char string and calls a callback function for each substring
+       of wide chars from the same Unicode subrange (and thus probably
+       available in the same real font).
+
+       Improve the XLFD emulation a bit.
+
+       * gdk/win32/gdkim.c (gdk_nmbstowchar_ts): Small bugfix.
+
+       * gdk/win32/gdkevents.c: Workaround for suspected bug on Win2k
+       Beta3, WM_IME_CHAR messages don't seem to contain the composed
+       multi-byte char as with the Active IMM on Win9x. Oh well, handle
+       WM_IME_COMPOSITION with GCS_RESULTSTR instead, use
+       ImmGetCompositionStringW() to get the composed Unicode chars.
+
+       * gdk/win32/gdkgc.c
+       * gdk/win32/gdkdraw.c: Changes needed because of the font private
+       struct changes.
+
+       * gdk/win32/gdk.def: Add the new functions.
+
 1999-11-04  Tor Lillqvist  <tml@iki.fi>
 
        * config.h.win32: Don't define HAVE_DIMM_H if MSC, as you have to
index 608f6d7582204eec6e0dba17b7c7d082116a3f56..d7b557e905a641d5156bd26662dd37df7e09dc5c 100644 (file)
@@ -1,3 +1,43 @@
+1999-11-07  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: New font private structures, related to
+       fontsets.
+
+       * gdk/win32/gdkfont.c: New functions gdk_font_list_new() and
+       gdk_font_list_free(). On X11, will just be wrappers to
+       XListFonts() and XFreeFontNames(). On Win32, the code previously
+       in gtkfontsel.c is now here.
+
+       New function gdk_font_xlfd_create(). On X11 will get the FONT
+       property of the font (for GDK_FONT_FONTs), or call
+       XBaseFontNameListOfFontSet (for GDK_FONT_FONTSETs), on Win32
+       builds a XLFD style name from the font information in the LOGFONT
+       struct(s).
+
+       New function gdk_font_xlfd_free(), which correspondingly frees the
+       string returned by gdk_font_xlfd_create().
+
+       Implement fontsets on Win32. Add a function that iterates over a
+       wide char string and calls a callback function for each substring
+       of wide chars from the same Unicode subrange (and thus probably
+       available in the same real font).
+
+       Improve the XLFD emulation a bit.
+
+       * gdk/win32/gdkim.c (gdk_nmbstowchar_ts): Small bugfix.
+
+       * gdk/win32/gdkevents.c: Workaround for suspected bug on Win2k
+       Beta3, WM_IME_CHAR messages don't seem to contain the composed
+       multi-byte char as with the Active IMM on Win9x. Oh well, handle
+       WM_IME_COMPOSITION with GCS_RESULTSTR instead, use
+       ImmGetCompositionStringW() to get the composed Unicode chars.
+
+       * gdk/win32/gdkgc.c
+       * gdk/win32/gdkdraw.c: Changes needed because of the font private
+       struct changes.
+
+       * gdk/win32/gdk.def: Add the new functions.
+
 1999-11-04  Tor Lillqvist  <tml@iki.fi>
 
        * config.h.win32: Don't define HAVE_DIMM_H if MSC, as you have to
index 1f56d0e03706ab41605b563aacf9aa5905d7a32b..79d7b8c71a80dd1cd749af31588cb9a1d6d3d68e 100644 (file)
@@ -105,9 +105,13 @@ EXPORTS
        gdk_flush
        gdk_font_equal
        gdk_font_id
+       gdk_font_list_free
+       gdk_font_list_new
        gdk_font_load
        gdk_font_ref
        gdk_font_unref
+       gdk_font_xlfd_create
+       gdk_font_xlfd_free
        gdk_fontset_load
        gdk_free_compound_text
        gdk_free_text_list
index 9e5cb9f0cabb2f6dea1bdc292df2e1b03e719241..e8fa5af5d246441b92751feab57910b557e8226e 100644 (file)
@@ -235,6 +235,7 @@ gdk_init_check (int    *argc,
   gdk_ProgInstance = GetModuleHandle (NULL);
   gdk_DC = CreateDC ("DISPLAY", NULL, NULL, NULL);
   gdk_root_window = GetDesktopWindow ();
+  windows_version = GetVersion ();
 
   CoInitialize (NULL);
 
index 1f56d0e03706ab41605b563aacf9aa5905d7a32b..79d7b8c71a80dd1cd749af31588cb9a1d6d3d68e 100644 (file)
@@ -105,9 +105,13 @@ EXPORTS
        gdk_flush
        gdk_font_equal
        gdk_font_id
+       gdk_font_list_free
+       gdk_font_list_new
        gdk_font_load
        gdk_font_ref
        gdk_font_unref
+       gdk_font_xlfd_create
+       gdk_font_xlfd_free
        gdk_fontset_load
        gdk_free_compound_text
        gdk_free_text_list
index 2fd8ca1b3c0714c9c22ff61532808466261786f6..6dd3dc732e536a07cd9689b13b19c1153ce3a212 100644 (file)
@@ -6,3 +6,4 @@
 #define GDK_HAVE_WCTYPE_H 1
 #endif
 #define GDK_USE_UTF8_MBS 1
+
index 85ca076ccecdbc980b983f1399bd0fbd8e69dcf9..be27056430597ef026633e9e354428c6a4bb68be 100644 (file)
@@ -209,8 +209,7 @@ gdk_draw_line (GdkDrawable *drawable,
    * we draw the end pixel separately... With wider pens we don't care.
    * //HB: But the NT developers don't read their API documentation ...
    */
-  if (gc_private->pen_width == 1
-      && GetVersion () > 0x80000000)
+  if (gc_private->pen_width == 1 && windows_version > 0x80000000)
     if (!LineTo (hdc, x2 + 1, y2))
       g_warning ("gdk_draw_line: LineTo #2 failed");
   gdk_gc_postdraw (drawable_private, gc_private);
@@ -423,6 +422,12 @@ gdk_draw_polygon (GdkDrawable *drawable,
   gdk_gc_postdraw (drawable_private, gc_private);
 }
 
+typedef struct
+{
+  gint x, y;
+  HDC hdc;
+} gdk_draw_text_arg;
+
 /* gdk_draw_string
  */
 void
@@ -436,9 +441,35 @@ gdk_draw_string (GdkDrawable *drawable,
   gdk_draw_text (drawable, font, gc, x, y, string, strlen (string));
 }
 
+static void
+gdk_draw_text_handler (GdkWin32SingleFont *singlefont,
+                      const wchar_t      *wcstr,
+                      int                 wclen,
+                      void               *arg)
+{
+  HDC hdc;
+  HGDIOBJ oldfont;
+  SIZE size;
+  GdkDrawablePrivate *drawable_private;
+  GdkGCPrivate *gc_private;
+  gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg;
+
+  if ((oldfont = SelectObject (argp->hdc, singlefont->xfont)) == NULL)
+    {
+      g_warning ("gdk_draw_text_handler: SelectObject failed");
+      return;
+    }
+  
+  if (!TextOutW (argp->hdc, argp->x, argp->y, wcstr, wclen))
+    g_warning ("gdk_draw_text_handler: TextOutW failed");
+  GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size);
+  argp->x += size.cx;
+
+  SelectObject (hdc, oldfont);
+}
+
 /* gdk_draw_text
  *
- * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
  */
 void
 gdk_draw_text (GdkDrawable *drawable,
@@ -449,14 +480,12 @@ gdk_draw_text (GdkDrawable *drawable,
               const gchar *text,
               gint         text_length)
 {
+  HDC hdc;
   GdkDrawablePrivate *drawable_private;
-  GdkFontPrivate *font_private;
   GdkGCPrivate *gc_private;
-  HDC hdc;
-  HFONT xfont;
-  HGDIOBJ oldfont;
   wchar_t *wcstr;
   gint wlen;
+  gdk_draw_text_arg arg;
 
   g_return_if_fail (drawable != NULL);
   g_return_if_fail (font != NULL);
@@ -473,30 +502,26 @@ gdk_draw_text (GdkDrawable *drawable,
 
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
-  font_private = (GdkFontPrivate*) font;
 
-  hdc = gdk_gc_predraw (drawable_private, gc_private);
-  xfont = (HFONT) font_private->xfont;
+  arg.x = x;
+  arg.y = y;
+  arg.hdc = gdk_gc_predraw (drawable_private, gc_private);
 
-  GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
-                          "+%d+%d font: %#x \"%.*s\" length: %d\n",
+  GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d,%d) \"%.*s\" (len %d)\n",
                           drawable_private->xwindow,
-                          gc_private, gc_private->xgc,
-                          x, y, xfont,
+                          x, y,
                           (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");
+  else
+    gdk_wchar_text_handle (font, wcstr, wlen,
+                          gdk_draw_text_handler, &arg);
+
   g_free (wcstr);
-  if (oldfont != NULL)
-    SelectObject (hdc, oldfont);
+
   gdk_gc_postdraw (drawable_private, gc_private);
 }
 
@@ -510,13 +535,11 @@ gdk_draw_text_wc (GdkDrawable      *drawable,
                  gint            text_length)
 {
   HDC hdc;
-  HGDIOBJ oldfont;
   GdkDrawablePrivate *drawable_private;
-  GdkFontPrivate *font_private;
   GdkGCPrivate *gc_private;
   gint i, wlen;
   wchar_t *wcstr;
-  guchar *str;
+  gdk_draw_text_arg arg;
 
   g_return_if_fail (drawable != NULL);
   g_return_if_fail (font != NULL);
@@ -533,19 +556,15 @@ gdk_draw_text_wc (GdkDrawable      *drawable,
 
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
-  font_private = (GdkFontPrivate*) font;
 
-  hdc = gdk_gc_predraw (drawable_private, gc_private);
+  arg.x = x;
+  arg.y = y;
+  arg.hdc = gdk_gc_predraw (drawable_private, gc_private);
 
-  GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
-                          "+%d+%d font: %#x length: %d\n",
+  GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d,%d) len: %d\n",
                           drawable_private->xwindow,
-                          gc_private, gc_private->xgc,
-                          x, y, font_private->xfont,
-                          text_length));
+                          x, y, text_length));
       
-  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);
@@ -555,13 +574,12 @@ gdk_draw_text_wc (GdkDrawable      *drawable,
   else
     wcstr = (wchar_t *) text;
 
-  if (!TextOutW (hdc, x, y, wcstr, text_length))
-    g_warning ("gdk_draw_text_wc: TextOutW failed");
+  gdk_wchar_text_handle (font, wcstr, text_length,
+                        gdk_draw_text_handler, &arg);
 
   if (sizeof (wchar_t) != sizeof (GdkWChar))
     g_free (wcstr);
-  if (oldfont != NULL)
-    SelectObject (hdc, oldfont);
+
   gdk_gc_postdraw (drawable_private, gc_private);
 }
 
index 85ca076ccecdbc980b983f1399bd0fbd8e69dcf9..be27056430597ef026633e9e354428c6a4bb68be 100644 (file)
@@ -209,8 +209,7 @@ gdk_draw_line (GdkDrawable *drawable,
    * we draw the end pixel separately... With wider pens we don't care.
    * //HB: But the NT developers don't read their API documentation ...
    */
-  if (gc_private->pen_width == 1
-      && GetVersion () > 0x80000000)
+  if (gc_private->pen_width == 1 && windows_version > 0x80000000)
     if (!LineTo (hdc, x2 + 1, y2))
       g_warning ("gdk_draw_line: LineTo #2 failed");
   gdk_gc_postdraw (drawable_private, gc_private);
@@ -423,6 +422,12 @@ gdk_draw_polygon (GdkDrawable *drawable,
   gdk_gc_postdraw (drawable_private, gc_private);
 }
 
+typedef struct
+{
+  gint x, y;
+  HDC hdc;
+} gdk_draw_text_arg;
+
 /* gdk_draw_string
  */
 void
@@ -436,9 +441,35 @@ gdk_draw_string (GdkDrawable *drawable,
   gdk_draw_text (drawable, font, gc, x, y, string, strlen (string));
 }
 
+static void
+gdk_draw_text_handler (GdkWin32SingleFont *singlefont,
+                      const wchar_t      *wcstr,
+                      int                 wclen,
+                      void               *arg)
+{
+  HDC hdc;
+  HGDIOBJ oldfont;
+  SIZE size;
+  GdkDrawablePrivate *drawable_private;
+  GdkGCPrivate *gc_private;
+  gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg;
+
+  if ((oldfont = SelectObject (argp->hdc, singlefont->xfont)) == NULL)
+    {
+      g_warning ("gdk_draw_text_handler: SelectObject failed");
+      return;
+    }
+  
+  if (!TextOutW (argp->hdc, argp->x, argp->y, wcstr, wclen))
+    g_warning ("gdk_draw_text_handler: TextOutW failed");
+  GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size);
+  argp->x += size.cx;
+
+  SelectObject (hdc, oldfont);
+}
+
 /* gdk_draw_text
  *
- * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
  */
 void
 gdk_draw_text (GdkDrawable *drawable,
@@ -449,14 +480,12 @@ gdk_draw_text (GdkDrawable *drawable,
               const gchar *text,
               gint         text_length)
 {
+  HDC hdc;
   GdkDrawablePrivate *drawable_private;
-  GdkFontPrivate *font_private;
   GdkGCPrivate *gc_private;
-  HDC hdc;
-  HFONT xfont;
-  HGDIOBJ oldfont;
   wchar_t *wcstr;
   gint wlen;
+  gdk_draw_text_arg arg;
 
   g_return_if_fail (drawable != NULL);
   g_return_if_fail (font != NULL);
@@ -473,30 +502,26 @@ gdk_draw_text (GdkDrawable *drawable,
 
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
-  font_private = (GdkFontPrivate*) font;
 
-  hdc = gdk_gc_predraw (drawable_private, gc_private);
-  xfont = (HFONT) font_private->xfont;
+  arg.x = x;
+  arg.y = y;
+  arg.hdc = gdk_gc_predraw (drawable_private, gc_private);
 
-  GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
-                          "+%d+%d font: %#x \"%.*s\" length: %d\n",
+  GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d,%d) \"%.*s\" (len %d)\n",
                           drawable_private->xwindow,
-                          gc_private, gc_private->xgc,
-                          x, y, xfont,
+                          x, y,
                           (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");
+  else
+    gdk_wchar_text_handle (font, wcstr, wlen,
+                          gdk_draw_text_handler, &arg);
+
   g_free (wcstr);
-  if (oldfont != NULL)
-    SelectObject (hdc, oldfont);
+
   gdk_gc_postdraw (drawable_private, gc_private);
 }
 
@@ -510,13 +535,11 @@ gdk_draw_text_wc (GdkDrawable      *drawable,
                  gint            text_length)
 {
   HDC hdc;
-  HGDIOBJ oldfont;
   GdkDrawablePrivate *drawable_private;
-  GdkFontPrivate *font_private;
   GdkGCPrivate *gc_private;
   gint i, wlen;
   wchar_t *wcstr;
-  guchar *str;
+  gdk_draw_text_arg arg;
 
   g_return_if_fail (drawable != NULL);
   g_return_if_fail (font != NULL);
@@ -533,19 +556,15 @@ gdk_draw_text_wc (GdkDrawable      *drawable,
 
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
-  font_private = (GdkFontPrivate*) font;
 
-  hdc = gdk_gc_predraw (drawable_private, gc_private);
+  arg.x = x;
+  arg.y = y;
+  arg.hdc = gdk_gc_predraw (drawable_private, gc_private);
 
-  GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
-                          "+%d+%d font: %#x length: %d\n",
+  GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d,%d) len: %d\n",
                           drawable_private->xwindow,
-                          gc_private, gc_private->xgc,
-                          x, y, font_private->xfont,
-                          text_length));
+                          x, y, text_length));
       
-  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);
@@ -555,13 +574,12 @@ gdk_draw_text_wc (GdkDrawable      *drawable,
   else
     wcstr = (wchar_t *) text;
 
-  if (!TextOutW (hdc, x, y, wcstr, text_length))
-    g_warning ("gdk_draw_text_wc: TextOutW failed");
+  gdk_wchar_text_handle (font, wcstr, text_length,
+                        gdk_draw_text_handler, &arg);
 
   if (sizeof (wchar_t) != sizeof (GdkWChar))
     g_free (wcstr);
-  if (oldfont != NULL)
-    SelectObject (hdc, oldfont);
+
   gdk_gc_postdraw (drawable_private, gc_private);
 }
 
index 279e831f559d1acae91183949a6002d362ef704a..dbdfbbf6f0f125d3189d3b54e94674c6be3648cb 100644 (file)
@@ -187,6 +187,11 @@ static gboolean is_AltGr_key = FALSE;
 static IActiveIMMApp *paimmapp = NULL;
 static IActiveIMMMessagePumpOwner *paimmmpo = NULL;
 
+typedef BOOL (WINAPI *PFN_TrackMouseEvent) (LPTRACKMOUSEEVENT);
+static PFN_TrackMouseEvent p_TrackMouseEvent = NULL;
+
+static gboolean use_IME_COMPOSITION = FALSE;
+
 LRESULT CALLBACK 
 gdk_WindowProc (HWND hWnd,
                UINT message,
@@ -381,7 +386,7 @@ void
 gdk_events_init (void)
 {
   HRESULT hres;
-  HMODULE user32;
+  HMODULE user32, imm32;
   HINSTANCE commctrl32;
 
   if (g_pipe_readable_msg == 0)
@@ -430,11 +435,21 @@ gdk_events_init (void)
   if ((p_TrackMouseEvent = GetProcAddress (user32, "TrackMouseEvent")) == NULL)
     {
       if ((commctrl32 = LoadLibrary ("commctrl32.dll")) != NULL)
-       p_TrackMouseEvent = GetProcAddress (commctrl32, "_TrackMouseEvent");
+       p_TrackMouseEvent = (PFN_TrackMouseEvent)
+         GetProcAddress (commctrl32, "_TrackMouseEvent");
     }
   if (p_TrackMouseEvent != NULL)
     GDK_NOTE (EVENTS, g_print ("Using TrackMouseEvent to detect leave events\n"));
 #endif
+  if (windows_version < 0x80000000 && (windows_version & 0xFF) == 5)
+    {
+      /* On Win2k (Beta 3, at least) WM_IME_CHAR doesn't seem to work
+       * correctly for non-Unicode applications. Handle
+       * WM_IME_COMPOSITION with GCS_RESULTSTR instead, fetch the
+       * Unicode char from the IME with ImmGetCompositionStringW().
+       */
+      use_IME_COMPOSITION = TRUE;
+    }
 }
 
 /*
@@ -1174,6 +1189,8 @@ gdk_add_client_message_filter (GdkAtom       message_type,
  * mapping functions, from the xterm sources.
  */
 
+#if 0 /* Keyval-to-Unicode isn't actually needed  */
+
 struct k2u {
   unsigned short keysym;
   unsigned short ucs;
@@ -1997,6 +2014,8 @@ keyval_to_unicode (guint keysym)
   return -1;
 }
 
+#endif /* 0 */
+
 struct u2k {
   unsigned short keysym;
   unsigned short ucs;
@@ -2841,6 +2860,7 @@ build_keypress_event (GdkWindowPrivate *window_private,
                      GdkEvent         *event,
                      MSG              *xevent)
 {
+  HIMC hIMC;
   gint i, bytesleft, bytecount, ucount, ucleft, len;
   guchar buf[100], *bp;
   wchar_t wbuf[100], *wcp;
@@ -2848,39 +2868,50 @@ build_keypress_event (GdkWindowPrivate *window_private,
   event->key.type = GDK_KEY_PRESS;
   event->key.time = xevent->time;
   
-  if (xevent->message == WM_CHAR)
+  if (xevent->message == WM_IME_COMPOSITION)
     {
-      bytecount = MIN ((xevent->lParam & 0xFFFF), sizeof (buf));
-      for (i = 0; i < bytecount; i++)
-       buf[i] = xevent->wParam;
+      hIMC = ImmGetContext (xevent->hwnd);
+
+      bytecount = ImmGetCompositionStringW (hIMC, GCS_RESULTSTR,
+                                           wbuf, sizeof (wbuf));
+      ucount = bytecount / 2;
     }
   else
     {
-      /* WM_IME_CHAR */
-      event->key.keyval = GDK_VoidSymbol;
-      if (xevent->wParam & 0xFF00)
+      if (xevent->message == WM_CHAR)
        {
-         /* Contrary to the documentation,
-          * the lead byte is the msb byte.
-          */
-         buf[0] = ((xevent->wParam >> 8) & 0xFF);
-         buf[1] = (xevent->wParam & 0xFF);
-         bytecount = 2;
+         bytecount = MIN ((xevent->lParam & 0xFFFF), sizeof (buf));
+         for (i = 0; i < bytecount; i++)
+           buf[i] = xevent->wParam;
        }
-      else
+      else /* WM_IME_CHAR */
        {
-         buf[0] = (xevent->wParam & 0xFF);
-         bytecount = 1;
+         event->key.keyval = GDK_VoidSymbol;
+         if (xevent->wParam & 0xFF00)
+           {
+             /* Contrary to some versions of the documentation,
+              * the lead byte is the most significant 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);
-  
+      /* 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, sizeof (wbuf) / sizeof (wbuf[0]));
+      
+    }
   if (ucount == 0)
     event->key.keyval = GDK_VoidSymbol;
   else if (xevent->message == WM_CHAR)
@@ -2958,6 +2989,35 @@ build_keypress_event (GdkWindowPrivate *window_private,
   *bp = 0;
 }
 
+static void
+build_keyrelease_event (GdkWindowPrivate *window_private,
+                       GdkEvent         *event,
+                       MSG              *xevent)
+{
+  guchar buf;
+  wchar_t wbuf;
+
+  event->key.type = GDK_KEY_RELEASE;
+  event->key.time = xevent->time;
+
+  if (xevent->message == WM_CHAR)
+    if (xevent->wParam < ' ')
+      event->key.keyval = xevent->wParam + '@';
+    else
+      {
+       buf = xevent->wParam;
+       MultiByteToWideChar (window_private->charset_info.ciACP,
+                            0, &buf, 1, &wbuf, 1);
+
+       event->key.keyval = unicode_to_keyval (wbuf);
+      }
+  else
+    event->key.keyval = GDK_VoidSymbol;
+  build_key_event_state (event);
+  event->key.string = NULL;
+  event->key.length = 0;
+}
+
 static void
 print_event_state (gint state)
 {
@@ -3368,7 +3428,7 @@ gdk_event_translate (GdkEvent *event,
   HDC bgdc;
   HGDIOBJ oldbitmap;
   int button;
-  int i, j;
+  int i, j, n, k;
   gchar buf[256];
   gchar *msgname;
   gboolean return_val;
@@ -3835,6 +3895,15 @@ gdk_event_translate (GdkEvent *event,
       return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
+    case WM_IME_COMPOSITION:
+      if (!use_IME_COMPOSITION)
+       break;
+      GDK_NOTE (EVENTS, g_print ("WM_IME_COMPOSITION: %#x  %#x\n",
+                                xevent->hwnd, xevent->lParam));
+      if (xevent->lParam & GCS_RESULTSTR)
+       goto wm_char;
+      break;
+
     case WM_IME_CHAR:
       GDK_NOTE (EVENTS,
                g_print ("WM_IME_CHAR: %#x  bytes: %#.04x\n",
@@ -3918,22 +3987,18 @@ gdk_event_translate (GdkEvent *event,
              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;
+         /* Return the key release event.  */
+         build_keyrelease_event (WINDOW_PRIVATE(window), event, xevent);
        }
       else if (return_val
               && (WINDOW_PRIVATE(window)->event_mask & GDK_KEY_PRESS_MASK))
        {
-         /* Return just the GDK_KEY_PRESS event. */
+         /* Return just the key press event. */
          build_keypress_event (WINDOW_PRIVATE(window), event, xevent);
        }
       else
        return_val = FALSE;
+
 #if 0 /* Don't reset is_AltGr_key here. Othewise we can't type several
        * AltGr-accessed chars while keeping the AltGr pressed down
        * all the time.
index 279e831f559d1acae91183949a6002d362ef704a..dbdfbbf6f0f125d3189d3b54e94674c6be3648cb 100644 (file)
@@ -187,6 +187,11 @@ static gboolean is_AltGr_key = FALSE;
 static IActiveIMMApp *paimmapp = NULL;
 static IActiveIMMMessagePumpOwner *paimmmpo = NULL;
 
+typedef BOOL (WINAPI *PFN_TrackMouseEvent) (LPTRACKMOUSEEVENT);
+static PFN_TrackMouseEvent p_TrackMouseEvent = NULL;
+
+static gboolean use_IME_COMPOSITION = FALSE;
+
 LRESULT CALLBACK 
 gdk_WindowProc (HWND hWnd,
                UINT message,
@@ -381,7 +386,7 @@ void
 gdk_events_init (void)
 {
   HRESULT hres;
-  HMODULE user32;
+  HMODULE user32, imm32;
   HINSTANCE commctrl32;
 
   if (g_pipe_readable_msg == 0)
@@ -430,11 +435,21 @@ gdk_events_init (void)
   if ((p_TrackMouseEvent = GetProcAddress (user32, "TrackMouseEvent")) == NULL)
     {
       if ((commctrl32 = LoadLibrary ("commctrl32.dll")) != NULL)
-       p_TrackMouseEvent = GetProcAddress (commctrl32, "_TrackMouseEvent");
+       p_TrackMouseEvent = (PFN_TrackMouseEvent)
+         GetProcAddress (commctrl32, "_TrackMouseEvent");
     }
   if (p_TrackMouseEvent != NULL)
     GDK_NOTE (EVENTS, g_print ("Using TrackMouseEvent to detect leave events\n"));
 #endif
+  if (windows_version < 0x80000000 && (windows_version & 0xFF) == 5)
+    {
+      /* On Win2k (Beta 3, at least) WM_IME_CHAR doesn't seem to work
+       * correctly for non-Unicode applications. Handle
+       * WM_IME_COMPOSITION with GCS_RESULTSTR instead, fetch the
+       * Unicode char from the IME with ImmGetCompositionStringW().
+       */
+      use_IME_COMPOSITION = TRUE;
+    }
 }
 
 /*
@@ -1174,6 +1189,8 @@ gdk_add_client_message_filter (GdkAtom       message_type,
  * mapping functions, from the xterm sources.
  */
 
+#if 0 /* Keyval-to-Unicode isn't actually needed  */
+
 struct k2u {
   unsigned short keysym;
   unsigned short ucs;
@@ -1997,6 +2014,8 @@ keyval_to_unicode (guint keysym)
   return -1;
 }
 
+#endif /* 0 */
+
 struct u2k {
   unsigned short keysym;
   unsigned short ucs;
@@ -2841,6 +2860,7 @@ build_keypress_event (GdkWindowPrivate *window_private,
                      GdkEvent         *event,
                      MSG              *xevent)
 {
+  HIMC hIMC;
   gint i, bytesleft, bytecount, ucount, ucleft, len;
   guchar buf[100], *bp;
   wchar_t wbuf[100], *wcp;
@@ -2848,39 +2868,50 @@ build_keypress_event (GdkWindowPrivate *window_private,
   event->key.type = GDK_KEY_PRESS;
   event->key.time = xevent->time;
   
-  if (xevent->message == WM_CHAR)
+  if (xevent->message == WM_IME_COMPOSITION)
     {
-      bytecount = MIN ((xevent->lParam & 0xFFFF), sizeof (buf));
-      for (i = 0; i < bytecount; i++)
-       buf[i] = xevent->wParam;
+      hIMC = ImmGetContext (xevent->hwnd);
+
+      bytecount = ImmGetCompositionStringW (hIMC, GCS_RESULTSTR,
+                                           wbuf, sizeof (wbuf));
+      ucount = bytecount / 2;
     }
   else
     {
-      /* WM_IME_CHAR */
-      event->key.keyval = GDK_VoidSymbol;
-      if (xevent->wParam & 0xFF00)
+      if (xevent->message == WM_CHAR)
        {
-         /* Contrary to the documentation,
-          * the lead byte is the msb byte.
-          */
-         buf[0] = ((xevent->wParam >> 8) & 0xFF);
-         buf[1] = (xevent->wParam & 0xFF);
-         bytecount = 2;
+         bytecount = MIN ((xevent->lParam & 0xFFFF), sizeof (buf));
+         for (i = 0; i < bytecount; i++)
+           buf[i] = xevent->wParam;
        }
-      else
+      else /* WM_IME_CHAR */
        {
-         buf[0] = (xevent->wParam & 0xFF);
-         bytecount = 1;
+         event->key.keyval = GDK_VoidSymbol;
+         if (xevent->wParam & 0xFF00)
+           {
+             /* Contrary to some versions of the documentation,
+              * the lead byte is the most significant 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);
-  
+      /* 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, sizeof (wbuf) / sizeof (wbuf[0]));
+      
+    }
   if (ucount == 0)
     event->key.keyval = GDK_VoidSymbol;
   else if (xevent->message == WM_CHAR)
@@ -2958,6 +2989,35 @@ build_keypress_event (GdkWindowPrivate *window_private,
   *bp = 0;
 }
 
+static void
+build_keyrelease_event (GdkWindowPrivate *window_private,
+                       GdkEvent         *event,
+                       MSG              *xevent)
+{
+  guchar buf;
+  wchar_t wbuf;
+
+  event->key.type = GDK_KEY_RELEASE;
+  event->key.time = xevent->time;
+
+  if (xevent->message == WM_CHAR)
+    if (xevent->wParam < ' ')
+      event->key.keyval = xevent->wParam + '@';
+    else
+      {
+       buf = xevent->wParam;
+       MultiByteToWideChar (window_private->charset_info.ciACP,
+                            0, &buf, 1, &wbuf, 1);
+
+       event->key.keyval = unicode_to_keyval (wbuf);
+      }
+  else
+    event->key.keyval = GDK_VoidSymbol;
+  build_key_event_state (event);
+  event->key.string = NULL;
+  event->key.length = 0;
+}
+
 static void
 print_event_state (gint state)
 {
@@ -3368,7 +3428,7 @@ gdk_event_translate (GdkEvent *event,
   HDC bgdc;
   HGDIOBJ oldbitmap;
   int button;
-  int i, j;
+  int i, j, n, k;
   gchar buf[256];
   gchar *msgname;
   gboolean return_val;
@@ -3835,6 +3895,15 @@ gdk_event_translate (GdkEvent *event,
       return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
+    case WM_IME_COMPOSITION:
+      if (!use_IME_COMPOSITION)
+       break;
+      GDK_NOTE (EVENTS, g_print ("WM_IME_COMPOSITION: %#x  %#x\n",
+                                xevent->hwnd, xevent->lParam));
+      if (xevent->lParam & GCS_RESULTSTR)
+       goto wm_char;
+      break;
+
     case WM_IME_CHAR:
       GDK_NOTE (EVENTS,
                g_print ("WM_IME_CHAR: %#x  bytes: %#.04x\n",
@@ -3918,22 +3987,18 @@ gdk_event_translate (GdkEvent *event,
              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;
+         /* Return the key release event.  */
+         build_keyrelease_event (WINDOW_PRIVATE(window), event, xevent);
        }
       else if (return_val
               && (WINDOW_PRIVATE(window)->event_mask & GDK_KEY_PRESS_MASK))
        {
-         /* Return just the GDK_KEY_PRESS event. */
+         /* Return just the key press event. */
          build_keypress_event (WINDOW_PRIVATE(window), event, xevent);
        }
       else
        return_val = FALSE;
+
 #if 0 /* Don't reset is_AltGr_key here. Othewise we can't type several
        * AltGr-accessed chars while keeping the AltGr pressed down
        * all the time.
index 59791945ba4706ca11b160664082eaa45e5170ef..f6b768bac7b773618ead46b2aafd1bbdee60ef90 100644 (file)
 #include <ctype.h>
 
 #include "gdkfont.h"
-#include "gdkprivate.h"
+#include "gdkx.h"
 
 static GHashTable *font_name_hash = NULL;
 static GHashTable *fontset_name_hash = NULL;
 
 static void
-gdk_font_hash_insert (GdkFontType type, GdkFont *font, const gchar *font_name)
+gdk_font_hash_insert (GdkFontType  type,
+                     GdkFont     *font,
+                     const gchar *font_name)
 {
-  GdkFontPrivate *private = (GdkFontPrivate *)font;
+  GdkFontPrivate *private = (GdkFontPrivate *) font;
   GHashTable **hashp = (type == GDK_FONT_FONT) ?
     &font_name_hash : &fontset_name_hash;
 
@@ -50,9 +52,10 @@ gdk_font_hash_insert (GdkFontType type, GdkFont *font, const gchar *font_name)
 }
 
 static void
-gdk_font_hash_remove (GdkFontType type, GdkFont *font)
+gdk_font_hash_remove (GdkFontType type,
+                     GdkFont    *font)
 {
-  GdkFontPrivate *private = (GdkFontPrivate *)font;
+  GdkFontPrivate *private = (GdkFontPrivate *) font;
   GSList *tmp_list;
   GHashTable *hash = (type == GDK_FONT_FONT) ?
     font_name_hash : fontset_name_hash;
@@ -71,7 +74,8 @@ gdk_font_hash_remove (GdkFontType type, GdkFont *font)
 }
 
 static GdkFont *
-gdk_font_hash_lookup (GdkFontType type, const gchar *font_name)
+gdk_font_hash_lookup (GdkFontType  type,
+                     const gchar *font_name)
 {
   GdkFont *result;
   GHashTable *hash = (type == GDK_FONT_FONT) ?
@@ -94,40 +98,353 @@ charset_name (DWORD charset)
 {
   switch (charset)
     {
-    case ANSI_CHARSET: return "ANSI";
-    case DEFAULT_CHARSET: return "DEFAULT";
-    case SYMBOL_CHARSET: return "SYMBOL";
-    case SHIFTJIS_CHARSET: return "SHIFTJIS";
-    case HANGEUL_CHARSET: return "HANGEUL";
-    case GB2312_CHARSET: return "GB2312";
-    case CHINESEBIG5_CHARSET: return "CHINESEBIG5";
-    case JOHAB_CHARSET: return "JOHAB";
-    case HEBREW_CHARSET: return "HEBREW";
-    case ARABIC_CHARSET: return "ARABIC";
-    case GREEK_CHARSET: return "GREEK";
-    case TURKISH_CHARSET: return "TURKISH";
-    case VIETNAMESE_CHARSET: return "VIETNAMESE";
-    case THAI_CHARSET: return "THAI";
-    case EASTEUROPE_CHARSET: return "EASTEUROPE";
-    case RUSSIAN_CHARSET: return "RUSSIAN";
-    case MAC_CHARSET: return "MAC";
-    case BALTIC_CHARSET: return "BALTIC";
+    case ANSI_CHARSET: return "ansi";
+    case DEFAULT_CHARSET: return "default";
+    case SYMBOL_CHARSET: return "symbol";
+    case SHIFTJIS_CHARSET: return "shiftjis";
+    case HANGEUL_CHARSET: return "hangeul";
+    case GB2312_CHARSET: return "gb2312";
+    case CHINESEBIG5_CHARSET: return "big5";
+    case JOHAB_CHARSET: return "johab";
+    case HEBREW_CHARSET: return "hebrew";
+    case ARABIC_CHARSET: return "arabic";
+    case GREEK_CHARSET: return "greek";
+    case TURKISH_CHARSET: return "turkish";
+    case VIETNAMESE_CHARSET: return "vietnamese";
+    case THAI_CHARSET: return "thai";
+    case EASTEUROPE_CHARSET: return "easteurope";
+    case RUSSIAN_CHARSET: return "russian";
+    case MAC_CHARSET: return "mac";
+    case BALTIC_CHARSET: return "baltic";
     }
   return "unknown";
 }
 
-GdkFont*
-gdk_font_load_internal (GdkFontType  type,
-                       const gchar *font_name)
+static gint num_fonts;
+static gint font_names_size;
+static gchar **xfontnames;
+
+static gchar *
+logfont_to_xlfd (const LOGFONT *lfp,
+                int            size,
+                int            res,
+                int            avg_width)
+{
+  const gchar *weight;
+  const gchar *registry, *encoding;
+  int point_size;
+  static int logpixelsy = 0;
+  gchar facename[LF_FACESIZE*3];
+  gchar *p;
+  const gchar *q;
+
+  if (logpixelsy == 0)
+    {
+      logpixelsy = GetDeviceCaps (gdk_DC, LOGPIXELSY);
+    }
+
+  if (lfp->lfWeight >= FW_HEAVY)
+    weight = "heavy";
+  else if (lfp->lfWeight >= FW_EXTRABOLD)
+    weight = "extrabold";
+  else if (lfp->lfWeight >= FW_BOLD)
+    weight = "bold";
+#ifdef FW_DEMIBOLD
+  else if (lfp->lfWeight >= FW_DEMIBOLD)
+    weight = "demibold";
+#endif
+  else if (lfp->lfWeight >= FW_MEDIUM)
+    weight = "medium";
+  else if (lfp->lfWeight >= FW_NORMAL)
+    weight = "normal";
+  else if (lfp->lfWeight >= FW_LIGHT)
+    weight = "light";
+  else if (lfp->lfWeight >= FW_EXTRALIGHT)
+    weight = "extralight";
+  else if (lfp->lfWeight >= FW_THIN)
+    weight = "thin";
+  else
+    weight = "regular";
+
+  switch (lfp->lfCharSet)
+    {
+    case ANSI_CHARSET:
+      registry = "iso8859";
+      encoding = "1";
+      break;
+    case SHIFTJIS_CHARSET:
+      registry = "jisx0208.1983";
+      encoding = "0";
+      break;
+    case HANGEUL_CHARSET:
+      registry = "ksc5601.1987";
+      encoding = "0";
+      break;
+    case GB2312_CHARSET:
+      registry = "gb2312.1980";
+      encoding = "0";
+      break;
+    case CHINESEBIG5_CHARSET:
+      registry = "big5";
+      encoding = "0";
+      break;
+    case GREEK_CHARSET:
+      registry = "iso8859";
+      encoding = "7";
+      break;
+    case TURKISH_CHARSET:
+      registry = "iso8859";
+      encoding = "9";
+      break;
+#if 0 /* Not a good idea, I think, to use ISO8859-8 and -6 for the Windows
+       * hebrew and arabic codepages, they differ too much.
+       */
+    case HEBREW_CHARSET:
+      registry = "iso8859";
+      encoding = "8";
+      break;
+    case ARABIC_CHARSET:
+      registry = "iso8859";
+      encoding = "6";
+      break;
+#endif
+    default:
+      registry = "microsoft";
+      encoding = charset_name (lfp->lfCharSet);
+    }
+  
+  point_size = (int) (((double) size/logpixelsy) * 720.);
+
+  if (res == -1)
+    res = logpixelsy;
+
+  /* Replace illegal characters with hex escapes. */
+  p = facename;
+  q = lfp->lfFaceName;
+  while (*q)
+    {
+      if (*q == '-' || *q == '*' || *q == '?' || *q == '%')
+       p += sprintf (p, "%%%.02x", *q);
+      else
+       *p++ = *q;
+      q++;
+    }
+  *p = '\0';
+
+  return  g_strdup_printf
+    ("-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d-%s-%s",
+     "unknown", 
+     facename,
+     weight,
+     (lfp->lfItalic ?
+      ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN
+       || (lfp->lfPitchAndFamily & 0xF0) == FF_SCRIPT ?
+       "i" : "o") : "r"),
+     "normal",
+     "",
+     size,
+     point_size,
+     res,
+     res,
+     ((lfp->lfPitchAndFamily & 0x03) == FIXED_PITCH ? "m" : "p"),
+     avg_width,
+     registry, encoding);
+}
+
+gchar *
+gdk_font_xlfd_create (GdkFont *font)
 {
-  GdkFont *font;
   GdkFontPrivate *private;
+  GdkWin32SingleFont *singlefont;
+  GSList *list;
+  GString *string;
+  gchar *result;
+  LOGFONT logfont;
+
+  g_return_val_if_fail (font != NULL, NULL);
+
+  private = (GdkFontPrivate *) font;
+
+  list = private->fonts;
+  string = g_string_new ("");
+
+  while (list)
+    {
+      singlefont = (GdkWin32SingleFont *) list->data;
+
+      if (GetObject (singlefont->xfont, sizeof (LOGFONT), &logfont) == 0)
+       {
+         g_warning ("gdk_win32_font_xlfd: GetObject failed");
+         return NULL;
+       }
+
+      string =
+       g_string_append (string,
+                        logfont_to_xlfd (&logfont, logfont.lfHeight, -1, 0));
+      list = list->next;
+      if (list)
+       string = g_string_append_c (string, ',');
+    }
+  result = string->str;
+  g_string_free (string, FALSE);
+  return result;
+}
+
+void
+gdk_font_xlfd_free (gchar *xlfd)
+{
+  g_free (xlfd);
+}
+
+static gboolean
+pattern_match (const gchar *pattern,
+              const gchar *string)
+{
+  const gchar *p = pattern, *n = string;
+  gchar c, c1;
+
+  /* Common case first */
+  if ((pattern[0] == '*'
+       && pattern[1] == '\0')
+      || (pattern[0] == '-'
+         && pattern[1] == '*'
+         && pattern[2] == '\0'))
+    return TRUE;
+
+  while ((c = *p++) != '\0')
+    {
+      c = tolower (c);
+
+      switch (c)
+       {
+       case '?':
+         if (*n == '\0')
+           return FALSE;
+         break;
+
+       case '*':
+         for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
+           if (c == '?' && *n == '\0')
+           return FALSE;
+
+         if (c == '\0')
+           return TRUE;
+
+         c1 = tolower (c);
+         for (--p; *n != '\0'; ++n)
+           if (tolower (*n) == c1
+               && pattern_match (p, n))
+             return TRUE;
+         return FALSE;
+
+       default:
+         if (c != tolower (*n))
+           return FALSE;
+       }
+
+      ++n;
+    }
+
+  if (*n == '\0')
+    return TRUE;
+
+  return FALSE;
+}
+
+int CALLBACK
+InnerEnumFontFamExProc (const LOGFONT    *lfp,
+                       const TEXTMETRIC *metrics,
+                       DWORD             fontType,
+                       LPARAM            lParam)
+{
+  int size;
+  gchar *xlfd;
+
+  if (fontType == TRUETYPE_FONTTYPE)
+    {
+      size = 0;
+    }
+  else
+    {
+      size = lfp->lfHeight;
+    }
+
+  xlfd = logfont_to_xlfd (lfp, size, 0, 0);
+
+  if (!pattern_match ((gchar *) lParam, xlfd))
+    {
+      g_free (xlfd);
+      return 1;
+    }
+
+  num_fonts++;
+  if (num_fonts == font_names_size)
+    {
+      font_names_size *= 2;
+      xfontnames = g_realloc (xfontnames, font_names_size * sizeof (gchar *));
+    }
+  xfontnames[num_fonts-1] = xlfd;
+    
+  return 1;
+}
+
+int CALLBACK
+EnumFontFamExProc (const LOGFONT    *lfp,
+                  const TEXTMETRIC *metrics,
+                  DWORD             fontType,
+                  LPARAM            lParam)
+{
+  if (fontType == TRUETYPE_FONTTYPE)
+    {
+      LOGFONT lf;
+
+      lf = *lfp;
+
+      EnumFontFamiliesEx (gdk_DC, &lf, InnerEnumFontFamExProc, lParam, 0);
+    }
+  else
+    InnerEnumFontFamExProc (lfp, metrics, fontType, lParam);
+
+  return 1;
+}
+
+gchar **
+gdk_font_list_new (const gchar *font_pattern,
+                  gint        *n_returned)
+{
+  LOGFONT logfont;
+  gchar **result;
+
+  num_fonts = 0;
+  font_names_size = 100;
+  xfontnames = g_new (gchar *, font_names_size);
+  memset (&logfont, 0, sizeof (logfont));
+  logfont.lfCharSet = DEFAULT_CHARSET;
+  EnumFontFamiliesEx (gdk_DC, &logfont, EnumFontFamExProc,
+                     (LPARAM) font_pattern, 0);
+
+  result = g_new (gchar *, num_fonts + 1);
+  memmove (result, xfontnames, num_fonts * sizeof (gchar *));
+  result[num_fonts] = NULL;
+  g_free (xfontnames);
+
+  *n_returned = num_fonts;
+  return result;
+}
+
+void
+gdk_font_list_free (gchar **font_list)
+{
+  g_strfreev (font_list);
+}
+
+GdkWin32SingleFont*
+gdk_font_load_internal (const gchar *font_name)
+{
+  GdkWin32SingleFont *singlefont;
   HFONT hfont;
   LOGFONT logfont;
-  HGDIOBJ oldfont;
-  TEXTMETRIC textmetric;
   CHARSETINFO csi;
-  HANDLE *f;
   DWORD fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet,
     fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily;
   const char *lpszFace;
@@ -145,10 +462,6 @@ gdk_font_load_internal (GdkFontType  type,
 
   GDK_NOTE (MISC, g_print ("gdk_font_load_internal: %s\n", font_name));
 
-  font = gdk_font_hash_lookup (type, font_name);
-  if (font)
-    return font;
-
   numfields = sscanf (font_name,
                      "-%30[^-]-%100[^-]-%30[^-]-%30[^-]-%30[^-]-%n",
                      foundry,
@@ -178,7 +491,6 @@ gdk_font_load_internal (GdkFontType  type,
   else if (numfields != 5)
     {
       g_warning ("gdk_font_load: font name %s illegal", font_name);
-      g_free (font);
       return NULL;
     }
   else
@@ -220,7 +532,6 @@ gdk_font_load_internal (GdkFontType  type,
       if (numfields != 14 || font_name[n1 + n2] != '\0')
        {
          g_warning ("gdk_font_load: font name %s illegal", font_name);
-         g_free (font);
          return NULL;
        }
 
@@ -299,9 +610,26 @@ gdk_font_load_internal (GdkFontType  type,
       if (g_strcasecmp (registry, "iso8859") == 0)
        if (strcmp (encoding, "1") == 0)
          fdwCharSet = ANSI_CHARSET;
+       else if (strcmp (encoding, "2") == 0)
+         fdwCharSet = EASTEUROPE_CHARSET;
+       else if (strcmp (encoding, "7") == 0)
+         fdwCharSet = GREEK_CHARSET;
+       else if (strcmp (encoding, "8") == 0)
+         fdwCharSet = HEBREW_CHARSET;
+       else if (strcmp (encoding, "9") == 0)
+         fdwCharSet = TURKISH_CHARSET;
        else
          fdwCharSet = ANSI_CHARSET; /* XXX ??? */
-      else if (g_strcasecmp (registry, "windows") == 0)
+      else if (g_strcasecmp (registry, "jisx0208.1983") == 0)
+       fdwCharSet = SHIFTJIS_CHARSET;
+      else if (g_strcasecmp (registry, "ksc5601.1987") == 0)
+       fdwCharSet = HANGEUL_CHARSET;
+      else if (g_strcasecmp (registry, "gb2312.1980") == 0)
+       fdwCharSet = GB2312_CHARSET;
+      else if (g_strcasecmp (registry, "big5") == 0)
+       fdwCharSet = CHINESEBIG5_CHARSET;
+      else if (g_strcasecmp (registry, "windows") == 0
+              || g_strcasecmp (registry, "microsoft") == 0)
        if (g_strcasecmp (encoding, "symbol") == 0)
          fdwCharSet = SYMBOL_CHARSET;
        else if (g_strcasecmp (encoding, "shiftjis") == 0)
@@ -310,7 +638,7 @@ gdk_font_load_internal (GdkFontType  type,
          fdwCharSet = GB2312_CHARSET;
        else if (g_strcasecmp (encoding, "hangeul") == 0)
          fdwCharSet = HANGEUL_CHARSET;
-       else if (g_strcasecmp (encoding, "chinesebig5") == 0)
+       else if (g_strcasecmp (encoding, "big5") == 0)
          fdwCharSet = CHINESEBIG5_CHARSET;
        else if (g_strcasecmp (encoding, "johab") == 0)
          fdwCharSet = JOHAB_CHARSET;
@@ -330,6 +658,8 @@ gdk_font_load_internal (GdkFontType  type,
          fdwCharSet = MAC_CHARSET;
        else if (g_strcasecmp (encoding, "baltic") == 0)
          fdwCharSet = BALTIC_CHARSET;
+       else if (g_strcasecmp (encoding, "cp1251") == 0)
+         fdwCharSet = RUSSIAN_CHARSET;
        else
          fdwCharSet = ANSI_CHARSET; /* XXX ??? */
       else
@@ -412,56 +742,140 @@ gdk_font_load_internal (GdkFontType  type,
   if (!hfont)
     return NULL;
       
+  singlefont = g_new (GdkWin32SingleFont, 1);
+  singlefont->xfont = hfont;
+  GetObject (singlefont->xfont, sizeof (logfont), &logfont);
+  TranslateCharsetInfo ((DWORD *) singlefont->charset, &csi, TCI_SRCCHARSET);
+  singlefont->codepage = csi.ciACP;
+  GetCPInfo (singlefont->codepage, &singlefont->cpinfo);
+
+  return singlefont;
+}
+
+GdkFont*
+gdk_font_load (const gchar *font_name)
+{
+  GdkFont *font;
+  GdkFontPrivate *private;
+  GdkWin32SingleFont *singlefont;
+  HGDIOBJ oldfont;
+  HANDLE *f;
+  TEXTMETRIC textmetric;
+
+  g_return_val_if_fail (font_name != NULL, NULL);
+
+  font = gdk_font_hash_lookup (GDK_FONT_FONTSET, font_name);
+  if (font)
+    return font;
+
+  singlefont = gdk_font_load_internal (font_name);
+
   private = g_new (GdkFontPrivate, 1);
   font = (GdkFont*) private;
 
-  private->xfont = hfont;
   private->ref_count = 1;
   private->names = NULL;
-  GetObject (private->xfont, sizeof (logfont), &logfont);
-  oldfont = SelectObject (gdk_DC, private->xfont);
+  private->fonts = g_slist_append (NULL, singlefont);
+
+  /* Pretend all fonts are fontsets... Gtktext and gtkentry work better
+   * that way, they use wide chars, which is necessary for non-ASCII
+   * chars to work. (Yes, even Latin-1, as we use Unicode internally.)
+   */
+  font->type = GDK_FONT_FONTSET;
+  oldfont = SelectObject (gdk_DC, singlefont->xfont);
   GetTextMetrics (gdk_DC, &textmetric);
-  private->charset = GetTextCharsetInfo (gdk_DC, &private->fs, 0);
+  singlefont->charset = GetTextCharsetInfo (gdk_DC, &singlefont->fs, 0);
   SelectObject (gdk_DC, oldfont);
-  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;
 
   GDK_NOTE (MISC, g_print ("... = %#x charset %s codepage %d (max %d bytes) "
                           "asc %d desc %d\n",
-                          private->xfont,
-                          charset_name (private->charset),
-                          private->codepage,
-                          private->cpinfo.MaxCharSize,
+                          singlefont->xfont,
+                          charset_name (singlefont->charset),
+                          singlefont->codepage,
+                          singlefont->cpinfo.MaxCharSize,
                           font->ascent, font->descent));
 
-  /* This memory is leaked, so shoot me. */
-  f = g_new (HANDLE, 1);
-  *f = (HANDLE) ((guint) private->xfont + HFONT_DITHER);
-  gdk_xid_table_insert (f, font);
-
-  gdk_font_hash_insert (type, font, font_name);
+  gdk_font_hash_insert (GDK_FONT_FONTSET, font, font_name);
 
   return font;
 }
 
-GdkFont*
-gdk_font_load (const gchar *font_name)
-{
-  /* Load all fonts as fontsets... Gtktext and gtkentry work better
-   * that way, they use wide chars, which is necessary for non-ASCII
-   * chars to work. (Yes, even Latin-1, as we use Unicode internally.)
-   */
-  return gdk_font_load_internal (GDK_FONT_FONTSET, font_name);
-}
-
 GdkFont*
 gdk_fontset_load (gchar *fontset_name)
 {
-  return gdk_font_load_internal (GDK_FONT_FONTSET, fontset_name);
+  GdkFont *font;
+  GdkFontPrivate *private;
+  GdkWin32SingleFont *singlefont;
+  HGDIOBJ oldfont;
+  HANDLE *f;
+  TEXTMETRIC textmetric;
+  GSList *base_font_list = NULL;
+  gchar *fs;
+  gchar *b, *p, *s;
+
+  g_return_val_if_fail (fontset_name != NULL, NULL);
+
+  font = gdk_font_hash_lookup (GDK_FONT_FONTSET, fontset_name);
+  if (font)
+    return font;
+
+  s = fs = g_strdup (fontset_name);
+  while (*s && isspace (*s))
+    s++;
+
+  g_return_val_if_fail (*s, NULL);
+
+  private = g_new (GdkFontPrivate, 1);
+  font = (GdkFont*) private;
+
+  private->ref_count = 1;
+  private->names = NULL;
+  private->fonts = NULL;
+
+  font->type = GDK_FONT_FONTSET;
+  font->ascent = 0;
+  font->descent = 0;
+
+  while (TRUE)
+    {
+      if ((p = strchr (s, ',')) != NULL)
+       b = p;
+      else
+       b = s + strlen (s);
+
+      while (isspace (b[-1]))
+       b--;
+      *b = '\0';
+      singlefont = gdk_font_load_internal (s);
+      if (singlefont)
+       {
+         private->fonts = g_slist_append (private->fonts, singlefont);
+         oldfont = SelectObject (gdk_DC, singlefont->xfont);
+         GetTextMetrics (gdk_DC, &textmetric);
+         singlefont->charset = GetTextCharsetInfo (gdk_DC, &singlefont->fs, 0);
+         SelectObject (gdk_DC, oldfont);
+         font->ascent = MAX (font->ascent, textmetric.tmAscent);
+         font->descent = MAX (font->descent, textmetric.tmDescent);
+       }
+      if (p)
+       {
+         s = p + 1;
+         while (*s && isspace (*s))
+           s++;
+       }
+      else
+       break;
+      if (!*s)
+       break;
+    }
+  
+  g_free (fs);
+
+  gdk_font_hash_insert (GDK_FONT_FONTSET, font, fontset_name);
+
+  return font;
 }
 
 GdkFont*
@@ -474,8 +888,10 @@ gdk_font_ref (GdkFont *font)
   private = (GdkFontPrivate*) font;
   private->ref_count += 1;
 
-  GDK_NOTE (MISC, g_print ("gdk_font_ref %#x %d\n",
-                          private->xfont, private->ref_count));
+  GDK_NOTE (MISC,
+           g_print ("gdk_font_ref %#x %d\n",
+                    ((GdkWin32SingleFont *) private->fonts->data)->xfont,
+                    private->ref_count));
   return font;
 }
 
@@ -483,6 +899,8 @@ void
 gdk_font_unref (GdkFont *font)
 {
   GdkFontPrivate *private;
+  GdkWin32SingleFont *singlefont;
+  GSList *list;
   private = (GdkFontPrivate*) font;
 
   g_return_if_fail (font != NULL);
@@ -490,9 +908,9 @@ gdk_font_unref (GdkFont *font)
 
   private->ref_count -= 1;
 
+  singlefont = (GdkWin32SingleFont *) private->fonts->data;
   GDK_NOTE (MISC, g_print ("gdk_font_unref %#x %d%s\n",
-                          private->xfont,
-                          private->ref_count,
+                          singlefont->xfont, private->ref_count,
                           (private->ref_count == 0 ? " freeing" : "")));
 
   if (private->ref_count == 0)
@@ -502,9 +920,18 @@ 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);
+         DeleteObject (singlefont->xfont);
+         break;
+
+       case GDK_FONT_FONTSET:
+         list = private->fonts;
+         while (list)
+           {
+             singlefont = (GdkWin32SingleFont *) list->data;
+             DeleteObject (singlefont->xfont);
+
+             list = list->next;
+           }
          break;
 
        default:
@@ -524,7 +951,7 @@ gdk_font_id (const GdkFont *font)
   font_private = (const GdkFontPrivate*) font;
 
   if (font->type == GDK_FONT_FONT)
-    return (gint) font_private->xfont;
+    return (gint) ((GdkWin32SingleFont *) font_private->fonts->data)->xfont;
   else
     return 0;
 }
@@ -543,9 +970,26 @@ gdk_font_equal (const GdkFont *fonta,
   privateb = (const GdkFontPrivate*) fontb;
 
   if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
-    return (privatea->xfont == privateb->xfont);
+    return (((GdkWin32SingleFont *) privatea->fonts->data)->xfont
+           == ((GdkWin32SingleFont *) privateb->fonts->data)->xfont);
   else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
-    return (privatea->xfont == privateb->xfont);
+    {
+      GSList *lista = privatea->fonts;
+      GSList *listb = privateb->fonts;
+
+      while (lista && listb)
+       {
+         if (((GdkWin32SingleFont *) lista->data)->xfont
+             != ((GdkWin32SingleFont *) listb->data)->xfont)
+           return 0;
+         lista = lista->next;
+         listb = listb->next;
+       }
+      if (lista || listb)
+       return 0;
+      else
+       return 1;
+    }
   else
     return 0;
 }
@@ -557,14 +1001,200 @@ gdk_string_width (GdkFont     *font,
   return gdk_text_width (font, string, strlen (string));
 }
 
-static gboolean
-gdk_text_size (GdkFont      *font,
-              const gchar  *text,
-              gint          text_length,
-              SIZE          *sizep)
+/* This table classifies Unicode characters according to the Microsoft
+ * Unicode subset numbering. This is from the table in "Developing
+ * International Software for Windows 95 and Windows NT". This is almost,
+ * but not quite, the same as the official Unicode block table in
+ * Blocks.txt from ftp.unicode.org. The bit number field is the bitfield
+ * number as in the FONTSIGNATURE struct's fsUsb field.
+ */
+static struct {
+  wchar_t low, high;
+  guint bit; 
+  gchar *name;
+} utab[] =
+{
+  { 0x0000, 0x007E, 0, "Basic Latin" },
+  { 0x00A0, 0x00FF, 1, "Latin-1 Supplement" },
+  { 0x0100, 0x017F, 2, "Latin Extended-A" },
+  { 0x0180, 0x024F, 3, "Latin Extended-B" },
+  { 0x0250, 0x02AF, 4, "IPA Extensions" },
+  { 0x02B0, 0x02FF, 5, "Spacing Modifier Letters" },
+  { 0x0300, 0x036F, 6, "Combining Diacritical Marks" },
+  { 0x0370, 0x03CF, 7, "Basic Greek" },
+  { 0x03D0, 0x03FF, 8, "Greek Symbols and Coptic" },
+  { 0x0400, 0x04FF, 9, "Cyrillic" },
+  { 0x0530, 0x058F, 10, "Armenian" },
+  { 0x0590, 0x05CF, 12, "Hebrew Extended" },
+  { 0x05D0, 0x05FF, 11, "Basic Hebrew" },
+  { 0x0600, 0x0652, 13, "Basic Arabic" },
+  { 0x0653, 0x06FF, 14, "Arabic Extended" },
+  { 0x0900, 0x097F, 15, "Devanagari" },
+  { 0x0980, 0x09FF, 16, "Bengali" },
+  { 0x0A00, 0x0A7F, 17, "Gurmukhi" },
+  { 0x0A80, 0x0AFF, 18, "Gujarati" },
+  { 0x0B00, 0x0B7F, 19, "Oriya" },
+  { 0x0B80, 0x0BFF, 20, "Tamil" },
+  { 0x0C00, 0x0C7F, 21, "Telugu" },
+  { 0x0C80, 0x0CFF, 22, "Kannada" },
+  { 0x0D00, 0x0D7F, 23, "Malayalam" },
+  { 0x0E00, 0x0E7F, 24, "Thai" },
+  { 0x0E80, 0x0EFF, 25, "Lao" },
+  { 0x10A0, 0x10CF, 27, "Georgian Extended" },
+  { 0x10D0, 0x10FF, 26, "Basic Georgian" },
+  { 0x1100, 0x11FF, 28, "Hangul Jamo" },
+  { 0x1E00, 0x1EFF, 29, "Latin Extended Additional" },
+  { 0x1F00, 0x1FFF, 30, "Greek Extended" },
+  { 0x2000, 0x206F, 31, "General Punctuation" },
+  { 0x2070, 0x209F, 32, "Superscripts and Subscripts" },
+  { 0x20A0, 0x20CF, 33, "Currency Symbols" },
+  { 0x20D0, 0x20FF, 34, "Combining Diacritical Marks for Symbols" },
+  { 0x2100, 0x214F, 35, "Letterlike Symbols" },
+  { 0x2150, 0x218F, 36, "Number Forms" },
+  { 0x2190, 0x21FF, 37, "Arrows" },
+  { 0x2200, 0x22FF, 38, "Mathematical Operators" },
+  { 0x2300, 0x23FF, 39, "Miscellaneous Technical" },
+  { 0x2400, 0x243F, 40, "Control Pictures" },
+  { 0x2440, 0x245F, 41, "Optical Character Recognition" },
+  { 0x2460, 0x24FF, 42, "Enclosed Alphanumerics" },
+  { 0x2500, 0x257F, 43, "Box Drawing" },
+  { 0x2580, 0x259F, 44, "Block Elements" },
+  { 0x25A0, 0x25FF, 45, "Geometric Shapes" },
+  { 0x2600, 0x26FF, 46, "Miscellaneous Symbols" },
+  { 0x2700, 0x27BF, 47, "Dingbats" },
+  { 0x3000, 0x303F, 48, "CJK Symbols and Punctuation" },
+  { 0x3040, 0x309F, 49, "Hiragana" },
+  { 0x30A0, 0x30FF, 50, "Katakana" },
+  { 0x3100, 0x312F, 51, "Bopomofo" },
+  { 0x3130, 0x318F, 52, "Hangul Compatibility Jamo" },
+  { 0x3190, 0x319F, 53, "CJK Miscellaneous" },
+  { 0x3200, 0x32FF, 54, "Enclosed CJK" },
+  { 0x3300, 0x33FF, 55, "CJK Compatibility" },
+  { 0x3400, 0x3D2D, 56, "Hangul" },
+  { 0x3D2E, 0x44B7, 57, "Hangul Supplementary-A" },
+  { 0x44B8, 0x4DFF, 58, "Hangul Supplementary-B" },
+  { 0x4E00, 0x9FFF, 59, "CJK Unified Ideographs" },
+  { 0xE000, 0xF8FF, 60, "Private Use Area" },
+  { 0xF900, 0xFAFF, 61, "CJK Compatibility Ideographs" },
+  { 0xFB00, 0xFB4F, 62, "Alphabetic Presentation Forms" },
+  { 0xFB50, 0xFDFF, 63, "Arabic Presentation Forms-A" },
+  { 0xFE20, 0xFE2F, 64, "Combining Half Marks" },
+  { 0xFE30, 0xFE4F, 65, "CJK Compatibility Forms" },
+  { 0xFE50, 0xFE6F, 66, "Small Form Variants" },
+  { 0xFE70, 0xFEFE, 67, "Arabic Presentation Forms-B" },
+  { 0xFEFF, 0xFEFF, 69, "Specials" },
+  { 0xFF00, 0xFFEF, 68, "Halfwidth and Fullwidth Forms" },
+  { 0xFFF0, 0xFFFD, 69, "Specials" }
+};
+
+/* Return the Unicode Subset bitfield number for a Unicode character */
+
+static int
+unicode_classify (wchar_t wc)
+{
+  int min = 0;
+  int max = sizeof (utab) / sizeof (utab[0]) - 1;
+  int mid;
+
+  while (max >= min)
+    {
+      mid = (min + max) / 2;
+      if (utab[mid].high < wc)
+       min = mid + 1;
+      else if (wc < utab[mid].low)
+       max = mid - 1;
+      else if (utab[mid].low <= wc && wc <= utab[mid].high)
+       return utab[mid].bit;
+      else
+       return -1;
+    }
+}
+
+void
+gdk_wchar_text_handle (GdkFont       *font,
+                      const wchar_t *wcstr,
+                      int            wclen,
+                      void         (*handler)(GdkWin32SingleFont *,
+                                              const wchar_t *,
+                                              int,
+                                              void *),
+                      void          *arg)
 {
   GdkFontPrivate *private;
+  GdkWin32SingleFont *singlefont;
+  GSList *list;
+  int i, block;
+  const wchar_t *start, *end, *wcp;
+
+  wcp = wcstr;
+  end = wcp + wclen;
+  private = (GdkFontPrivate *) font;
+
+  while (wcp < end)
+    {
+      /* Split Unicode string into pieces of the same class */
+      start = wcp;
+      block = unicode_classify (*wcp);
+      while (wcp + 1 < end && unicode_classify (wcp[1]) == block)
+       wcp++;
+
+      /* Find a font in the fontset that can handle this class */
+      list = private->fonts;
+      while (list)
+       {
+         singlefont = (GdkWin32SingleFont *) list->data;
+         
+         if (singlefont->fs.fsUsb[block/32] & (1 << (block % 32)))
+           break;
+
+         list = list->next;
+       }
+
+      if (!list)
+       singlefont = NULL;
+
+      /* Call the callback function */
+      (*handler) (singlefont, start, wcp+1 - start, arg);
+      wcp++;
+    }
+}
+
+typedef struct
+{
+  SIZE total;
+  SIZE max;
+} gdk_text_size_arg;
+
+static void
+gdk_text_size_handler (GdkWin32SingleFont *singlefont,
+                      const wchar_t      *wcstr,
+                      int                 wclen,
+                      void               *argp)
+{
+  SIZE this_size;
   HGDIOBJ oldfont;
+  gdk_text_size_arg *arg = (gdk_text_size_arg *) argp;
+
+  if ((oldfont = SelectObject (gdk_DC, singlefont->xfont)) == NULL)
+    {
+      g_warning ("gdk_text_size_handler: SelectObject failed");
+      return;
+    }
+  GetTextExtentPoint32W (gdk_DC, wcstr, wclen, &this_size);
+  SelectObject (gdk_DC, oldfont);
+
+  arg->total.cx += this_size.cx;
+  arg->total.cy += this_size.cy;
+  arg->max.cx = MAX (this_size.cx, arg->max.cx);
+  arg->max.cy = MAX (this_size.cy, arg->max.cy);
+}
+
+static gboolean
+gdk_text_size (GdkFont           *font,
+              const gchar       *text,
+              gint               text_length,
+              gdk_text_size_arg *arg)
+{
   gint wlen;
   wchar_t *wcstr;
 
@@ -574,16 +1204,8 @@ gdk_text_size (GdkFont      *font,
   if (text_length == 0)
     return 0;
 
-  private = (GdkFontPrivate*) font;
-
   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
 
-  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
-    {
-      g_warning ("gdk_text_width: SelectObject failed");
-      return FALSE;
-    }
-
   wcstr = g_new (wchar_t, text_length);
   if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
     {
@@ -591,10 +1213,9 @@ gdk_text_size (GdkFont      *font,
       return FALSE;
     }
 
-  GetTextExtentPoint32W (gdk_DC, wcstr, wlen, sizep);
+  gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, arg);
 
   g_free (wcstr);
-  SelectObject (gdk_DC, oldfont);
 
   return TRUE;
 }
@@ -604,12 +1225,15 @@ gdk_text_width (GdkFont      *font,
                const gchar  *text,
                gint          text_length)
 {
-  SIZE size;
+  gdk_text_size_arg arg;
+
+  arg.total.cx = arg.total.cy = 0;
+  arg.max.cx = arg.max.cy = 0;
 
-  if (!gdk_text_size (font, text, text_length, &size))
+  if (!gdk_text_size (font, text, text_length, &arg))
     return -1;
 
-  return size.cx;
+  return arg.total.cx;
 }
 
 gint
@@ -617,11 +1241,8 @@ gdk_text_width_wc (GdkFont          *font,
                   const GdkWChar *text,
                   gint            text_length)
 {
-  GdkFontPrivate *private;
-  HGDIOBJ oldfont;
-  SIZE size;
+  gdk_text_size_arg arg;
   wchar_t *wcstr;
-  guchar *str;
   gint i;
 
   g_return_val_if_fail (font != NULL, -1);
@@ -632,12 +1253,6 @@ gdk_text_width_wc (GdkFont          *font,
 
   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
 
-  private = (GdkFontPrivate*) font;
-
-  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
-    
-    g_warning ("gdk_text_width_wc: SelectObject failed");
-
   if (sizeof (wchar_t) != sizeof (GdkWChar))
     {
       wcstr = g_new (wchar_t, text_length);
@@ -647,15 +1262,16 @@ gdk_text_width_wc (GdkFont         *font,
   else
     wcstr = (wchar_t *) text;
 
-  GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
+  arg.total.cx = arg.total.cy = 0;
+  arg.max.cx = arg.max.cy = 0;
+
+  gdk_wchar_text_handle (font, wcstr, text_length,
+                        gdk_text_size_handler, &arg);
 
   if (sizeof (wchar_t) != sizeof (GdkWChar))
     g_free (wcstr);
 
-  if (oldfont != NULL)
-    SelectObject (gdk_DC, oldfont);
-
-  return size.cx;
+  return arg.total.cx;
 }
 
 gint
@@ -698,9 +1314,7 @@ gdk_text_extents (GdkFont     *font,
                  gint        *ascent,
                  gint        *descent)
 {
-  GdkFontPrivate *private;
-  HGDIOBJ oldfont;
-  SIZE size;
+  gdk_text_size_arg arg;
   gint wlen;
   wchar_t *wcstr;
 
@@ -724,33 +1338,24 @@ gdk_text_extents (GdkFont     *font,
 
   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
 
-  private = (GdkFontPrivate*) font;
-
-  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
-    g_warning ("gdk_text_extents: SelectObject failed");
+  arg.total.cx = arg.total.cy = 0;
+  arg.max.cx = arg.max.cy = 0;
 
   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;
-    }
+    g_warning ("gdk_text_extents: gdk_nmbstowchar_ts failed");
   else
-    GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+    gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, &arg);
 
-  if (oldfont != NULL)
-    SelectObject (gdk_DC, oldfont);
-
-  /* XXX This is all quite bogus */
+  /* XXX This is quite bogus */
   if (lbearing)
     *lbearing = 0;
   if (rbearing)
     *rbearing = 0;
   if (width)
-    *width = size.cx;
+    *width = arg.total.cx;
   if (ascent)
-    *ascent = size.cy + 1;
+    *ascent = arg.max.cy + 1;
   if (descent)
     *descent = font->descent + 1;
 }
@@ -765,9 +1370,7 @@ gdk_text_extents_wc (GdkFont        *font,
                     gint           *ascent,
                     gint           *descent)
 {
-  GdkFontPrivate *private;
-  HGDIOBJ oldfont;
-  SIZE size;
+  gdk_text_size_arg arg;
   wchar_t *wcstr;
   gint i;
 
@@ -791,8 +1394,6 @@ gdk_text_extents_wc (GdkFont        *font,
 
   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
 
-  private = (GdkFontPrivate*) font;
-
   if (sizeof (wchar_t) != sizeof (GdkWChar))
     {
       wcstr = g_new (wchar_t, text_length);
@@ -802,26 +1403,24 @@ gdk_text_extents_wc (GdkFont        *font,
   else
     wcstr = (wchar_t *) text;
 
-  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
-    g_warning ("gdk_text_extents_wc: SelectObject failed");
+  arg.total.cx = arg.total.cy = 0;
+  arg.max.cx = arg.max.cy = 0;
 
-  GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
+  gdk_wchar_text_handle (font, wcstr, text_length,
+                        gdk_text_size_handler, &arg);
 
   if (sizeof (wchar_t) != sizeof (GdkWChar))
     g_free (wcstr);
 
-  if (oldfont != NULL)
-    SelectObject (gdk_DC, oldfont);
-
-  /* XXX This is all quite bogus */
+  /* XXX This is quite bogus */
   if (lbearing)
     *lbearing = 0;
   if (rbearing)
     *rbearing = 0;
   if (width)
-    *width = size.cx;
+    *width = arg.total.cx;
   if (ascent)
-    *ascent = size.cy + 1;
+    *ascent = arg.max.cy + 1;
   if (descent)
     *descent = font->descent + 1;
 }
@@ -873,12 +1472,15 @@ gdk_text_height (GdkFont     *font,
                 const gchar *text,
                 gint         text_length)
 {
-  SIZE size;
+  gdk_text_size_arg arg;
+
+  arg.total.cx = arg.total.cy = 0;
+  arg.max.cx = arg.max.cy = 0;
 
-  if (!gdk_text_size (font, text, text_length, &size))
+  if (!gdk_text_size (font, text, text_length, &arg))
     return -1;
 
-  return size.cy;
+  return arg.max.cy;
 }
 
 gint
index 59791945ba4706ca11b160664082eaa45e5170ef..f6b768bac7b773618ead46b2aafd1bbdee60ef90 100644 (file)
 #include <ctype.h>
 
 #include "gdkfont.h"
-#include "gdkprivate.h"
+#include "gdkx.h"
 
 static GHashTable *font_name_hash = NULL;
 static GHashTable *fontset_name_hash = NULL;
 
 static void
-gdk_font_hash_insert (GdkFontType type, GdkFont *font, const gchar *font_name)
+gdk_font_hash_insert (GdkFontType  type,
+                     GdkFont     *font,
+                     const gchar *font_name)
 {
-  GdkFontPrivate *private = (GdkFontPrivate *)font;
+  GdkFontPrivate *private = (GdkFontPrivate *) font;
   GHashTable **hashp = (type == GDK_FONT_FONT) ?
     &font_name_hash : &fontset_name_hash;
 
@@ -50,9 +52,10 @@ gdk_font_hash_insert (GdkFontType type, GdkFont *font, const gchar *font_name)
 }
 
 static void
-gdk_font_hash_remove (GdkFontType type, GdkFont *font)
+gdk_font_hash_remove (GdkFontType type,
+                     GdkFont    *font)
 {
-  GdkFontPrivate *private = (GdkFontPrivate *)font;
+  GdkFontPrivate *private = (GdkFontPrivate *) font;
   GSList *tmp_list;
   GHashTable *hash = (type == GDK_FONT_FONT) ?
     font_name_hash : fontset_name_hash;
@@ -71,7 +74,8 @@ gdk_font_hash_remove (GdkFontType type, GdkFont *font)
 }
 
 static GdkFont *
-gdk_font_hash_lookup (GdkFontType type, const gchar *font_name)
+gdk_font_hash_lookup (GdkFontType  type,
+                     const gchar *font_name)
 {
   GdkFont *result;
   GHashTable *hash = (type == GDK_FONT_FONT) ?
@@ -94,40 +98,353 @@ charset_name (DWORD charset)
 {
   switch (charset)
     {
-    case ANSI_CHARSET: return "ANSI";
-    case DEFAULT_CHARSET: return "DEFAULT";
-    case SYMBOL_CHARSET: return "SYMBOL";
-    case SHIFTJIS_CHARSET: return "SHIFTJIS";
-    case HANGEUL_CHARSET: return "HANGEUL";
-    case GB2312_CHARSET: return "GB2312";
-    case CHINESEBIG5_CHARSET: return "CHINESEBIG5";
-    case JOHAB_CHARSET: return "JOHAB";
-    case HEBREW_CHARSET: return "HEBREW";
-    case ARABIC_CHARSET: return "ARABIC";
-    case GREEK_CHARSET: return "GREEK";
-    case TURKISH_CHARSET: return "TURKISH";
-    case VIETNAMESE_CHARSET: return "VIETNAMESE";
-    case THAI_CHARSET: return "THAI";
-    case EASTEUROPE_CHARSET: return "EASTEUROPE";
-    case RUSSIAN_CHARSET: return "RUSSIAN";
-    case MAC_CHARSET: return "MAC";
-    case BALTIC_CHARSET: return "BALTIC";
+    case ANSI_CHARSET: return "ansi";
+    case DEFAULT_CHARSET: return "default";
+    case SYMBOL_CHARSET: return "symbol";
+    case SHIFTJIS_CHARSET: return "shiftjis";
+    case HANGEUL_CHARSET: return "hangeul";
+    case GB2312_CHARSET: return "gb2312";
+    case CHINESEBIG5_CHARSET: return "big5";
+    case JOHAB_CHARSET: return "johab";
+    case HEBREW_CHARSET: return "hebrew";
+    case ARABIC_CHARSET: return "arabic";
+    case GREEK_CHARSET: return "greek";
+    case TURKISH_CHARSET: return "turkish";
+    case VIETNAMESE_CHARSET: return "vietnamese";
+    case THAI_CHARSET: return "thai";
+    case EASTEUROPE_CHARSET: return "easteurope";
+    case RUSSIAN_CHARSET: return "russian";
+    case MAC_CHARSET: return "mac";
+    case BALTIC_CHARSET: return "baltic";
     }
   return "unknown";
 }
 
-GdkFont*
-gdk_font_load_internal (GdkFontType  type,
-                       const gchar *font_name)
+static gint num_fonts;
+static gint font_names_size;
+static gchar **xfontnames;
+
+static gchar *
+logfont_to_xlfd (const LOGFONT *lfp,
+                int            size,
+                int            res,
+                int            avg_width)
+{
+  const gchar *weight;
+  const gchar *registry, *encoding;
+  int point_size;
+  static int logpixelsy = 0;
+  gchar facename[LF_FACESIZE*3];
+  gchar *p;
+  const gchar *q;
+
+  if (logpixelsy == 0)
+    {
+      logpixelsy = GetDeviceCaps (gdk_DC, LOGPIXELSY);
+    }
+
+  if (lfp->lfWeight >= FW_HEAVY)
+    weight = "heavy";
+  else if (lfp->lfWeight >= FW_EXTRABOLD)
+    weight = "extrabold";
+  else if (lfp->lfWeight >= FW_BOLD)
+    weight = "bold";
+#ifdef FW_DEMIBOLD
+  else if (lfp->lfWeight >= FW_DEMIBOLD)
+    weight = "demibold";
+#endif
+  else if (lfp->lfWeight >= FW_MEDIUM)
+    weight = "medium";
+  else if (lfp->lfWeight >= FW_NORMAL)
+    weight = "normal";
+  else if (lfp->lfWeight >= FW_LIGHT)
+    weight = "light";
+  else if (lfp->lfWeight >= FW_EXTRALIGHT)
+    weight = "extralight";
+  else if (lfp->lfWeight >= FW_THIN)
+    weight = "thin";
+  else
+    weight = "regular";
+
+  switch (lfp->lfCharSet)
+    {
+    case ANSI_CHARSET:
+      registry = "iso8859";
+      encoding = "1";
+      break;
+    case SHIFTJIS_CHARSET:
+      registry = "jisx0208.1983";
+      encoding = "0";
+      break;
+    case HANGEUL_CHARSET:
+      registry = "ksc5601.1987";
+      encoding = "0";
+      break;
+    case GB2312_CHARSET:
+      registry = "gb2312.1980";
+      encoding = "0";
+      break;
+    case CHINESEBIG5_CHARSET:
+      registry = "big5";
+      encoding = "0";
+      break;
+    case GREEK_CHARSET:
+      registry = "iso8859";
+      encoding = "7";
+      break;
+    case TURKISH_CHARSET:
+      registry = "iso8859";
+      encoding = "9";
+      break;
+#if 0 /* Not a good idea, I think, to use ISO8859-8 and -6 for the Windows
+       * hebrew and arabic codepages, they differ too much.
+       */
+    case HEBREW_CHARSET:
+      registry = "iso8859";
+      encoding = "8";
+      break;
+    case ARABIC_CHARSET:
+      registry = "iso8859";
+      encoding = "6";
+      break;
+#endif
+    default:
+      registry = "microsoft";
+      encoding = charset_name (lfp->lfCharSet);
+    }
+  
+  point_size = (int) (((double) size/logpixelsy) * 720.);
+
+  if (res == -1)
+    res = logpixelsy;
+
+  /* Replace illegal characters with hex escapes. */
+  p = facename;
+  q = lfp->lfFaceName;
+  while (*q)
+    {
+      if (*q == '-' || *q == '*' || *q == '?' || *q == '%')
+       p += sprintf (p, "%%%.02x", *q);
+      else
+       *p++ = *q;
+      q++;
+    }
+  *p = '\0';
+
+  return  g_strdup_printf
+    ("-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d-%s-%s",
+     "unknown", 
+     facename,
+     weight,
+     (lfp->lfItalic ?
+      ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN
+       || (lfp->lfPitchAndFamily & 0xF0) == FF_SCRIPT ?
+       "i" : "o") : "r"),
+     "normal",
+     "",
+     size,
+     point_size,
+     res,
+     res,
+     ((lfp->lfPitchAndFamily & 0x03) == FIXED_PITCH ? "m" : "p"),
+     avg_width,
+     registry, encoding);
+}
+
+gchar *
+gdk_font_xlfd_create (GdkFont *font)
 {
-  GdkFont *font;
   GdkFontPrivate *private;
+  GdkWin32SingleFont *singlefont;
+  GSList *list;
+  GString *string;
+  gchar *result;
+  LOGFONT logfont;
+
+  g_return_val_if_fail (font != NULL, NULL);
+
+  private = (GdkFontPrivate *) font;
+
+  list = private->fonts;
+  string = g_string_new ("");
+
+  while (list)
+    {
+      singlefont = (GdkWin32SingleFont *) list->data;
+
+      if (GetObject (singlefont->xfont, sizeof (LOGFONT), &logfont) == 0)
+       {
+         g_warning ("gdk_win32_font_xlfd: GetObject failed");
+         return NULL;
+       }
+
+      string =
+       g_string_append (string,
+                        logfont_to_xlfd (&logfont, logfont.lfHeight, -1, 0));
+      list = list->next;
+      if (list)
+       string = g_string_append_c (string, ',');
+    }
+  result = string->str;
+  g_string_free (string, FALSE);
+  return result;
+}
+
+void
+gdk_font_xlfd_free (gchar *xlfd)
+{
+  g_free (xlfd);
+}
+
+static gboolean
+pattern_match (const gchar *pattern,
+              const gchar *string)
+{
+  const gchar *p = pattern, *n = string;
+  gchar c, c1;
+
+  /* Common case first */
+  if ((pattern[0] == '*'
+       && pattern[1] == '\0')
+      || (pattern[0] == '-'
+         && pattern[1] == '*'
+         && pattern[2] == '\0'))
+    return TRUE;
+
+  while ((c = *p++) != '\0')
+    {
+      c = tolower (c);
+
+      switch (c)
+       {
+       case '?':
+         if (*n == '\0')
+           return FALSE;
+         break;
+
+       case '*':
+         for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
+           if (c == '?' && *n == '\0')
+           return FALSE;
+
+         if (c == '\0')
+           return TRUE;
+
+         c1 = tolower (c);
+         for (--p; *n != '\0'; ++n)
+           if (tolower (*n) == c1
+               && pattern_match (p, n))
+             return TRUE;
+         return FALSE;
+
+       default:
+         if (c != tolower (*n))
+           return FALSE;
+       }
+
+      ++n;
+    }
+
+  if (*n == '\0')
+    return TRUE;
+
+  return FALSE;
+}
+
+int CALLBACK
+InnerEnumFontFamExProc (const LOGFONT    *lfp,
+                       const TEXTMETRIC *metrics,
+                       DWORD             fontType,
+                       LPARAM            lParam)
+{
+  int size;
+  gchar *xlfd;
+
+  if (fontType == TRUETYPE_FONTTYPE)
+    {
+      size = 0;
+    }
+  else
+    {
+      size = lfp->lfHeight;
+    }
+
+  xlfd = logfont_to_xlfd (lfp, size, 0, 0);
+
+  if (!pattern_match ((gchar *) lParam, xlfd))
+    {
+      g_free (xlfd);
+      return 1;
+    }
+
+  num_fonts++;
+  if (num_fonts == font_names_size)
+    {
+      font_names_size *= 2;
+      xfontnames = g_realloc (xfontnames, font_names_size * sizeof (gchar *));
+    }
+  xfontnames[num_fonts-1] = xlfd;
+    
+  return 1;
+}
+
+int CALLBACK
+EnumFontFamExProc (const LOGFONT    *lfp,
+                  const TEXTMETRIC *metrics,
+                  DWORD             fontType,
+                  LPARAM            lParam)
+{
+  if (fontType == TRUETYPE_FONTTYPE)
+    {
+      LOGFONT lf;
+
+      lf = *lfp;
+
+      EnumFontFamiliesEx (gdk_DC, &lf, InnerEnumFontFamExProc, lParam, 0);
+    }
+  else
+    InnerEnumFontFamExProc (lfp, metrics, fontType, lParam);
+
+  return 1;
+}
+
+gchar **
+gdk_font_list_new (const gchar *font_pattern,
+                  gint        *n_returned)
+{
+  LOGFONT logfont;
+  gchar **result;
+
+  num_fonts = 0;
+  font_names_size = 100;
+  xfontnames = g_new (gchar *, font_names_size);
+  memset (&logfont, 0, sizeof (logfont));
+  logfont.lfCharSet = DEFAULT_CHARSET;
+  EnumFontFamiliesEx (gdk_DC, &logfont, EnumFontFamExProc,
+                     (LPARAM) font_pattern, 0);
+
+  result = g_new (gchar *, num_fonts + 1);
+  memmove (result, xfontnames, num_fonts * sizeof (gchar *));
+  result[num_fonts] = NULL;
+  g_free (xfontnames);
+
+  *n_returned = num_fonts;
+  return result;
+}
+
+void
+gdk_font_list_free (gchar **font_list)
+{
+  g_strfreev (font_list);
+}
+
+GdkWin32SingleFont*
+gdk_font_load_internal (const gchar *font_name)
+{
+  GdkWin32SingleFont *singlefont;
   HFONT hfont;
   LOGFONT logfont;
-  HGDIOBJ oldfont;
-  TEXTMETRIC textmetric;
   CHARSETINFO csi;
-  HANDLE *f;
   DWORD fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet,
     fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily;
   const char *lpszFace;
@@ -145,10 +462,6 @@ gdk_font_load_internal (GdkFontType  type,
 
   GDK_NOTE (MISC, g_print ("gdk_font_load_internal: %s\n", font_name));
 
-  font = gdk_font_hash_lookup (type, font_name);
-  if (font)
-    return font;
-
   numfields = sscanf (font_name,
                      "-%30[^-]-%100[^-]-%30[^-]-%30[^-]-%30[^-]-%n",
                      foundry,
@@ -178,7 +491,6 @@ gdk_font_load_internal (GdkFontType  type,
   else if (numfields != 5)
     {
       g_warning ("gdk_font_load: font name %s illegal", font_name);
-      g_free (font);
       return NULL;
     }
   else
@@ -220,7 +532,6 @@ gdk_font_load_internal (GdkFontType  type,
       if (numfields != 14 || font_name[n1 + n2] != '\0')
        {
          g_warning ("gdk_font_load: font name %s illegal", font_name);
-         g_free (font);
          return NULL;
        }
 
@@ -299,9 +610,26 @@ gdk_font_load_internal (GdkFontType  type,
       if (g_strcasecmp (registry, "iso8859") == 0)
        if (strcmp (encoding, "1") == 0)
          fdwCharSet = ANSI_CHARSET;
+       else if (strcmp (encoding, "2") == 0)
+         fdwCharSet = EASTEUROPE_CHARSET;
+       else if (strcmp (encoding, "7") == 0)
+         fdwCharSet = GREEK_CHARSET;
+       else if (strcmp (encoding, "8") == 0)
+         fdwCharSet = HEBREW_CHARSET;
+       else if (strcmp (encoding, "9") == 0)
+         fdwCharSet = TURKISH_CHARSET;
        else
          fdwCharSet = ANSI_CHARSET; /* XXX ??? */
-      else if (g_strcasecmp (registry, "windows") == 0)
+      else if (g_strcasecmp (registry, "jisx0208.1983") == 0)
+       fdwCharSet = SHIFTJIS_CHARSET;
+      else if (g_strcasecmp (registry, "ksc5601.1987") == 0)
+       fdwCharSet = HANGEUL_CHARSET;
+      else if (g_strcasecmp (registry, "gb2312.1980") == 0)
+       fdwCharSet = GB2312_CHARSET;
+      else if (g_strcasecmp (registry, "big5") == 0)
+       fdwCharSet = CHINESEBIG5_CHARSET;
+      else if (g_strcasecmp (registry, "windows") == 0
+              || g_strcasecmp (registry, "microsoft") == 0)
        if (g_strcasecmp (encoding, "symbol") == 0)
          fdwCharSet = SYMBOL_CHARSET;
        else if (g_strcasecmp (encoding, "shiftjis") == 0)
@@ -310,7 +638,7 @@ gdk_font_load_internal (GdkFontType  type,
          fdwCharSet = GB2312_CHARSET;
        else if (g_strcasecmp (encoding, "hangeul") == 0)
          fdwCharSet = HANGEUL_CHARSET;
-       else if (g_strcasecmp (encoding, "chinesebig5") == 0)
+       else if (g_strcasecmp (encoding, "big5") == 0)
          fdwCharSet = CHINESEBIG5_CHARSET;
        else if (g_strcasecmp (encoding, "johab") == 0)
          fdwCharSet = JOHAB_CHARSET;
@@ -330,6 +658,8 @@ gdk_font_load_internal (GdkFontType  type,
          fdwCharSet = MAC_CHARSET;
        else if (g_strcasecmp (encoding, "baltic") == 0)
          fdwCharSet = BALTIC_CHARSET;
+       else if (g_strcasecmp (encoding, "cp1251") == 0)
+         fdwCharSet = RUSSIAN_CHARSET;
        else
          fdwCharSet = ANSI_CHARSET; /* XXX ??? */
       else
@@ -412,56 +742,140 @@ gdk_font_load_internal (GdkFontType  type,
   if (!hfont)
     return NULL;
       
+  singlefont = g_new (GdkWin32SingleFont, 1);
+  singlefont->xfont = hfont;
+  GetObject (singlefont->xfont, sizeof (logfont), &logfont);
+  TranslateCharsetInfo ((DWORD *) singlefont->charset, &csi, TCI_SRCCHARSET);
+  singlefont->codepage = csi.ciACP;
+  GetCPInfo (singlefont->codepage, &singlefont->cpinfo);
+
+  return singlefont;
+}
+
+GdkFont*
+gdk_font_load (const gchar *font_name)
+{
+  GdkFont *font;
+  GdkFontPrivate *private;
+  GdkWin32SingleFont *singlefont;
+  HGDIOBJ oldfont;
+  HANDLE *f;
+  TEXTMETRIC textmetric;
+
+  g_return_val_if_fail (font_name != NULL, NULL);
+
+  font = gdk_font_hash_lookup (GDK_FONT_FONTSET, font_name);
+  if (font)
+    return font;
+
+  singlefont = gdk_font_load_internal (font_name);
+
   private = g_new (GdkFontPrivate, 1);
   font = (GdkFont*) private;
 
-  private->xfont = hfont;
   private->ref_count = 1;
   private->names = NULL;
-  GetObject (private->xfont, sizeof (logfont), &logfont);
-  oldfont = SelectObject (gdk_DC, private->xfont);
+  private->fonts = g_slist_append (NULL, singlefont);
+
+  /* Pretend all fonts are fontsets... Gtktext and gtkentry work better
+   * that way, they use wide chars, which is necessary for non-ASCII
+   * chars to work. (Yes, even Latin-1, as we use Unicode internally.)
+   */
+  font->type = GDK_FONT_FONTSET;
+  oldfont = SelectObject (gdk_DC, singlefont->xfont);
   GetTextMetrics (gdk_DC, &textmetric);
-  private->charset = GetTextCharsetInfo (gdk_DC, &private->fs, 0);
+  singlefont->charset = GetTextCharsetInfo (gdk_DC, &singlefont->fs, 0);
   SelectObject (gdk_DC, oldfont);
-  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;
 
   GDK_NOTE (MISC, g_print ("... = %#x charset %s codepage %d (max %d bytes) "
                           "asc %d desc %d\n",
-                          private->xfont,
-                          charset_name (private->charset),
-                          private->codepage,
-                          private->cpinfo.MaxCharSize,
+                          singlefont->xfont,
+                          charset_name (singlefont->charset),
+                          singlefont->codepage,
+                          singlefont->cpinfo.MaxCharSize,
                           font->ascent, font->descent));
 
-  /* This memory is leaked, so shoot me. */
-  f = g_new (HANDLE, 1);
-  *f = (HANDLE) ((guint) private->xfont + HFONT_DITHER);
-  gdk_xid_table_insert (f, font);
-
-  gdk_font_hash_insert (type, font, font_name);
+  gdk_font_hash_insert (GDK_FONT_FONTSET, font, font_name);
 
   return font;
 }
 
-GdkFont*
-gdk_font_load (const gchar *font_name)
-{
-  /* Load all fonts as fontsets... Gtktext and gtkentry work better
-   * that way, they use wide chars, which is necessary for non-ASCII
-   * chars to work. (Yes, even Latin-1, as we use Unicode internally.)
-   */
-  return gdk_font_load_internal (GDK_FONT_FONTSET, font_name);
-}
-
 GdkFont*
 gdk_fontset_load (gchar *fontset_name)
 {
-  return gdk_font_load_internal (GDK_FONT_FONTSET, fontset_name);
+  GdkFont *font;
+  GdkFontPrivate *private;
+  GdkWin32SingleFont *singlefont;
+  HGDIOBJ oldfont;
+  HANDLE *f;
+  TEXTMETRIC textmetric;
+  GSList *base_font_list = NULL;
+  gchar *fs;
+  gchar *b, *p, *s;
+
+  g_return_val_if_fail (fontset_name != NULL, NULL);
+
+  font = gdk_font_hash_lookup (GDK_FONT_FONTSET, fontset_name);
+  if (font)
+    return font;
+
+  s = fs = g_strdup (fontset_name);
+  while (*s && isspace (*s))
+    s++;
+
+  g_return_val_if_fail (*s, NULL);
+
+  private = g_new (GdkFontPrivate, 1);
+  font = (GdkFont*) private;
+
+  private->ref_count = 1;
+  private->names = NULL;
+  private->fonts = NULL;
+
+  font->type = GDK_FONT_FONTSET;
+  font->ascent = 0;
+  font->descent = 0;
+
+  while (TRUE)
+    {
+      if ((p = strchr (s, ',')) != NULL)
+       b = p;
+      else
+       b = s + strlen (s);
+
+      while (isspace (b[-1]))
+       b--;
+      *b = '\0';
+      singlefont = gdk_font_load_internal (s);
+      if (singlefont)
+       {
+         private->fonts = g_slist_append (private->fonts, singlefont);
+         oldfont = SelectObject (gdk_DC, singlefont->xfont);
+         GetTextMetrics (gdk_DC, &textmetric);
+         singlefont->charset = GetTextCharsetInfo (gdk_DC, &singlefont->fs, 0);
+         SelectObject (gdk_DC, oldfont);
+         font->ascent = MAX (font->ascent, textmetric.tmAscent);
+         font->descent = MAX (font->descent, textmetric.tmDescent);
+       }
+      if (p)
+       {
+         s = p + 1;
+         while (*s && isspace (*s))
+           s++;
+       }
+      else
+       break;
+      if (!*s)
+       break;
+    }
+  
+  g_free (fs);
+
+  gdk_font_hash_insert (GDK_FONT_FONTSET, font, fontset_name);
+
+  return font;
 }
 
 GdkFont*
@@ -474,8 +888,10 @@ gdk_font_ref (GdkFont *font)
   private = (GdkFontPrivate*) font;
   private->ref_count += 1;
 
-  GDK_NOTE (MISC, g_print ("gdk_font_ref %#x %d\n",
-                          private->xfont, private->ref_count));
+  GDK_NOTE (MISC,
+           g_print ("gdk_font_ref %#x %d\n",
+                    ((GdkWin32SingleFont *) private->fonts->data)->xfont,
+                    private->ref_count));
   return font;
 }
 
@@ -483,6 +899,8 @@ void
 gdk_font_unref (GdkFont *font)
 {
   GdkFontPrivate *private;
+  GdkWin32SingleFont *singlefont;
+  GSList *list;
   private = (GdkFontPrivate*) font;
 
   g_return_if_fail (font != NULL);
@@ -490,9 +908,9 @@ gdk_font_unref (GdkFont *font)
 
   private->ref_count -= 1;
 
+  singlefont = (GdkWin32SingleFont *) private->fonts->data;
   GDK_NOTE (MISC, g_print ("gdk_font_unref %#x %d%s\n",
-                          private->xfont,
-                          private->ref_count,
+                          singlefont->xfont, private->ref_count,
                           (private->ref_count == 0 ? " freeing" : "")));
 
   if (private->ref_count == 0)
@@ -502,9 +920,18 @@ 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);
+         DeleteObject (singlefont->xfont);
+         break;
+
+       case GDK_FONT_FONTSET:
+         list = private->fonts;
+         while (list)
+           {
+             singlefont = (GdkWin32SingleFont *) list->data;
+             DeleteObject (singlefont->xfont);
+
+             list = list->next;
+           }
          break;
 
        default:
@@ -524,7 +951,7 @@ gdk_font_id (const GdkFont *font)
   font_private = (const GdkFontPrivate*) font;
 
   if (font->type == GDK_FONT_FONT)
-    return (gint) font_private->xfont;
+    return (gint) ((GdkWin32SingleFont *) font_private->fonts->data)->xfont;
   else
     return 0;
 }
@@ -543,9 +970,26 @@ gdk_font_equal (const GdkFont *fonta,
   privateb = (const GdkFontPrivate*) fontb;
 
   if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
-    return (privatea->xfont == privateb->xfont);
+    return (((GdkWin32SingleFont *) privatea->fonts->data)->xfont
+           == ((GdkWin32SingleFont *) privateb->fonts->data)->xfont);
   else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
-    return (privatea->xfont == privateb->xfont);
+    {
+      GSList *lista = privatea->fonts;
+      GSList *listb = privateb->fonts;
+
+      while (lista && listb)
+       {
+         if (((GdkWin32SingleFont *) lista->data)->xfont
+             != ((GdkWin32SingleFont *) listb->data)->xfont)
+           return 0;
+         lista = lista->next;
+         listb = listb->next;
+       }
+      if (lista || listb)
+       return 0;
+      else
+       return 1;
+    }
   else
     return 0;
 }
@@ -557,14 +1001,200 @@ gdk_string_width (GdkFont     *font,
   return gdk_text_width (font, string, strlen (string));
 }
 
-static gboolean
-gdk_text_size (GdkFont      *font,
-              const gchar  *text,
-              gint          text_length,
-              SIZE          *sizep)
+/* This table classifies Unicode characters according to the Microsoft
+ * Unicode subset numbering. This is from the table in "Developing
+ * International Software for Windows 95 and Windows NT". This is almost,
+ * but not quite, the same as the official Unicode block table in
+ * Blocks.txt from ftp.unicode.org. The bit number field is the bitfield
+ * number as in the FONTSIGNATURE struct's fsUsb field.
+ */
+static struct {
+  wchar_t low, high;
+  guint bit; 
+  gchar *name;
+} utab[] =
+{
+  { 0x0000, 0x007E, 0, "Basic Latin" },
+  { 0x00A0, 0x00FF, 1, "Latin-1 Supplement" },
+  { 0x0100, 0x017F, 2, "Latin Extended-A" },
+  { 0x0180, 0x024F, 3, "Latin Extended-B" },
+  { 0x0250, 0x02AF, 4, "IPA Extensions" },
+  { 0x02B0, 0x02FF, 5, "Spacing Modifier Letters" },
+  { 0x0300, 0x036F, 6, "Combining Diacritical Marks" },
+  { 0x0370, 0x03CF, 7, "Basic Greek" },
+  { 0x03D0, 0x03FF, 8, "Greek Symbols and Coptic" },
+  { 0x0400, 0x04FF, 9, "Cyrillic" },
+  { 0x0530, 0x058F, 10, "Armenian" },
+  { 0x0590, 0x05CF, 12, "Hebrew Extended" },
+  { 0x05D0, 0x05FF, 11, "Basic Hebrew" },
+  { 0x0600, 0x0652, 13, "Basic Arabic" },
+  { 0x0653, 0x06FF, 14, "Arabic Extended" },
+  { 0x0900, 0x097F, 15, "Devanagari" },
+  { 0x0980, 0x09FF, 16, "Bengali" },
+  { 0x0A00, 0x0A7F, 17, "Gurmukhi" },
+  { 0x0A80, 0x0AFF, 18, "Gujarati" },
+  { 0x0B00, 0x0B7F, 19, "Oriya" },
+  { 0x0B80, 0x0BFF, 20, "Tamil" },
+  { 0x0C00, 0x0C7F, 21, "Telugu" },
+  { 0x0C80, 0x0CFF, 22, "Kannada" },
+  { 0x0D00, 0x0D7F, 23, "Malayalam" },
+  { 0x0E00, 0x0E7F, 24, "Thai" },
+  { 0x0E80, 0x0EFF, 25, "Lao" },
+  { 0x10A0, 0x10CF, 27, "Georgian Extended" },
+  { 0x10D0, 0x10FF, 26, "Basic Georgian" },
+  { 0x1100, 0x11FF, 28, "Hangul Jamo" },
+  { 0x1E00, 0x1EFF, 29, "Latin Extended Additional" },
+  { 0x1F00, 0x1FFF, 30, "Greek Extended" },
+  { 0x2000, 0x206F, 31, "General Punctuation" },
+  { 0x2070, 0x209F, 32, "Superscripts and Subscripts" },
+  { 0x20A0, 0x20CF, 33, "Currency Symbols" },
+  { 0x20D0, 0x20FF, 34, "Combining Diacritical Marks for Symbols" },
+  { 0x2100, 0x214F, 35, "Letterlike Symbols" },
+  { 0x2150, 0x218F, 36, "Number Forms" },
+  { 0x2190, 0x21FF, 37, "Arrows" },
+  { 0x2200, 0x22FF, 38, "Mathematical Operators" },
+  { 0x2300, 0x23FF, 39, "Miscellaneous Technical" },
+  { 0x2400, 0x243F, 40, "Control Pictures" },
+  { 0x2440, 0x245F, 41, "Optical Character Recognition" },
+  { 0x2460, 0x24FF, 42, "Enclosed Alphanumerics" },
+  { 0x2500, 0x257F, 43, "Box Drawing" },
+  { 0x2580, 0x259F, 44, "Block Elements" },
+  { 0x25A0, 0x25FF, 45, "Geometric Shapes" },
+  { 0x2600, 0x26FF, 46, "Miscellaneous Symbols" },
+  { 0x2700, 0x27BF, 47, "Dingbats" },
+  { 0x3000, 0x303F, 48, "CJK Symbols and Punctuation" },
+  { 0x3040, 0x309F, 49, "Hiragana" },
+  { 0x30A0, 0x30FF, 50, "Katakana" },
+  { 0x3100, 0x312F, 51, "Bopomofo" },
+  { 0x3130, 0x318F, 52, "Hangul Compatibility Jamo" },
+  { 0x3190, 0x319F, 53, "CJK Miscellaneous" },
+  { 0x3200, 0x32FF, 54, "Enclosed CJK" },
+  { 0x3300, 0x33FF, 55, "CJK Compatibility" },
+  { 0x3400, 0x3D2D, 56, "Hangul" },
+  { 0x3D2E, 0x44B7, 57, "Hangul Supplementary-A" },
+  { 0x44B8, 0x4DFF, 58, "Hangul Supplementary-B" },
+  { 0x4E00, 0x9FFF, 59, "CJK Unified Ideographs" },
+  { 0xE000, 0xF8FF, 60, "Private Use Area" },
+  { 0xF900, 0xFAFF, 61, "CJK Compatibility Ideographs" },
+  { 0xFB00, 0xFB4F, 62, "Alphabetic Presentation Forms" },
+  { 0xFB50, 0xFDFF, 63, "Arabic Presentation Forms-A" },
+  { 0xFE20, 0xFE2F, 64, "Combining Half Marks" },
+  { 0xFE30, 0xFE4F, 65, "CJK Compatibility Forms" },
+  { 0xFE50, 0xFE6F, 66, "Small Form Variants" },
+  { 0xFE70, 0xFEFE, 67, "Arabic Presentation Forms-B" },
+  { 0xFEFF, 0xFEFF, 69, "Specials" },
+  { 0xFF00, 0xFFEF, 68, "Halfwidth and Fullwidth Forms" },
+  { 0xFFF0, 0xFFFD, 69, "Specials" }
+};
+
+/* Return the Unicode Subset bitfield number for a Unicode character */
+
+static int
+unicode_classify (wchar_t wc)
+{
+  int min = 0;
+  int max = sizeof (utab) / sizeof (utab[0]) - 1;
+  int mid;
+
+  while (max >= min)
+    {
+      mid = (min + max) / 2;
+      if (utab[mid].high < wc)
+       min = mid + 1;
+      else if (wc < utab[mid].low)
+       max = mid - 1;
+      else if (utab[mid].low <= wc && wc <= utab[mid].high)
+       return utab[mid].bit;
+      else
+       return -1;
+    }
+}
+
+void
+gdk_wchar_text_handle (GdkFont       *font,
+                      const wchar_t *wcstr,
+                      int            wclen,
+                      void         (*handler)(GdkWin32SingleFont *,
+                                              const wchar_t *,
+                                              int,
+                                              void *),
+                      void          *arg)
 {
   GdkFontPrivate *private;
+  GdkWin32SingleFont *singlefont;
+  GSList *list;
+  int i, block;
+  const wchar_t *start, *end, *wcp;
+
+  wcp = wcstr;
+  end = wcp + wclen;
+  private = (GdkFontPrivate *) font;
+
+  while (wcp < end)
+    {
+      /* Split Unicode string into pieces of the same class */
+      start = wcp;
+      block = unicode_classify (*wcp);
+      while (wcp + 1 < end && unicode_classify (wcp[1]) == block)
+       wcp++;
+
+      /* Find a font in the fontset that can handle this class */
+      list = private->fonts;
+      while (list)
+       {
+         singlefont = (GdkWin32SingleFont *) list->data;
+         
+         if (singlefont->fs.fsUsb[block/32] & (1 << (block % 32)))
+           break;
+
+         list = list->next;
+       }
+
+      if (!list)
+       singlefont = NULL;
+
+      /* Call the callback function */
+      (*handler) (singlefont, start, wcp+1 - start, arg);
+      wcp++;
+    }
+}
+
+typedef struct
+{
+  SIZE total;
+  SIZE max;
+} gdk_text_size_arg;
+
+static void
+gdk_text_size_handler (GdkWin32SingleFont *singlefont,
+                      const wchar_t      *wcstr,
+                      int                 wclen,
+                      void               *argp)
+{
+  SIZE this_size;
   HGDIOBJ oldfont;
+  gdk_text_size_arg *arg = (gdk_text_size_arg *) argp;
+
+  if ((oldfont = SelectObject (gdk_DC, singlefont->xfont)) == NULL)
+    {
+      g_warning ("gdk_text_size_handler: SelectObject failed");
+      return;
+    }
+  GetTextExtentPoint32W (gdk_DC, wcstr, wclen, &this_size);
+  SelectObject (gdk_DC, oldfont);
+
+  arg->total.cx += this_size.cx;
+  arg->total.cy += this_size.cy;
+  arg->max.cx = MAX (this_size.cx, arg->max.cx);
+  arg->max.cy = MAX (this_size.cy, arg->max.cy);
+}
+
+static gboolean
+gdk_text_size (GdkFont           *font,
+              const gchar       *text,
+              gint               text_length,
+              gdk_text_size_arg *arg)
+{
   gint wlen;
   wchar_t *wcstr;
 
@@ -574,16 +1204,8 @@ gdk_text_size (GdkFont      *font,
   if (text_length == 0)
     return 0;
 
-  private = (GdkFontPrivate*) font;
-
   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
 
-  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
-    {
-      g_warning ("gdk_text_width: SelectObject failed");
-      return FALSE;
-    }
-
   wcstr = g_new (wchar_t, text_length);
   if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
     {
@@ -591,10 +1213,9 @@ gdk_text_size (GdkFont      *font,
       return FALSE;
     }
 
-  GetTextExtentPoint32W (gdk_DC, wcstr, wlen, sizep);
+  gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, arg);
 
   g_free (wcstr);
-  SelectObject (gdk_DC, oldfont);
 
   return TRUE;
 }
@@ -604,12 +1225,15 @@ gdk_text_width (GdkFont      *font,
                const gchar  *text,
                gint          text_length)
 {
-  SIZE size;
+  gdk_text_size_arg arg;
+
+  arg.total.cx = arg.total.cy = 0;
+  arg.max.cx = arg.max.cy = 0;
 
-  if (!gdk_text_size (font, text, text_length, &size))
+  if (!gdk_text_size (font, text, text_length, &arg))
     return -1;
 
-  return size.cx;
+  return arg.total.cx;
 }
 
 gint
@@ -617,11 +1241,8 @@ gdk_text_width_wc (GdkFont          *font,
                   const GdkWChar *text,
                   gint            text_length)
 {
-  GdkFontPrivate *private;
-  HGDIOBJ oldfont;
-  SIZE size;
+  gdk_text_size_arg arg;
   wchar_t *wcstr;
-  guchar *str;
   gint i;
 
   g_return_val_if_fail (font != NULL, -1);
@@ -632,12 +1253,6 @@ gdk_text_width_wc (GdkFont          *font,
 
   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
 
-  private = (GdkFontPrivate*) font;
-
-  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
-    
-    g_warning ("gdk_text_width_wc: SelectObject failed");
-
   if (sizeof (wchar_t) != sizeof (GdkWChar))
     {
       wcstr = g_new (wchar_t, text_length);
@@ -647,15 +1262,16 @@ gdk_text_width_wc (GdkFont         *font,
   else
     wcstr = (wchar_t *) text;
 
-  GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
+  arg.total.cx = arg.total.cy = 0;
+  arg.max.cx = arg.max.cy = 0;
+
+  gdk_wchar_text_handle (font, wcstr, text_length,
+                        gdk_text_size_handler, &arg);
 
   if (sizeof (wchar_t) != sizeof (GdkWChar))
     g_free (wcstr);
 
-  if (oldfont != NULL)
-    SelectObject (gdk_DC, oldfont);
-
-  return size.cx;
+  return arg.total.cx;
 }
 
 gint
@@ -698,9 +1314,7 @@ gdk_text_extents (GdkFont     *font,
                  gint        *ascent,
                  gint        *descent)
 {
-  GdkFontPrivate *private;
-  HGDIOBJ oldfont;
-  SIZE size;
+  gdk_text_size_arg arg;
   gint wlen;
   wchar_t *wcstr;
 
@@ -724,33 +1338,24 @@ gdk_text_extents (GdkFont     *font,
 
   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
 
-  private = (GdkFontPrivate*) font;
-
-  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
-    g_warning ("gdk_text_extents: SelectObject failed");
+  arg.total.cx = arg.total.cy = 0;
+  arg.max.cx = arg.max.cy = 0;
 
   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;
-    }
+    g_warning ("gdk_text_extents: gdk_nmbstowchar_ts failed");
   else
-    GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+    gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, &arg);
 
-  if (oldfont != NULL)
-    SelectObject (gdk_DC, oldfont);
-
-  /* XXX This is all quite bogus */
+  /* XXX This is quite bogus */
   if (lbearing)
     *lbearing = 0;
   if (rbearing)
     *rbearing = 0;
   if (width)
-    *width = size.cx;
+    *width = arg.total.cx;
   if (ascent)
-    *ascent = size.cy + 1;
+    *ascent = arg.max.cy + 1;
   if (descent)
     *descent = font->descent + 1;
 }
@@ -765,9 +1370,7 @@ gdk_text_extents_wc (GdkFont        *font,
                     gint           *ascent,
                     gint           *descent)
 {
-  GdkFontPrivate *private;
-  HGDIOBJ oldfont;
-  SIZE size;
+  gdk_text_size_arg arg;
   wchar_t *wcstr;
   gint i;
 
@@ -791,8 +1394,6 @@ gdk_text_extents_wc (GdkFont        *font,
 
   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
 
-  private = (GdkFontPrivate*) font;
-
   if (sizeof (wchar_t) != sizeof (GdkWChar))
     {
       wcstr = g_new (wchar_t, text_length);
@@ -802,26 +1403,24 @@ gdk_text_extents_wc (GdkFont        *font,
   else
     wcstr = (wchar_t *) text;
 
-  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
-    g_warning ("gdk_text_extents_wc: SelectObject failed");
+  arg.total.cx = arg.total.cy = 0;
+  arg.max.cx = arg.max.cy = 0;
 
-  GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
+  gdk_wchar_text_handle (font, wcstr, text_length,
+                        gdk_text_size_handler, &arg);
 
   if (sizeof (wchar_t) != sizeof (GdkWChar))
     g_free (wcstr);
 
-  if (oldfont != NULL)
-    SelectObject (gdk_DC, oldfont);
-
-  /* XXX This is all quite bogus */
+  /* XXX This is quite bogus */
   if (lbearing)
     *lbearing = 0;
   if (rbearing)
     *rbearing = 0;
   if (width)
-    *width = size.cx;
+    *width = arg.total.cx;
   if (ascent)
-    *ascent = size.cy + 1;
+    *ascent = arg.max.cy + 1;
   if (descent)
     *descent = font->descent + 1;
 }
@@ -873,12 +1472,15 @@ gdk_text_height (GdkFont     *font,
                 const gchar *text,
                 gint         text_length)
 {
-  SIZE size;
+  gdk_text_size_arg arg;
+
+  arg.total.cx = arg.total.cy = 0;
+  arg.max.cx = arg.max.cy = 0;
 
-  if (!gdk_text_size (font, text, text_length, &size))
+  if (!gdk_text_size (font, text, text_length, &arg))
     return -1;
 
-  return size.cy;
+  return arg.max.cy;
 }
 
 gint
index fb59c593f95619fe9fa3556149ba762e2dc5d30f..339ce04038b9315c45ae2ae0c5ba29accf5ee00c 100644 (file)
@@ -90,9 +90,12 @@ gdk_gc_new_with_values (GdkWindow    *window,
   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;
+      private->font = values->font;
+      gdk_font_ref (private->font);
       GDK_NOTE (MISC, g_print (" font=%#x", private->font));
     }
+  else
+    private->font = NULL;
 
   if (values_mask & GDK_GC_FUNCTION)
     {
@@ -294,28 +297,17 @@ gdk_gc_unref (GdkGC *gc)
   else
     {
       if (private->values_mask & GDK_GC_FONT)
-       {
-#if 0
-         if (!DeleteObject (private->font))
-           g_warning ("gdk_gc_unref: DeleteObject #3 failed");
-#endif
-       }
+       gdk_font_unref (private->font);
 
       if (private->values_mask & GDK_GC_TILE)
-       {
-         gdk_pixmap_unref (private->tile);
-       }
+       gdk_pixmap_unref (private->tile);
       
       if (private->values_mask & GDK_GC_STIPPLE)
-       {
-         gdk_pixmap_unref (private->stipple);
-       }
+       gdk_pixmap_unref (private->stipple);
       
       if (private->values_mask & GDK_GC_CLIP_MASK)
-       {
-         DeleteObject (private->clip_region);
-       }
-      memset (gc, 0, sizeof (GdkGCPrivate));
+       DeleteObject (private->clip_region);
+
       g_free (gc);
     }
 }
@@ -333,7 +325,7 @@ gdk_gc_get_values (GdkGC       *gc,
 
   values->foreground = private->foreground;
   values->background = private->background;
-  values->font = gdk_font_lookup (private->font);
+  values->font = private->font;
 
   switch (private->rop2)
     {
@@ -477,6 +469,7 @@ gdk_gc_set_font (GdkGC       *gc,
 {
   GdkGCPrivate *gc_private;
   GdkFontPrivate *font_private;
+  gchar *xlfd;
 
   g_return_if_fail (gc != NULL);
   g_return_if_fail (font != NULL);
@@ -485,12 +478,16 @@ gdk_gc_set_font (GdkGC     *gc,
       || font->type == GDK_FONT_FONTSET)
     {
       gc_private = (GdkGCPrivate*) gc;
-      font_private = (GdkFontPrivate*) font;
       
-      GDK_NOTE (MISC, g_print ("gdk_gc_set_font: (%d) %#x\n",
-                              gc_private, font_private->xfont));
-
-      gc_private->font = font_private->xfont;
+      GDK_NOTE (MISC, (xlfd = gdk_font_xlfd_create (font),
+                      g_print ("gdk_gc_set_font: (%d) %s\n",
+                               gc_private, xlfd),
+                      gdk_font_xlfd_free (xlfd)));
+
+      if (gc_private->font != NULL)
+       gdk_font_unref (gc_private->font);
+      gc_private->font = font;
+      gdk_font_ref (gc_private->font);
       gc_private->values_mask |= GDK_GC_FONT;
     }
 }
@@ -1067,10 +1064,6 @@ gdk_gc_predraw (GdkDrawablePrivate *drawable_private,
   if (SetTextAlign (gc_private->xgc, TA_BASELINE) == GDI_ERROR)
     g_warning ("gdk_gc_predraw: SetTextAlign failed");
   
-  if (gc_private->values_mask & GDK_GC_FONT)
-    if (SelectObject (gc_private->xgc, gc_private->font) == NULL)
-      g_warning ("gdk_gc_predraw: SelectObject #4 failed");
-  
   if (gc_private->values_mask & GDK_GC_FUNCTION)
     if (SetROP2 (gc_private->xgc, gc_private->rop2) == 0)
       g_warning ("gdk_gc_predraw: SetROP2 failed");
index fb59c593f95619fe9fa3556149ba762e2dc5d30f..339ce04038b9315c45ae2ae0c5ba29accf5ee00c 100644 (file)
@@ -90,9 +90,12 @@ gdk_gc_new_with_values (GdkWindow    *window,
   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;
+      private->font = values->font;
+      gdk_font_ref (private->font);
       GDK_NOTE (MISC, g_print (" font=%#x", private->font));
     }
+  else
+    private->font = NULL;
 
   if (values_mask & GDK_GC_FUNCTION)
     {
@@ -294,28 +297,17 @@ gdk_gc_unref (GdkGC *gc)
   else
     {
       if (private->values_mask & GDK_GC_FONT)
-       {
-#if 0
-         if (!DeleteObject (private->font))
-           g_warning ("gdk_gc_unref: DeleteObject #3 failed");
-#endif
-       }
+       gdk_font_unref (private->font);
 
       if (private->values_mask & GDK_GC_TILE)
-       {
-         gdk_pixmap_unref (private->tile);
-       }
+       gdk_pixmap_unref (private->tile);
       
       if (private->values_mask & GDK_GC_STIPPLE)
-       {
-         gdk_pixmap_unref (private->stipple);
-       }
+       gdk_pixmap_unref (private->stipple);
       
       if (private->values_mask & GDK_GC_CLIP_MASK)
-       {
-         DeleteObject (private->clip_region);
-       }
-      memset (gc, 0, sizeof (GdkGCPrivate));
+       DeleteObject (private->clip_region);
+
       g_free (gc);
     }
 }
@@ -333,7 +325,7 @@ gdk_gc_get_values (GdkGC       *gc,
 
   values->foreground = private->foreground;
   values->background = private->background;
-  values->font = gdk_font_lookup (private->font);
+  values->font = private->font;
 
   switch (private->rop2)
     {
@@ -477,6 +469,7 @@ gdk_gc_set_font (GdkGC       *gc,
 {
   GdkGCPrivate *gc_private;
   GdkFontPrivate *font_private;
+  gchar *xlfd;
 
   g_return_if_fail (gc != NULL);
   g_return_if_fail (font != NULL);
@@ -485,12 +478,16 @@ gdk_gc_set_font (GdkGC     *gc,
       || font->type == GDK_FONT_FONTSET)
     {
       gc_private = (GdkGCPrivate*) gc;
-      font_private = (GdkFontPrivate*) font;
       
-      GDK_NOTE (MISC, g_print ("gdk_gc_set_font: (%d) %#x\n",
-                              gc_private, font_private->xfont));
-
-      gc_private->font = font_private->xfont;
+      GDK_NOTE (MISC, (xlfd = gdk_font_xlfd_create (font),
+                      g_print ("gdk_gc_set_font: (%d) %s\n",
+                               gc_private, xlfd),
+                      gdk_font_xlfd_free (xlfd)));
+
+      if (gc_private->font != NULL)
+       gdk_font_unref (gc_private->font);
+      gc_private->font = font;
+      gdk_font_ref (gc_private->font);
       gc_private->values_mask |= GDK_GC_FONT;
     }
 }
@@ -1067,10 +1064,6 @@ gdk_gc_predraw (GdkDrawablePrivate *drawable_private,
   if (SetTextAlign (gc_private->xgc, TA_BASELINE) == GDI_ERROR)
     g_warning ("gdk_gc_predraw: SetTextAlign failed");
   
-  if (gc_private->values_mask & GDK_GC_FONT)
-    if (SelectObject (gc_private->xgc, gc_private->font) == NULL)
-      g_warning ("gdk_gc_predraw: SelectObject #4 failed");
-  
   if (gc_private->values_mask & GDK_GC_FUNCTION)
     if (SetROP2 (gc_private->xgc, gc_private->rop2) == 0)
       g_warning ("gdk_gc_predraw: SetROP2 failed");
index 9946f23eb8a97bdbf47bc1e97ef0b04f80e877da..4f9f498a724af6a1091d6510a1fc2aaae898f3bb 100644 (file)
@@ -46,6 +46,6 @@ gint              gdk_error_code;
 gint              gdk_error_warnings = TRUE;
 gint              gdk_null_window_warnings = TRUE;
 
-GMutex *gdk_threads_mutex = NULL;          /* Global GDK lock */
+GMutex           *gdk_threads_mutex = NULL;
 
-PFN_TrackMouseEvent p_TrackMouseEvent = NULL;
+DWORD            windows_version = 0;
index 9946f23eb8a97bdbf47bc1e97ef0b04f80e877da..4f9f498a724af6a1091d6510a1fc2aaae898f3bb 100644 (file)
@@ -46,6 +46,6 @@ gint              gdk_error_code;
 gint              gdk_error_warnings = TRUE;
 gint              gdk_null_window_warnings = TRUE;
 
-GMutex *gdk_threads_mutex = NULL;          /* Global GDK lock */
+GMutex           *gdk_threads_mutex = NULL;
 
-PFN_TrackMouseEvent p_TrackMouseEvent = NULL;
+DWORD            windows_version = 0;
index 0d553176555febc50ba87ebc85c2ac5330ad7ab7..a9083b96e3f8aa667f9cf14d8af2c9bd758c2f75 100644 (file)
@@ -337,13 +337,15 @@ gdk_nmbstowchar_ts (wchar_t     *dest,
                    gint         src_len,
                    gint         dest_max)
 {
+  wchar_t *wcp;
   guchar *cp, *end;
   gint n;
   
+  wcp = dest;
   cp = (guchar *) src;
   end = cp + src_len;
   n = 0;
-  while (cp != end && dest != dest + dest_max)
+  while (cp != end && wcp != dest + dest_max)
     {
       gint i, mask = 0, len;
       guchar c = *cp;
@@ -369,19 +371,19 @@ gdk_nmbstowchar_ts (wchar_t     *dest,
       if (cp + len > end)
        return -1;
 
-      *dest = (cp[0] & mask);
+      *wcp = (cp[0] & mask);
       for (i = 1; i < len; i++)
        {
          if ((cp[i] & 0xc0) != 0x80)
            return -1;
-         *dest <<= 6;
-         *dest |= (cp[i] & 0x3f);
+         *wcp <<= 6;
+         *wcp |= (cp[i] & 0x3f);
        }
-      if (*dest == 0xFFFF)
+      if (*wcp == 0xFFFF)
        return -1;
 
       cp += len;
-      dest++;
+      wcp++;
       n++;
     }
   if (cp != end)
index 0d553176555febc50ba87ebc85c2ac5330ad7ab7..a9083b96e3f8aa667f9cf14d8af2c9bd758c2f75 100644 (file)
@@ -337,13 +337,15 @@ gdk_nmbstowchar_ts (wchar_t     *dest,
                    gint         src_len,
                    gint         dest_max)
 {
+  wchar_t *wcp;
   guchar *cp, *end;
   gint n;
   
+  wcp = dest;
   cp = (guchar *) src;
   end = cp + src_len;
   n = 0;
-  while (cp != end && dest != dest + dest_max)
+  while (cp != end && wcp != dest + dest_max)
     {
       gint i, mask = 0, len;
       guchar c = *cp;
@@ -369,19 +371,19 @@ gdk_nmbstowchar_ts (wchar_t     *dest,
       if (cp + len > end)
        return -1;
 
-      *dest = (cp[0] & mask);
+      *wcp = (cp[0] & mask);
       for (i = 1; i < len; i++)
        {
          if ((cp[i] & 0xc0) != 0x80)
            return -1;
-         *dest <<= 6;
-         *dest |= (cp[i] & 0x3f);
+         *wcp <<= 6;
+         *wcp |= (cp[i] & 0x3f);
        }
-      if (*dest == 0xFFFF)
+      if (*wcp == 0xFFFF)
        return -1;
 
       cp += len;
-      dest++;
+      wcp++;
       n++;
     }
   if (cp != end)
index 9e5cb9f0cabb2f6dea1bdc292df2e1b03e719241..e8fa5af5d246441b92751feab57910b557e8226e 100644 (file)
@@ -235,6 +235,7 @@ gdk_init_check (int    *argc,
   gdk_ProgInstance = GetModuleHandle (NULL);
   gdk_DC = CreateDC ("DISPLAY", NULL, NULL, NULL);
   gdk_root_window = GetDesktopWindow ();
+  windows_version = GetVersion ();
 
   CoInitialize (NULL);
 
index e65d3b0e099c19df3a867feb33e9a94a55d2f1d1..30b276d42b9865fb418c8275d31062e46d90fa67 100644 (file)
 #define gdk_window_lookup(xid)    ((GdkWindow*) gdk_xid_table_lookup (xid))
 #define gdk_pixmap_lookup(xid)    ((GdkPixmap*) gdk_xid_table_lookup (xid))
 
-/* HFONTs clash with HWNDs, so add dithering to HFONTs... (hack) */
-#define HFONT_DITHER 43
-#define gdk_font_lookup(xid)      ((GdkFont*) gdk_xid_table_lookup ((HANDLE) ((guint) xid + HFONT_DITHER)))
-
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -249,7 +245,7 @@ struct _GdkGCPrivate
   GdkGCValuesMask values_mask;
   GdkColor foreground;
   GdkColor background;
-  HFONT font;
+  GdkFont *font;
   gint rop2;
   GdkFill fill_style;
   GdkPixmap *tile;
@@ -299,20 +295,22 @@ struct _GdkVisualPrivate
   Visual *xvisual;
 };
 
-struct _GdkFontPrivate
+typedef struct
 {
-  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;
-
-  GSList *names;
   DWORD charset;
   UINT codepage;
   CPINFO cpinfo;
   FONTSIGNATURE fs;
+} GdkWin32SingleFont;
+
+struct _GdkFontPrivate
+{
+  GdkFont font;
+  guint ref_count;
+
+  GSList *fonts;
+  GSList *names;
 };
 
 struct _GdkCursorPrivate
@@ -381,17 +379,26 @@ void    gdk_sel_prop_store (GdkWindow *owner,
                            guchar    *data,
                            gint       length);
 
-void       gdk_event_queue_append (GdkEvent *event);
+void gdk_event_queue_append (GdkEvent *event);
 
-gint      gdk_nmbstowcs (GdkWChar    *dest,
+gint gdk_nmbstowcs (GdkWChar    *dest,
                          const gchar *src,
                          gint         src_len,
                          gint         dest_max);
-gint      gdk_nmbstowchar_ts (wchar_t     *dest,
+gint gdk_nmbstowchar_ts (wchar_t     *dest,
                               const gchar *src,
                               gint         src_len,
                               gint         dest_max);
 
+void gdk_wchar_text_handle (GdkFont       *font,
+                           const wchar_t *wcstr,
+                           int            wclen,
+                           void         (*handler)(GdkWin32SingleFont *,
+                                                   const wchar_t *,
+                                                   int,
+                                                   void *),
+                           void          *arg);
+
 /* 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);
@@ -420,11 +427,10 @@ extern GdkAtom             gdk_clipboard_atom;
 extern GdkAtom          gdk_win32_dropfiles_atom;
 extern GdkAtom          gdk_ole2_dnd_atom;
 
-typedef BOOL (WINAPI *PFN_TrackMouseEvent) (LPTRACKMOUSEEVENT);
-extern PFN_TrackMouseEvent p_TrackMouseEvent;
-
 extern LRESULT CALLBACK gdk_WindowProc (HWND, UINT, WPARAM, LPARAM);
 
+extern DWORD            windows_version;
+
 /* Debugging support */
 
 #ifdef G_ENABLE_DEBUG
index e65d3b0e099c19df3a867feb33e9a94a55d2f1d1..30b276d42b9865fb418c8275d31062e46d90fa67 100644 (file)
 #define gdk_window_lookup(xid)    ((GdkWindow*) gdk_xid_table_lookup (xid))
 #define gdk_pixmap_lookup(xid)    ((GdkPixmap*) gdk_xid_table_lookup (xid))
 
-/* HFONTs clash with HWNDs, so add dithering to HFONTs... (hack) */
-#define HFONT_DITHER 43
-#define gdk_font_lookup(xid)      ((GdkFont*) gdk_xid_table_lookup ((HANDLE) ((guint) xid + HFONT_DITHER)))
-
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -249,7 +245,7 @@ struct _GdkGCPrivate
   GdkGCValuesMask values_mask;
   GdkColor foreground;
   GdkColor background;
-  HFONT font;
+  GdkFont *font;
   gint rop2;
   GdkFill fill_style;
   GdkPixmap *tile;
@@ -299,20 +295,22 @@ struct _GdkVisualPrivate
   Visual *xvisual;
 };
 
-struct _GdkFontPrivate
+typedef struct
 {
-  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;
-
-  GSList *names;
   DWORD charset;
   UINT codepage;
   CPINFO cpinfo;
   FONTSIGNATURE fs;
+} GdkWin32SingleFont;
+
+struct _GdkFontPrivate
+{
+  GdkFont font;
+  guint ref_count;
+
+  GSList *fonts;
+  GSList *names;
 };
 
 struct _GdkCursorPrivate
@@ -381,17 +379,26 @@ void    gdk_sel_prop_store (GdkWindow *owner,
                            guchar    *data,
                            gint       length);
 
-void       gdk_event_queue_append (GdkEvent *event);
+void gdk_event_queue_append (GdkEvent *event);
 
-gint      gdk_nmbstowcs (GdkWChar    *dest,
+gint gdk_nmbstowcs (GdkWChar    *dest,
                          const gchar *src,
                          gint         src_len,
                          gint         dest_max);
-gint      gdk_nmbstowchar_ts (wchar_t     *dest,
+gint gdk_nmbstowchar_ts (wchar_t     *dest,
                               const gchar *src,
                               gint         src_len,
                               gint         dest_max);
 
+void gdk_wchar_text_handle (GdkFont       *font,
+                           const wchar_t *wcstr,
+                           int            wclen,
+                           void         (*handler)(GdkWin32SingleFont *,
+                                                   const wchar_t *,
+                                                   int,
+                                                   void *),
+                           void          *arg);
+
 /* 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);
@@ -420,11 +427,10 @@ extern GdkAtom             gdk_clipboard_atom;
 extern GdkAtom          gdk_win32_dropfiles_atom;
 extern GdkAtom          gdk_ole2_dnd_atom;
 
-typedef BOOL (WINAPI *PFN_TrackMouseEvent) (LPTRACKMOUSEEVENT);
-extern PFN_TrackMouseEvent p_TrackMouseEvent;
-
 extern LRESULT CALLBACK gdk_WindowProc (HWND, UINT, WPARAM, LPARAM);
 
+extern DWORD            windows_version;
+
 /* Debugging support */
 
 #ifdef G_ENABLE_DEBUG
index 092765b89e5c41e4e57e9e34ad495526cfb6c4b3..5814c39cd9282ee744fb22267ede904245ca7fa4 100644 (file)
@@ -48,7 +48,6 @@
 #define GDK_COLORMAP_XCOLORMAP(cmap)  (((GdkColormapPrivate*) cmap)->xcolormap)
 #define GDK_VISUAL_XVISUAL(vis)       (((GdkVisualPrivate*) vis)->xvisual)
 #define GDK_FONT_XDISPLAY(font)       NULL
-#define GDK_FONT_XFONT(font)          (((GdkFontPrivate*) font)->xfont)
 
 GdkVisual*   gdkx_visual_get   (VisualID xvisualid);
 /* XXX: Do not use this function until it is fixed. An X Colormap
index 092765b89e5c41e4e57e9e34ad495526cfb6c4b3..5814c39cd9282ee744fb22267ede904245ca7fa4 100644 (file)
@@ -48,7 +48,6 @@
 #define GDK_COLORMAP_XCOLORMAP(cmap)  (((GdkColormapPrivate*) cmap)->xcolormap)
 #define GDK_VISUAL_XVISUAL(vis)       (((GdkVisualPrivate*) vis)->xvisual)
 #define GDK_FONT_XDISPLAY(font)       NULL
-#define GDK_FONT_XFONT(font)          (((GdkFontPrivate*) font)->xfont)
 
 GdkVisual*   gdkx_visual_get   (VisualID xvisualid);
 /* XXX: Do not use this function until it is fixed. An X Colormap
index 4a50e85f357a52efbe39596a115f7afa0918582b..d1e719957d92b87210720526aaf9fb85c95ca07b 100644 (file)
@@ -18,8 +18,8 @@ LOCALEDIR = /WINDOWS/$(PACKAGE)/locale
 endif
 
 # uk (Ukrainian) is skipped, as native2ascii doesn't know the KOI8_U 
-# encoding, sigh
-LANGUAGES= $(basename $(basename .Big5,$(wildcard $(addsuffix .po,ca cs da de el es et eu fi fr ga gl hr hu it ja ko nl no pl pt pt_BR ru sk sl sv wa zh_TW.Big5))))
+# encoding, sigh. Or is it suffuciently similar to KOI8_R?
+LANGUAGES= $(basename $(basename $(wildcard $(addsuffix .po,ca cs da de el es et eu fi fr ga gl hr hu it ja ko nl no pl pt pt_BR ru sk sl sv wa zh_TW.Big5))))
 
 ################################################################