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