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