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