summaryrefslogtreecommitdiff
path: root/gdk/win32
diff options
context:
space:
mode:
Diffstat (limited to 'gdk/win32')
-rw-r--r--gdk/win32/gdk-win32.def4
-rw-r--r--gdk/win32/gdk.c1
-rw-r--r--gdk/win32/gdk.def4
-rw-r--r--gdk/win32/gdkconfig.h1
-rw-r--r--gdk/win32/gdkdraw.c92
-rw-r--r--gdk/win32/gdkdrawable-win32.c92
-rw-r--r--gdk/win32/gdkevents-win32.c135
-rw-r--r--gdk/win32/gdkevents.c135
-rw-r--r--gdk/win32/gdkfont-win32.c896
-rw-r--r--gdk/win32/gdkfont.c896
-rw-r--r--gdk/win32/gdkgc-win32.c47
-rw-r--r--gdk/win32/gdkgc.c47
-rw-r--r--gdk/win32/gdkglobals-win32.c4
-rw-r--r--gdk/win32/gdkglobals.c4
-rw-r--r--gdk/win32/gdkim-win32.c14
-rw-r--r--gdk/win32/gdkim.c14
-rw-r--r--gdk/win32/gdkmain-win32.c1
-rw-r--r--gdk/win32/gdkprivate-win32.h44
-rw-r--r--gdk/win32/gdkprivate.h44
-rw-r--r--gdk/win32/gdkwin32.h1
-rw-r--r--gdk/win32/gdkx.h1
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