XDefaultOMIF.c revision e9fcaa8a
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 ? (char *)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 = (FontSet) Xmalloc(sizeof(FontSetRec));
132    if (font_set == NULL)
133	return False;
134    bzero((char *) font_set, sizeof(FontSetRec));
135
136    gen = XOC_GENERIC(oc);
137    gen->font_set = font_set;
138
139    font_set->font_data_count = data->font_data_count;
140    font_set->font_data = data->font_data;
141
142    return True;
143}
144
145static char *
146get_prop_name(
147    Display *dpy,
148    XFontStruct	*fs)
149{
150    unsigned long fp;
151
152    if (XGetFontProperty(fs, XA_FONT, &fp))
153	return XGetAtomName(dpy, fp);
154
155    return (char *) NULL;
156}
157
158static FontData
159check_charset(
160    FontSet font_set,
161    char *font_name)
162{
163    FontData font_data;
164    char *last;
165    int count;
166    ssize_t length, name_len;
167
168    name_len = strlen(font_name);
169    last = font_name + name_len;
170
171    count = font_set->font_data_count;
172    font_data = font_set->font_data;
173
174    for ( ; count-- > 0; font_data++) {
175	length = strlen(font_data->name);
176
177	if (length > name_len)
178	    return(NULL);
179
180	if (_XlcCompareISOLatin1(last - length, font_data->name) == 0)
181	    return font_data;
182    }
183    return (FontData) NULL;
184}
185
186#if 0 /* Unused */
187static int
188check_fontname(
189    XOC oc,
190    char *name)
191{
192    Display *dpy = oc->core.om->core.display;
193    XOCGenericPart *gen = XOC_GENERIC(oc);
194    FontData data;
195    FontSet font_set;
196    XFontStruct *fs_list;
197    char **fn_list, *fname, *prop_fname = NULL;
198    int list_num, i;
199    int list2_num;
200    char **fn2_list = NULL;
201    int found_num = 0;
202
203    fn_list = XListFonts(dpy, name, MAXFONTS, &list_num);
204    if (fn_list == NULL)
205	return found_num;
206
207    for (i = 0; i < list_num; i++) {
208	fname = fn_list[i];
209
210	font_set = gen->font_set;
211
212	if ((data = check_charset(font_set, fname)) == NULL) {
213	    if ((fn2_list = XListFontsWithInfo(dpy, name, MAXFONTS,
214					       &list2_num, &fs_list))
215		&& (prop_fname = get_prop_name(dpy, fs_list))
216		&& (data = check_charset(font_set, prop_fname)))
217		fname = prop_fname;
218	}
219	if (data) {
220	    font_set->font_name = (char *) Xmalloc(strlen(fname) + 1);
221	    if (font_set->font_name) {
222		strcpy(font_set->font_name, fname);
223		found_num++;
224	    }
225	}
226	if (fn2_list) {
227	    XFreeFontInfo(fn2_list, fs_list, list2_num);
228	    fn2_list = NULL;
229	    if (prop_fname) {
230		Xfree(prop_fname);
231		prop_fname = NULL;
232	    }
233	}
234	if (found_num == 1)
235	    break;
236    }
237    XFreeFontNames(fn_list);
238    return found_num;
239}
240#endif
241
242static Bool
243load_font(
244    XOC oc)
245{
246    Display *dpy = oc->core.om->core.display;
247    XOCGenericPart *gen = XOC_GENERIC(oc);
248    FontSet font_set = gen->font_set;
249
250    if (font_set->font_name == NULL)
251	return False;
252
253    if (font_set->font == NULL) {
254	font_set->font = XLoadQueryFont(dpy, font_set->font_name);
255	if (font_set->font == NULL)
256	    return False;
257    }
258    return True;
259}
260
261#if 0
262static Bool
263load_font_info(
264    XOC oc)
265{
266    Display *dpy = oc->core.om->core.display;
267    XOCGenericPart *gen = XOC_GENERIC(oc);
268    FontSet font_set = gen->font_set;
269    char **fn_list;
270    int fn_num;
271
272    if (font_set->font_name == NULL)
273	return False;
274
275    if (font_set->info == NULL) {
276	fn_list = XListFontsWithInfo(dpy, font_set->font_name, 1, &fn_num,
277				     &font_set->info);
278	if (font_set->info == NULL)
279	    return False;
280	if (fn_num > 0)
281	    font_set->info->fid = XLoadFont(dpy, font_set->font_name);
282
283	if (fn_list) XFreeFontNames(fn_list);
284    }
285    return True;
286}
287#endif
288
289static void
290set_fontset_extents(
291    XOC oc)
292{
293    XRectangle *ink = &oc->core.font_set_extents.max_ink_extent;
294    XRectangle *logical = &oc->core.font_set_extents.max_logical_extent;
295    XFontStruct **font_list, *font;
296    XCharStruct overall;
297    int logical_ascent, logical_descent;
298
299    font_list = oc->core.font_info.font_struct_list;
300    font = *font_list++;
301    overall = font->max_bounds;
302    overall.lbearing = font->min_bounds.lbearing;
303    logical_ascent = font->ascent;
304    logical_descent = font->descent;
305
306    ink->x = overall.lbearing;
307    ink->y = -(overall.ascent);
308    ink->width = overall.rbearing - overall.lbearing;
309    ink->height = overall.ascent + overall.descent;
310
311    logical->x = 0;
312    logical->y = -(logical_ascent);
313    logical->width = overall.width;
314    logical->height = logical_ascent + logical_descent;
315}
316
317static Bool
318init_core_part(
319    XOC oc)
320{
321    XOCGenericPart *gen = XOC_GENERIC(oc);
322    FontSet font_set;
323    XFontStruct **font_struct_list;
324    char **font_name_list, *font_name_buf;
325    int	count, length;
326
327    font_set = gen->font_set;
328    count = length = 0;
329
330    if (font_set->font_name != NULL) {
331	length += strlen(font_set->font_name) + 1;
332	count++;
333    }
334    if (count == 0)
335        return False;
336
337    font_struct_list = (XFontStruct **) Xmalloc(sizeof(XFontStruct *));
338    if (font_struct_list == NULL)
339	return False;
340
341    font_name_list = (char **) Xmalloc(sizeof(char *));
342    if (font_name_list == NULL)
343	goto err;
344
345    font_name_buf = (char *) Xmalloc(length);
346    if (font_name_buf == NULL)
347	goto err;
348
349    oc->core.font_info.num_font = 1;
350    oc->core.font_info.font_name_list = font_name_list;
351    oc->core.font_info.font_struct_list = font_struct_list;
352
353    font_set = gen->font_set;
354
355    if (font_set->font_name != NULL) {
356	font_set->id = 1;
357	if (font_set->font)
358	    *font_struct_list++ = font_set->font;
359	else
360	    *font_struct_list++ = font_set->info;
361	strcpy(font_name_buf, font_set->font_name);
362	Xfree(font_set->font_name);
363	*font_name_list++ = font_set->font_name = font_name_buf;
364	font_name_buf += strlen(font_name_buf) + 1;
365    }
366
367    set_fontset_extents(oc);
368
369    return True;
370
371err:
372    if (font_name_list)
373	Xfree(font_name_list);
374    Xfree(font_struct_list);
375
376    return False;
377}
378
379static char *
380get_font_name(
381    XOC oc,
382    char *pattern)
383{
384    char **list, *name, *prop_name;
385    int count;
386    XFontStruct *fs;
387    Display *dpy = oc->core.om->core.display;
388
389    list = XListFonts(dpy, pattern, 1, &count);
390    if (list != NULL) {
391	name = (char *) Xmalloc(strlen(*list) + 1);
392	if (name)
393	    strcpy(name, *list);
394
395	XFreeFontNames(list);
396    } else {
397	fs = XLoadQueryFont(dpy, pattern);
398	if (fs == NULL) return NULL;
399
400	prop_name = get_prop_name(dpy, fs);
401	if (prop_name == NULL) return NULL;
402
403	name = (char*) Xmalloc(strlen(prop_name) + 1);
404	if (name)
405	    strcpy(name, prop_name);
406
407	XFreeFont(dpy, fs);
408    }
409    return name;
410}
411
412static int
413parse_fontname(
414    XOC oc)
415{
416    XOCGenericPart *gen = XOC_GENERIC(oc);
417    FontSet font_set;
418    FontData font_data;
419    char *pattern, *last, buf[BUFSIZ];
420    int font_data_count, found_num = 0;
421    ssize_t length;
422    int count, num_fields;
423    char *base_name, *font_name, **name_list, **cur_name_list;
424    char *charset_p = NULL;
425    Bool append_charset;
426    /*
427       append_charset flag should be set to True when the XLFD fontname
428       doesn't contain a chaset part.
429     */
430
431    name_list = _XParseBaseFontNameList(oc->core.base_name_list, &count);
432    if (name_list == NULL)
433	return -1;
434    cur_name_list = name_list;
435
436    while (count-- > 0) {
437        pattern = *cur_name_list++;
438	if (pattern == NULL || *pattern == '\0')
439	    continue;
440
441	append_charset = False;
442
443	if (strchr(pattern, '*') == NULL &&
444	    (font_name = get_font_name(oc, pattern))) {
445
446	    font_set = gen->font_set;
447
448	    font_data = check_charset(font_set, font_name);
449	    if (font_data == NULL) {
450		Display *dpy = oc->core.om->core.display;
451		char **fn_list = NULL, *prop_fname = NULL;
452		int list_num;
453		XFontStruct *fs_list;
454		if ((fn_list = XListFontsWithInfo(dpy, font_name,
455						  MAXFONTS,
456						  &list_num, &fs_list))
457		    && (prop_fname = get_prop_name(dpy, fs_list))
458		    && (font_data = check_charset(font_set, prop_fname))) {
459		    if (fn_list) {
460			XFreeFontInfo(fn_list, fs_list, list_num);
461			fn_list = NULL;
462		    }
463		    font_name = prop_fname;
464		}
465	    }
466	    if (font_data == NULL)
467		continue;
468
469	    font_set->font_name = (char *) Xmalloc(strlen(font_name) + 1);
470	    if (font_set->font_name == NULL) {
471		Xfree(font_name);
472		goto err;
473	    }
474	    strcpy(font_set->font_name, font_name);
475	    Xfree(font_name);
476	    found_num++;
477	    goto found;
478	}
479/*
4801266793
481Limit the length of the string copy to prevent stack corruption.
482	strcpy(buf, pattern);
483*/
484	strncpy(buf, pattern, BUFSIZ);
485	buf[BUFSIZ-1] = '\0';
486	length = strlen(buf);
487	last = buf + length - 1;
488
489	for (num_fields = 0, base_name = buf; *base_name != '\0'; base_name++)
490	    if (*base_name == '-') num_fields++;
491	if (strchr(pattern, '*') == NULL) {
492	    if (num_fields == 12) {
493		append_charset = True;
494		*++last = '-';
495		last++;
496	    } else
497		continue;
498	} else {
499	    if (num_fields == 13 || num_fields == 14) {
500	    /*
501	     * There are 14 fields in an XLFD name -- make certain the
502	     * charset (& encoding) is placed in the correct field.
503	     */
504		append_charset = True;
505		last = strrchr (buf, '-');
506		if (num_fields == 14) {
507		    *last = '\0';
508		    last = strrchr (buf, '-');
509		}
510		last++;
511	    } else if (*last == '*') {
512		append_charset = True;
513		if (length > 3 && *(last-3) == '-' && *(last-2) == '*'
514		    && *(last-1) == '-') {
515		    last -= 2;
516		}
517		*++last = '-';
518		last++;
519	    } else {
520		last = strrchr (buf, '-');
521		charset_p = last;
522		charset_p = strrchr (buf, '-');
523		while (*(--charset_p) != '-');
524		charset_p++;
525	    }
526	}
527
528	font_set = gen->font_set;
529
530	font_data = font_set->font_data;
531	font_data_count = font_set->font_data_count;
532	for ( ; font_data_count-- > 0; font_data++) {
533	    if (append_charset)
534		{
535/*
5361266793
537Limit the length of the string copy to prevent stack corruption.
538		strcpy(last, font_data->name);
539*/
540		strncpy(last, font_data->name, BUFSIZ - length);
541		buf[BUFSIZ-1] = '\0';
542		}
543	    else {
544		if (_XlcCompareISOLatin1(charset_p,
545					 font_data->name)) {
546		    continue;
547		}
548	    }
549	    if ((font_set->font_name = get_font_name(oc, buf)))
550		break;
551	}
552	if (font_set->font_name != NULL) {
553	    found_num++;
554	    goto found;
555	}
556    }
557  found:
558    base_name = (char *) Xmalloc(strlen(oc->core.base_name_list) + 1);
559    if (base_name == NULL)
560	goto err;
561
562    strcpy(base_name, oc->core.base_name_list);
563    oc->core.base_name_list = base_name;
564
565    XFreeStringList(name_list);
566
567    return found_num;
568err:
569    XFreeStringList(name_list);
570
571    return -1;
572}
573
574static Bool
575set_missing_list(
576    XOC oc)
577{
578    XOCGenericPart *gen = XOC_GENERIC(oc);
579    FontSet font_set;
580    char **charset_list, *charset_buf;
581    int	count, length;
582
583    font_set = gen->font_set;
584    count = length = 0;
585
586    if (!font_set->info && !font_set->font) {
587	length += strlen(font_set->font_data->name) + 1;
588	count++;
589    }
590
591    if (count == 0)
592	return True;
593
594    charset_list = (char **) Xmalloc(sizeof(char *));
595    if (charset_list == NULL)
596	return False;
597
598    charset_buf = (char *) Xmalloc(length);
599    if (charset_buf == NULL) {
600	Xfree(charset_list);
601	return False;
602    }
603
604    oc->core.missing_list.charset_list = charset_list;
605
606    font_set = gen->font_set;
607
608    if (!font_set->info && !font_set->font) {
609	strcpy(charset_buf, font_set->font_data->name);
610	*charset_list++ = charset_buf;
611	charset_buf += strlen(charset_buf) + 1;
612    }
613    return True;
614}
615
616static Bool
617create_fontset(
618    XOC oc)
619{
620    int found_num;
621
622    if (init_fontset(oc) == False)
623        return False;
624
625    found_num = parse_fontname(oc);
626    if (found_num <= 0) {
627	if (found_num == 0)
628	    set_missing_list(oc);
629	return False;
630    }
631
632    if (load_font(oc) == False)
633	return False;
634
635    if (init_core_part(oc) == False)
636	return False;
637
638    if (set_missing_list(oc) == False)
639	return False;
640
641    return True;
642}
643
644static void
645destroy_oc(
646    XOC oc)
647{
648    Display *dpy = oc->core.om->core.display;
649    XOCGenericPart *gen = XOC_GENERIC(oc);
650    XFontStruct **font_list, *font;
651
652    if (gen->font_set)
653	Xfree(gen->font_set);
654
655    if (oc->core.base_name_list)
656	Xfree(oc->core.base_name_list);
657
658    if (oc->core.font_info.font_name_list)
659	XFreeStringList(oc->core.font_info.font_name_list);
660
661    if ((font_list = oc->core.font_info.font_struct_list)) {
662	if ((font = *font_list)) {
663	    if (font->fid)
664		XFreeFont(dpy, font);
665	    else
666		XFreeFontInfo(NULL, font, 1);
667	}
668	Xfree(oc->core.font_info.font_struct_list);
669    }
670
671    if (oc->core.missing_list.charset_list)
672	XFreeStringList(oc->core.missing_list.charset_list);
673
674#ifdef notdef
675    if (oc->core.res_name)
676	Xfree(oc->core.res_name);
677    if (oc->core.res_class)
678	Xfree(oc->core.res_class);
679#endif
680
681    Xfree(oc);
682}
683
684static char *
685set_oc_values(
686    XOC oc,
687    XlcArgList args,
688    int num_args)
689{
690    if (oc->core.resources == NULL)
691	return NULL;
692
693    return _XlcSetValues((XPointer) oc, oc->core.resources,
694			 oc->core.num_resources, args, num_args, XlcSetMask);
695}
696
697static char *
698get_oc_values(
699    XOC oc,
700    XlcArgList args,
701    int num_args)
702{
703    if (oc->core.resources == NULL)
704	return NULL;
705
706    return _XlcGetValues((XPointer) oc, oc->core.resources,
707			 oc->core.num_resources, args, num_args, XlcGetMask);
708}
709
710static Bool
711wcs_to_mbs(
712    XOC oc,
713    char *to,
714    _Xconst wchar_t *from,
715    int length)
716{
717    XlcConv conv = XOC_GENERIC(oc)->wcs_to_cs;
718    XLCd lcd;
719    int ret, to_left = length;
720
721    if (conv == NULL) {
722	lcd = oc->core.om->core.lcd;
723	conv = _XlcOpenConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte);
724	if (conv == NULL)
725	    return False;
726	XOC_GENERIC(oc)->wcs_to_cs = conv;
727    } else
728	_XlcResetConverter(conv);
729
730    ret = _XlcConvert(conv, (XPointer *) &from, &length, (XPointer *) &to,
731		      &to_left, NULL, 0);
732    if (ret != 0 || length > 0)
733	return False;
734
735    return True;
736}
737
738static int
739_XmbDefaultTextEscapement(XOC oc, _Xconst char *text, int length)
740{
741    return XTextWidth(*oc->core.font_info.font_struct_list, text, length);
742}
743
744static int
745_XwcDefaultTextEscapement(XOC oc, _Xconst wchar_t *text, int length)
746{
747    DefineLocalBuf;
748    char *buf = AllocLocalBuf(length);
749    int ret = 0;
750
751    if (buf == NULL)
752	return 0;
753
754    if (wcs_to_mbs(oc, buf, text, length) == False)
755	goto err;
756
757    ret = _XmbDefaultTextEscapement(oc, buf, length);
758
759err:
760    FreeLocalBuf(buf);
761
762    return ret;
763}
764
765static int
766_XmbDefaultTextExtents(XOC oc, _Xconst char *text, int length,
767		       XRectangle *overall_ink, XRectangle *overall_logical)
768{
769    int direction, logical_ascent, logical_descent;
770    XCharStruct overall;
771
772    XTextExtents(*oc->core.font_info.font_struct_list, text, length, &direction,
773		 &logical_ascent, &logical_descent, &overall);
774
775    if (overall_ink) {
776	overall_ink->x = overall.lbearing;
777	overall_ink->y = -(overall.ascent);
778	overall_ink->width = overall.rbearing - overall.lbearing;
779	overall_ink->height = overall.ascent + overall.descent;
780    }
781
782    if (overall_logical) {
783	overall_logical->x = 0;
784        overall_logical->y = -(logical_ascent);
785	overall_logical->width = overall.width;
786        overall_logical->height = logical_ascent + logical_descent;
787    }
788
789    return overall.width;
790}
791
792static int
793_XwcDefaultTextExtents(XOC oc, _Xconst wchar_t *text, int length,
794		       XRectangle *overall_ink, XRectangle *overall_logical)
795{
796    DefineLocalBuf;
797    char *buf = AllocLocalBuf(length);
798    int ret = 0;
799
800    if (buf == NULL)
801	return 0;
802
803    if (wcs_to_mbs(oc, buf, text, length) == False)
804	goto err;
805
806    ret = _XmbDefaultTextExtents(oc, buf, length, overall_ink, overall_logical);
807
808err:
809    FreeLocalBuf(buf);
810
811    return ret;
812}
813
814static Status
815_XmbDefaultTextPerCharExtents(XOC oc, _Xconst char *text, int length,
816			      XRectangle *ink_buf, XRectangle *logical_buf,
817			      int buf_size, int *num_chars,
818			      XRectangle *overall_ink,
819			      XRectangle *overall_logical)
820{
821    XFontStruct *font = *oc->core.font_info.font_struct_list;
822    XCharStruct *def, *cs, overall;
823    Bool first = True;
824
825    if (buf_size < length)
826	return 0;
827
828    bzero((char *) &overall, sizeof(XCharStruct));
829    *num_chars = 0;
830
831    CI_GET_DEFAULT_INFO_1D(font, def)
832
833    while (length-- > 0) {
834	CI_GET_CHAR_INFO_1D(font, *text, def, cs)
835	text++;
836	if (cs == NULL)
837	    continue;
838
839	ink_buf->x = overall.width + cs->lbearing;
840	ink_buf->y = -(cs->ascent);
841	ink_buf->width = cs->rbearing - cs->lbearing;
842	ink_buf->height = cs->ascent + cs->descent;
843	ink_buf++;
844
845	logical_buf->x = overall.width;
846	logical_buf->y = -(font->ascent);
847	logical_buf->width = cs->width;
848	logical_buf->height = font->ascent + font->descent;
849	logical_buf++;
850
851	if (first) {
852	    overall = *cs;
853	    first = False;
854	} else {
855	    overall.ascent = max(overall.ascent, cs->ascent);
856	    overall.descent = max(overall.descent, cs->descent);
857	    overall.lbearing = min(overall.lbearing, overall.width +
858				   cs->lbearing);
859	    overall.rbearing = max(overall.rbearing, overall.width +
860				   cs->rbearing);
861	    overall.width += cs->width;
862	}
863   	(*num_chars)++;
864    }
865
866    if (overall_ink) {
867	overall_ink->x = overall.lbearing;
868	overall_ink->y = -(overall.ascent);
869	overall_ink->width = overall.rbearing - overall.lbearing;
870	overall_ink->height = overall.ascent + overall.descent;
871    }
872
873    if (overall_logical) {
874	overall_logical->x = 0;
875	overall_logical->y = -(font->ascent);
876	overall_logical->width = overall.width;
877	overall_logical->height = font->ascent + font->descent;
878    }
879
880    return 1;
881}
882
883static Status
884_XwcDefaultTextPerCharExtents(XOC oc, _Xconst wchar_t *text, int length,
885			      XRectangle *ink_buf, XRectangle *logical_buf,
886			      int buf_size, int *num_chars,
887			      XRectangle *overall_ink,
888			      XRectangle *overall_logical)
889{
890    DefineLocalBuf;
891    char *buf = AllocLocalBuf(length);
892    Status ret = 0;
893
894    if (buf == NULL)
895	return 0;
896
897    if (wcs_to_mbs(oc, buf, text, length) == False)
898	goto err;
899
900    ret = _XmbDefaultTextPerCharExtents(oc, buf, length, ink_buf, logical_buf,
901					buf_size, num_chars, overall_ink,
902					overall_logical);
903
904err:
905    FreeLocalBuf(buf);
906
907    return ret;
908}
909
910static int
911_XmbDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
912		      _Xconst char *text, int length)
913{
914    XFontStruct *font = *oc->core.font_info.font_struct_list;
915
916    XSetFont(dpy, gc, font->fid);
917    XDrawString(dpy, d, gc, x, y, text, length);
918
919    return XTextWidth(font, text, length);
920}
921
922static int
923_XwcDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
924		      _Xconst wchar_t *text, int length)
925{
926    DefineLocalBuf;
927    char *buf = AllocLocalBuf(length);
928    int ret = 0;
929
930    if (buf == NULL)
931	return 0;
932
933    if (wcs_to_mbs(oc, buf, text, length) == False)
934	goto err;
935
936    ret = _XmbDefaultDrawString(dpy, d, oc, gc, x, y, buf, length);
937
938err:
939    FreeLocalBuf(buf);
940
941    return ret;
942}
943
944static void
945_XmbDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
946			   int y, _Xconst char *text, int length)
947{
948    XSetFont(dpy, gc, (*oc->core.font_info.font_struct_list)->fid);
949    XDrawImageString(dpy, d, gc, x, y, text, length);
950}
951
952static void
953_XwcDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
954			   int y, _Xconst wchar_t *text, int length)
955{
956    DefineLocalBuf;
957    char *buf = AllocLocalBuf(length);
958
959    if (buf == NULL)
960	return;
961
962    if (wcs_to_mbs(oc, buf, text, length) == False)
963	goto err;
964
965    _XmbDefaultDrawImageString(dpy, d, oc, gc, x, y, buf, length);
966
967err:
968    FreeLocalBuf(buf);
969}
970
971static _Xconst XOCMethodsRec oc_default_methods = {
972    destroy_oc,
973    set_oc_values,
974    get_oc_values,
975    _XmbDefaultTextEscapement,
976    _XmbDefaultTextExtents,
977    _XmbDefaultTextPerCharExtents,
978    _XmbDefaultDrawString,
979    _XmbDefaultDrawImageString,
980    _XwcDefaultTextEscapement,
981    _XwcDefaultTextExtents,
982    _XwcDefaultTextPerCharExtents,
983    _XwcDefaultDrawString,
984    _XwcDefaultDrawImageString
985};
986
987static XlcResource oc_resources[] = {
988    { XNBaseFontName, NULLQUARK, sizeof(char *),
989      XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask },
990    { XNOMAutomatic, NULLQUARK, sizeof(Bool),
991      XOffsetOf(XOCRec, core.om_automatic), XlcGetMask },
992    { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList),
993      XOffsetOf(XOCRec, core.missing_list), XlcGetMask },
994    { XNDefaultString, NULLQUARK, sizeof(char *),
995      XOffsetOf(XOCRec, core.default_string), XlcGetMask },
996    { XNOrientation, NULLQUARK, sizeof(XOrientation),
997      XOffsetOf(XOCRec, core.orientation), XlcSetMask | XlcGetMask },
998    { XNResourceName, NULLQUARK, sizeof(char *),
999      XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask },
1000    { XNResourceClass, NULLQUARK, sizeof(char *),
1001      XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask },
1002    { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo),
1003      XOffsetOf(XOCRec, core.font_info), XlcGetMask }
1004};
1005
1006static XOC
1007create_oc(
1008    XOM om,
1009    XlcArgList args,
1010    int num_args)
1011{
1012    XOC oc;
1013
1014    oc = (XOC) Xmalloc(sizeof(XOCGenericRec));
1015    if (oc == NULL)
1016	return (XOC) NULL;
1017    bzero((char *) oc, sizeof(XOCGenericRec));
1018
1019    oc->core.om = om;
1020
1021    if (oc_resources[0].xrm_name == NULLQUARK)
1022	_XlcCompileResourceList(oc_resources, XlcNumber(oc_resources));
1023
1024    if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources),
1025		      args, num_args, XlcCreateMask | XlcDefaultMask))
1026	goto err;
1027
1028    if (oc->core.base_name_list == NULL)
1029	goto err;
1030
1031    oc->core.resources = oc_resources;
1032    oc->core.num_resources = XlcNumber(oc_resources);
1033
1034    if (create_fontset(oc) == False)
1035	goto err;
1036
1037    oc->methods = (XOCMethods)&oc_default_methods;
1038
1039    return oc;
1040
1041err:
1042    destroy_oc(oc);
1043
1044    return (XOC) NULL;
1045}
1046
1047static Status
1048close_om(
1049    XOM om)
1050{
1051    XOMGenericPart *gen = XOM_GENERIC(om);
1052    OMData data;
1053    FontData font_data;
1054    int count;
1055
1056    if ((data = gen->data)) {
1057	if (data->font_data) {
1058	  for (font_data = data->font_data, count = data->font_data_count;
1059	       count-- > 0 ; font_data++) {
1060	    if (font_data->name)
1061		Xfree(font_data->name);
1062	  }
1063	  Xfree(data->font_data);
1064	}
1065	Xfree(gen->data);
1066    }
1067
1068    if (om->core.res_name)
1069	Xfree(om->core.res_name);
1070    if (om->core.res_class)
1071	Xfree(om->core.res_class);
1072    if (om->core.required_charset.charset_list)
1073	XFreeStringList(om->core.required_charset.charset_list);
1074    else
1075	Xfree((char*)om->core.required_charset.charset_list);
1076    if (om->core.orientation_list.orientation)
1077	Xfree(om->core.orientation_list.orientation);
1078
1079    Xfree(om);
1080
1081    return 1;
1082}
1083
1084static char *
1085set_om_values(
1086    XOM om,
1087    XlcArgList args,
1088    int num_args)
1089{
1090    if (om->core.resources == NULL)
1091	return NULL;
1092
1093    return _XlcSetValues((XPointer) om, om->core.resources,
1094			 om->core.num_resources, args, num_args, XlcSetMask);
1095}
1096
1097static char *
1098get_om_values(
1099    XOM om,
1100    XlcArgList args,
1101    int num_args)
1102{
1103    if (om->core.resources == NULL)
1104	return NULL;
1105
1106    return _XlcGetValues((XPointer) om, om->core.resources,
1107			 om->core.num_resources, args, num_args, XlcGetMask);
1108}
1109
1110static _Xconst XOMMethodsRec methods = {
1111    close_om,
1112    set_om_values,
1113    get_om_values,
1114    create_oc
1115};
1116
1117static XlcResource om_resources[] = {
1118    { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList),
1119      XOffsetOf(XOMRec, core.required_charset), XlcGetMask },
1120    { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation),
1121      XOffsetOf(XOMRec, core.orientation_list), XlcGetMask },
1122    { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool),
1123      XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask },
1124    { XNContextualDrawing, NULLQUARK, sizeof(Bool),
1125      XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask }
1126};
1127
1128static OMData
1129add_data(
1130    XOM om)
1131{
1132    XOMGenericPart *gen = XOM_GENERIC(om);
1133    OMData new;
1134
1135    new = (OMData) Xmalloc(sizeof(OMDataRec));
1136
1137    if (new == NULL)
1138        return NULL;
1139
1140    gen->data = new;
1141
1142    bzero((char *) new, sizeof(OMDataRec));
1143
1144    return new;
1145}
1146
1147static _Xconst char *supported_charset_list[] = {
1148    "ISO8859-1",
1149/* fix for bug4332979 */
1150    "adobe-fontspecific",
1151/* fix for bug4237353: "JISX0201.1976-0" entry should be removed from
1152   supported_charset_list because it is not a supported_charset for C locale
1153    "JISX0201.1976-0", */
1154    "SUNOLCURSOR-1",
1155    "SUNOLGLYPH-1"
1156};
1157
1158static Bool
1159init_om(
1160    XOM om)
1161{
1162    XOMGenericPart *gen = XOM_GENERIC(om);
1163    OMData data;
1164    FontData font_data;
1165    char **required_list;
1166    XOrientation *orientation;
1167    char **value, buf[BUFSIZ], *bufptr;
1168    int count, length = 0;
1169
1170    value = (char**)supported_charset_list;
1171    count = XlcNumber(supported_charset_list);
1172
1173    data = add_data(om);
1174    if (data == NULL)
1175	return False;
1176
1177    font_data = (FontData) Xmalloc(sizeof(FontDataRec) * count);
1178    if (font_data == NULL)
1179	return False;
1180    bzero((char *) font_data, sizeof(FontDataRec) * count);
1181    data->font_data = font_data;
1182    data->font_data_count = count;
1183
1184    for ( ; count-- > 0; font_data++) {
1185/*
11861266793
1187This one is fine.  *value points to one of the local strings in
1188supported_charset_list[].
1189*/
1190	strcpy(buf, *value++);
1191	font_data->name = (char *) Xmalloc(strlen(buf) + 1);
1192	if (font_data->name == NULL)
1193	    return False;
1194	strcpy(font_data->name, buf);
1195    }
1196
1197    length += strlen(data->font_data->name) + 1;
1198
1199    /* required charset list */
1200    required_list = (char **) Xmalloc(sizeof(char *));
1201    if (required_list == NULL)
1202	return False;
1203
1204    bufptr = (char *) Xmalloc(length);
1205    if (bufptr == NULL) {
1206	Xfree(required_list);
1207	return False;
1208    }
1209
1210    om->core.required_charset.charset_list = required_list;
1211    om->core.required_charset.charset_count = 1; /* always 1 */
1212
1213    data = gen->data;
1214
1215    strcpy(bufptr, data->font_data->name);
1216    *required_list++ = bufptr;
1217    bufptr += strlen(bufptr) + 1;
1218
1219    /* orientation list */
1220    orientation = (XOrientation *) Xmalloc(sizeof(XOrientation));
1221    if (orientation == NULL)
1222	return False;
1223
1224    *orientation = XOMOrientation_LTR_TTB;
1225    om->core.orientation_list.orientation = orientation;
1226    om->core.orientation_list.num_orientation = 1;
1227
1228    /* directional dependent drawing */
1229    om->core.directional_dependent = False;
1230
1231    /* contexual drawing */
1232    om->core.contextual_drawing = False;
1233
1234    /* context dependent */
1235    om->core.context_dependent = False;
1236
1237    return True;
1238}
1239
1240XOM
1241_XDefaultOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb,
1242		_Xconst char *res_name, _Xconst char *res_class)
1243{
1244    XOM om;
1245
1246    om = (XOM) Xmalloc(sizeof(XOMGenericRec));
1247    if (om == NULL)
1248	return (XOM) NULL;
1249    bzero((char *) om, sizeof(XOMGenericRec));
1250
1251    om->methods = (XOMMethods)&methods;
1252    om->core.lcd = lcd;
1253    om->core.display = dpy;
1254    om->core.rdb = rdb;
1255    if (res_name) {
1256	om->core.res_name = (char *)Xmalloc(strlen(res_name) + 1);
1257	if (om->core.res_name == NULL)
1258	    goto err;
1259	strcpy(om->core.res_name, res_name);
1260    }
1261    if (res_class) {
1262	om->core.res_class = (char *)Xmalloc(strlen(res_class) + 1);
1263	if (om->core.res_class == NULL)
1264	    goto err;
1265	strcpy(om->core.res_class, res_class);
1266    }
1267
1268    if (om_resources[0].xrm_name == NULLQUARK)
1269	_XlcCompileResourceList(om_resources, XlcNumber(om_resources));
1270
1271    om->core.resources = om_resources;
1272    om->core.num_resources = XlcNumber(om_resources);
1273
1274    if (init_om(om) == False)
1275	goto err;
1276
1277    return om;
1278err:
1279    close_om(om);
1280
1281    return (XOM) NULL;
1282}
1283