1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25  */
26 
27 #undef GDK_DISABLE_DEPRECATED
28 
29 #include "config.h"
30 #include <X11/Xlib.h>
31 #include <X11/Xos.h>
32 #include <locale.h>
33 
34 #include "gdkx.h"
35 #include "gdkfont.h"
36 #include "gdkprivate-x11.h"
37 #include "gdkinternals.h"
38 #include "gdkdisplay-x11.h"
39 #include "gdkscreen-x11.h"
40 #include "gdkalias.h"
41 
42 typedef struct _GdkFontPrivateX        GdkFontPrivateX;
43 
44 struct _GdkFontPrivateX
45 {
46   GdkFontPrivate base;
47   /* XFontStruct *xfont; */
48   /* generic pointer point to XFontStruct or XFontSet */
49   gpointer xfont;
50   GdkDisplay *display;
51 
52   GSList *names;
53   XID xid;
54 };
55 
56 static GHashTable *
gdk_font_name_hash_get(GdkDisplay * display)57 gdk_font_name_hash_get (GdkDisplay *display)
58 {
59   GHashTable *result;
60   static GQuark font_name_quark = 0;
61 
62   if (!font_name_quark)
63     font_name_quark = g_quark_from_static_string ("gdk-font-hash");
64 
65   result = g_object_get_qdata (G_OBJECT (display), font_name_quark);
66 
67   if (!result)
68     {
69       result = g_hash_table_new (g_str_hash, g_str_equal);
70       g_object_set_qdata_full (G_OBJECT (display),
71          font_name_quark, result, (GDestroyNotify) g_hash_table_destroy);
72     }
73 
74   return result;
75 }
76 
77 static GHashTable *
gdk_fontset_name_hash_get(GdkDisplay * display)78 gdk_fontset_name_hash_get (GdkDisplay *display)
79 {
80   GHashTable *result;
81   static GQuark fontset_name_quark = 0;
82 
83   if (!fontset_name_quark)
84     fontset_name_quark = g_quark_from_static_string ("gdk-fontset-hash");
85 
86   result = g_object_get_qdata (G_OBJECT (display), fontset_name_quark);
87 
88   if (!result)
89     {
90       result = g_hash_table_new (g_str_hash, g_str_equal);
91       g_object_set_qdata_full (G_OBJECT (display),
92          fontset_name_quark, result, (GDestroyNotify) g_hash_table_destroy);
93     }
94 
95   return result;
96 }
97 
98 /**
99  * gdk_font_get_display:
100  * @font: the #GdkFont.
101  *
102  * Returns the #GdkDisplay for @font.
103  *
104  * Returns: the corresponding #GdkDisplay.
105  *
106  * Since: 2.2
107  **/
108 GdkDisplay*
gdk_font_get_display(GdkFont * font)109 gdk_font_get_display (GdkFont* font)
110 {
111   return ((GdkFontPrivateX *)font)->display;
112 }
113 
114 static void
gdk_font_hash_insert(GdkFontType type,GdkFont * font,const gchar * font_name)115 gdk_font_hash_insert (GdkFontType  type,
116 		      GdkFont     *font,
117 		      const gchar *font_name)
118 {
119   GdkFontPrivateX *private = (GdkFontPrivateX *)font;
120   GHashTable *hash = (type == GDK_FONT_FONT) ?
121     gdk_font_name_hash_get (private->display) : gdk_fontset_name_hash_get (private->display);
122 
123   private->names = g_slist_prepend (private->names, g_strdup (font_name));
124   g_hash_table_insert (hash, private->names->data, font);
125 }
126 
127 static void
gdk_font_hash_remove(GdkFontType type,GdkFont * font)128 gdk_font_hash_remove (GdkFontType type,
129 		      GdkFont    *font)
130 {
131   GdkFontPrivateX *private = (GdkFontPrivateX *)font;
132   GSList *tmp_list;
133   GHashTable *hash = (type == GDK_FONT_FONT) ?
134     gdk_font_name_hash_get (private->display) : gdk_fontset_name_hash_get (private->display);
135 
136   tmp_list = private->names;
137   while (tmp_list)
138     {
139       g_hash_table_remove (hash, tmp_list->data);
140       g_free (tmp_list->data);
141 
142       tmp_list = tmp_list->next;
143     }
144 
145   g_slist_free (private->names);
146   private->names = NULL;
147 }
148 
149 static GdkFont *
gdk_font_hash_lookup(GdkDisplay * display,GdkFontType type,const gchar * font_name)150 gdk_font_hash_lookup (GdkDisplay  *display,
151 		      GdkFontType  type,
152 		      const gchar *font_name)
153 {
154   GdkFont *result;
155   GHashTable *hash;
156   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
157 
158   hash = (type == GDK_FONT_FONT) ? gdk_font_name_hash_get (display) :
159 				   gdk_fontset_name_hash_get (display);
160   if (!hash)
161     return NULL;
162   else
163     {
164       result = g_hash_table_lookup (hash, font_name);
165       if (result)
166 	gdk_font_ref (result);
167 
168       return result;
169     }
170 }
171 
172 /**
173  * gdk_font_load_for_display:
174  * @display: a #GdkDisplay
175  * @font_name: a XLFD describing the font to load.
176  * @returns: a #GdkFont, or %NULL if the font could not be loaded.
177  *
178  * Loads a font for use on @display.
179  *
180  * The font may be newly loaded or looked up the font in a cache.
181  * You should make no assumptions about the initial reference count.
182  *
183  * Since: 2.2
184  */
185 GdkFont *
gdk_font_load_for_display(GdkDisplay * display,const gchar * font_name)186 gdk_font_load_for_display (GdkDisplay  *display,
187 			   const gchar *font_name)
188 {
189   GdkFont *font;
190   GdkFontPrivateX *private;
191   XFontStruct *xfont;
192 
193   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
194   g_return_val_if_fail (font_name != NULL, NULL);
195 
196   font = gdk_font_hash_lookup (display, GDK_FONT_FONT, font_name);
197   if (font)
198     return font;
199 
200   xfont = XLoadQueryFont (GDK_DISPLAY_XDISPLAY (display), font_name);
201   if (xfont == NULL)
202     return NULL;
203 
204   font = gdk_font_lookup_for_display (display, xfont->fid);
205   if (font != NULL)
206     {
207       private = (GdkFontPrivateX *) font;
208       if (xfont != private->xfont)
209 	XFreeFont (GDK_DISPLAY_XDISPLAY (display), xfont);
210 
211       gdk_font_ref (font);
212     }
213   else
214     {
215       private = g_new (GdkFontPrivateX, 1);
216       private->display = display;
217       private->xfont = xfont;
218       private->base.ref_count = 1;
219       private->names = NULL;
220       private->xid = xfont->fid | XID_FONT_BIT;
221 
222       font = (GdkFont*) private;
223       font->type = GDK_FONT_FONT;
224       font->ascent =  xfont->ascent;
225       font->descent = xfont->descent;
226 
227       _gdk_xid_table_insert (display, &private->xid, font);
228     }
229 
230   gdk_font_hash_insert (GDK_FONT_FONT, font, font_name);
231 
232   return font;
233 }
234 
235 /**
236  * gdk_font_from_description_for_display:
237  * @display: a #GdkDisplay
238  * @font_desc: a #PangoFontDescription.
239  *
240  * Loads a #GdkFont based on a Pango font description for use on @display.
241  * This font will only be an approximation of the Pango font, and
242  * internationalization will not be handled correctly. This function
243  * should only be used for legacy code that cannot be easily converted
244  * to use Pango. Using Pango directly will produce better results.
245  *
246  * Return value: the newly loaded font, or %NULL if the font
247  * cannot be loaded.
248  *
249  * Since: 2.2
250  */
251 GdkFont *
gdk_font_from_description_for_display(GdkDisplay * display,PangoFontDescription * font_desc)252 gdk_font_from_description_for_display (GdkDisplay           *display,
253 				       PangoFontDescription *font_desc)
254 {
255   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
256   g_return_val_if_fail (font_desc != NULL, NULL);
257 
258   return gdk_font_load_for_display (display, "fixed");
259 }
260 
261 /**
262  * gdk_fontset_load_for_display:
263  * @display: a #GdkDisplay
264  * @fontset_name: a comma-separated list of XLFDs describing
265  *   the component fonts of the fontset to load.
266  * @returns: a #GdkFont, or %NULL if the fontset could not be loaded.
267  *
268  * Loads a fontset for use on @display.
269  *
270  * The fontset may be newly loaded or looked up in a cache.
271  * You should make no assumptions about the initial reference count.
272  *
273  * Since: 2.2
274  */
275 GdkFont *
gdk_fontset_load_for_display(GdkDisplay * display,const gchar * fontset_name)276 gdk_fontset_load_for_display (GdkDisplay  *display,
277 			      const gchar *fontset_name)
278 {
279   GdkFont *font;
280   GdkFontPrivateX *private;
281   XFontSet fontset;
282   gint  missing_charset_count;
283   gchar **missing_charset_list;
284   gchar *def_string;
285 
286   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
287 
288   font = gdk_font_hash_lookup (display, GDK_FONT_FONTSET, fontset_name);
289   if (font)
290     return font;
291 
292   private = g_new (GdkFontPrivateX, 1);
293   font = (GdkFont*) private;
294 
295   private->display = display;
296   fontset = XCreateFontSet (GDK_DISPLAY_XDISPLAY (display), fontset_name,
297 			    &missing_charset_list, &missing_charset_count,
298 			    &def_string);
299 
300   if (missing_charset_count)
301     {
302       gint i;
303       g_printerr ("The font \"%s\" does not support all the required character sets for the current locale \"%s\"\n",
304                  fontset_name, setlocale (LC_ALL, NULL));
305       for (i=0;i<missing_charset_count;i++)
306 	g_printerr ("  (Missing character set \"%s\")\n",
307                     missing_charset_list[i]);
308       XFreeStringList (missing_charset_list);
309     }
310 
311   private->base.ref_count = 1;
312 
313   if (!fontset)
314     {
315       g_free (font);
316       return NULL;
317     }
318   else
319     {
320       gint num_fonts;
321       gint i;
322       XFontStruct **font_structs;
323       gchar **font_names;
324 
325       private->xfont = fontset;
326       font->type = GDK_FONT_FONTSET;
327       num_fonts = XFontsOfFontSet (fontset, &font_structs, &font_names);
328 
329       font->ascent = font->descent = 0;
330 
331       for (i = 0; i < num_fonts; i++)
332 	{
333 	  font->ascent = MAX (font->ascent, font_structs[i]->ascent);
334 	  font->descent = MAX (font->descent, font_structs[i]->descent);
335 	}
336 
337       private->names = NULL;
338       gdk_font_hash_insert (GDK_FONT_FONTSET, font, fontset_name);
339 
340       return font;
341     }
342 }
343 
344 /**
345  * gdk_fontset_load:
346  * @fontset_name: a comma-separated list of XLFDs describing
347  *     the component fonts of the fontset to load.
348  *
349  * Loads a fontset.
350  *
351  * The fontset may be newly loaded or looked up in a cache.
352  * You should make no assumptions about the initial reference count.
353  *
354  * Return value: a #GdkFont, or %NULL if the fontset could not be loaded.
355  **/
356 GdkFont*
gdk_fontset_load(const gchar * fontset_name)357 gdk_fontset_load (const gchar *fontset_name)
358 {
359   return gdk_fontset_load_for_display (gdk_display_get_default (), fontset_name);
360 }
361 
362 void
_gdk_font_destroy(GdkFont * font)363 _gdk_font_destroy (GdkFont *font)
364 {
365   GdkFontPrivateX *private = (GdkFontPrivateX *)font;
366 
367   gdk_font_hash_remove (font->type, font);
368 
369   switch (font->type)
370     {
371     case GDK_FONT_FONT:
372       _gdk_xid_table_remove (private->display, private->xid);
373       XFreeFont (GDK_DISPLAY_XDISPLAY (private->display),
374 		  (XFontStruct *) private->xfont);
375       break;
376     case GDK_FONT_FONTSET:
377       XFreeFontSet (GDK_DISPLAY_XDISPLAY (private->display),
378 		    (XFontSet) private->xfont);
379       break;
380     default:
381       g_error ("unknown font type.");
382       break;
383     }
384   g_free (font);
385 }
386 
387 gint
_gdk_font_strlen(GdkFont * font,const gchar * str)388 _gdk_font_strlen (GdkFont     *font,
389 		  const gchar *str)
390 {
391   GdkFontPrivateX *font_private;
392   gint length = 0;
393 
394   g_return_val_if_fail (font != NULL, -1);
395   g_return_val_if_fail (str != NULL, -1);
396 
397   font_private = (GdkFontPrivateX*) font;
398 
399   if (font->type == GDK_FONT_FONT)
400     {
401       XFontStruct *xfont = (XFontStruct *) font_private->xfont;
402       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
403 	{
404 	  length = strlen (str);
405 	}
406       else
407 	{
408 	  guint16 *string_2b = (guint16 *)str;
409 
410 	  while (*(string_2b++))
411 	    length++;
412 	}
413     }
414   else if (font->type == GDK_FONT_FONTSET)
415     {
416       length = strlen (str);
417     }
418   else
419     g_error("undefined font type\n");
420 
421   return length;
422 }
423 
424 /**
425  * gdk_font_id:
426  * @font: a #GdkFont.
427  *
428  * Returns the X Font ID for the given font.
429  *
430  * Return value: the numeric X Font ID
431  **/
432 gint
gdk_font_id(const GdkFont * font)433 gdk_font_id (const GdkFont *font)
434 {
435   const GdkFontPrivateX *font_private;
436 
437   g_return_val_if_fail (font != NULL, 0);
438 
439   font_private = (const GdkFontPrivateX*) font;
440 
441   if (font->type == GDK_FONT_FONT)
442     {
443       return ((XFontStruct *) font_private->xfont)->fid;
444     }
445   else
446     {
447       return 0;
448     }
449 }
450 
451 /**
452  * gdk_font_equal:
453  * @fonta: a #GdkFont.
454  * @fontb: another #GdkFont.
455  *
456  * Compares two fonts for equality. Single fonts compare equal
457  * if they have the same X font ID. This operation does
458  * not currently work correctly for fontsets.
459  *
460  * Return value: %TRUE if the fonts are equal.
461  **/
462 gboolean
gdk_font_equal(const GdkFont * fonta,const GdkFont * fontb)463 gdk_font_equal (const GdkFont *fonta,
464                 const GdkFont *fontb)
465 {
466   const GdkFontPrivateX *privatea;
467   const GdkFontPrivateX *privateb;
468 
469   g_return_val_if_fail (fonta != NULL, FALSE);
470   g_return_val_if_fail (fontb != NULL, FALSE);
471 
472   privatea = (const GdkFontPrivateX*) fonta;
473   privateb = (const GdkFontPrivateX*) fontb;
474 
475   if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
476     {
477       return (((XFontStruct *) privatea->xfont)->fid ==
478 	      ((XFontStruct *) privateb->xfont)->fid);
479     }
480   else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
481     {
482       gchar *namea, *nameb;
483 
484       namea = XBaseFontNameListOfFontSet((XFontSet) privatea->xfont);
485       nameb = XBaseFontNameListOfFontSet((XFontSet) privateb->xfont);
486 
487       return (strcmp(namea, nameb) == 0);
488     }
489   else
490     /* fontset != font */
491     return FALSE;
492 }
493 
494 /**
495  * gdk_text_width:
496  * @font: a #GdkFont
497  * @text: the text to measure.
498  * @text_length: the length of the text in bytes.
499  *
500  * Determines the width of a given string.
501  *
502  * Return value: the width of the string in pixels.
503  **/
504 gint
gdk_text_width(GdkFont * font,const gchar * text,gint text_length)505 gdk_text_width (GdkFont      *font,
506 		const gchar  *text,
507 		gint          text_length)
508 {
509   GdkFontPrivateX *private;
510   gint width;
511   XFontStruct *xfont;
512   XFontSet fontset;
513 
514   g_return_val_if_fail (font != NULL, -1);
515   g_return_val_if_fail (text != NULL, -1);
516 
517   private = (GdkFontPrivateX*) font;
518 
519   switch (font->type)
520     {
521     case GDK_FONT_FONT:
522       xfont = (XFontStruct *) private->xfont;
523       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
524 	{
525 	  width = XTextWidth (xfont, text, text_length);
526 	}
527       else
528 	{
529 	  width = XTextWidth16 (xfont, (XChar2b *) text, text_length / 2);
530 	}
531       break;
532     case GDK_FONT_FONTSET:
533       fontset = (XFontSet) private->xfont;
534       width = XmbTextEscapement (fontset, text, text_length);
535       break;
536     default:
537       width = 0;
538     }
539   return width;
540 }
541 
542 /**
543  * gdk_text_width_wc:
544  * @font: a #GdkFont
545  * @text: the text to measure.
546  * @text_length: the length of the text in characters.
547  *
548  * Determines the width of a given wide-character string.
549  *
550  * Return value: the width of the string in pixels.
551  **/
552 gint
gdk_text_width_wc(GdkFont * font,const GdkWChar * text,gint text_length)553 gdk_text_width_wc (GdkFont	  *font,
554 		   const GdkWChar *text,
555 		   gint		   text_length)
556 {
557   GdkFontPrivateX *private;
558   gint width;
559   XFontStruct *xfont;
560   XFontSet fontset;
561 
562   g_return_val_if_fail (font != NULL, -1);
563   g_return_val_if_fail (text != NULL, -1);
564 
565   private = (GdkFontPrivateX*) font;
566 
567   switch (font->type)
568     {
569     case GDK_FONT_FONT:
570       xfont = (XFontStruct *) private->xfont;
571       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
572         {
573           gchar *text_8bit;
574           gint i;
575           text_8bit = g_new (gchar, text_length);
576           for (i=0; i<text_length; i++) text_8bit[i] = text[i];
577           width = XTextWidth (xfont, text_8bit, text_length);
578           g_free (text_8bit);
579         }
580       else
581         {
582           width = 0;
583         }
584       break;
585     case GDK_FONT_FONTSET:
586       if (sizeof(GdkWChar) == sizeof(wchar_t))
587 	{
588 	  fontset = (XFontSet) private->xfont;
589 	  width = XwcTextEscapement (fontset, (wchar_t *)text, text_length);
590 	}
591       else
592 	{
593 	  wchar_t *text_wchar;
594 	  gint i;
595 	  fontset = (XFontSet) private->xfont;
596 	  text_wchar = g_new(wchar_t, text_length);
597 	  for (i=0; i<text_length; i++) text_wchar[i] = text[i];
598 	  width = XwcTextEscapement (fontset, text_wchar, text_length);
599 	  g_free (text_wchar);
600 	}
601       break;
602     default:
603       width = 0;
604     }
605   return width;
606 }
607 
608 /**
609  * gdk_text_extents:
610  * @font: a #GdkFont
611  * @text: the text to measure
612  * @text_length: the length of the text in bytes. (If the
613  *    font is a 16-bit font, this is twice the length
614  *    of the text in characters.)
615  * @lbearing: the left bearing of the string.
616  * @rbearing: the right bearing of the string.
617  * @width: the width of the string.
618  * @ascent: the ascent of the string.
619  * @descent: the descent of the string.
620  *
621  * Gets the metrics of a string.
622  **/
623 void
gdk_text_extents(GdkFont * font,const gchar * text,gint text_length,gint * lbearing,gint * rbearing,gint * width,gint * ascent,gint * descent)624 gdk_text_extents (GdkFont     *font,
625                   const gchar *text,
626                   gint         text_length,
627 		  gint        *lbearing,
628 		  gint        *rbearing,
629 		  gint        *width,
630 		  gint        *ascent,
631 		  gint        *descent)
632 {
633   GdkFontPrivateX *private;
634   XCharStruct overall;
635   XFontStruct *xfont;
636   XFontSet    fontset;
637   XRectangle  ink, logical;
638   int direction;
639   int font_ascent;
640   int font_descent;
641 
642   g_return_if_fail (font != NULL);
643   g_return_if_fail (text != NULL);
644 
645   private = (GdkFontPrivateX*) font;
646 
647   switch (font->type)
648     {
649     case GDK_FONT_FONT:
650       xfont = (XFontStruct *) private->xfont;
651       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
652 	{
653 	  XTextExtents (xfont, text, text_length,
654 			&direction, &font_ascent, &font_descent,
655 			&overall);
656 	}
657       else
658 	{
659 	  XTextExtents16 (xfont, (XChar2b *) text, text_length / 2,
660 			  &direction, &font_ascent, &font_descent,
661 			  &overall);
662 	}
663       if (lbearing)
664 	*lbearing = overall.lbearing;
665       if (rbearing)
666 	*rbearing = overall.rbearing;
667       if (width)
668 	*width = overall.width;
669       if (ascent)
670 	*ascent = overall.ascent;
671       if (descent)
672 	*descent = overall.descent;
673       break;
674     case GDK_FONT_FONTSET:
675       fontset = (XFontSet) private->xfont;
676       XmbTextExtents (fontset, text, text_length, &ink, &logical);
677       if (lbearing)
678 	*lbearing = ink.x;
679       if (rbearing)
680 	*rbearing = ink.x + ink.width;
681       if (width)
682 	*width = logical.width;
683       if (ascent)
684 	*ascent = -ink.y;
685       if (descent)
686 	*descent = ink.y + ink.height;
687       break;
688     }
689 
690 }
691 
692 /**
693  * gdk_text_extents_wc:
694  * @font: a #GdkFont
695  * @text: the text to measure.
696  * @text_length: the length of the text in character.
697  * @lbearing: the left bearing of the string.
698  * @rbearing: the right bearing of the string.
699  * @width: the width of the string.
700  * @ascent: the ascent of the string.
701  * @descent: the descent of the string.
702  *
703  * Gets the metrics of a string of wide characters.
704  **/
705 void
gdk_text_extents_wc(GdkFont * font,const GdkWChar * text,gint text_length,gint * lbearing,gint * rbearing,gint * width,gint * ascent,gint * descent)706 gdk_text_extents_wc (GdkFont        *font,
707 		     const GdkWChar *text,
708 		     gint            text_length,
709 		     gint           *lbearing,
710 		     gint           *rbearing,
711 		     gint           *width,
712 		     gint           *ascent,
713 		     gint           *descent)
714 {
715   GdkFontPrivateX *private;
716   XCharStruct overall;
717   XFontStruct *xfont;
718   XFontSet    fontset;
719   XRectangle  ink, logical;
720   int direction;
721   int font_ascent;
722   int font_descent;
723 
724   g_return_if_fail (font != NULL);
725   g_return_if_fail (text != NULL);
726 
727   private = (GdkFontPrivateX*) font;
728 
729   switch (font->type)
730     {
731     case GDK_FONT_FONT:
732       {
733 	gchar *text_8bit;
734 	gint i;
735 
736 	xfont = (XFontStruct *) private->xfont;
737 	g_return_if_fail ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0));
738 
739 	text_8bit = g_new (gchar, text_length);
740 	for (i=0; i<text_length; i++)
741 	  text_8bit[i] = text[i];
742 
743 	XTextExtents (xfont, text_8bit, text_length,
744 		      &direction, &font_ascent, &font_descent,
745 		      &overall);
746 	g_free (text_8bit);
747 
748 	if (lbearing)
749 	  *lbearing = overall.lbearing;
750 	if (rbearing)
751 	  *rbearing = overall.rbearing;
752 	if (width)
753 	  *width = overall.width;
754 	if (ascent)
755 	  *ascent = overall.ascent;
756 	if (descent)
757 	  *descent = overall.descent;
758 	break;
759       }
760     case GDK_FONT_FONTSET:
761       fontset = (XFontSet) private->xfont;
762 
763       if (sizeof(GdkWChar) == sizeof(wchar_t))
764 	XwcTextExtents (fontset, (wchar_t *)text, text_length, &ink, &logical);
765       else
766 	{
767 	  wchar_t *text_wchar;
768 	  gint i;
769 
770 	  text_wchar = g_new (wchar_t, text_length);
771 	  for (i = 0; i < text_length; i++)
772 	    text_wchar[i] = text[i];
773 	  XwcTextExtents (fontset, text_wchar, text_length, &ink, &logical);
774 	  g_free (text_wchar);
775 	}
776       if (lbearing)
777 	*lbearing = ink.x;
778       if (rbearing)
779 	*rbearing = ink.x + ink.width;
780       if (width)
781 	*width = logical.width;
782       if (ascent)
783 	*ascent = -ink.y;
784       if (descent)
785 	*descent = ink.y + ink.height;
786       break;
787     }
788 
789 }
790 
791 /**
792  * gdk_x11_font_get_xdisplay:
793  * @font: a #GdkFont.
794  *
795  * Returns the display of a #GdkFont.
796  *
797  * Return value:  an Xlib <type>Display*</type>.
798  **/
799 Display *
gdk_x11_font_get_xdisplay(GdkFont * font)800 gdk_x11_font_get_xdisplay (GdkFont *font)
801 {
802   g_return_val_if_fail (font != NULL, NULL);
803 
804   return GDK_DISPLAY_XDISPLAY (((GdkFontPrivateX *)font)->display);
805 }
806 
807 /**
808  * gdk_x11_font_get_xfont:
809  * @font: a #GdkFont.
810  *
811  * Returns the X font belonging to a #GdkFont.
812  *
813  * Return value: an Xlib <type>XFontStruct*</type> or an <type>XFontSet</type>.
814  **/
815 gpointer
gdk_x11_font_get_xfont(GdkFont * font)816 gdk_x11_font_get_xfont (GdkFont *font)
817 {
818   g_return_val_if_fail (font != NULL, NULL);
819 
820   return ((GdkFontPrivateX *)font)->xfont;
821 }
822 
823 /**
824  * gdk_x11_font_get_name:
825  * @font: a #GdkFont.
826  *
827  * Return the X Logical Font Description (for font->type == GDK_FONT_FONT)
828  * or comma separated list of XLFDs (for font->type == GDK_FONT_FONTSET)
829  * that was used to load the font. If the same font was loaded
830  * via multiple names, which name is returned is undefined.
831  *
832  * Return value: the name of the font. This string is owned
833  *   by GDK and must not be modified or freed.
834  **/
835 const char *
gdk_x11_font_get_name(GdkFont * font)836 gdk_x11_font_get_name (GdkFont *font)
837 {
838   GdkFontPrivateX *private = (GdkFontPrivateX *)font;
839 
840   g_return_val_if_fail (font != NULL, NULL);
841 
842   g_assert (private->names);
843 
844   return private->names->data;
845 }
846 
847 #define __GDK_FONT_X11_C__
848 #include "gdkaliasdef.c"
849