omGeneric.c revision 2d67cb4f
1/*  #define FONTDEBUG */
2/*
3 * Copyright 1992, 1993 by TOSHIBA Corp.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation for any purpose and without fee is hereby granted, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of TOSHIBA not be used in advertising
10 * or publicity pertaining to distribution of the software without specific,
11 * written prior permission. TOSHIBA make no representations about the
12 * suitability of this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 *
15 * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 * SOFTWARE.
22 *
23 * Author: Katsuhisa Yano	TOSHIBA Corp.
24 *			   	mopi@osa.ilab.toshiba.co.jp
25 */
26/*
27 * Copyright 1995 by FUJITSU LIMITED
28 * This is source code modified by FUJITSU LIMITED under the Joint
29 * Development Agreement for the CDE/Motif PST.
30 *
31 * Modifier:  Takanori Tateno   FUJITSU LIMITED
32 *
33 */
34
35/*
36 * Fixed the algorithms in parse_fontname() and parse_fontdata()
37 * to improve the logic for determining which font should be
38 * returned for a given CharSet.  We even added some comments
39 * so that you can figure out what in the heck we're doing. We
40 * realize this is a departure from the norm, but hey, we're
41 * rebels! :-) :-)
42 *
43 * Modifiers: Jeff Walls, Paul Anderson: HEWLETT-PACKARD
44 */
45/*
46 * Cleaned up mess, removed some blabla
47 * Egbert Eich, SuSE Linux AG
48 */
49
50#ifdef HAVE_CONFIG_H
51#include <config.h>
52#endif
53#include "Xlibint.h"
54#include "XomGeneric.h"
55#include "XlcGeneric.h"
56#include <X11/Xos.h>
57#include <X11/Xatom.h>
58#include <stdio.h>
59#include <string.h>
60#include <ctype.h>
61
62#define MAXFONTS		100
63#define	PIXEL_SIZE_FIELD	 7
64#define	POINT_SIZE_FIELD	 8
65#define	CHARSET_ENCODING_FIELD	14
66#define XLFD_MAX_LEN		255
67
68/* For VW/UDC start */
69
70static FontData
71init_fontdata(
72    FontData	font_data,
73    int		font_data_count)
74{
75    FontData	fd;
76    int		i;
77
78    fd = Xcalloc(font_data_count, sizeof(FontDataRec));
79    if(fd == (FontData) NULL)
80	return False;
81
82    for(i = 0 ; i < font_data_count ; i++)
83	fd[i] = font_data[i];
84
85    return fd;
86}
87
88static VRotate
89init_vrotate(
90    FontData	font_data,
91    int		font_data_count,
92    int		type,
93    CodeRange	code_range,
94    int		code_range_num)
95{
96    VRotate	vrotate;
97    int		i;
98
99    if(type == VROTATE_NONE)
100	return (VRotate)NULL;
101
102    vrotate = Xcalloc(font_data_count, sizeof(VRotateRec));
103    if(vrotate == (VRotate) NULL)
104	return False;
105
106    for(i = 0 ; i < font_data_count ; i++) {
107	vrotate[i].charset_name = font_data[i].name;
108	vrotate[i].side = font_data[i].side;
109	if(type == VROTATE_PART) {
110	    vrotate[i].num_cr = code_range_num;
111	    vrotate[i].code_range = code_range;
112	}
113    }
114
115    return vrotate;
116}
117
118static Bool
119init_fontset(
120    XOC oc)
121{
122    XOCGenericPart *gen;
123    FontSet font_set;
124    OMData data;
125    int count;
126
127    count = XOM_GENERIC(oc->core.om)->data_num;
128    data = XOM_GENERIC(oc->core.om)->data;
129
130    font_set = Xcalloc(count, sizeof(FontSetRec));
131    if (font_set == NULL)
132	return False;
133
134    gen = XOC_GENERIC(oc);
135    gen->font_set_num = count;
136    gen->font_set = font_set;
137
138    for ( ; count-- > 0; data++, font_set++) {
139	font_set->charset_count = data->charset_count;
140	font_set->charset_list = data->charset_list;
141
142	if((font_set->font_data = init_fontdata(data->font_data,
143				  data->font_data_count)) == NULL)
144	    goto err;
145	font_set->font_data_count = data->font_data_count;
146	if((font_set->substitute = init_fontdata(data->substitute,
147				   data->substitute_num)) == NULL)
148	    goto err;
149	font_set->substitute_num = data->substitute_num;
150	if((font_set->vmap = init_fontdata(data->vmap,
151			     data->vmap_num)) == NULL)
152	    goto err;
153	font_set->vmap_num       = data->vmap_num;
154
155	if(data->vrotate_type != VROTATE_NONE) {
156	    /* A vrotate member is specified primary font data */
157	    /* as initial value.                               */
158	    if((font_set->vrotate = init_vrotate(data->font_data,
159						 data->font_data_count,
160						 data->vrotate_type,
161						 data->vrotate,
162						 data->vrotate_num)) == NULL)
163		goto err;
164	    font_set->vrotate_num = data->font_data_count;
165	}
166    }
167    return True;
168
169err:
170
171    Xfree(font_set->font_data);
172    Xfree(font_set->substitute);
173    Xfree(font_set->vmap);
174    Xfree(font_set->vrotate);
175    Xfree(font_set);
176    gen->font_set = (FontSet) NULL;
177    gen->font_set_num = 0;
178    return False;
179}
180
181/* For VW/UDC end */
182
183static char *
184get_prop_name(
185    Display *dpy,
186    XFontStruct	*fs)
187{
188    unsigned long fp;
189
190    if (XGetFontProperty(fs, XA_FONT, &fp))
191	return XGetAtomName(dpy, fp);
192
193    return (char *) NULL;
194}
195
196/* For VW/UDC start */
197
198static Bool
199load_fontdata(
200    XOC		oc,
201    FontData	font_data,
202    int		font_data_num)
203{
204    Display	*dpy = oc->core.om->core.display;
205    FontData	fd = font_data;
206
207    if(font_data == NULL) return(True);
208    for( ; font_data_num-- ; fd++) {
209	if(fd->xlfd_name != (char *) NULL && fd->font == NULL) {
210	    fd->font = XLoadQueryFont(dpy, fd->xlfd_name);
211	    if (fd->font == NULL){
212		return False;
213	    }
214	}
215    }
216    return True;
217}
218
219static Bool
220load_fontset_data(
221    XOC		oc,
222    FontSet	font_set)
223{
224    Display	*dpy = oc->core.om->core.display;
225
226    if(font_set->font_name == (char *)NULL) return False ;
227
228   /* If font_set->font is not NULL, it contains the *best*
229    * match font for this FontSet.
230    * -- jjw/pma (HP)
231    */
232    if(font_set->font == NULL) {
233       font_set->font = XLoadQueryFont(dpy, font_set->font_name);
234       if (font_set->font == NULL){
235		return False;
236       }
237    }
238    return True;
239}
240
241static Bool
242load_font(
243    XOC oc)
244{
245    XOCGenericPart *gen = XOC_GENERIC(oc);
246    FontSet font_set = gen->font_set;
247    int num = gen->font_set_num;
248
249    for ( ; num-- > 0; font_set++) {
250	if (font_set->font_name == NULL)
251	    continue;
252
253        if (load_fontset_data (oc, font_set) != True)
254	    return False;
255#ifndef TESTVERSION
256	if(load_fontdata(oc, font_set->font_data,
257			 font_set->font_data_count) != True)
258	    return False;
259
260	if(load_fontdata(oc, font_set->substitute,
261			 font_set->substitute_num) != True)
262	    return False;
263#endif
264
265/* Add 1996.05.20 */
266        if( oc->core.orientation == XOMOrientation_TTB_RTL ||
267            oc->core.orientation == XOMOrientation_TTB_LTR ){
268	    if (font_set->vpart_initialize == 0) {
269	       load_fontdata(oc, font_set->vmap, font_set->vmap_num);
270	       load_fontdata(oc, (FontData) font_set->vrotate,
271			 font_set->vrotate_num);
272                font_set->vpart_initialize = 1;
273	    }
274        }
275
276	if (font_set->font->min_byte1 || font_set->font->max_byte1)
277	    font_set->is_xchar2b = True;
278	else
279	    font_set->is_xchar2b = False;
280    }
281
282    return True;
283}
284
285/* For VW/UDC end */
286
287static Bool
288load_font_info(
289    XOC oc)
290{
291    Display *dpy = oc->core.om->core.display;
292    XOCGenericPart *gen = XOC_GENERIC(oc);
293    FontSet font_set = gen->font_set;
294    char **fn_list;
295    int fn_num, num = gen->font_set_num;
296
297    for ( ; num-- > 0; font_set++) {
298	if (font_set->font_name == NULL)
299	    continue;
300
301	if (font_set->info == NULL) {
302	    fn_list = XListFontsWithInfo(dpy, font_set->font_name, 1, &fn_num,
303					 &font_set->info);
304	    if (font_set->info == NULL)
305		return False;
306
307	    XFreeFontNames(fn_list);
308	}
309    }
310
311    return True;
312}
313
314/* For Vertical Writing start */
315
316static void
317check_fontset_extents(
318    XCharStruct		*overall,
319    int			*logical_ascent,
320    int                 *logical_descent,
321    XFontStruct		*font)
322{
323    overall->lbearing = min(overall->lbearing, font->min_bounds.lbearing);
324    overall->rbearing = max(overall->rbearing, font->max_bounds.rbearing);
325    overall->ascent   = max(overall->ascent,   font->max_bounds.ascent);
326    overall->descent  = max(overall->descent,  font->max_bounds.descent);
327    overall->width    = max(overall->width,    font->max_bounds.width);
328    *logical_ascent   = max(*logical_ascent,   font->ascent);
329    *logical_descent  = max(*logical_descent,  font->descent);
330}
331
332/* For Vertical Writing end */
333
334static void
335set_fontset_extents(
336    XOC oc)
337{
338    XRectangle *ink = &oc->core.font_set_extents.max_ink_extent;
339    XRectangle *logical = &oc->core.font_set_extents.max_logical_extent;
340    XFontStruct **font_list, *font;
341    XCharStruct overall;
342    int logical_ascent, logical_descent;
343    int	num = oc->core.font_info.num_font;
344
345    font_list = oc->core.font_info.font_struct_list;
346    font = *font_list++;
347    overall = font->max_bounds;
348    overall.lbearing = font->min_bounds.lbearing;
349    logical_ascent = font->ascent;
350    logical_descent = font->descent;
351
352    /* For Vertical Writing start */
353
354    while (--num > 0) {
355	font = *font_list++;
356	check_fontset_extents(&overall, &logical_ascent, &logical_descent,
357			      font);
358    }
359
360    {
361	XOCGenericPart  *gen = XOC_GENERIC(oc);
362	FontSet		font_set = gen->font_set;
363	FontData	font_data;
364	int		font_set_num = gen->font_set_num;
365	int		font_data_count;
366
367	for( ; font_set_num-- ; font_set++) {
368	    if(font_set->vmap_num > 0) {
369		font_data = font_set->vmap;
370		font_data_count = font_set->vmap_num;
371		for( ; font_data_count-- ; font_data++) {
372		    if(font_data->font != NULL) {
373			check_fontset_extents(&overall, &logical_ascent,
374					      &logical_descent,
375					      font_data->font);
376		    }
377		}
378	    }
379
380	    if(font_set->vrotate_num > 0 && font_set->vrotate != NULL) {
381		font_data = (FontData) font_set->vrotate;
382		font_data_count = font_set->vrotate_num;
383		for( ; font_data_count-- ; font_data++) {
384		    if(font_data->font != NULL) {
385			check_fontset_extents(&overall, &logical_ascent,
386					      &logical_descent,
387					      font_data->font);
388		    }
389		}
390	    }
391	}
392    }
393
394    /* For Vertical Writing start */
395
396    ink->x = overall.lbearing;
397    ink->y = -(overall.ascent);
398    ink->width = overall.rbearing - overall.lbearing;
399    ink->height = overall.ascent + overall.descent;
400
401    logical->x = 0;
402    logical->y = -(logical_ascent);
403    logical->width = overall.width;
404    logical->height = logical_ascent + logical_descent;
405}
406
407static Bool
408init_core_part(
409    XOC oc)
410{
411    XOCGenericPart *gen = XOC_GENERIC(oc);
412    FontSet font_set;
413    int font_set_num;
414    XFontStruct **font_struct_list;
415    char **font_name_list, *font_name_buf;
416    int	count, length;
417
418    font_set = gen->font_set;
419    font_set_num = gen->font_set_num;
420    count = length = 0;
421
422    for ( ; font_set_num-- > 0; font_set++) {
423	if (font_set->font_name == NULL)
424	    continue;
425
426	length += strlen(font_set->font_name) + 1;
427
428	count++;
429    }
430    if (count == 0)
431        return False;
432
433    font_struct_list = Xmalloc(sizeof(XFontStruct *) * count);
434    if (font_struct_list == NULL)
435	return False;
436
437    font_name_list = Xmalloc(sizeof(char *) * count);
438    if (font_name_list == NULL)
439	goto err;
440
441    font_name_buf = Xmalloc(length);
442    if (font_name_buf == NULL)
443	goto err;
444
445    oc->core.font_info.num_font = count;
446    oc->core.font_info.font_name_list = font_name_list;
447    oc->core.font_info.font_struct_list = font_struct_list;
448
449    font_set = gen->font_set;
450    font_set_num = gen->font_set_num;
451
452    for (count = 0; font_set_num-- > 0; font_set++) {
453	if (font_set->font_name == NULL)
454	    continue;
455
456	font_set->id = count;
457	if (font_set->font)
458	    *font_struct_list++ = font_set->font;
459	else
460	    *font_struct_list++ = font_set->info;
461	strcpy(font_name_buf, font_set->font_name);
462	Xfree(font_set->font_name);
463	*font_name_list++ = font_set->font_name = font_name_buf;
464	font_name_buf += strlen(font_name_buf) + 1;
465
466	count++;
467    }
468
469    set_fontset_extents(oc);
470
471    return True;
472
473err:
474
475    Xfree(font_name_list);
476    Xfree(font_struct_list);
477
478    return False;
479}
480
481static char *
482get_font_name(
483    XOC oc,
484    char *pattern)
485{
486    char **list, *name;
487    int count = 0;
488
489    list = XListFonts(oc->core.om->core.display, pattern, 1, &count);
490    if (list == NULL)
491	return NULL;
492
493    name = strdup(*list);
494
495    XFreeFontNames(list);
496
497    return name;
498}
499
500/* For VW/UDC start*/
501
502static char *
503get_rotate_fontname(
504    char *font_name)
505{
506    char *pattern = NULL, *ptr = NULL;
507    char *fields[CHARSET_ENCODING_FIELD];
508    char str_pixel[32], str_point[4];
509    char *rotate_font_ptr = NULL;
510    int pixel_size = 0;
511    int field_num = 0, len = 0;
512
513    if(font_name == (char *) NULL || (len = strlen(font_name)) <= 0
514       || len > XLFD_MAX_LEN)
515	return NULL;
516
517    pattern = strdup(font_name);
518    if(!pattern)
519	return NULL;
520
521    memset(fields, 0, sizeof(char *) * 14);
522    ptr = pattern;
523    while(isspace(*ptr)) {
524	ptr++;
525    }
526    if(*ptr == '-')
527	ptr++;
528
529    for(field_num = 0 ; field_num < CHARSET_ENCODING_FIELD && ptr && *ptr ;
530			ptr++, field_num++) {
531	fields[field_num] = ptr;
532
533	if((ptr = strchr(ptr, '-'))) {
534	    *ptr = '\0';
535	} else {
536	    field_num++;	/* Count last field */
537	    break;
538	}
539    }
540
541    if(field_num < CHARSET_ENCODING_FIELD)
542	goto free_pattern;
543
544    /* Pixel Size field : fields[6] */
545    for(ptr = fields[PIXEL_SIZE_FIELD - 1] ; ptr && *ptr; ptr++) {
546	if(!isdigit(*ptr)) {
547	    if(*ptr == '['){ /* 960730 */
548	        strcpy(pattern, font_name);
549		return(pattern);
550	    }
551	    goto free_pattern;
552	}
553    }
554    pixel_size = atoi(fields[PIXEL_SIZE_FIELD - 1]);
555    snprintf(str_pixel, sizeof(str_pixel),
556	     "[ 0 ~%d %d 0 ]", pixel_size, pixel_size);
557    fields[6] = str_pixel;
558
559    /* Point Size field : fields[7] */
560    strcpy(str_point, "*");
561    fields[POINT_SIZE_FIELD - 1] = str_point;
562
563    len = 0;
564    for (field_num = 0; field_num < CHARSET_ENCODING_FIELD &&
565			fields[field_num]; field_num++) {
566	len += 1 + strlen(fields[field_num]);
567    }
568
569    /* Max XLFD length is 255 */
570    if (len > XLFD_MAX_LEN)
571	goto free_pattern;
572
573    rotate_font_ptr = Xmalloc(len + 1);
574    if(!rotate_font_ptr)
575	goto free_pattern;
576
577    rotate_font_ptr[0] = '\0';
578
579    for(field_num = 0 ; field_num < CHARSET_ENCODING_FIELD &&
580			fields[field_num] ; field_num++) {
581	strcat(rotate_font_ptr, "-");
582	strcat(rotate_font_ptr, fields[field_num]);
583    }
584
585free_pattern:
586    Xfree(pattern);
587
588    return rotate_font_ptr;
589}
590
591static Bool
592is_match_charset(
593    FontData	font_data,
594    char	*font_name)
595{
596    char *last;
597    int length, name_len;
598
599    name_len = strlen(font_name);
600    last = font_name + name_len;
601
602    length = strlen(font_data->name);
603    if (length > name_len)
604	return False;
605
606    if (_XlcCompareISOLatin1(last - length, font_data->name) == 0)
607	return True;
608
609    return False;
610}
611
612static int
613parse_all_name(
614    XOC		oc,
615    FontData	font_data,
616    char	*pattern)
617{
618
619#ifdef OLDCODE
620    if(is_match_charset(font_data, pattern) != True)
621 	return False;
622
623    font_data->xlfd_name = strdup(pattern);
624    if(font_data->xlfd_name == NULL)
625	return (-1);
626
627    return True;
628#else  /* OLDCODE */
629    Display *dpy = oc->core.om->core.display;
630    char **fn_list = NULL, *prop_fname = NULL;
631    int list_num;
632    XFontStruct *fs_list;
633    if(is_match_charset(font_data, pattern) != True) {
634	/*
635	 * pattern should not contain any wildcard (execpt '?')
636	 * this was probably added to make this case insensitive.
637	 */
638	if ((fn_list = XListFontsWithInfo(dpy, pattern,
639				      MAXFONTS,
640				      &list_num, &fs_list)) == NULL) {
641            return False;
642        }
643	/* shouldn't we loop here ? */
644        else if ((prop_fname = get_prop_name(dpy, fs_list)) == NULL) {
645            XFreeFontInfo(fn_list, fs_list, list_num);
646            return False;
647        }
648        else if ((is_match_charset(font_data, prop_fname) != True)) {
649            XFree(prop_fname);
650            XFreeFontInfo(fn_list, fs_list, list_num);
651            return False;
652        }
653        else {
654	    font_data->xlfd_name = prop_fname;
655            XFreeFontInfo(fn_list, fs_list, list_num);
656            return True;
657        }
658    }
659
660    font_data->xlfd_name = strdup(pattern);
661    if(font_data->xlfd_name == NULL)
662	return (-1);
663
664    return True;
665#endif /* OLDCODE */
666}
667
668static int
669parse_omit_name(
670    XOC		oc,
671    FontData	font_data,
672    char	*pattern)
673{
674    char*	last = (char *) NULL;
675    char*	base_name;
676    char	buf[XLFD_MAX_LEN + 1];
677    int		length = 0;
678    int		num_fields;
679   /*
680    * If the font specified by "pattern" is expandable to be
681    * a member of "font_data"'s FontSet, we've found a match.
682    */
683    if(is_match_charset(font_data, pattern) == True) {
684	if ((font_data->xlfd_name = get_font_name(oc, pattern)) != NULL) {
685	    return True;
686	}
687    }
688
689    length = strlen (pattern);
690
691    if (length > XLFD_MAX_LEN)
692	return -1;
693
694    strcpy(buf, pattern);
695    last = buf + length - 1;
696
697    /* Replace the original encoding with the encoding for this FontSet. */
698
699    /* Figure out how many fields have been specified in this xlfd. */
700    for (num_fields = 0, base_name = buf; *base_name != '\0'; base_name++)
701	if (*base_name == '-') num_fields++;
702
703    switch (num_fields) {
704    case 12:
705	/* This is the best way to have specifed the fontset.  In this
706	 * case, there is no original encoding. E.g.,
707         *       -*-*-*-*-*-*-14-*-*-*-*-*
708	 * To this, we'll append a dash:
709         *       -*-*-*-*-*-*-14-*-*-*-*-*-
710	 * then append the encoding to get:
711         *       -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
712	 */
713	/*
714	 * Take care of:
715	 *       -*-*-*-*-*-*-14-*-*-*-*-
716	 */
717	if (*(last) == '-')
718	    *++last = '*';
719
720	*++last = '-';
721	break;
722    case 13:
723	/* Got the charset, not the encoding, zap the charset  In this
724	 * case, there is no original encoding, but there is a charset. E.g.,
725         *       -*-*-*-*-*-*-14-*-*-*-*-*-jisx0212.1990
726	 * To this, we remove the charset:
727         *       -*-*-*-*-*-*-14-*-*-*-*-*-
728	 * then append the new encoding to get:
729         *       -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
730	 */
731	last = strrchr (buf, '-');
732	num_fields = 12;
733	break;
734    case 14:
735	/* Both the charset and the encoding are specified.  Get rid
736	 * of them so that we can append the new charset encoding.  E.g.,
737         *       -*-*-*-*-*-*-14-*-*-*-*-*-jisx0212.1990-0
738	 * To this, we'll remove the encoding and charset to get:
739         *       -*-*-*-*-*-*-14-*-*-*-*-*-
740	 * then append the new encoding to get:
741         *       -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
742	 */
743	last = strrchr (buf, '-');
744	*last = '\0';
745	last = strrchr (buf, '-');
746	num_fields = 12;
747	break;
748    default:
749	if (*last != '-')
750	    *++last = '-';
751	break;
752    }
753
754   /* At this point, "last" is pointing to the last "-" in the
755    * xlfd, and all xlfd's at this point take a form similar to:
756    *       -*-*-*-*-*-*-14-*-*-*-*-*-
757    * (i.e., no encoding).
758    * After the strcpy, we'll end up with something similar to:
759    *       -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
760    *
761    * If the modified font is found in the current FontSet,
762    * we've found a match.
763    */
764
765    last++;
766
767    if ((last - buf) + strlen(font_data->name) > XLFD_MAX_LEN)
768	return -1;
769
770    strcpy(last, font_data->name);
771    if ((font_data->xlfd_name = get_font_name(oc, buf)) != NULL)
772	return True;
773
774    /* This may mot be needed anymore as XListFonts() takes care of this */
775    if (num_fields < 12) {
776	if ((last - buf) > (XLFD_MAX_LEN - 2))
777	    return -1;
778	*last = '*';
779	*(last + 1) = '-';
780	strcpy(last + 2, font_data->name);
781	num_fields++;
782	last+=2;
783	if ((font_data->xlfd_name = get_font_name(oc, buf)) != NULL)
784	    return True;
785    }
786
787
788    return False;
789}
790
791
792typedef enum{C_PRIMARY, C_SUBSTITUTE, C_VMAP, C_VROTATE } ClassType;
793
794static int
795parse_fontdata(
796    XOC		 oc,
797    FontSet      font_set,
798    FontData	 font_data,
799    int		 font_data_count,
800    char	 **name_list,
801    int		 name_list_count,
802    ClassType	 class,
803    FontDataRec *font_data_return)
804{
805
806    char	**cur_name_list = name_list;
807    char	*font_name      = (char *) NULL;
808    char	*pattern        = (char *) NULL;
809    int		found_num       = 0, ret = 0;
810    int		count           = name_list_count;
811
812    if(name_list == NULL || count <= 0) {
813	return False;
814    }
815
816    if(font_data == NULL || font_data_count <= 0) {
817	return False;
818    }
819
820    /* Loop through each font encoding defined in the "font_data" FontSet. */
821    for ( ; font_data_count-- > 0; font_data++) {
822	Bool	is_found = False;
823	font_name = (char *) NULL;
824	count = name_list_count;
825	cur_name_list = name_list;
826
827       /*
828	* Loop through each font specified by the user
829	* in the call to XCreateFontset().
830	*/
831	while (count-- > 0) {
832            pattern = *cur_name_list++;
833	    if (pattern == NULL || *pattern == '\0')
834		continue;
835#ifdef FONTDEBUG
836		fprintf(stderr,"Font pattern: %s %s\n",
837		pattern,font_data->name);
838#endif
839
840	    /*
841	     * If the current font is fully specified (i.e., the
842	     * xlfd contains no wildcards) and the font exists on
843	     * the X Server, we have a match.
844	     */
845	    if (strchr(pattern, '*') == NULL &&
846		(font_name = get_font_name(oc, pattern))) {
847               /*
848		* Find the full xlfd name for this font. If the font is
849		* already in xlfd format, it is simply returned.  If the
850		* font is an alias for another font, the xlfd of the
851		* aliased font is returned.
852		*/
853		ret = parse_all_name(oc, font_data, font_name);
854		Xfree(font_name);
855
856                if (ret == -1)    return -1;
857	        if (ret == False) continue;
858               /*
859		* Since there was an exact match of a fully-specified font
860		* or a font alias, we can return now since the desired font
861		* was found for the current font encoding for this FontSet.
862		*
863		* Previous implementations of this algorithm would
864		* not return here. Instead, they continued searching
865		* through the font encodings for this FontSet. The side-effect
866		* of that behavior is you may return a "substitute" match
867		* instead of an "exact" match.  We believe there should be a
868		* preference on exact matches.  Therefore, as soon as we
869		* find one, we bail.
870		*
871		* Also, previous implementations seemed to think it was
872		* important to find either a primary or substitute font
873		* for each Font encoding in the FontSet before returning an
874		* acceptable font.  We don't believe this is necessary.
875		* All the client cares about is finding a reasonable font
876		* for what was passed in.  If we find an exact match,
877		* there's no reason to look any further.
878		*
879		* -- jjw/pma (HP)
880		*/
881		if (font_data_return) {
882		    font_data_return->xlfd_name = strdup(font_data->xlfd_name);
883		    if (!font_data_return->xlfd_name) return -1;
884
885		    font_data_return->side      = font_data->side;
886		}
887#ifdef FONTDEBUG
888		fprintf(stderr,"XLFD name: %s\n",font_data->xlfd_name);
889#endif
890
891		return True;
892	    }
893	    /*
894	     * If the font name is not fully specified
895	     * (i.e., it has wildcards), we have more work to do.
896	     * See the comments in parse_omit_name()
897	     * for the list of things to do.
898	     */
899	    ret = parse_omit_name(oc, font_data, pattern);
900
901            if (ret == -1)    return -1;
902	    if (ret == False) continue;
903
904           /*
905	    * A font which matched the wild-carded specification was found.
906	    * Only update the return data if a font has not yet been found.
907	    * This maintains the convention that FontSets listed higher in
908	    * a CodeSet in the Locale Database have higher priority than
909	    * those FontSets listed lower in the CodeSet.  In the following
910	    * example:
911	    *
912	    * fs1 {
913	    *        charset     HP-JIS:GR
914	    *        font        JISX0208.1990-0:GL;\
915	    *                    JISX0208.1990-1:GR;\
916	    *                    JISX0208.1983-0:GL;\
917	    *                    JISX0208.1983-1:GR
918	    * }
919	    *
920	    * a font found in the JISX0208.1990-0 FontSet will have a
921	    * higher priority than a font found in the JISX0208.1983-0
922	    * FontSet.
923	    */
924	    if (font_data_return && font_data_return->xlfd_name == NULL) {
925
926#ifdef FONTDEBUG
927		fprintf(stderr,"XLFD name: %s\n",font_data->xlfd_name);
928#endif
929		font_data_return->xlfd_name = strdup(font_data->xlfd_name);
930                if (!font_data_return->xlfd_name) return -1;
931
932	        font_data_return->side      = font_data->side;
933	    }
934
935	    found_num++;
936	    is_found = True;
937
938	    break;
939	}
940
941	switch(class) {
942	  case C_PRIMARY:
943	       if(is_found == False) {
944		 /*
945		  * Did not find a font for the current FontSet.  Check the
946		  * FontSet's "substitute" font for a match.  If we find a
947		  * match, we'll keep searching in hopes of finding an exact
948		  * match later down the FontSet list.
949		  *
950		  * when we return and we have found a font font_data_return
951		  * contains the first (ie. best) match no matter if this
952		  * is a C_PRIMARY or a C_SUBSTITUTE font
953		  */
954		  ret = parse_fontdata(oc, font_set, font_set->substitute,
955				       font_set->substitute_num, name_list,
956				       name_list_count, C_SUBSTITUTE,
957				       font_data_return);
958                  if (ret == -1)    return -1;
959		  if (ret == False) continue;
960
961		  found_num++;
962		  is_found = True;
963               }
964#ifdef TESTVERSION
965	       else
966		   return True;
967#endif
968	       break;
969
970	  case C_SUBSTITUTE:
971	  case C_VMAP:
972	       if(is_found == True)
973		  return True;
974	       break;
975
976	  case C_VROTATE:
977	       if(is_found == True) {
978		  char	*rotate_name;
979
980		  if((rotate_name = get_rotate_fontname(font_data->xlfd_name))
981		     != NULL) {
982		      Xfree(font_data->xlfd_name);
983		      font_data->xlfd_name = rotate_name;
984
985		      return True;
986		  }
987		  Xfree(font_data->xlfd_name);
988		  font_data->xlfd_name = NULL;
989		  return False;
990	       }
991	       break;
992	}
993    }
994
995    if(class == C_PRIMARY && found_num >= 1)
996	return True;
997
998    return False;
999}
1000
1001
1002static int
1003parse_vw(
1004    XOC		oc,
1005    FontSet	font_set,
1006    char	**name_list,
1007    int		count)
1008{
1009    FontData	vmap = font_set->vmap;
1010    VRotate	vrotate = font_set->vrotate;
1011    int		vmap_num = font_set->vmap_num;
1012    int		vrotate_num = font_set->vrotate_num;
1013    int		ret = 0, i = 0;
1014
1015    if(vmap_num > 0) {
1016	if(parse_fontdata(oc, font_set, vmap, vmap_num, name_list,
1017			  count, C_VMAP,NULL) == -1)
1018	    return (-1);
1019    }
1020
1021    if(vrotate_num > 0) {
1022	ret = parse_fontdata(oc, font_set, (FontData) vrotate, vrotate_num,
1023			     name_list, count, C_VROTATE, NULL);
1024	if(ret == -1) {
1025	    return (-1);
1026	} else if(ret == False) {
1027	    CodeRange	code_range;
1028	    int		num_cr;
1029	    int		sub_num = font_set->substitute_num;
1030
1031	    code_range = vrotate[0].code_range; /* ? */
1032	    num_cr = vrotate[0].num_cr;         /* ? */
1033	    for(i = 0 ; i < vrotate_num ; i++) {
1034		if(vrotate[i].xlfd_name)
1035		    Xfree(vrotate[i].xlfd_name);
1036	    }
1037	    Xfree(vrotate);
1038
1039	    if(sub_num > 0) {
1040		vrotate = font_set->vrotate = Xcalloc(sub_num,
1041                                                      sizeof(VRotateRec));
1042		if(font_set->vrotate == (VRotate)NULL)
1043		    return (-1);
1044
1045		for(i = 0 ; i < sub_num ; i++) {
1046		    vrotate[i].charset_name = font_set->substitute[i].name;
1047		    vrotate[i].side = font_set->substitute[i].side;
1048		    vrotate[i].code_range = code_range;
1049		    vrotate[i].num_cr = num_cr;
1050		}
1051		vrotate_num = font_set->vrotate_num = sub_num;
1052	    } else {
1053		vrotate = font_set->vrotate = (VRotate)NULL;
1054	    }
1055
1056	    ret = parse_fontdata(oc, font_set, (FontData) vrotate, vrotate_num,
1057				 name_list, count, C_VROTATE, NULL);
1058	    if(ret == -1)
1059		return (-1);
1060	}
1061    }
1062
1063    return True;
1064}
1065
1066static int
1067parse_fontname(
1068    XOC oc)
1069{
1070    XOCGenericPart *gen = XOC_GENERIC(oc);
1071    FontSet     font_set;
1072    FontDataRec font_data_return;
1073    char *base_name, **name_list;
1074    int font_set_num = 0;
1075    int found_num = 0;
1076    int count = 0;
1077    int	ret;
1078    int i;
1079
1080    name_list = _XParseBaseFontNameList(oc->core.base_name_list, &count);
1081    if (name_list == NULL)
1082	return -1;
1083
1084    font_set = gen->font_set;
1085    font_set_num = gen->font_set_num;
1086
1087   /* Loop through all of the CharSets defined in the Locale
1088    * database for the current Locale.
1089    */
1090    for( ; font_set_num-- > 0 ; font_set++) {
1091	if(font_set->font_name)
1092	    continue;
1093
1094	if(font_set->font_data_count > 0) {
1095
1096           /*
1097	    * If there are a non-zero number of FontSets defined
1098	    * for this CharSet.
1099            * Try to find a font for this CharSet.  If we find an
1100	    * acceptable font, we save the information for return
1101	    * to the client.  If we do not find an acceptable font,
1102	    * a "missing_charset" will be reported to the client
1103	    * for this CharSet.
1104	    */
1105	    font_data_return.xlfd_name  = NULL;
1106	    font_data_return.side       = XlcUnknown;
1107
1108	    ret = parse_fontdata(oc, font_set, font_set->font_data,
1109				 font_set->font_data_count,
1110				 name_list, count, C_PRIMARY,
1111				 &font_data_return);
1112	    if(ret == -1) {
1113		goto err;
1114	    } else if(ret == True) {
1115		/*
1116		 * We can't just loop thru fontset->font_data to
1117		 * find the first (ie. best) match: parse_fontdata
1118		 * will try a substitute font if no primary one could
1119		 * be matched. It returns the required information in
1120		 * font_data_return.
1121		 */
1122		font_set->font_name = strdup(font_data_return.xlfd_name);
1123		if(font_set->font_name == (char *) NULL)
1124		    goto err;
1125
1126		font_set->side = font_data_return.side;
1127
1128                Xfree (font_data_return.xlfd_name);
1129                font_data_return.xlfd_name = NULL;
1130
1131		if(parse_vw(oc, font_set, name_list, count) == -1)
1132		    goto err;
1133		found_num++;
1134	    }
1135
1136	} else if(font_set->substitute_num > 0) {
1137           /*
1138	    * If there are no FontSets defined for this
1139	    * CharSet.  We can only find "substitute" fonts.
1140	    */
1141	    ret = parse_fontdata(oc, font_set, font_set->substitute,
1142				 font_set->substitute_num,
1143				 name_list, count, C_SUBSTITUTE, NULL);
1144	    if(ret == -1) {
1145		goto err;
1146	    } else if(ret == True) {
1147		for(i=0;i<font_set->substitute_num;i++){
1148		    if(font_set->substitute[i].xlfd_name != NULL){
1149			break;
1150		    }
1151		}
1152		font_set->font_name = strdup(font_set->substitute[i].xlfd_name);
1153		if(font_set->font_name == (char *) NULL)
1154		    goto err;
1155
1156		font_set->side = font_set->substitute[i].side;
1157		if(parse_vw(oc, font_set, name_list, count) == -1)
1158		    goto err;
1159
1160		found_num++;
1161	    }
1162	}
1163    }
1164
1165    base_name = strdup(oc->core.base_name_list);
1166    if (base_name == NULL)
1167	goto err;
1168
1169    oc->core.base_name_list = base_name;
1170
1171    XFreeStringList(name_list);
1172
1173    return found_num;
1174
1175err:
1176    XFreeStringList(name_list);
1177    /* Prevent this from being freed twice */
1178    oc->core.base_name_list = NULL;
1179
1180    return -1;
1181}
1182
1183/* For VW/UDC end*/
1184
1185static Bool
1186set_missing_list(
1187    XOC oc)
1188{
1189    XOCGenericPart *gen = XOC_GENERIC(oc);
1190    FontSet font_set;
1191    char **charset_list, *charset_buf;
1192    int	count, length, font_set_num;
1193    int result = 1;
1194
1195    font_set = gen->font_set;
1196    font_set_num = gen->font_set_num;
1197    count = length = 0;
1198
1199    for ( ; font_set_num-- > 0; font_set++) {
1200	if (font_set->info || font_set->font) {
1201	    continue;
1202	}
1203
1204	/* Change 1996.01.23 start */
1205	if(font_set->font_data_count <= 0 ||
1206	   font_set->font_data == (FontData)NULL) {
1207	    if(font_set->substitute_num <= 0 ||
1208	       font_set->substitute == (FontData)NULL) {
1209		if(font_set->charset_list != NULL){
1210		 length +=
1211		  strlen(font_set->charset_list[0]->encoding_name) + 1;
1212		} else {
1213		  length += 1;
1214		}
1215	    } else {
1216		length += strlen(font_set->substitute->name) + 1;
1217	    }
1218	} else {
1219	    length += strlen(font_set->font_data->name) + 1;
1220	}
1221	/* Change 1996.01.23 end */
1222	count++;
1223    }
1224
1225    if (count < 1) {
1226	return True;
1227    }
1228
1229    charset_list = Xmalloc(sizeof(char *) * count);
1230    if (charset_list == NULL) {
1231	return False;
1232    }
1233
1234    charset_buf = Xmalloc(length);
1235    if (charset_buf == NULL) {
1236	Xfree(charset_list);
1237	return False;
1238    }
1239
1240    oc->core.missing_list.charset_list = charset_list;
1241    oc->core.missing_list.charset_count = count;
1242
1243    font_set = gen->font_set;
1244    font_set_num = gen->font_set_num;
1245
1246    for ( ; font_set_num-- > 0; font_set++) {
1247	if (font_set->info || font_set->font) {
1248	    continue;
1249	}
1250
1251	/* Change 1996.01.23 start */
1252	if(font_set->font_data_count <= 0 ||
1253	   font_set->font_data == (FontData)NULL) {
1254	    if(font_set->substitute_num <= 0 ||
1255	       font_set->substitute == (FontData)NULL) {
1256		if(font_set->charset_list != NULL){
1257		 strcpy(charset_buf,
1258			font_set->charset_list[0]->encoding_name);
1259		} else {
1260		 strcpy(charset_buf, "");
1261		}
1262		result = 0;
1263	    } else {
1264		strcpy(charset_buf, font_set->substitute->name);
1265	    }
1266	} else {
1267	    strcpy(charset_buf, font_set->font_data->name);
1268	}
1269	/* Change 1996.01.23 end */
1270	*charset_list++ = charset_buf;
1271	charset_buf += strlen(charset_buf) + 1;
1272    }
1273
1274    if(result == 0) {
1275	return(False);
1276    }
1277
1278    return True;
1279}
1280
1281static Bool
1282create_fontset(
1283    XOC oc)
1284{
1285    XOMGenericPart *gen = XOM_GENERIC(oc->core.om);
1286    int found_num;
1287
1288    if (init_fontset(oc) == False)
1289        return False;
1290
1291    found_num = parse_fontname(oc);
1292    if (found_num <= 0) {
1293	if (found_num == 0)
1294	    set_missing_list(oc);
1295	return False;
1296    }
1297
1298    if (gen->on_demand_loading == True) {
1299	if (load_font_info(oc) == False)
1300	    return False;
1301    } else {
1302	if (load_font(oc) == False)
1303	    return False;
1304    }
1305
1306    if (init_core_part(oc) == False)
1307	return False;
1308
1309    if (set_missing_list(oc) == False)
1310	return False;
1311
1312    return True;
1313}
1314
1315/* For VW/UDC start */
1316static void
1317free_fontdataOC(
1318    Display	*dpy,
1319    FontData	font_data,
1320    int		font_data_count)
1321{
1322    for( ; font_data_count-- ; font_data++) {
1323	if(font_data->xlfd_name){
1324	    Xfree(font_data->xlfd_name);
1325	    font_data->xlfd_name = NULL;
1326	}
1327	if(font_data->font){				/* ADD 1996.01.7 */
1328	    if(font_data->font->fid)			/* Add 1996.01.23 */
1329		XFreeFont(dpy,font_data->font);		/* ADD 1996.01.7 */
1330	    else					/* Add 1996.01.23 */
1331		XFreeFontInfo(NULL, font_data->font, 1);/* Add 1996.01.23 */
1332	    font_data->font = NULL;
1333	}
1334/*
1335 * font_data->name and font_data->scopes belong to the OM not OC.
1336 * To save space this data is shared between OM and OC. We are
1337 * not allowed to free it here.
1338 * It has been moved to free_fontdataOM()
1339 */
1340/*
1341	if(font_data->scopes){
1342	    Xfree(font_data->scopes);
1343	    font_data->scopes = NULL;
1344	}
1345	if(font_data->name){
1346	    Xfree(font_data->name);
1347	    font_data->name = NULL;
1348	}
1349*/
1350    }
1351}
1352
1353static void destroy_fontdata(
1354    XOCGenericPart *gen,
1355    Display *dpy)
1356{
1357    FontSet	font_set = (FontSet) NULL;
1358    int		font_set_num = 0;
1359
1360    if (gen->font_set) {
1361	font_set = gen->font_set;
1362	font_set_num = gen->font_set_num;
1363	for( ; font_set_num-- ; font_set++) {
1364	    if (font_set->font) {
1365		if(font_set->font->fid)
1366		    XFreeFont(dpy,font_set->font);
1367		else
1368		    XFreeFontInfo(NULL, font_set->font, 1);
1369		font_set->font = NULL;
1370	    }
1371	    if(font_set->font_data) {
1372		if (font_set->info)
1373		    XFreeFontInfo(NULL, font_set->info, 1);
1374		free_fontdataOC(dpy,
1375			font_set->font_data, font_set->font_data_count);
1376		Xfree(font_set->font_data);
1377		font_set->font_data = NULL;
1378	    }
1379	    if(font_set->substitute) {
1380		free_fontdataOC(dpy,
1381			font_set->substitute, font_set->substitute_num);
1382		Xfree(font_set->substitute);
1383		font_set->substitute = NULL;
1384	    }
1385	    if(font_set->vmap) {
1386		free_fontdataOC(dpy,
1387			font_set->vmap, font_set->vmap_num);
1388		Xfree(font_set->vmap);
1389		font_set->vmap = NULL;
1390	    }
1391	    if(font_set->vrotate) {
1392		free_fontdataOC(dpy,
1393			(FontData)font_set->vrotate,
1394			      font_set->vrotate_num);
1395		Xfree(font_set->vrotate);
1396		font_set->vrotate = NULL;
1397	    }
1398	}
1399	Xfree(gen->font_set);
1400	gen->font_set = NULL;
1401    }
1402}
1403/* For VW/UDC end */
1404
1405static void
1406destroy_oc(
1407    XOC oc)
1408{
1409    Display *dpy = oc->core.om->core.display;
1410    XOCGenericPart *gen = XOC_GENERIC(oc);
1411
1412    if (gen->mbs_to_cs)
1413	_XlcCloseConverter(gen->mbs_to_cs);
1414
1415    if (gen->wcs_to_cs)
1416	_XlcCloseConverter(gen->wcs_to_cs);
1417
1418    if (gen->utf8_to_cs)
1419	_XlcCloseConverter(gen->utf8_to_cs);
1420
1421/* For VW/UDC start */ /* Change 1996.01.8 */
1422    destroy_fontdata(gen,dpy);
1423/*
1424*/
1425/* For VW/UDC end */
1426
1427    Xfree(oc->core.base_name_list);
1428    XFreeStringList(oc->core.font_info.font_name_list);
1429    Xfree(oc->core.font_info.font_struct_list);
1430    XFreeStringList(oc->core.missing_list.charset_list);
1431
1432#ifdef notdef
1433
1434    Xfree(oc->core.res_name);
1435    Xfree(oc->core.res_class);
1436#endif
1437
1438    Xfree(oc);
1439}
1440
1441static char *
1442set_oc_values(
1443    XOC oc,
1444    XlcArgList args,
1445    int num_args)
1446{
1447    XOCGenericPart *gen = XOC_GENERIC(oc);
1448    FontSet font_set = gen->font_set;
1449    char *ret;
1450    int num = gen->font_set_num;
1451
1452    if (oc->core.resources == NULL)
1453	return NULL;
1454
1455    ret = _XlcSetValues((XPointer) oc, oc->core.resources,
1456			oc->core.num_resources, args, num_args, XlcSetMask);
1457    if(ret != NULL){
1458	return(ret);
1459    } else {
1460	for ( ; num-- > 0; font_set++) {
1461	    if (font_set->font_name == NULL)
1462	        continue;
1463	    if (font_set->vpart_initialize != 0)
1464	        continue;
1465	    if( oc->core.orientation == XOMOrientation_TTB_RTL ||
1466		oc->core.orientation == XOMOrientation_TTB_LTR ){
1467	    	load_fontdata(oc, font_set->vmap, font_set->vmap_num);
1468		load_fontdata(oc, (FontData) font_set->vrotate,
1469			    font_set->vrotate_num);
1470		font_set->vpart_initialize = 1;
1471	    }
1472	}
1473	return(NULL);
1474    }
1475}
1476
1477static char *
1478get_oc_values(
1479    XOC oc,
1480    XlcArgList args,
1481    int num_args)
1482{
1483    if (oc->core.resources == NULL)
1484	return NULL;
1485
1486    return _XlcGetValues((XPointer) oc, oc->core.resources,
1487			 oc->core.num_resources, args, num_args, XlcGetMask);
1488}
1489
1490static XOCMethodsRec oc_default_methods = {
1491    destroy_oc,
1492    set_oc_values,
1493    get_oc_values,
1494    _XmbDefaultTextEscapement,
1495    _XmbDefaultTextExtents,
1496    _XmbDefaultTextPerCharExtents,
1497    _XmbDefaultDrawString,
1498    _XmbDefaultDrawImageString,
1499    _XwcDefaultTextEscapement,
1500    _XwcDefaultTextExtents,
1501    _XwcDefaultTextPerCharExtents,
1502    _XwcDefaultDrawString,
1503    _XwcDefaultDrawImageString,
1504    _Xutf8DefaultTextEscapement,
1505    _Xutf8DefaultTextExtents,
1506    _Xutf8DefaultTextPerCharExtents,
1507    _Xutf8DefaultDrawString,
1508    _Xutf8DefaultDrawImageString
1509};
1510
1511static XOCMethodsRec oc_generic_methods = {
1512    destroy_oc,
1513    set_oc_values,
1514    get_oc_values,
1515    _XmbGenericTextEscapement,
1516    _XmbGenericTextExtents,
1517    _XmbGenericTextPerCharExtents,
1518    _XmbGenericDrawString,
1519    _XmbGenericDrawImageString,
1520    _XwcGenericTextEscapement,
1521    _XwcGenericTextExtents,
1522    _XwcGenericTextPerCharExtents,
1523    _XwcGenericDrawString,
1524    _XwcGenericDrawImageString,
1525    _Xutf8GenericTextEscapement,
1526    _Xutf8GenericTextExtents,
1527    _Xutf8GenericTextPerCharExtents,
1528    _Xutf8GenericDrawString,
1529    _Xutf8GenericDrawImageString
1530};
1531
1532typedef struct _XOCMethodsListRec {
1533    const char *name;
1534    XOCMethods methods;
1535} XOCMethodsListRec, *XOCMethodsList;
1536
1537static XOCMethodsListRec oc_methods_list[] = {
1538    { "default", &oc_default_methods },
1539    { "generic", &oc_generic_methods }
1540};
1541
1542static XlcResource oc_resources[] = {
1543    { XNBaseFontName, NULLQUARK, sizeof(char *),
1544      XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask },
1545    { XNOMAutomatic, NULLQUARK, sizeof(Bool),
1546      XOffsetOf(XOCRec, core.om_automatic), XlcGetMask },
1547    { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList),
1548      XOffsetOf(XOCRec, core.missing_list), XlcGetMask },
1549    { XNDefaultString, NULLQUARK, sizeof(char *),
1550      XOffsetOf(XOCRec, core.default_string), XlcGetMask },
1551    { XNOrientation, NULLQUARK, sizeof(XOrientation),
1552      XOffsetOf(XOCRec, core.orientation), XlcDefaultMask | XlcSetMask | XlcGetMask },
1553    { XNResourceName, NULLQUARK, sizeof(char *),
1554      XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask },
1555    { XNResourceClass, NULLQUARK, sizeof(char *),
1556      XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask },
1557    { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo),
1558      XOffsetOf(XOCRec, core.font_info), XlcGetMask }
1559};
1560
1561static XOC
1562create_oc(
1563    XOM om,
1564    XlcArgList args,
1565    int num_args)
1566{
1567    XOC oc;
1568    XOMGenericPart *gen = XOM_GENERIC(om);
1569    XOCMethodsList methods_list = oc_methods_list;
1570    int count;
1571
1572    oc = Xcalloc(1, sizeof(XOCGenericRec));
1573    if (oc == NULL)
1574	return (XOC) NULL;
1575
1576    oc->core.om = om;
1577
1578    if (oc_resources[0].xrm_name == NULLQUARK)
1579	_XlcCompileResourceList(oc_resources, XlcNumber(oc_resources));
1580
1581    if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources),
1582		      args, num_args, XlcCreateMask | XlcDefaultMask))
1583	goto err;
1584
1585    if (oc->core.base_name_list == NULL)
1586	goto err;
1587
1588    oc->core.resources = oc_resources;
1589    oc->core.num_resources = XlcNumber(oc_resources);
1590
1591    if (create_fontset(oc) == False)
1592	goto err;
1593
1594    oc->methods = &oc_generic_methods;
1595
1596    if (gen->object_name) {
1597	count = XlcNumber(oc_methods_list);
1598
1599	for ( ; count-- > 0; methods_list++) {
1600	    if (!_XlcCompareISOLatin1(gen->object_name, methods_list->name)) {
1601		oc->methods = methods_list->methods;
1602		break;
1603	    }
1604	}
1605    }
1606
1607    return oc;
1608
1609err:
1610    destroy_oc(oc);
1611
1612    return (XOC) NULL;
1613}
1614
1615static void
1616free_fontdataOM(
1617    FontData	font_data,
1618    int		font_data_count)
1619{
1620    for( ; font_data_count-- ; font_data++) {
1621	if(font_data->name){
1622	    Xfree(font_data->name);
1623	    font_data->name = NULL;
1624	}
1625	if(font_data->scopes){
1626	    Xfree(font_data->scopes);
1627	    font_data->scopes = NULL;
1628	}
1629    }
1630}
1631
1632static Status
1633close_om(
1634    XOM om)
1635{
1636    XOMGenericPart *gen = XOM_GENERIC(om);
1637    OMData data;
1638    int count;
1639
1640    if ((data = gen->data)) {
1641	for (count = gen->data_num; count-- > 0; data++) {
1642	    if (data->charset_list){
1643		Xfree(data->charset_list);
1644		data->charset_list = NULL;
1645	    }
1646	    /* free font_data for om */
1647	    if (data->font_data) {
1648		free_fontdataOM(data->font_data,data->font_data_count);
1649		Xfree(data->font_data);
1650		data->font_data = NULL;
1651	    }
1652	    /* free substitute for om */
1653	    if (data->substitute) {
1654		free_fontdataOM(data->substitute,data->substitute_num);
1655		Xfree(data->substitute);
1656		data->substitute = NULL;
1657	    }
1658	    /* free vmap for om */
1659	    if (data->vmap) {
1660		free_fontdataOM(data->vmap,data->vmap_num);
1661		Xfree(data->vmap);
1662		data->vmap = NULL;
1663	    }
1664	    /* free vrotate for om */
1665	    if (data->vrotate) {
1666		Xfree(data->vrotate);
1667		data->vrotate = NULL;
1668	    }
1669	}
1670	Xfree(gen->data);
1671	gen->data = NULL;
1672    }
1673
1674    if (gen->object_name){
1675	Xfree(gen->object_name);
1676	gen->object_name = NULL;
1677    }
1678
1679    if (om->core.res_name){
1680	Xfree(om->core.res_name);
1681	om->core.res_name = NULL;
1682    }
1683    if (om->core.res_class){
1684	Xfree(om->core.res_class);
1685	om->core.res_class = NULL;
1686    }
1687    if (om->core.required_charset.charset_list &&
1688	om->core.required_charset.charset_count > 0){
1689	XFreeStringList(om->core.required_charset.charset_list);
1690	om->core.required_charset.charset_list = NULL;
1691    } else {
1692	Xfree((char*)om->core.required_charset.charset_list);
1693	om->core.required_charset.charset_list = NULL;
1694    }
1695    if (om->core.orientation_list.orientation){
1696	Xfree(om->core.orientation_list.orientation);
1697	om->core.orientation_list.orientation = NULL;
1698    }
1699
1700    Xfree(om);
1701
1702    return 1;
1703}
1704
1705static char *
1706set_om_values(
1707    XOM om,
1708    XlcArgList args,
1709    int num_args)
1710{
1711    if (om->core.resources == NULL)
1712	return NULL;
1713
1714    return _XlcSetValues((XPointer) om, om->core.resources,
1715			 om->core.num_resources, args, num_args, XlcSetMask);
1716}
1717
1718static char *
1719get_om_values(
1720    XOM om,
1721    XlcArgList args,
1722    int num_args)
1723{
1724    if (om->core.resources == NULL)
1725	return NULL;
1726
1727    return _XlcGetValues((XPointer) om, om->core.resources,
1728			 om->core.num_resources, args, num_args, XlcGetMask);
1729}
1730
1731static XOMMethodsRec methods = {
1732    close_om,
1733    set_om_values,
1734    get_om_values,
1735    create_oc
1736};
1737
1738static XlcResource om_resources[] = {
1739    { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList),
1740      XOffsetOf(XOMRec, core.required_charset), XlcGetMask },
1741    { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation),
1742      XOffsetOf(XOMRec, core.orientation_list), XlcGetMask },
1743    { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool),
1744      XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask },
1745    { XNContextualDrawing, NULLQUARK, sizeof(Bool),
1746      XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask }
1747};
1748
1749static XOM
1750create_om(
1751    XLCd lcd,
1752    Display *dpy,
1753    XrmDatabase rdb,
1754    _Xconst char *res_name,
1755    _Xconst char *res_class)
1756{
1757    XOM om;
1758
1759    om = Xcalloc(1, sizeof(XOMGenericRec));
1760    if (om == NULL)
1761	return (XOM) NULL;
1762
1763    om->methods = &methods;
1764    om->core.lcd = lcd;
1765    om->core.display = dpy;
1766    om->core.rdb = rdb;
1767    if (res_name) {
1768	om->core.res_name = strdup(res_name);
1769	if (om->core.res_name == NULL)
1770	    goto err;
1771    }
1772    if (res_class) {
1773	om->core.res_class = strdup(res_class);
1774	if (om->core.res_class == NULL)
1775	    goto err;
1776    }
1777
1778    if (om_resources[0].xrm_name == NULLQUARK)
1779	_XlcCompileResourceList(om_resources, XlcNumber(om_resources));
1780
1781    om->core.resources = om_resources;
1782    om->core.num_resources = XlcNumber(om_resources);
1783
1784    return om;
1785
1786err:
1787    close_om(om);
1788
1789    return (XOM) NULL;
1790}
1791
1792static OMData
1793add_data(
1794    XOM om)
1795{
1796    XOMGenericPart *gen = XOM_GENERIC(om);
1797    OMData new;
1798    int num;
1799
1800    if ((num = gen->data_num))
1801        new = Xrealloc(gen->data, (num + 1) * sizeof(OMDataRec));
1802    else
1803        new = Xmalloc(sizeof(OMDataRec));
1804
1805    if (new == NULL)
1806        return NULL;
1807
1808    gen->data_num = num + 1;
1809    gen->data = new;
1810
1811    new += num;
1812    bzero((char *) new, sizeof(OMDataRec));
1813
1814    return new;
1815}
1816
1817/* For VW/UDC */
1818
1819FontData
1820read_EncodingInfo(
1821    int count,
1822    char **value)
1823{
1824    FontData font_data,ret;
1825    char *buf, *bufptr,*scp;
1826    int len, i;
1827    font_data = Xcalloc(count, sizeof(FontDataRec));
1828    if (font_data == NULL)
1829        return NULL;
1830
1831    ret = font_data;
1832    for (i = 0; i < count; i++, font_data++) {
1833/*
1834        strcpy(buf, *value++);
1835*/
1836	buf = *value; value++;
1837        if ((bufptr = strchr(buf, ':'))) {
1838	    len = (int)(bufptr - buf);
1839            bufptr++ ;
1840	} else
1841            len = strlen(buf);
1842        font_data->name = Xmalloc(len + 1);
1843        if (font_data->name == NULL) {
1844            free_fontdataOM(ret, i + 1);
1845            Xfree(ret);
1846            return NULL;
1847	}
1848        strncpy(font_data->name, buf,len);
1849	font_data->name[len] = 0;
1850        if (bufptr && _XlcCompareISOLatin1(bufptr, "GL") == 0)
1851            font_data->side = XlcGL;
1852        else if (bufptr && _XlcCompareISOLatin1(bufptr, "GR") == 0)
1853            font_data->side = XlcGR;
1854        else
1855            font_data->side = XlcGLGR;
1856
1857        if (bufptr && (scp = strchr(bufptr, '['))){
1858            font_data->scopes = _XlcParse_scopemaps(scp,&(font_data->scopes_num));
1859        }
1860    }
1861    return(ret);
1862}
1863
1864static CodeRange read_vrotate(
1865    int count,
1866    char **value,
1867    int *type,
1868    int *vrotate_num)
1869{
1870    CodeRange   range;
1871    if(!strcmp(value[0],"all")){
1872	*type 	     = VROTATE_ALL ;
1873	*vrotate_num = 0 ;
1874	return (NULL);
1875    } else if(*(value[0]) == '['){
1876	*type 	     = VROTATE_PART ;
1877        range = (CodeRange) _XlcParse_scopemaps(value[0],vrotate_num);
1878	return (range);
1879    } else {
1880	*type 	     = VROTATE_NONE ;
1881	*vrotate_num = 0 ;
1882	return (NULL);
1883    }
1884}
1885
1886static void read_vw(
1887    XLCd    lcd,
1888    OMData  font_set,
1889    int     num)
1890{
1891    char **value, buf[BUFSIZ];
1892    int count;
1893
1894    snprintf(buf, sizeof(buf), "fs%d.font.vertical_map", num);
1895    _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
1896    if (count > 0){
1897        _XlcDbg_printValue(buf,value,count);
1898        font_set->vmap_num = count;
1899        font_set->vmap = read_EncodingInfo(count,value);
1900    }
1901
1902    snprintf(buf, sizeof(buf), "fs%d.font.vertical_rotate", num);
1903    _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
1904    if (count > 0){
1905        _XlcDbg_printValue(buf,value,count);
1906        font_set->vrotate = read_vrotate(count,value,&(font_set->vrotate_type),
1907				&(font_set->vrotate_num));
1908    }
1909}
1910/* VW/UDC end */
1911static Bool
1912init_om(
1913    XOM om)
1914{
1915    XLCd lcd = om->core.lcd;
1916    XOMGenericPart *gen = XOM_GENERIC(om);
1917    OMData data;
1918    XlcCharSet *charset_list;
1919    FontData font_data;
1920    char **required_list;
1921    XOrientation *orientation;
1922    char **value, buf[BUFSIZ], *bufptr;
1923    int count = 0, num = 0, length = 0;
1924
1925    _XlcGetResource(lcd, "XLC_FONTSET", "on_demand_loading", &value, &count);
1926    if (count > 0 && _XlcCompareISOLatin1(*value, "True") == 0)
1927	gen->on_demand_loading = True;
1928
1929    _XlcGetResource(lcd, "XLC_FONTSET", "object_name", &value, &count);
1930    if (count > 0) {
1931	gen->object_name = strdup(*value);
1932	if (gen->object_name == NULL)
1933	    return False;
1934    }
1935
1936    for (num = 0; ; num++) {
1937
1938        snprintf(buf, sizeof(buf), "fs%d.charset.name", num);
1939        _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
1940
1941        if( count < 1){
1942            snprintf(buf, sizeof(buf), "fs%d.charset", num);
1943            _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
1944            if (count < 1)
1945                break;
1946        }
1947
1948	data = add_data(om);
1949	if (data == NULL)
1950	    return False;
1951
1952	charset_list = Xmalloc(sizeof(XlcCharSet) * count);
1953	if (charset_list == NULL)
1954	    return False;
1955	data->charset_list = charset_list;
1956	data->charset_count = count;
1957
1958	while (count-- > 0){
1959	    *charset_list++ = _XlcGetCharSet(*value++);
1960        }
1961        snprintf(buf, sizeof(buf), "fs%d.charset.udc_area", num);
1962        _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
1963        if( count > 0){
1964            UDCArea udc;
1965            int i,flag = 0;
1966            udc = Xmalloc(count * sizeof(UDCAreaRec));
1967	    if (udc == NULL)
1968	        return False;
1969            for(i=0;i<count;i++){
1970                sscanf(value[i],"\\x%lx,\\x%lx", &(udc[i].start),
1971		       &(udc[i].end));
1972            }
1973            for(i=0;i<data->charset_count;i++){
1974		if(data->charset_list[i]->udc_area == NULL){
1975		    data->charset_list[i]->udc_area     = udc;
1976		    data->charset_list[i]->udc_area_num = count;
1977		    flag = 1;
1978		}
1979            }
1980	    if(flag == 0){
1981		Xfree(udc);
1982	    }
1983        }
1984
1985        snprintf(buf, sizeof(buf), "fs%d.font.primary", num);
1986        _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
1987        if (count < 1){
1988            snprintf(buf, sizeof(buf), "fs%d.font", num);
1989            _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
1990            if (count < 1)
1991                return False;
1992        }
1993
1994	font_data = read_EncodingInfo(count,value);
1995	if (font_data == NULL)
1996	    return False;
1997
1998	data->font_data = font_data;
1999	data->font_data_count = count;
2000
2001        snprintf(buf, sizeof(buf), "fs%d.font.substitute", num);
2002        _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
2003        if (count > 0){
2004            font_data = read_EncodingInfo(count,value);
2005            if (font_data == NULL)
2006	        return False;
2007            data->substitute      = font_data;
2008            data->substitute_num = count;
2009        } else {
2010            snprintf(buf, sizeof(buf), "fs%d.font", num);
2011            _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
2012            if (count < 1) {
2013                data->substitute      = NULL;
2014                data->substitute_num = 0;
2015	    } else {
2016                font_data = read_EncodingInfo(count,value);
2017                data->substitute      = font_data;
2018                data->substitute_num = count;
2019	    }
2020	}
2021        read_vw(lcd,data,num);
2022	length += strlen(data->font_data->name) + 1;
2023    }
2024
2025    /* required charset list */
2026    required_list = Xmalloc(sizeof(char *) * gen->data_num);
2027    if (required_list == NULL)
2028	return False;
2029
2030    om->core.required_charset.charset_list = required_list;
2031    om->core.required_charset.charset_count = gen->data_num;
2032
2033    count = gen->data_num;
2034    data = gen->data;
2035
2036    if (count > 0) {
2037	bufptr = Xmalloc(length);
2038	if (bufptr == NULL) {
2039	    Xfree(required_list);
2040	    return False;
2041	}
2042
2043	for ( ; count-- > 0; data++) {
2044	    strcpy(bufptr, data->font_data->name);
2045	    *required_list++ = bufptr;
2046	    bufptr += strlen(bufptr) + 1;
2047	}
2048    }
2049
2050    /* orientation list */
2051    orientation = Xmalloc(sizeof(XOrientation) * 2);
2052    if (orientation == NULL)
2053	return False;
2054
2055    orientation[0] = XOMOrientation_LTR_TTB;
2056    orientation[1] = XOMOrientation_TTB_RTL;
2057    om->core.orientation_list.orientation = orientation;
2058    om->core.orientation_list.num_orientation = 2;
2059
2060    /* directional dependent drawing */
2061    om->core.directional_dependent = False;
2062
2063    /* contexual drawing */
2064    om->core.contextual_drawing = False;
2065
2066    /* context dependent */
2067    om->core.context_dependent = False;
2068
2069    return True;
2070}
2071
2072XOM
2073_XomGenericOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb,
2074		  _Xconst char *res_name, _Xconst char *res_class)
2075{
2076    XOM om;
2077
2078    om = create_om(lcd, dpy, rdb, res_name, res_class);
2079    if (om == NULL)
2080	return (XOM) NULL;
2081
2082    if (init_om(om) == False)
2083	goto err;
2084
2085    return om;
2086
2087err:
2088    close_om(om);
2089
2090    return (XOM) NULL;
2091}
2092
2093Bool
2094_XInitOM(
2095    XLCd lcd)
2096{
2097    lcd->methods->open_om = _XomGenericOpenOM;
2098
2099    return True;
2100}
2101