diff options
author | Tor Lillqvist <tml@iki.fi> | 1999-11-08 00:09:29 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@src.gnome.org> | 1999-11-08 00:09:29 +0000 |
commit | 0ad4aa57d696dbff96e35e571925330afa1ad2d1 (patch) | |
tree | 8d5d782a4e903a2dd97c3194ef247bf7ca271465 /gdk | |
parent | 559a8c86912e1cbdf06e6a441a0a6e5576337341 (diff) | |
download | gtk+-0ad4aa57d696dbff96e35e571925330afa1ad2d1.tar.gz |
New font private structures, related to fontsets.
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.
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/win32/gdk-win32.def | 4 | ||||
-rw-r--r-- | gdk/win32/gdk.c | 1 | ||||
-rw-r--r-- | gdk/win32/gdk.def | 4 | ||||
-rw-r--r-- | gdk/win32/gdkconfig.h | 1 | ||||
-rw-r--r-- | gdk/win32/gdkdraw.c | 92 | ||||
-rw-r--r-- | gdk/win32/gdkdrawable-win32.c | 92 | ||||
-rw-r--r-- | gdk/win32/gdkevents-win32.c | 135 | ||||
-rw-r--r-- | gdk/win32/gdkevents.c | 135 | ||||
-rw-r--r-- | gdk/win32/gdkfont-win32.c | 896 | ||||
-rw-r--r-- | gdk/win32/gdkfont.c | 896 | ||||
-rw-r--r-- | gdk/win32/gdkgc-win32.c | 47 | ||||
-rw-r--r-- | gdk/win32/gdkgc.c | 47 | ||||
-rw-r--r-- | gdk/win32/gdkglobals-win32.c | 4 | ||||
-rw-r--r-- | gdk/win32/gdkglobals.c | 4 | ||||
-rw-r--r-- | gdk/win32/gdkim-win32.c | 14 | ||||
-rw-r--r-- | gdk/win32/gdkim.c | 14 | ||||
-rw-r--r-- | gdk/win32/gdkmain-win32.c | 1 | ||||
-rw-r--r-- | gdk/win32/gdkprivate-win32.h | 44 | ||||
-rw-r--r-- | gdk/win32/gdkprivate.h | 44 | ||||
-rw-r--r-- | gdk/win32/gdkwin32.h | 1 | ||||
-rw-r--r-- | gdk/win32/gdkx.h | 1 |
21 files changed, 1929 insertions, 548 deletions
diff --git a/gdk/win32/gdk-win32.def b/gdk/win32/gdk-win32.def index 1f56d0e037..79d7b8c71a 100644 --- a/gdk/win32/gdk-win32.def +++ b/gdk/win32/gdk-win32.def @@ -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 diff --git a/gdk/win32/gdk.c b/gdk/win32/gdk.c index 9e5cb9f0ca..e8fa5af5d2 100644 --- a/gdk/win32/gdk.c +++ b/gdk/win32/gdk.c @@ -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); diff --git a/gdk/win32/gdk.def b/gdk/win32/gdk.def index 1f56d0e037..79d7b8c71a 100644 --- a/gdk/win32/gdk.def +++ b/gdk/win32/gdk.def @@ -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 diff --git a/gdk/win32/gdkconfig.h b/gdk/win32/gdkconfig.h index 2fd8ca1b3c..6dd3dc732e 100644 --- a/gdk/win32/gdkconfig.h +++ b/gdk/win32/gdkconfig.h @@ -6,3 +6,4 @@ #define GDK_HAVE_WCTYPE_H 1 #endif #define GDK_USE_UTF8_MBS 1 + diff --git a/gdk/win32/gdkdraw.c b/gdk/win32/gdkdraw.c index 85ca076cce..be27056430 100644 --- a/gdk/win32/gdkdraw.c +++ b/gdk/win32/gdkdraw.c @@ -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); } diff --git a/gdk/win32/gdkdrawable-win32.c b/gdk/win32/gdkdrawable-win32.c index 85ca076cce..be27056430 100644 --- a/gdk/win32/gdkdrawable-win32.c +++ b/gdk/win32/gdkdrawable-win32.c @@ -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); } diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c index 279e831f55..dbdfbbf6f0 100644 --- a/gdk/win32/gdkevents-win32.c +++ b/gdk/win32/gdkevents-win32.c @@ -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) @@ -2959,6 +2990,35 @@ build_keypress_event (GdkWindowPrivate *window_private, } 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) { if (state & GDK_SHIFT_MASK) @@ -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. diff --git a/gdk/win32/gdkevents.c b/gdk/win32/gdkevents.c index 279e831f55..dbdfbbf6f0 100644 --- a/gdk/win32/gdkevents.c +++ b/gdk/win32/gdkevents.c @@ -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) @@ -2959,6 +2990,35 @@ build_keypress_event (GdkWindowPrivate *window_private, } 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) { if (state & GDK_SHIFT_MASK) @@ -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. diff --git a/gdk/win32/gdkfont-win32.c b/gdk/win32/gdkfont-win32.c index 59791945ba..f6b768bac7 100644 --- a/gdk/win32/gdkfont-win32.c +++ b/gdk/win32/gdkfont-win32.c @@ -30,15 +30,17 @@ #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 diff --git a/gdk/win32/gdkfont.c b/gdk/win32/gdkfont.c index 59791945ba..f6b768bac7 100644 --- a/gdk/win32/gdkfont.c +++ b/gdk/win32/gdkfont.c @@ -30,15 +30,17 @@ #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 diff --git a/gdk/win32/gdkgc-win32.c b/gdk/win32/gdkgc-win32.c index fb59c593f9..339ce04038 100644 --- a/gdk/win32/gdkgc-win32.c +++ b/gdk/win32/gdkgc-win32.c @@ -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"); diff --git a/gdk/win32/gdkgc.c b/gdk/win32/gdkgc.c index fb59c593f9..339ce04038 100644 --- a/gdk/win32/gdkgc.c +++ b/gdk/win32/gdkgc.c @@ -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"); diff --git a/gdk/win32/gdkglobals-win32.c b/gdk/win32/gdkglobals-win32.c index 9946f23eb8..4f9f498a72 100644 --- a/gdk/win32/gdkglobals-win32.c +++ b/gdk/win32/gdkglobals-win32.c @@ -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; diff --git a/gdk/win32/gdkglobals.c b/gdk/win32/gdkglobals.c index 9946f23eb8..4f9f498a72 100644 --- a/gdk/win32/gdkglobals.c +++ b/gdk/win32/gdkglobals.c @@ -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; diff --git a/gdk/win32/gdkim-win32.c b/gdk/win32/gdkim-win32.c index 0d55317655..a9083b96e3 100644 --- a/gdk/win32/gdkim-win32.c +++ b/gdk/win32/gdkim-win32.c @@ -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) diff --git a/gdk/win32/gdkim.c b/gdk/win32/gdkim.c index 0d55317655..a9083b96e3 100644 --- a/gdk/win32/gdkim.c +++ b/gdk/win32/gdkim.c @@ -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) diff --git a/gdk/win32/gdkmain-win32.c b/gdk/win32/gdkmain-win32.c index 9e5cb9f0ca..e8fa5af5d2 100644 --- a/gdk/win32/gdkmain-win32.c +++ b/gdk/win32/gdkmain-win32.c @@ -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); diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h index e65d3b0e09..30b276d42b 100644 --- a/gdk/win32/gdkprivate-win32.h +++ b/gdk/win32/gdkprivate-win32.h @@ -78,10 +78,6 @@ #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 diff --git a/gdk/win32/gdkprivate.h b/gdk/win32/gdkprivate.h index e65d3b0e09..30b276d42b 100644 --- a/gdk/win32/gdkprivate.h +++ b/gdk/win32/gdkprivate.h @@ -78,10 +78,6 @@ #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 diff --git a/gdk/win32/gdkwin32.h b/gdk/win32/gdkwin32.h index 092765b89e..5814c39cd9 100644 --- a/gdk/win32/gdkwin32.h +++ b/gdk/win32/gdkwin32.h @@ -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 diff --git a/gdk/win32/gdkx.h b/gdk/win32/gdkx.h index 092765b89e..5814c39cd9 100644 --- a/gdk/win32/gdkx.h +++ b/gdk/win32/gdkx.h @@ -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 |