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