Home | History | Annotate | Line # | Download | only in xlibi18n
      1 /*
      2 Copyright 1985, 1986, 1987, 1991, 1998  The Open Group
      3 
      4 Permission is hereby granted, free of charge, to any person obtaining a
      5 copy of this software and associated documentation files (the
      6 "Software"), to deal in the Software without restriction, including
      7 without limitation the rights to use, copy, modify, merge, publish,
      8 distribute, sublicense, and/or sell copies of the Software, and to
      9 permit persons to whom the Software is furnished to do so, subject to
     10 the following conditions: The above copyright notice and this
     11 permission notice shall be included in all copies or substantial
     12 portions of the Software.
     13 
     14 
     15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
     21 EVEN IF ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
     22 
     23 
     24 Except as contained in this notice, the name of The Open Group shall not be
     25 used in advertising or otherwise to promote the sale, use or other dealings
     26 in this Software without prior written authorization from The Open Group.
     27 
     28 
     29 X Window System is a trademark of The Open Group
     30 
     31 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
     32 logo, LBX, X Window System, and Xinerama are trademarks of the Open
     33 Group. All other trademarks and registered trademarks mentioned herein
     34 are the property of their respective owners. No right, title or
     35 interest in or to any trademark, service mark, logo or trade name of
     36 Sun Microsystems, Inc. or its licensors is granted.
     37 
     38 */
     39 /*
     40  * Copyright (c) 2000, Oracle and/or its affiliates.
     41  *
     42  * Permission is hereby granted, free of charge, to any person obtaining a
     43  * copy of this software and associated documentation files (the "Software"),
     44  * to deal in the Software without restriction, including without limitation
     45  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     46  * and/or sell copies of the Software, and to permit persons to whom the
     47  * Software is furnished to do so, subject to the following conditions:
     48  *
     49  * The above copyright notice and this permission notice (including the next
     50  * paragraph) shall be included in all copies or substantial portions of the
     51  * Software.
     52  *
     53  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     54  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     55  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     56  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     57  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     58  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     59  * DEALINGS IN THE SOFTWARE.
     60  */
     61 
     62 
     63 #ifdef HAVE_CONFIG_H
     64 #include <config.h>
     65 #endif
     66 #include "Xlibint.h"
     67 #include "Xlcint.h"
     68 #include "XlcPublic.h"
     69 #include <X11/Xos.h>
     70 #include <X11/Xatom.h>
     71 #include <stdio.h>
     72 
     73 #define MAXFONTS		100
     74 
     75 #define XOM_GENERIC(om)		(&((XOMGeneric) om)->gen)
     76 #define XOC_GENERIC(font_set)	(&((XOCGeneric) font_set)->gen)
     77 
     78 #define DefineLocalBuf		char local_buf[BUFSIZ]
     79 #define AllocLocalBuf(length)	(length > BUFSIZ ? Xmalloc(length) : local_buf)
     80 #define FreeLocalBuf(ptr)	if (ptr != local_buf) Xfree(ptr)
     81 
     82 typedef struct _FontDataRec {
     83     char *name;
     84 } FontDataRec, *FontData;
     85 
     86 typedef struct _OMDataRec {
     87     int font_data_count;
     88     FontData font_data;
     89 } OMDataRec, *OMData;
     90 
     91 typedef struct _XOMGenericPart {
     92     OMData data;
     93 } XOMGenericPart;
     94 
     95 typedef struct _XOMGenericRec {
     96     XOMMethods methods;
     97     XOMCoreRec core;
     98     XOMGenericPart gen;
     99 } XOMGenericRec, *XOMGeneric;
    100 
    101 typedef struct _FontSetRec {
    102     int id;
    103     int font_data_count;
    104     FontData font_data;
    105     char *font_name;
    106     XFontStruct *info;
    107     XFontStruct *font;
    108 } FontSetRec, *FontSet;
    109 
    110 typedef struct _XOCGenericPart {
    111     XlcConv wcs_to_cs;
    112     FontSet font_set;
    113 } XOCGenericPart;
    114 
    115 typedef struct _XOCGenericRec {
    116     XOCMethods methods;
    117     XOCCoreRec core;
    118     XOCGenericPart gen;
    119 } XOCGenericRec, *XOCGeneric;
    120 
    121 static Bool
    122 init_fontset(
    123     XOC oc)
    124 {
    125     XOCGenericPart *gen;
    126     FontSet font_set;
    127     OMData data;
    128 
    129     data = XOM_GENERIC(oc->core.om)->data;
    130 
    131     font_set = Xcalloc(1, sizeof(FontSetRec));
    132     if (font_set == NULL)
    133 	return False;
    134 
    135     gen = XOC_GENERIC(oc);
    136     gen->font_set = font_set;
    137 
    138     font_set->font_data_count = data->font_data_count;
    139     font_set->font_data = data->font_data;
    140 
    141     return True;
    142 }
    143 
    144 static char *
    145 get_prop_name(
    146     Display *dpy,
    147     XFontStruct	*fs)
    148 {
    149     unsigned long fp;
    150 
    151     if (XGetFontProperty(fs, XA_FONT, &fp))
    152 	return XGetAtomName(dpy, fp);
    153 
    154     return (char *) NULL;
    155 }
    156 
    157 static FontData
    158 check_charset(
    159     FontSet font_set,
    160     char *font_name)
    161 {
    162     FontData font_data;
    163     char *last;
    164     int count;
    165     ssize_t length, name_len;
    166 
    167     name_len = (ssize_t) strlen(font_name);
    168     last = font_name + name_len;
    169 
    170     count = font_set->font_data_count;
    171     font_data = font_set->font_data;
    172 
    173     for ( ; count-- > 0; font_data++) {
    174 	length = (ssize_t) strlen(font_data->name);
    175 
    176 	if (length > name_len)
    177 	    return(NULL);
    178 
    179 	if (_XlcCompareISOLatin1(last - length, font_data->name) == 0)
    180 	    return font_data;
    181     }
    182     return (FontData) NULL;
    183 }
    184 
    185 static Bool
    186 load_font(
    187     XOC oc)
    188 {
    189     Display *dpy = oc->core.om->core.display;
    190     XOCGenericPart *gen = XOC_GENERIC(oc);
    191     FontSet font_set = gen->font_set;
    192 
    193     if (font_set->font_name == NULL)
    194 	return False;
    195 
    196     if (font_set->font == NULL) {
    197 	font_set->font = XLoadQueryFont(dpy, font_set->font_name);
    198 	if (font_set->font == NULL)
    199 	    return False;
    200     }
    201     return True;
    202 }
    203 
    204 static void
    205 set_fontset_extents(
    206     XOC oc)
    207 {
    208     XRectangle *ink = &oc->core.font_set_extents.max_ink_extent;
    209     XRectangle *logical = &oc->core.font_set_extents.max_logical_extent;
    210     XFontStruct **font_list, *font;
    211     XCharStruct overall;
    212     int logical_ascent, logical_descent;
    213 
    214     font_list = oc->core.font_info.font_struct_list;
    215     font = *font_list++;
    216     overall = font->max_bounds;
    217     overall.lbearing = font->min_bounds.lbearing;
    218     logical_ascent = font->ascent;
    219     logical_descent = font->descent;
    220 
    221     ink->x = overall.lbearing;
    222     ink->y = -(overall.ascent);
    223     ink->width = overall.rbearing - overall.lbearing;
    224     ink->height = overall.ascent + overall.descent;
    225 
    226     logical->x = 0;
    227     logical->y = -(logical_ascent);
    228     logical->width = overall.width;
    229     logical->height = logical_ascent + logical_descent;
    230 }
    231 
    232 static Bool
    233 init_core_part(
    234     XOC oc)
    235 {
    236     XOCGenericPart *gen = XOC_GENERIC(oc);
    237     FontSet font_set;
    238     XFontStruct **font_struct_list;
    239     char **font_name_list, *font_name_buf;
    240 
    241     font_set = gen->font_set;
    242 
    243     if (font_set->font_name == NULL)
    244         return False;
    245 
    246     font_struct_list = Xmalloc(sizeof(XFontStruct *));
    247     if (font_struct_list == NULL)
    248 	return False;
    249 
    250     font_name_list = Xmalloc(sizeof(char *));
    251     if (font_name_list == NULL)
    252 	goto err;
    253 
    254     font_name_buf = strdup(font_set->font_name);
    255     if (font_name_buf == NULL)
    256 	goto err;
    257 
    258     oc->core.font_info.num_font = 1;
    259     oc->core.font_info.font_name_list = font_name_list;
    260     oc->core.font_info.font_struct_list = font_struct_list;
    261 
    262     font_set->id = 1;
    263     if (font_set->font)
    264         *font_struct_list = font_set->font;
    265     else
    266         *font_struct_list = font_set->info;
    267     Xfree(font_set->font_name);
    268     *font_name_list = font_set->font_name = font_name_buf;
    269 
    270     set_fontset_extents(oc);
    271 
    272     return True;
    273 
    274 err:
    275 
    276     Xfree(font_name_list);
    277     Xfree(font_struct_list);
    278 
    279     return False;
    280 }
    281 
    282 static char *
    283 get_font_name(
    284     XOC oc,
    285     char *pattern)
    286 {
    287     char **list, *name;
    288     int count;
    289     XFontStruct *fs;
    290     Display *dpy = oc->core.om->core.display;
    291 
    292     list = XListFonts(dpy, pattern, 1, &count);
    293     if (list != NULL) {
    294 	name = strdup(*list);
    295 
    296 	XFreeFontNames(list);
    297     } else {
    298 	fs = XLoadQueryFont(dpy, pattern);
    299 	if (fs == NULL) return NULL;
    300 
    301 	name = get_prop_name(dpy, fs);
    302 	XFreeFont(dpy, fs);
    303     }
    304     return name;
    305 }
    306 
    307 static int
    308 parse_fontname(
    309     XOC oc)
    310 {
    311     XOCGenericPart *gen = XOC_GENERIC(oc);
    312     FontSet font_set;
    313     FontData font_data;
    314     char *pattern, *last, buf[BUFSIZ];
    315     int font_data_count, found_num = 0;
    316     ssize_t length;
    317     int count, num_fields;
    318     char *base_name, *font_name, **name_list, **cur_name_list;
    319     char *charset_p = NULL;
    320     Bool append_charset;
    321     /*
    322        append_charset flag should be set to True when the XLFD fontname
    323        doesn't contain a chaset part.
    324      */
    325 
    326     name_list = _XParseBaseFontNameList(oc->core.base_name_list, &count);
    327     if (name_list == NULL)
    328 	return -1;
    329     cur_name_list = name_list;
    330 
    331     while (count-- > 0) {
    332         pattern = *cur_name_list++;
    333 	if (pattern == NULL || *pattern == '\0')
    334 	    continue;
    335 
    336 	append_charset = False;
    337 
    338 	if (strchr(pattern, '*') == NULL &&
    339 	    (font_name = get_font_name(oc, pattern))) {
    340 
    341 	    font_set = gen->font_set;
    342 
    343 	    font_data = check_charset(font_set, font_name);
    344 	    if (font_data == NULL) {
    345 		Display *dpy = oc->core.om->core.display;
    346 		char **fn_list = NULL, *prop_fname = NULL;
    347 		int list_num;
    348 		XFontStruct *fs_list;
    349 		if ((fn_list = XListFontsWithInfo(dpy, font_name,
    350 						  MAXFONTS,
    351 						  &list_num, &fs_list))
    352 		    && (prop_fname = get_prop_name(dpy, fs_list))
    353 		    && (font_data = check_charset(font_set, prop_fname))) {
    354 		    if (fn_list) {
    355 			XFreeFontInfo(fn_list, fs_list, list_num);
    356 			fn_list = NULL;
    357 		    }
    358 		    font_name = prop_fname;
    359 		}
    360 	    }
    361 	    if (font_data == NULL)
    362 		continue;
    363 
    364 	    font_set->font_name = strdup(font_name);
    365 	    Xfree(font_name);
    366 	    if (font_set->font_name == NULL) {
    367 		goto err;
    368 	    }
    369 	    found_num++;
    370 	    goto found;
    371 	}
    372 
    373 	strncpy(buf, pattern, BUFSIZ);
    374 	buf[BUFSIZ-1] = '\0';
    375 	length = (ssize_t) strlen(buf);
    376 	last = buf + length - 1;
    377 
    378 	for (num_fields = 0, base_name = buf; *base_name != '\0'; base_name++)
    379 	    if (*base_name == '-') num_fields++;
    380 	if (strchr(pattern, '*') == NULL) {
    381 	    if (num_fields == 12) {
    382 		append_charset = True;
    383 		*++last = '-';
    384 		last++;
    385 	    } else
    386 		continue;
    387 	} else {
    388 	    if (num_fields == 13 || num_fields == 14) {
    389 	    /*
    390 	     * There are 14 fields in an XLFD name -- make certain the
    391 	     * charset (& encoding) is placed in the correct field.
    392 	     */
    393 		append_charset = True;
    394 		last = strrchr (buf, '-');
    395 		if (num_fields == 14) {
    396 		    *last = '\0';
    397 		    last = strrchr (buf, '-');
    398 		}
    399 		last++;
    400 	    } else if (*last == '*') {
    401 		append_charset = True;
    402 		if (length > 3 && *(last-3) == '-' && *(last-2) == '*'
    403 		    && *(last-1) == '-') {
    404 		    last -= 2;
    405 		}
    406 		*++last = '-';
    407 		last++;
    408 	    } else {
    409 		last = strrchr (buf, '-');
    410 		charset_p = last;
    411 		charset_p = strrchr (buf, '-');
    412 		while (*(--charset_p) != '-');
    413 		charset_p++;
    414 	    }
    415 	}
    416 
    417 	font_set = gen->font_set;
    418 
    419 	font_data = font_set->font_data;
    420 	font_data_count = font_set->font_data_count;
    421 	for ( ; font_data_count-- > 0; font_data++) {
    422 	    if (append_charset)
    423 		{
    424 		strncpy(last, font_data->name, (size_t) (BUFSIZ - length));
    425 		buf[BUFSIZ-1] = '\0';
    426 		}
    427 	    else {
    428 		if (_XlcCompareISOLatin1(charset_p,
    429 					 font_data->name)) {
    430 		    continue;
    431 		}
    432 	    }
    433 	    if ((font_set->font_name = get_font_name(oc, buf)))
    434 		break;
    435 	}
    436 	if (font_set->font_name != NULL) {
    437 	    found_num++;
    438 	    goto found;
    439 	}
    440     }
    441   found:
    442     base_name = strdup(oc->core.base_name_list);
    443     if (base_name == NULL)
    444 	goto err;
    445 
    446     oc->core.base_name_list = base_name;
    447 
    448     XFreeStringList(name_list);
    449 
    450     return found_num;
    451 err:
    452     XFreeStringList(name_list);
    453 
    454     return -1;
    455 }
    456 
    457 static Bool
    458 set_missing_list(
    459     XOC oc)
    460 {
    461     XOCGenericPart *gen = XOC_GENERIC(oc);
    462     FontSet font_set;
    463     char **charset_list, *charset_buf;
    464 
    465     font_set = gen->font_set;
    466 
    467     if (font_set->info == NULL || font_set->font == NULL)
    468 	return True;
    469 
    470     charset_list = Xmalloc(sizeof(char *));
    471     if (charset_list == NULL)
    472 	return False;
    473 
    474     charset_buf = strdup(font_set->font_data->name);
    475     if (charset_buf == NULL) {
    476 	Xfree(charset_list);
    477 	return False;
    478     }
    479 
    480     oc->core.missing_list.charset_list = charset_list;
    481 
    482     *charset_list = charset_buf;
    483 
    484     return True;
    485 }
    486 
    487 static Bool
    488 create_fontset(
    489     XOC oc)
    490 {
    491     int found_num;
    492 
    493     if (init_fontset(oc) == False)
    494         return False;
    495 
    496     found_num = parse_fontname(oc);
    497     if (found_num <= 0) {
    498 	if (found_num == 0)
    499 	    set_missing_list(oc);
    500 	return False;
    501     }
    502 
    503     if (load_font(oc) == False)
    504 	return False;
    505 
    506     if (init_core_part(oc) == False)
    507 	return False;
    508 
    509     if (set_missing_list(oc) == False)
    510 	return False;
    511 
    512     return True;
    513 }
    514 
    515 static void
    516 destroy_oc(
    517     XOC oc)
    518 {
    519     Display *dpy = oc->core.om->core.display;
    520     XOCGenericPart *gen = XOC_GENERIC(oc);
    521     XFontStruct **font_list, *font;
    522 
    523 
    524     Xfree(gen->font_set);
    525     Xfree(oc->core.base_name_list);
    526     XFreeStringList(oc->core.font_info.font_name_list);
    527 
    528     if ((font_list = oc->core.font_info.font_struct_list)) {
    529 	if ((font = *font_list)) {
    530 	    if (font->fid)
    531 		XFreeFont(dpy, font);
    532 	    else
    533 		XFreeFontInfo(NULL, font, 1);
    534 	}
    535 	Xfree(oc->core.font_info.font_struct_list);
    536     }
    537 
    538 
    539     XFreeStringList(oc->core.missing_list.charset_list);
    540 
    541 #ifdef notdef
    542     Xfree(oc->core.res_name);
    543     Xfree(oc->core.res_class);
    544 #endif
    545 
    546     Xfree(oc);
    547 }
    548 
    549 static char *
    550 set_oc_values(
    551     XOC oc,
    552     XlcArgList args,
    553     int num_args)
    554 {
    555     if (oc->core.resources == NULL)
    556 	return NULL;
    557 
    558     return _XlcSetValues((XPointer) oc, oc->core.resources,
    559 			 oc->core.num_resources, args, num_args, XlcSetMask);
    560 }
    561 
    562 static char *
    563 get_oc_values(
    564     XOC oc,
    565     XlcArgList args,
    566     int num_args)
    567 {
    568     if (oc->core.resources == NULL)
    569 	return NULL;
    570 
    571     return _XlcGetValues((XPointer) oc, oc->core.resources,
    572 			 oc->core.num_resources, args, num_args, XlcGetMask);
    573 }
    574 
    575 static Bool
    576 wcs_to_mbs(
    577     XOC oc,
    578     char *to,
    579     _Xconst wchar_t *from,
    580     int length)
    581 {
    582     XlcConv conv = XOC_GENERIC(oc)->wcs_to_cs;
    583     XLCd lcd;
    584     int ret, to_left = length;
    585 
    586     if (conv == NULL) {
    587 	lcd = oc->core.om->core.lcd;
    588 	conv = _XlcOpenConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte);
    589 	if (conv == NULL)
    590 	    return False;
    591 	XOC_GENERIC(oc)->wcs_to_cs = conv;
    592     } else
    593 	_XlcResetConverter(conv);
    594 
    595     ret = _XlcConvert(conv, (XPointer *) &from, &length, (XPointer *) &to,
    596 		      &to_left, NULL, 0);
    597     if (ret != 0 || length > 0)
    598 	return False;
    599 
    600     return True;
    601 }
    602 
    603 static int
    604 _XmbDefaultTextEscapement(XOC oc, _Xconst char *text, int length)
    605 {
    606     return XTextWidth(*oc->core.font_info.font_struct_list, text, length);
    607 }
    608 
    609 static int
    610 _XwcDefaultTextEscapement(XOC oc, _Xconst wchar_t *text, int length)
    611 {
    612     DefineLocalBuf;
    613     char *buf = AllocLocalBuf(length);
    614     int ret = 0;
    615 
    616     if (buf == NULL)
    617 	return 0;
    618 
    619     if (wcs_to_mbs(oc, buf, text, length) == False)
    620 	goto err;
    621 
    622     ret = _XmbDefaultTextEscapement(oc, buf, length);
    623 
    624 err:
    625     FreeLocalBuf(buf);
    626 
    627     return ret;
    628 }
    629 
    630 static int
    631 _XmbDefaultTextExtents(XOC oc, _Xconst char *text, int length,
    632 		       XRectangle *overall_ink, XRectangle *overall_logical)
    633 {
    634     int direction, logical_ascent, logical_descent;
    635     XCharStruct overall;
    636 
    637     XTextExtents(*oc->core.font_info.font_struct_list, text, length, &direction,
    638 		 &logical_ascent, &logical_descent, &overall);
    639 
    640     if (overall_ink) {
    641 	overall_ink->x = overall.lbearing;
    642 	overall_ink->y = -(overall.ascent);
    643 	overall_ink->width = overall.rbearing - overall.lbearing;
    644 	overall_ink->height = overall.ascent + overall.descent;
    645     }
    646 
    647     if (overall_logical) {
    648 	overall_logical->x = 0;
    649         overall_logical->y = -(logical_ascent);
    650 	overall_logical->width = overall.width;
    651         overall_logical->height = logical_ascent + logical_descent;
    652     }
    653 
    654     return overall.width;
    655 }
    656 
    657 static int
    658 _XwcDefaultTextExtents(XOC oc, _Xconst wchar_t *text, int length,
    659 		       XRectangle *overall_ink, XRectangle *overall_logical)
    660 {
    661     DefineLocalBuf;
    662     char *buf = AllocLocalBuf(length);
    663     int ret = 0;
    664 
    665     if (buf == NULL)
    666 	return 0;
    667 
    668     if (wcs_to_mbs(oc, buf, text, length) == False)
    669 	goto err;
    670 
    671     ret = _XmbDefaultTextExtents(oc, buf, length, overall_ink, overall_logical);
    672 
    673 err:
    674     FreeLocalBuf(buf);
    675 
    676     return ret;
    677 }
    678 
    679 static Status
    680 _XmbDefaultTextPerCharExtents(XOC oc, _Xconst char *text, int length,
    681 			      XRectangle *ink_buf, XRectangle *logical_buf,
    682 			      int buf_size, int *num_chars,
    683 			      XRectangle *overall_ink,
    684 			      XRectangle *overall_logical)
    685 {
    686     XFontStruct *font = *oc->core.font_info.font_struct_list;
    687     XCharStruct *def, *cs, overall;
    688     Bool first = True;
    689 
    690     if (buf_size < length)
    691 	return 0;
    692 
    693     bzero((char *) &overall, sizeof(XCharStruct));
    694     *num_chars = 0;
    695 
    696     CI_GET_DEFAULT_INFO_1D(font, def);
    697 
    698     while (length-- > 0) {
    699 	CI_GET_CHAR_INFO_1D(font, *text, def, cs);
    700 	text++;
    701 	if (cs == NULL)
    702 	    continue;
    703 
    704 	ink_buf->x = overall.width + cs->lbearing;
    705 	ink_buf->y = -(cs->ascent);
    706 	ink_buf->width = cs->rbearing - cs->lbearing;
    707 	ink_buf->height = cs->ascent + cs->descent;
    708 	ink_buf++;
    709 
    710 	logical_buf->x = overall.width;
    711 	logical_buf->y = -(font->ascent);
    712 	logical_buf->width = cs->width;
    713 	logical_buf->height = font->ascent + font->descent;
    714 	logical_buf++;
    715 
    716 	if (first) {
    717 	    overall = *cs;
    718 	    first = False;
    719 	} else {
    720 	    overall.ascent = max(overall.ascent, cs->ascent);
    721 	    overall.descent = max(overall.descent, cs->descent);
    722 	    overall.lbearing = min(overall.lbearing, overall.width +
    723 				   cs->lbearing);
    724 	    overall.rbearing = max(overall.rbearing, overall.width +
    725 				   cs->rbearing);
    726 	    overall.width += cs->width;
    727 	}
    728    	(*num_chars)++;
    729     }
    730 
    731     if (overall_ink) {
    732 	overall_ink->x = overall.lbearing;
    733 	overall_ink->y = -(overall.ascent);
    734 	overall_ink->width = overall.rbearing - overall.lbearing;
    735 	overall_ink->height = overall.ascent + overall.descent;
    736     }
    737 
    738     if (overall_logical) {
    739 	overall_logical->x = 0;
    740 	overall_logical->y = -(font->ascent);
    741 	overall_logical->width = overall.width;
    742 	overall_logical->height = font->ascent + font->descent;
    743     }
    744 
    745     return 1;
    746 }
    747 
    748 static Status
    749 _XwcDefaultTextPerCharExtents(XOC oc, _Xconst wchar_t *text, int length,
    750 			      XRectangle *ink_buf, XRectangle *logical_buf,
    751 			      int buf_size, int *num_chars,
    752 			      XRectangle *overall_ink,
    753 			      XRectangle *overall_logical)
    754 {
    755     DefineLocalBuf;
    756     char *buf = AllocLocalBuf(length);
    757     Status ret = 0;
    758 
    759     if (buf == NULL)
    760 	return 0;
    761 
    762     if (wcs_to_mbs(oc, buf, text, length) == False)
    763 	goto err;
    764 
    765     ret = _XmbDefaultTextPerCharExtents(oc, buf, length, ink_buf, logical_buf,
    766 					buf_size, num_chars, overall_ink,
    767 					overall_logical);
    768 
    769 err:
    770     FreeLocalBuf(buf);
    771 
    772     return ret;
    773 }
    774 
    775 static int
    776 _XmbDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
    777 		      _Xconst char *text, int length)
    778 {
    779     XFontStruct *font = *oc->core.font_info.font_struct_list;
    780 
    781     XSetFont(dpy, gc, font->fid);
    782     XDrawString(dpy, d, gc, x, y, text, length);
    783 
    784     return XTextWidth(font, text, length);
    785 }
    786 
    787 static int
    788 _XwcDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
    789 		      _Xconst wchar_t *text, int length)
    790 {
    791     DefineLocalBuf;
    792     char *buf = AllocLocalBuf(length);
    793     int ret = 0;
    794 
    795     if (buf == NULL)
    796 	return 0;
    797 
    798     if (wcs_to_mbs(oc, buf, text, length) == False)
    799 	goto err;
    800 
    801     ret = _XmbDefaultDrawString(dpy, d, oc, gc, x, y, buf, length);
    802 
    803 err:
    804     FreeLocalBuf(buf);
    805 
    806     return ret;
    807 }
    808 
    809 static void
    810 _XmbDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
    811 			   int y, _Xconst char *text, int length)
    812 {
    813     XSetFont(dpy, gc, (*oc->core.font_info.font_struct_list)->fid);
    814     XDrawImageString(dpy, d, gc, x, y, text, length);
    815 }
    816 
    817 static void
    818 _XwcDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
    819 			   int y, _Xconst wchar_t *text, int length)
    820 {
    821     DefineLocalBuf;
    822     char *buf = AllocLocalBuf(length);
    823 
    824     if (buf == NULL)
    825 	return;
    826 
    827     if (wcs_to_mbs(oc, buf, text, length) == False)
    828 	goto err;
    829 
    830     _XmbDefaultDrawImageString(dpy, d, oc, gc, x, y, buf, length);
    831 
    832 err:
    833     FreeLocalBuf(buf);
    834 }
    835 
    836 static _Xconst XOCMethodsRec oc_default_methods = {
    837     destroy_oc,
    838     set_oc_values,
    839     get_oc_values,
    840     _XmbDefaultTextEscapement,
    841     _XmbDefaultTextExtents,
    842     _XmbDefaultTextPerCharExtents,
    843     _XmbDefaultDrawString,
    844     _XmbDefaultDrawImageString,
    845     _XwcDefaultTextEscapement,
    846     _XwcDefaultTextExtents,
    847     _XwcDefaultTextPerCharExtents,
    848     _XwcDefaultDrawString,
    849     _XwcDefaultDrawImageString
    850 };
    851 
    852 static XlcResource oc_resources[] = {
    853     { XNBaseFontName, NULLQUARK, sizeof(char *),
    854       XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask },
    855     { XNOMAutomatic, NULLQUARK, sizeof(Bool),
    856       XOffsetOf(XOCRec, core.om_automatic), XlcGetMask },
    857     { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList),
    858       XOffsetOf(XOCRec, core.missing_list), XlcGetMask },
    859     { XNDefaultString, NULLQUARK, sizeof(char *),
    860       XOffsetOf(XOCRec, core.default_string), XlcGetMask },
    861     { XNOrientation, NULLQUARK, sizeof(XOrientation),
    862       XOffsetOf(XOCRec, core.orientation), XlcSetMask | XlcGetMask },
    863     { XNResourceName, NULLQUARK, sizeof(char *),
    864       XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask },
    865     { XNResourceClass, NULLQUARK, sizeof(char *),
    866       XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask },
    867     { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo),
    868       XOffsetOf(XOCRec, core.font_info), XlcGetMask }
    869 };
    870 
    871 static XOC
    872 create_oc(
    873     XOM om,
    874     XlcArgList args,
    875     int num_args)
    876 {
    877     XOC oc;
    878 
    879     oc = Xcalloc(1, sizeof(XOCGenericRec));
    880     if (oc == NULL)
    881 	return (XOC) NULL;
    882 
    883     oc->core.om = om;
    884 
    885     if (oc_resources[0].xrm_name == NULLQUARK)
    886 	_XlcCompileResourceList(oc_resources, XlcNumber(oc_resources));
    887 
    888     if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources),
    889 		      args, num_args, XlcCreateMask | XlcDefaultMask))
    890 	goto err;
    891 
    892     if (oc->core.base_name_list == NULL)
    893 	goto err;
    894 
    895     oc->core.resources = oc_resources;
    896     oc->core.num_resources = XlcNumber(oc_resources);
    897 
    898     if (create_fontset(oc) == False)
    899 	goto err;
    900 
    901     oc->methods = (XOCMethods)&oc_default_methods;
    902 
    903     return oc;
    904 
    905 err:
    906     destroy_oc(oc);
    907 
    908     return (XOC) NULL;
    909 }
    910 
    911 static Status
    912 close_om(
    913     XOM om)
    914 {
    915     XOMGenericPart *gen = XOM_GENERIC(om);
    916     OMData data;
    917     FontData font_data;
    918     int count;
    919 
    920     if ((data = gen->data)) {
    921 	if (data->font_data) {
    922 	  for (font_data = data->font_data, count = data->font_data_count;
    923 	       count-- > 0 ; font_data++) {
    924 		Xfree(font_data->name);
    925 	  }
    926 	  Xfree(data->font_data);
    927 	}
    928 	Xfree(gen->data);
    929     }
    930 
    931 
    932     Xfree(om->core.res_name);
    933     Xfree(om->core.res_class);
    934 
    935     if (om->core.required_charset.charset_list)
    936 	XFreeStringList(om->core.required_charset.charset_list);
    937     else
    938 	Xfree((char*)om->core.required_charset.charset_list);
    939 
    940     Xfree(om->core.orientation_list.orientation);
    941     Xfree(om);
    942 
    943     return 1;
    944 }
    945 
    946 static char *
    947 set_om_values(
    948     XOM om,
    949     XlcArgList args,
    950     int num_args)
    951 {
    952     if (om->core.resources == NULL)
    953 	return NULL;
    954 
    955     return _XlcSetValues((XPointer) om, om->core.resources,
    956 			 om->core.num_resources, args, num_args, XlcSetMask);
    957 }
    958 
    959 static char *
    960 get_om_values(
    961     XOM om,
    962     XlcArgList args,
    963     int num_args)
    964 {
    965     if (om->core.resources == NULL)
    966 	return NULL;
    967 
    968     return _XlcGetValues((XPointer) om, om->core.resources,
    969 			 om->core.num_resources, args, num_args, XlcGetMask);
    970 }
    971 
    972 static _Xconst XOMMethodsRec methods = {
    973     close_om,
    974     set_om_values,
    975     get_om_values,
    976     create_oc
    977 };
    978 
    979 static XlcResource om_resources[] = {
    980     { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList),
    981       XOffsetOf(XOMRec, core.required_charset), XlcGetMask },
    982     { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation),
    983       XOffsetOf(XOMRec, core.orientation_list), XlcGetMask },
    984     { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool),
    985       XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask },
    986     { XNContextualDrawing, NULLQUARK, sizeof(Bool),
    987       XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask }
    988 };
    989 
    990 static OMData
    991 add_data(
    992     XOM om)
    993 {
    994     XOMGenericPart *gen = XOM_GENERIC(om);
    995     OMData new;
    996 
    997     new = Xcalloc(1, sizeof(OMDataRec));
    998 
    999     if (new == NULL)
   1000         return NULL;
   1001 
   1002     gen->data = new;
   1003 
   1004     return new;
   1005 }
   1006 
   1007 static _Xconst char *supported_charset_list[] = {
   1008     "ISO8859-1",
   1009     "adobe-fontspecific",
   1010     "SUNOLCURSOR-1",
   1011     "SUNOLGLYPH-1"
   1012 };
   1013 
   1014 static Bool
   1015 init_om(
   1016     XOM om)
   1017 {
   1018     XOMGenericPart *gen = XOM_GENERIC(om);
   1019     OMData data;
   1020     FontData font_data;
   1021     char **required_list;
   1022     XOrientation *orientation;
   1023     char *bufptr;
   1024     int i, count;
   1025 
   1026     count = XlcNumber(supported_charset_list);
   1027 
   1028     data = add_data(om);
   1029     if (data == NULL)
   1030 	return False;
   1031 
   1032     font_data = Xcalloc(count, sizeof(FontDataRec));
   1033     if (font_data == NULL)
   1034 	return False;
   1035     data->font_data = font_data;
   1036     data->font_data_count = count;
   1037 
   1038     for (i = 0; i < count; i++, font_data++) {
   1039 	font_data->name = strdup(supported_charset_list[i]);
   1040 	if (font_data->name == NULL)
   1041 	    return False;
   1042     }
   1043 
   1044     /* required charset list */
   1045     required_list = Xmalloc(sizeof(char *));
   1046     if (required_list == NULL)
   1047 	return False;
   1048 
   1049     bufptr = strdup(data->font_data->name);
   1050     if (bufptr == NULL) {
   1051 	Xfree(required_list);
   1052 	return False;
   1053     }
   1054 
   1055     om->core.required_charset.charset_list = required_list;
   1056     om->core.required_charset.charset_count = 1; /* always 1 */
   1057 
   1058     data = gen->data;
   1059 
   1060     *required_list = bufptr;
   1061 
   1062     /* orientation list */
   1063     orientation = Xmalloc(sizeof(XOrientation));
   1064     if (orientation == NULL)
   1065 	return False;
   1066 
   1067     *orientation = XOMOrientation_LTR_TTB;
   1068     om->core.orientation_list.orientation = orientation;
   1069     om->core.orientation_list.num_orientation = 1;
   1070 
   1071     /* directional dependent drawing */
   1072     om->core.directional_dependent = False;
   1073 
   1074     /* contextual drawing */
   1075     om->core.contextual_drawing = False;
   1076 
   1077     /* context dependent */
   1078     om->core.context_dependent = False;
   1079 
   1080     return True;
   1081 }
   1082 
   1083 XOM
   1084 _XDefaultOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb,
   1085 		_Xconst char *res_name, _Xconst char *res_class)
   1086 {
   1087     XOM om;
   1088 
   1089     om = Xcalloc(1, sizeof(XOMGenericRec));
   1090     if (om == NULL)
   1091 	return (XOM) NULL;
   1092 
   1093     om->methods = (XOMMethods)&methods;
   1094     om->core.lcd = lcd;
   1095     om->core.display = dpy;
   1096     om->core.rdb = rdb;
   1097     if (res_name) {
   1098 	om->core.res_name = strdup(res_name);
   1099 	if (om->core.res_name == NULL)
   1100 	    goto err;
   1101     }
   1102     if (res_class) {
   1103 	om->core.res_class = strdup(res_class);
   1104 	if (om->core.res_class == NULL)
   1105 	    goto err;
   1106     }
   1107 
   1108     if (om_resources[0].xrm_name == NULLQUARK)
   1109 	_XlcCompileResourceList(om_resources, XlcNumber(om_resources));
   1110 
   1111     om->core.resources = om_resources;
   1112     om->core.num_resources = XlcNumber(om_resources);
   1113 
   1114     if (init_om(om) == False)
   1115 	goto err;
   1116 
   1117     return om;
   1118 err:
   1119     close_om(om);
   1120 
   1121     return (XOM) NULL;
   1122 }
   1123