XDefaultOMIF.c revision 818534a1
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    if (font_name_list)
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    if (gen->font_set)
640	Xfree(gen->font_set);
641
642    if (oc->core.base_name_list)
643	Xfree(oc->core.base_name_list);
644
645    if (oc->core.font_info.font_name_list)
646	XFreeStringList(oc->core.font_info.font_name_list);
647
648    if ((font_list = oc->core.font_info.font_struct_list)) {
649	if ((font = *font_list)) {
650	    if (font->fid)
651		XFreeFont(dpy, font);
652	    else
653		XFreeFontInfo(NULL, font, 1);
654	}
655	Xfree(oc->core.font_info.font_struct_list);
656    }
657
658    if (oc->core.missing_list.charset_list)
659	XFreeStringList(oc->core.missing_list.charset_list);
660
661#ifdef notdef
662    if (oc->core.res_name)
663	Xfree(oc->core.res_name);
664    if (oc->core.res_class)
665	Xfree(oc->core.res_class);
666#endif
667
668    Xfree(oc);
669}
670
671static char *
672set_oc_values(
673    XOC oc,
674    XlcArgList args,
675    int num_args)
676{
677    if (oc->core.resources == NULL)
678	return NULL;
679
680    return _XlcSetValues((XPointer) oc, oc->core.resources,
681			 oc->core.num_resources, args, num_args, XlcSetMask);
682}
683
684static char *
685get_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 _XlcGetValues((XPointer) oc, oc->core.resources,
694			 oc->core.num_resources, args, num_args, XlcGetMask);
695}
696
697static Bool
698wcs_to_mbs(
699    XOC oc,
700    char *to,
701    _Xconst wchar_t *from,
702    int length)
703{
704    XlcConv conv = XOC_GENERIC(oc)->wcs_to_cs;
705    XLCd lcd;
706    int ret, to_left = length;
707
708    if (conv == NULL) {
709	lcd = oc->core.om->core.lcd;
710	conv = _XlcOpenConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte);
711	if (conv == NULL)
712	    return False;
713	XOC_GENERIC(oc)->wcs_to_cs = conv;
714    } else
715	_XlcResetConverter(conv);
716
717    ret = _XlcConvert(conv, (XPointer *) &from, &length, (XPointer *) &to,
718		      &to_left, NULL, 0);
719    if (ret != 0 || length > 0)
720	return False;
721
722    return True;
723}
724
725static int
726_XmbDefaultTextEscapement(XOC oc, _Xconst char *text, int length)
727{
728    return XTextWidth(*oc->core.font_info.font_struct_list, text, length);
729}
730
731static int
732_XwcDefaultTextEscapement(XOC oc, _Xconst wchar_t *text, int length)
733{
734    DefineLocalBuf;
735    char *buf = AllocLocalBuf(length);
736    int ret = 0;
737
738    if (buf == NULL)
739	return 0;
740
741    if (wcs_to_mbs(oc, buf, text, length) == False)
742	goto err;
743
744    ret = _XmbDefaultTextEscapement(oc, buf, length);
745
746err:
747    FreeLocalBuf(buf);
748
749    return ret;
750}
751
752static int
753_XmbDefaultTextExtents(XOC oc, _Xconst char *text, int length,
754		       XRectangle *overall_ink, XRectangle *overall_logical)
755{
756    int direction, logical_ascent, logical_descent;
757    XCharStruct overall;
758
759    XTextExtents(*oc->core.font_info.font_struct_list, text, length, &direction,
760		 &logical_ascent, &logical_descent, &overall);
761
762    if (overall_ink) {
763	overall_ink->x = overall.lbearing;
764	overall_ink->y = -(overall.ascent);
765	overall_ink->width = overall.rbearing - overall.lbearing;
766	overall_ink->height = overall.ascent + overall.descent;
767    }
768
769    if (overall_logical) {
770	overall_logical->x = 0;
771        overall_logical->y = -(logical_ascent);
772	overall_logical->width = overall.width;
773        overall_logical->height = logical_ascent + logical_descent;
774    }
775
776    return overall.width;
777}
778
779static int
780_XwcDefaultTextExtents(XOC oc, _Xconst wchar_t *text, int length,
781		       XRectangle *overall_ink, XRectangle *overall_logical)
782{
783    DefineLocalBuf;
784    char *buf = AllocLocalBuf(length);
785    int ret = 0;
786
787    if (buf == NULL)
788	return 0;
789
790    if (wcs_to_mbs(oc, buf, text, length) == False)
791	goto err;
792
793    ret = _XmbDefaultTextExtents(oc, buf, length, overall_ink, overall_logical);
794
795err:
796    FreeLocalBuf(buf);
797
798    return ret;
799}
800
801static Status
802_XmbDefaultTextPerCharExtents(XOC oc, _Xconst char *text, int length,
803			      XRectangle *ink_buf, XRectangle *logical_buf,
804			      int buf_size, int *num_chars,
805			      XRectangle *overall_ink,
806			      XRectangle *overall_logical)
807{
808    XFontStruct *font = *oc->core.font_info.font_struct_list;
809    XCharStruct *def, *cs, overall;
810    Bool first = True;
811
812    if (buf_size < length)
813	return 0;
814
815    bzero((char *) &overall, sizeof(XCharStruct));
816    *num_chars = 0;
817
818    CI_GET_DEFAULT_INFO_1D(font, def)
819
820    while (length-- > 0) {
821	CI_GET_CHAR_INFO_1D(font, *text, def, cs)
822	text++;
823	if (cs == NULL)
824	    continue;
825
826	ink_buf->x = overall.width + cs->lbearing;
827	ink_buf->y = -(cs->ascent);
828	ink_buf->width = cs->rbearing - cs->lbearing;
829	ink_buf->height = cs->ascent + cs->descent;
830	ink_buf++;
831
832	logical_buf->x = overall.width;
833	logical_buf->y = -(font->ascent);
834	logical_buf->width = cs->width;
835	logical_buf->height = font->ascent + font->descent;
836	logical_buf++;
837
838	if (first) {
839	    overall = *cs;
840	    first = False;
841	} else {
842	    overall.ascent = max(overall.ascent, cs->ascent);
843	    overall.descent = max(overall.descent, cs->descent);
844	    overall.lbearing = min(overall.lbearing, overall.width +
845				   cs->lbearing);
846	    overall.rbearing = max(overall.rbearing, overall.width +
847				   cs->rbearing);
848	    overall.width += cs->width;
849	}
850   	(*num_chars)++;
851    }
852
853    if (overall_ink) {
854	overall_ink->x = overall.lbearing;
855	overall_ink->y = -(overall.ascent);
856	overall_ink->width = overall.rbearing - overall.lbearing;
857	overall_ink->height = overall.ascent + overall.descent;
858    }
859
860    if (overall_logical) {
861	overall_logical->x = 0;
862	overall_logical->y = -(font->ascent);
863	overall_logical->width = overall.width;
864	overall_logical->height = font->ascent + font->descent;
865    }
866
867    return 1;
868}
869
870static Status
871_XwcDefaultTextPerCharExtents(XOC oc, _Xconst wchar_t *text, int length,
872			      XRectangle *ink_buf, XRectangle *logical_buf,
873			      int buf_size, int *num_chars,
874			      XRectangle *overall_ink,
875			      XRectangle *overall_logical)
876{
877    DefineLocalBuf;
878    char *buf = AllocLocalBuf(length);
879    Status ret = 0;
880
881    if (buf == NULL)
882	return 0;
883
884    if (wcs_to_mbs(oc, buf, text, length) == False)
885	goto err;
886
887    ret = _XmbDefaultTextPerCharExtents(oc, buf, length, ink_buf, logical_buf,
888					buf_size, num_chars, overall_ink,
889					overall_logical);
890
891err:
892    FreeLocalBuf(buf);
893
894    return ret;
895}
896
897static int
898_XmbDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
899		      _Xconst char *text, int length)
900{
901    XFontStruct *font = *oc->core.font_info.font_struct_list;
902
903    XSetFont(dpy, gc, font->fid);
904    XDrawString(dpy, d, gc, x, y, text, length);
905
906    return XTextWidth(font, text, length);
907}
908
909static int
910_XwcDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
911		      _Xconst wchar_t *text, int length)
912{
913    DefineLocalBuf;
914    char *buf = AllocLocalBuf(length);
915    int ret = 0;
916
917    if (buf == NULL)
918	return 0;
919
920    if (wcs_to_mbs(oc, buf, text, length) == False)
921	goto err;
922
923    ret = _XmbDefaultDrawString(dpy, d, oc, gc, x, y, buf, length);
924
925err:
926    FreeLocalBuf(buf);
927
928    return ret;
929}
930
931static void
932_XmbDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
933			   int y, _Xconst char *text, int length)
934{
935    XSetFont(dpy, gc, (*oc->core.font_info.font_struct_list)->fid);
936    XDrawImageString(dpy, d, gc, x, y, text, length);
937}
938
939static void
940_XwcDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
941			   int y, _Xconst wchar_t *text, int length)
942{
943    DefineLocalBuf;
944    char *buf = AllocLocalBuf(length);
945
946    if (buf == NULL)
947	return;
948
949    if (wcs_to_mbs(oc, buf, text, length) == False)
950	goto err;
951
952    _XmbDefaultDrawImageString(dpy, d, oc, gc, x, y, buf, length);
953
954err:
955    FreeLocalBuf(buf);
956}
957
958static _Xconst XOCMethodsRec oc_default_methods = {
959    destroy_oc,
960    set_oc_values,
961    get_oc_values,
962    _XmbDefaultTextEscapement,
963    _XmbDefaultTextExtents,
964    _XmbDefaultTextPerCharExtents,
965    _XmbDefaultDrawString,
966    _XmbDefaultDrawImageString,
967    _XwcDefaultTextEscapement,
968    _XwcDefaultTextExtents,
969    _XwcDefaultTextPerCharExtents,
970    _XwcDefaultDrawString,
971    _XwcDefaultDrawImageString
972};
973
974static XlcResource oc_resources[] = {
975    { XNBaseFontName, NULLQUARK, sizeof(char *),
976      XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask },
977    { XNOMAutomatic, NULLQUARK, sizeof(Bool),
978      XOffsetOf(XOCRec, core.om_automatic), XlcGetMask },
979    { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList),
980      XOffsetOf(XOCRec, core.missing_list), XlcGetMask },
981    { XNDefaultString, NULLQUARK, sizeof(char *),
982      XOffsetOf(XOCRec, core.default_string), XlcGetMask },
983    { XNOrientation, NULLQUARK, sizeof(XOrientation),
984      XOffsetOf(XOCRec, core.orientation), XlcSetMask | XlcGetMask },
985    { XNResourceName, NULLQUARK, sizeof(char *),
986      XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask },
987    { XNResourceClass, NULLQUARK, sizeof(char *),
988      XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask },
989    { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo),
990      XOffsetOf(XOCRec, core.font_info), XlcGetMask }
991};
992
993static XOC
994create_oc(
995    XOM om,
996    XlcArgList args,
997    int num_args)
998{
999    XOC oc;
1000
1001    oc = Xcalloc(1, sizeof(XOCGenericRec));
1002    if (oc == NULL)
1003	return (XOC) NULL;
1004
1005    oc->core.om = om;
1006
1007    if (oc_resources[0].xrm_name == NULLQUARK)
1008	_XlcCompileResourceList(oc_resources, XlcNumber(oc_resources));
1009
1010    if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources),
1011		      args, num_args, XlcCreateMask | XlcDefaultMask))
1012	goto err;
1013
1014    if (oc->core.base_name_list == NULL)
1015	goto err;
1016
1017    oc->core.resources = oc_resources;
1018    oc->core.num_resources = XlcNumber(oc_resources);
1019
1020    if (create_fontset(oc) == False)
1021	goto err;
1022
1023    oc->methods = (XOCMethods)&oc_default_methods;
1024
1025    return oc;
1026
1027err:
1028    destroy_oc(oc);
1029
1030    return (XOC) NULL;
1031}
1032
1033static Status
1034close_om(
1035    XOM om)
1036{
1037    XOMGenericPart *gen = XOM_GENERIC(om);
1038    OMData data;
1039    FontData font_data;
1040    int count;
1041
1042    if ((data = gen->data)) {
1043	if (data->font_data) {
1044	  for (font_data = data->font_data, count = data->font_data_count;
1045	       count-- > 0 ; font_data++) {
1046	    if (font_data->name)
1047		Xfree(font_data->name);
1048	  }
1049	  Xfree(data->font_data);
1050	}
1051	Xfree(gen->data);
1052    }
1053
1054    if (om->core.res_name)
1055	Xfree(om->core.res_name);
1056    if (om->core.res_class)
1057	Xfree(om->core.res_class);
1058    if (om->core.required_charset.charset_list)
1059	XFreeStringList(om->core.required_charset.charset_list);
1060    else
1061	Xfree((char*)om->core.required_charset.charset_list);
1062    if (om->core.orientation_list.orientation)
1063	Xfree(om->core.orientation_list.orientation);
1064
1065    Xfree(om);
1066
1067    return 1;
1068}
1069
1070static char *
1071set_om_values(
1072    XOM om,
1073    XlcArgList args,
1074    int num_args)
1075{
1076    if (om->core.resources == NULL)
1077	return NULL;
1078
1079    return _XlcSetValues((XPointer) om, om->core.resources,
1080			 om->core.num_resources, args, num_args, XlcSetMask);
1081}
1082
1083static char *
1084get_om_values(
1085    XOM om,
1086    XlcArgList args,
1087    int num_args)
1088{
1089    if (om->core.resources == NULL)
1090	return NULL;
1091
1092    return _XlcGetValues((XPointer) om, om->core.resources,
1093			 om->core.num_resources, args, num_args, XlcGetMask);
1094}
1095
1096static _Xconst XOMMethodsRec methods = {
1097    close_om,
1098    set_om_values,
1099    get_om_values,
1100    create_oc
1101};
1102
1103static XlcResource om_resources[] = {
1104    { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList),
1105      XOffsetOf(XOMRec, core.required_charset), XlcGetMask },
1106    { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation),
1107      XOffsetOf(XOMRec, core.orientation_list), XlcGetMask },
1108    { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool),
1109      XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask },
1110    { XNContextualDrawing, NULLQUARK, sizeof(Bool),
1111      XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask }
1112};
1113
1114static OMData
1115add_data(
1116    XOM om)
1117{
1118    XOMGenericPart *gen = XOM_GENERIC(om);
1119    OMData new;
1120
1121    new = Xcalloc(1, sizeof(OMDataRec));
1122
1123    if (new == NULL)
1124        return NULL;
1125
1126    gen->data = new;
1127
1128    return new;
1129}
1130
1131static _Xconst char *supported_charset_list[] = {
1132    "ISO8859-1",
1133/* fix for bug4332979 */
1134    "adobe-fontspecific",
1135/* fix for bug4237353: "JISX0201.1976-0" entry should be removed from
1136   supported_charset_list because it is not a supported_charset for C locale
1137    "JISX0201.1976-0", */
1138    "SUNOLCURSOR-1",
1139    "SUNOLGLYPH-1"
1140};
1141
1142static Bool
1143init_om(
1144    XOM om)
1145{
1146    XOMGenericPart *gen = XOM_GENERIC(om);
1147    OMData data;
1148    FontData font_data;
1149    char **required_list;
1150    XOrientation *orientation;
1151    char *bufptr;
1152    int i, count, length = 0;
1153
1154    count = XlcNumber(supported_charset_list);
1155
1156    data = add_data(om);
1157    if (data == NULL)
1158	return False;
1159
1160    font_data = Xcalloc(count, sizeof(FontDataRec));
1161    if (font_data == NULL)
1162	return False;
1163    data->font_data = font_data;
1164    data->font_data_count = count;
1165
1166    for (i = 0; i < count; i++, font_data++) {
1167	font_data->name = strdup(supported_charset_list[i]);
1168	if (font_data->name == NULL)
1169	    return False;
1170    }
1171
1172    length += strlen(data->font_data->name) + 1;
1173
1174    /* required charset list */
1175    required_list = Xmalloc(sizeof(char *));
1176    if (required_list == NULL)
1177	return False;
1178
1179    bufptr = Xmalloc(length);
1180    if (bufptr == NULL) {
1181	Xfree(required_list);
1182	return False;
1183    }
1184
1185    om->core.required_charset.charset_list = required_list;
1186    om->core.required_charset.charset_count = 1; /* always 1 */
1187
1188    data = gen->data;
1189
1190    strcpy(bufptr, data->font_data->name);
1191    *required_list++ = bufptr;
1192    bufptr += strlen(bufptr) + 1;
1193
1194    /* orientation list */
1195    orientation = Xmalloc(sizeof(XOrientation));
1196    if (orientation == NULL)
1197	return False;
1198
1199    *orientation = XOMOrientation_LTR_TTB;
1200    om->core.orientation_list.orientation = orientation;
1201    om->core.orientation_list.num_orientation = 1;
1202
1203    /* directional dependent drawing */
1204    om->core.directional_dependent = False;
1205
1206    /* contexual drawing */
1207    om->core.contextual_drawing = False;
1208
1209    /* context dependent */
1210    om->core.context_dependent = False;
1211
1212    return True;
1213}
1214
1215XOM
1216_XDefaultOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb,
1217		_Xconst char *res_name, _Xconst char *res_class)
1218{
1219    XOM om;
1220
1221    om = Xcalloc(1, sizeof(XOMGenericRec));
1222    if (om == NULL)
1223	return (XOM) NULL;
1224
1225    om->methods = (XOMMethods)&methods;
1226    om->core.lcd = lcd;
1227    om->core.display = dpy;
1228    om->core.rdb = rdb;
1229    if (res_name) {
1230	om->core.res_name = strdup(res_name);
1231	if (om->core.res_name == NULL)
1232	    goto err;
1233    }
1234    if (res_class) {
1235	om->core.res_class = strdup(res_class);
1236	if (om->core.res_class == NULL)
1237	    goto err;
1238    }
1239
1240    if (om_resources[0].xrm_name == NULLQUARK)
1241	_XlcCompileResourceList(om_resources, XlcNumber(om_resources));
1242
1243    om->core.resources = om_resources;
1244    om->core.num_resources = XlcNumber(om_resources);
1245
1246    if (init_om(om) == False)
1247	goto err;
1248
1249    return om;
1250err:
1251    close_om(om);
1252
1253    return (XOM) NULL;
1254}
1255