omGeneric.c revision 818534a1
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 = 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 = 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 = 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 = Xmalloc(sizeof(XFontStruct *) * count);
467    if (font_struct_list == NULL)
468	return False;
469
470    font_name_list = Xmalloc(sizeof(char *) * count);
471    if (font_name_list == NULL)
472	goto err;
473
474    font_name_buf = 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    snprintf(str_pixel, sizeof(str_pixel),
589	     "[ 0 ~%d %d 0 ]", pixel_size, pixel_size);
590    fields[6] = str_pixel;
591
592    /* Point Size field : fields[7] */
593    strcpy(str_point, "*");
594    fields[POINT_SIZE_FIELD - 1] = str_point;
595
596    len = 0;
597    for (field_num = 0; field_num < CHARSET_ENCODING_FIELD &&
598			fields[field_num]; field_num++) {
599	len += 1 + strlen(fields[field_num]);
600    }
601
602    /* Max XLFD length is 255 */
603    if (len > XLFD_MAX_LEN)
604	goto free_pattern;
605
606    rotate_font_ptr = Xmalloc(len + 1);
607    if(!rotate_font_ptr)
608	goto free_pattern;
609
610    rotate_font_ptr[0] = '\0';
611
612    for(field_num = 0 ; field_num < CHARSET_ENCODING_FIELD &&
613			fields[field_num] ; field_num++) {
614	strcat(rotate_font_ptr, "-");
615	strcat(rotate_font_ptr, fields[field_num]);
616    }
617
618free_pattern:
619    Xfree(pattern);
620
621    return rotate_font_ptr;
622}
623
624static Bool
625is_match_charset(
626    FontData	font_data,
627    char	*font_name)
628{
629    char *last;
630    int length, name_len;
631
632    name_len = strlen(font_name);
633    last = font_name + name_len;
634
635    length = strlen(font_data->name);
636    if (length > name_len)
637	return False;
638
639    if (_XlcCompareISOLatin1(last - length, font_data->name) == 0)
640	return True;
641
642    return False;
643}
644
645#if 0
646static char *
647get_font_name_from_list(
648    XOC oc,
649    char *pattern,
650    FontData    font_data)
651{
652    char **list, *name = (char *)NULL, *fname;
653    int count = 0, i;
654
655    list = XListFonts(oc->core.om->core.display, pattern, MAXFONTS, &count);
656    if (list == NULL)
657	return NULL;
658
659    for (i = 0; i < count; i++) {
660        fname = list[i];
661        if(is_match_charset(font_data, fname) == True) {
662            name = strdup(fname);
663            break;
664        }
665    }
666
667    XFreeFontNames(list);
668
669    return name;
670}
671#endif
672
673static int
674parse_all_name(
675    XOC		oc,
676    FontData	font_data,
677    char	*pattern)
678{
679
680#ifdef OLDCODE
681    if(is_match_charset(font_data, pattern) != True)
682 	return False;
683
684    font_data->xlfd_name = strdup(pattern);
685    if(font_data->xlfd_name == NULL)
686	return (-1);
687
688    return True;
689#else  /* OLDCODE */
690    Display *dpy = oc->core.om->core.display;
691    char **fn_list = NULL, *prop_fname = NULL;
692    int list_num;
693    XFontStruct *fs_list;
694    if(is_match_charset(font_data, pattern) != True) {
695	/*
696	 * pattern should not contain any wildcard (execpt '?')
697	 * this was probably added to make this case insensitive.
698	 */
699	if ((fn_list = XListFontsWithInfo(dpy, pattern,
700				      MAXFONTS,
701				      &list_num, &fs_list)) == NULL) {
702            return False;
703        }
704	/* shouldn't we loop here ? */
705        else if ((prop_fname = get_prop_name(dpy, fs_list)) == NULL) {
706            XFreeFontInfo(fn_list, fs_list, list_num);
707            return False;
708        }
709        else if ((is_match_charset(font_data, prop_fname) != True)) {
710            XFree(prop_fname);
711            XFreeFontInfo(fn_list, fs_list, list_num);
712            return False;
713        }
714        else {
715	    font_data->xlfd_name = prop_fname;
716            XFreeFontInfo(fn_list, fs_list, list_num);
717            return True;
718        }
719    }
720
721    font_data->xlfd_name = strdup(pattern);
722    if(font_data->xlfd_name == NULL)
723	return (-1);
724
725    return True;
726#endif /* OLDCODE */
727}
728
729static int
730parse_omit_name(
731    XOC		oc,
732    FontData	font_data,
733    char	*pattern)
734{
735    char*	last = (char *) NULL;
736    char*	base_name;
737    char	buf[XLFD_MAX_LEN + 1];
738    int		length = 0;
739    int		num_fields;
740   /*
741    * If the font specified by "pattern" is expandable to be
742    * a member of "font_data"'s FontSet, we've found a match.
743    */
744    if(is_match_charset(font_data, pattern) == True) {
745	if ((font_data->xlfd_name = get_font_name(oc, pattern)) != NULL) {
746	    return True;
747	}
748    }
749
750    length = strlen (pattern);
751
752    if (length > XLFD_MAX_LEN)
753	return -1;
754
755    strcpy(buf, pattern);
756    last = buf + length - 1;
757
758    /* Replace the original encoding with the encoding for this FontSet. */
759
760    /* Figure out how many fields have been specified in this xlfd. */
761    for (num_fields = 0, base_name = buf; *base_name != '\0'; base_name++)
762	if (*base_name == '-') num_fields++;
763
764    switch (num_fields) {
765    case 12:
766	/* This is the best way to have specifed the fontset.  In this
767	 * case, there is no original encoding. E.g.,
768         *       -*-*-*-*-*-*-14-*-*-*-*-*
769	 * To this, we'll append a dash:
770         *       -*-*-*-*-*-*-14-*-*-*-*-*-
771	 * then append the encoding to get:
772         *       -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
773	 */
774	/*
775	 * Take care of:
776	 *       -*-*-*-*-*-*-14-*-*-*-*-
777	 */
778	if (*(last) == '-')
779	    *++last = '*';
780
781	*++last = '-';
782	break;
783    case 13:
784	/* Got the charset, not the encoding, zap the charset  In this
785	 * case, there is no original encoding, but there is a charset. E.g.,
786         *       -*-*-*-*-*-*-14-*-*-*-*-*-jisx0212.1990
787	 * To this, we remove the charset:
788         *       -*-*-*-*-*-*-14-*-*-*-*-*-
789	 * then append the new encoding to get:
790         *       -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
791	 */
792	last = strrchr (buf, '-');
793	num_fields = 12;
794	break;
795    case 14:
796	/* Both the charset and the encoding are specified.  Get rid
797	 * of them so that we can append the new charset encoding.  E.g.,
798         *       -*-*-*-*-*-*-14-*-*-*-*-*-jisx0212.1990-0
799	 * To this, we'll remove the encoding and charset to get:
800         *       -*-*-*-*-*-*-14-*-*-*-*-*-
801	 * then append the new encoding to get:
802         *       -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
803	 */
804	last = strrchr (buf, '-');
805	*last = '\0';
806	last = strrchr (buf, '-');
807	num_fields = 12;
808	break;
809    default:
810	if (*last != '-')
811	    *++last = '-';
812	break;
813    }
814
815   /* At this point, "last" is pointing to the last "-" in the
816    * xlfd, and all xlfd's at this point take a form similar to:
817    *       -*-*-*-*-*-*-14-*-*-*-*-*-
818    * (i.e., no encoding).
819    * After the strcpy, we'll end up with something similar to:
820    *       -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
821    *
822    * If the modified font is found in the current FontSet,
823    * we've found a match.
824    */
825
826    last++;
827
828    if ((last - buf) + strlen(font_data->name) > XLFD_MAX_LEN)
829	return -1;
830
831    strcpy(last, font_data->name);
832    if ((font_data->xlfd_name = get_font_name(oc, buf)) != NULL)
833	return True;
834
835    /* This may mot be needed anymore as XListFonts() takes care of this */
836    while (num_fields < 12) {
837	if ((last - buf) > (XLFD_MAX_LEN - 2))
838	    return -1;
839	*last = '*';
840	*(last + 1) = '-';
841	strcpy(last + 2, font_data->name);
842	num_fields++;
843	last+=2;
844	if ((font_data->xlfd_name = get_font_name(oc, buf)) != NULL)
845	    return True;
846    }
847
848
849    return False;
850}
851
852
853typedef enum{C_PRIMARY, C_SUBSTITUTE, C_VMAP, C_VROTATE } ClassType;
854
855static int
856parse_fontdata(
857    XOC		 oc,
858    FontSet      font_set,
859    FontData	 font_data,
860    int		 font_data_count,
861    char	 **name_list,
862    int		 name_list_count,
863    ClassType	 class,
864    FontDataRec *font_data_return)
865{
866
867    char	**cur_name_list = name_list;
868    char	*font_name      = (char *) NULL;
869    char	*pattern        = (char *) NULL;
870    int		found_num       = 0, ret = 0;
871    int		count           = name_list_count;
872
873    if(name_list == NULL || count <= 0) {
874	return False;
875    }
876
877    if(font_data == NULL || font_data_count <= 0) {
878	return False;
879    }
880
881    /* Loop through each font encoding defined in the "font_data" FontSet. */
882    for ( ; font_data_count-- > 0; font_data++) {
883	Bool	is_found = False;
884	font_name = (char *) NULL;
885	count = name_list_count;
886	cur_name_list = name_list;
887
888       /*
889	* Loop through each font specified by the user
890	* in the call to XCreateFontset().
891	*/
892	while (count-- > 0) {
893            pattern = *cur_name_list++;
894	    if (pattern == NULL || *pattern == '\0')
895		continue;
896#ifdef FONTDEBUG
897		fprintf(stderr,"Font pattern: %s %s\n",
898		pattern,font_data->name);
899#endif
900
901	    /*
902	     * If the current font is fully specified (i.e., the
903	     * xlfd contains no wildcards) and the font exists on
904	     * the X Server, we have a match.
905	     */
906	    if (strchr(pattern, '*') == NULL &&
907		(font_name = get_font_name(oc, pattern))) {
908               /*
909		* Find the full xlfd name for this font. If the font is
910		* already in xlfd format, it is simply returned.  If the
911		* font is an alias for another font, the xlfd of the
912		* aliased font is returned.
913		*/
914		ret = parse_all_name(oc, font_data, font_name);
915		Xfree(font_name);
916
917                if (ret == -1)    return -1;
918	        if (ret == False) continue;
919               /*
920		* Since there was an exact match of a fully-specified font
921		* or a font alias, we can return now since the desired font
922		* was found for the current font encoding for this FontSet.
923		*
924		* Previous implementations of this algorithm would
925		* not return here. Instead, they continued searching
926		* through the font encodings for this FontSet. The side-effect
927		* of that behavior is you may return a "substitute" match
928		* instead of an "exact" match.  We believe there should be a
929		* preference on exact matches.  Therefore, as soon as we
930		* find one, we bail.
931		*
932		* Also, previous implementations seemed to think it was
933		* important to find either a primary or substitute font
934		* for each Font encoding in the FontSet before returning an
935		* acceptable font.  We don't believe this is necessary.
936		* All the client cares about is finding a reasonable font
937		* for what was passed in.  If we find an exact match,
938		* there's no reason to look any further.
939		*
940		* -- jjw/pma (HP)
941		*/
942		if (font_data_return) {
943		    font_data_return->xlfd_name = strdup(font_data->xlfd_name);
944		    if (!font_data_return->xlfd_name) return -1;
945
946		    font_data_return->side      = font_data->side;
947		}
948#ifdef FONTDEBUG
949		fprintf(stderr,"XLFD name: %s\n",font_data->xlfd_name);
950#endif
951
952		return True;
953	    }
954	    /*
955	     * If the font name is not fully specified
956	     * (i.e., it has wildcards), we have more work to do.
957	     * See the comments in parse_omit_name()
958	     * for the list of things to do.
959	     */
960	    ret = parse_omit_name(oc, font_data, pattern);
961
962            if (ret == -1)    return -1;
963	    if (ret == False) continue;
964
965           /*
966	    * A font which matched the wild-carded specification was found.
967	    * Only update the return data if a font has not yet been found.
968	    * This maintains the convention that FontSets listed higher in
969	    * a CodeSet in the Locale Database have higher priority than
970	    * those FontSets listed lower in the CodeSet.  In the following
971	    * example:
972	    *
973	    * fs1 {
974	    *        charset     HP-JIS:GR
975	    *        font        JISX0208.1990-0:GL;\
976	    *                    JISX0208.1990-1:GR;\
977	    *                    JISX0208.1983-0:GL;\
978	    *                    JISX0208.1983-1:GR
979	    * }
980	    *
981	    * a font found in the JISX0208.1990-0 FontSet will have a
982	    * higher priority than a font found in the JISX0208.1983-0
983	    * FontSet.
984	    */
985	    if (font_data_return && font_data_return->xlfd_name == NULL) {
986
987#ifdef FONTDEBUG
988		fprintf(stderr,"XLFD name: %s\n",font_data->xlfd_name);
989#endif
990		font_data_return->xlfd_name = strdup(font_data->xlfd_name);
991                if (!font_data_return->xlfd_name) return -1;
992
993	        font_data_return->side      = font_data->side;
994	    }
995
996	    found_num++;
997	    is_found = True;
998
999	    break;
1000	}
1001
1002	switch(class) {
1003	  case C_PRIMARY:
1004	       if(is_found == False) {
1005		 /*
1006		  * Did not find a font for the current FontSet.  Check the
1007		  * FontSet's "substitute" font for a match.  If we find a
1008		  * match, we'll keep searching in hopes of finding an exact
1009		  * match later down the FontSet list.
1010		  *
1011		  * when we return and we have found a font font_data_return
1012		  * contains the first (ie. best) match no matter if this
1013		  * is a C_PRIMARY or a C_SUBSTITUTE font
1014		  */
1015		  ret = parse_fontdata(oc, font_set, font_set->substitute,
1016				       font_set->substitute_num, name_list,
1017				       name_list_count, C_SUBSTITUTE,
1018				       font_data_return);
1019                  if (ret == -1)    return -1;
1020		  if (ret == False) continue;
1021
1022		  found_num++;
1023		  is_found = True;
1024               }
1025#ifdef TESTVERSION
1026	       else
1027		   return True;
1028#endif
1029	       break;
1030
1031	  case C_SUBSTITUTE:
1032	  case C_VMAP:
1033	       if(is_found == True)
1034		  return True;
1035	       break;
1036
1037	  case C_VROTATE:
1038	       if(is_found == True) {
1039		  char	*rotate_name;
1040
1041		  if((rotate_name = get_rotate_fontname(font_data->xlfd_name))
1042		     != NULL) {
1043		      Xfree(font_data->xlfd_name);
1044		      font_data->xlfd_name = rotate_name;
1045
1046		      return True;
1047		  }
1048		  Xfree(font_data->xlfd_name);
1049		  font_data->xlfd_name = NULL;
1050		  return False;
1051	       }
1052	       break;
1053	}
1054    }
1055
1056    if(class == C_PRIMARY && found_num >= 1)
1057	return True;
1058
1059    return False;
1060}
1061
1062
1063static int
1064parse_vw(
1065    XOC		oc,
1066    FontSet	font_set,
1067    char	**name_list,
1068    int		count)
1069{
1070    FontData	vmap = font_set->vmap;
1071    VRotate	vrotate = font_set->vrotate;
1072    int		vmap_num = font_set->vmap_num;
1073    int		vrotate_num = font_set->vrotate_num;
1074    int		ret = 0, i = 0;
1075
1076    if(vmap_num > 0) {
1077	if(parse_fontdata(oc, font_set, vmap, vmap_num, name_list,
1078			  count, C_VMAP,NULL) == -1)
1079	    return (-1);
1080    }
1081
1082    if(vrotate_num > 0) {
1083	ret = parse_fontdata(oc, font_set, (FontData) vrotate, vrotate_num,
1084			     name_list, count, C_VROTATE, NULL);
1085	if(ret == -1) {
1086	    return (-1);
1087	} else if(ret == False) {
1088	    CodeRange	code_range;
1089	    int		num_cr;
1090	    int		sub_num = font_set->substitute_num;
1091
1092	    code_range = vrotate[0].code_range; /* ? */
1093	    num_cr = vrotate[0].num_cr;         /* ? */
1094	    for(i = 0 ; i < vrotate_num ; i++) {
1095		if(vrotate[i].xlfd_name)
1096		    Xfree(vrotate[i].xlfd_name);
1097	    }
1098	    Xfree(vrotate);
1099
1100	    if(sub_num > 0) {
1101		vrotate = font_set->vrotate = Xmalloc
1102						(sizeof(VRotateRec) * sub_num);
1103		if(font_set->vrotate == (VRotate)NULL)
1104		    return (-1);
1105		memset(font_set->vrotate, 0x00, sizeof(VRotateRec) * sub_num);
1106
1107		for(i = 0 ; i < sub_num ; i++) {
1108		    vrotate[i].charset_name = font_set->substitute[i].name;
1109		    vrotate[i].side = font_set->substitute[i].side;
1110		    vrotate[i].code_range = code_range;
1111		    vrotate[i].num_cr = num_cr;
1112		}
1113		vrotate_num = font_set->vrotate_num = sub_num;
1114	    } else {
1115		vrotate = font_set->vrotate = (VRotate)NULL;
1116	    }
1117
1118	    ret = parse_fontdata(oc, font_set, (FontData) vrotate, vrotate_num,
1119				 name_list, count, C_VROTATE, NULL);
1120	    if(ret == -1)
1121		return (-1);
1122	}
1123    }
1124
1125    return True;
1126}
1127
1128static int
1129parse_fontname(
1130    XOC oc)
1131{
1132    XOCGenericPart *gen = XOC_GENERIC(oc);
1133    FontSet     font_set;
1134    FontDataRec font_data_return;
1135    char *base_name, **name_list;
1136    int font_set_num = 0;
1137    int found_num = 0;
1138    int count = 0;
1139    int	ret;
1140    int i;
1141
1142    name_list = _XParseBaseFontNameList(oc->core.base_name_list, &count);
1143    if (name_list == NULL)
1144	return -1;
1145
1146    font_set = gen->font_set;
1147    font_set_num = gen->font_set_num;
1148
1149   /* Loop through all of the CharSets defined in the Locale
1150    * database for the current Locale.
1151    */
1152    for( ; font_set_num-- > 0 ; font_set++) {
1153	if(font_set->font_name)
1154	    continue;
1155
1156	if(font_set->font_data_count > 0) {
1157
1158           /*
1159	    * If there are a non-zero number of FontSets defined
1160	    * for this CharSet.
1161            * Try to find a font for this CharSet.  If we find an
1162	    * acceptable font, we save the information for return
1163	    * to the client.  If we do not find an acceptable font,
1164	    * a "missing_charset" will be reported to the client
1165	    * for this CharSet.
1166	    */
1167	    font_data_return.xlfd_name  = NULL;
1168	    font_data_return.side       = XlcUnknown;
1169
1170	    ret = parse_fontdata(oc, font_set, font_set->font_data,
1171				 font_set->font_data_count,
1172				 name_list, count, C_PRIMARY,
1173				 &font_data_return);
1174	    if(ret == -1) {
1175		goto err;
1176	    } else if(ret == True) {
1177		/*
1178		 * We can't just loop thru fontset->font_data to
1179		 * find the first (ie. best) match: parse_fontdata
1180		 * will try a substitute font if no primary one could
1181		 * be matched. It returns the required information in
1182		 * font_data_return.
1183		 */
1184		font_set->font_name = strdup(font_data_return.xlfd_name);
1185		if(font_set->font_name == (char *) NULL)
1186		    goto err;
1187
1188		font_set->side = font_data_return.side;
1189
1190                Xfree (font_data_return.xlfd_name);
1191                font_data_return.xlfd_name = NULL;
1192
1193		if(parse_vw(oc, font_set, name_list, count) == -1)
1194		    goto err;
1195		found_num++;
1196	    }
1197
1198	} else if(font_set->substitute_num > 0) {
1199           /*
1200	    * If there are no FontSets defined for this
1201	    * CharSet.  We can only find "substitute" fonts.
1202	    */
1203	    ret = parse_fontdata(oc, font_set, font_set->substitute,
1204				 font_set->substitute_num,
1205				 name_list, count, C_SUBSTITUTE, NULL);
1206	    if(ret == -1) {
1207		goto err;
1208	    } else if(ret == True) {
1209		for(i=0;i<font_set->substitute_num;i++){
1210		    if(font_set->substitute[i].xlfd_name != NULL){
1211			break;
1212		    }
1213		}
1214		font_set->font_name = strdup(font_set->substitute[i].xlfd_name);
1215		if(font_set->font_name == (char *) NULL)
1216		    goto err;
1217
1218		font_set->side = font_set->substitute[i].side;
1219		if(parse_vw(oc, font_set, name_list, count) == -1)
1220		    goto err;
1221
1222		found_num++;
1223	    }
1224	}
1225    }
1226
1227    base_name = strdup(oc->core.base_name_list);
1228    if (base_name == NULL)
1229	goto err;
1230
1231    oc->core.base_name_list = base_name;
1232
1233    XFreeStringList(name_list);
1234
1235    return found_num;
1236
1237err:
1238    XFreeStringList(name_list);
1239    /* Prevent this from being freed twice */
1240    oc->core.base_name_list = NULL;
1241
1242    return -1;
1243}
1244
1245/* For VW/UDC end*/
1246
1247static Bool
1248set_missing_list(
1249    XOC oc)
1250{
1251    XOCGenericPart *gen = XOC_GENERIC(oc);
1252    FontSet font_set;
1253    char **charset_list, *charset_buf;
1254    int	count, length, font_set_num;
1255    int result = 1;
1256
1257    font_set = gen->font_set;
1258    font_set_num = gen->font_set_num;
1259    count = length = 0;
1260
1261    for ( ; font_set_num-- > 0; font_set++) {
1262	if (font_set->info || font_set->font) {
1263	    continue;
1264	}
1265
1266	/* Change 1996.01.23 start */
1267	if(font_set->font_data_count <= 0 ||
1268	   font_set->font_data == (FontData)NULL) {
1269	    if(font_set->substitute_num <= 0 ||
1270	       font_set->substitute == (FontData)NULL) {
1271		if(font_set->charset_list != NULL){
1272		 length +=
1273		  strlen(font_set->charset_list[0]->encoding_name) + 1;
1274		} else {
1275		  length += 1;
1276		}
1277	    } else {
1278		length += strlen(font_set->substitute->name) + 1;
1279	    }
1280	} else {
1281	    length += strlen(font_set->font_data->name) + 1;
1282	}
1283	/* Change 1996.01.23 end */
1284	count++;
1285    }
1286
1287    if (count < 1) {
1288	return True;
1289    }
1290
1291    charset_list = Xmalloc(sizeof(char *) * count);
1292    if (charset_list == NULL) {
1293	return False;
1294    }
1295
1296    charset_buf = Xmalloc(length);
1297    if (charset_buf == NULL) {
1298	Xfree(charset_list);
1299	return False;
1300    }
1301
1302    oc->core.missing_list.charset_list = charset_list;
1303    oc->core.missing_list.charset_count = count;
1304
1305    font_set = gen->font_set;
1306    font_set_num = gen->font_set_num;
1307
1308    for ( ; font_set_num-- > 0; font_set++) {
1309	if (font_set->info || font_set->font) {
1310	    continue;
1311	}
1312
1313	/* Change 1996.01.23 start */
1314	if(font_set->font_data_count <= 0 ||
1315	   font_set->font_data == (FontData)NULL) {
1316	    if(font_set->substitute_num <= 0 ||
1317	       font_set->substitute == (FontData)NULL) {
1318		if(font_set->charset_list != NULL){
1319		 strcpy(charset_buf,
1320			font_set->charset_list[0]->encoding_name);
1321		} else {
1322		 strcpy(charset_buf, "");
1323		}
1324		result = 0;
1325	    } else {
1326		strcpy(charset_buf, font_set->substitute->name);
1327	    }
1328	} else {
1329	    strcpy(charset_buf, font_set->font_data->name);
1330	}
1331	/* Change 1996.01.23 end */
1332	*charset_list++ = charset_buf;
1333	charset_buf += strlen(charset_buf) + 1;
1334    }
1335
1336    if(result == 0) {
1337	return(False);
1338    }
1339
1340    return True;
1341}
1342
1343static Bool
1344create_fontset(
1345    XOC oc)
1346{
1347    XOMGenericPart *gen = XOM_GENERIC(oc->core.om);
1348    int found_num;
1349
1350    if (init_fontset(oc) == False)
1351        return False;
1352
1353    found_num = parse_fontname(oc);
1354    if (found_num <= 0) {
1355	if (found_num == 0)
1356	    set_missing_list(oc);
1357	return False;
1358    }
1359
1360    if (gen->on_demand_loading == True) {
1361	if (load_font_info(oc) == False)
1362	    return False;
1363    } else {
1364	if (load_font(oc) == False)
1365	    return False;
1366    }
1367
1368    if (init_core_part(oc) == False)
1369	return False;
1370
1371    if (set_missing_list(oc) == False)
1372	return False;
1373
1374    return True;
1375}
1376
1377/* For VW/UDC start */
1378static void
1379free_fontdataOC(
1380    Display	*dpy,
1381    FontData	font_data,
1382    int		font_data_count)
1383{
1384    for( ; font_data_count-- ; font_data++) {
1385	if(font_data->xlfd_name){
1386	    Xfree(font_data->xlfd_name);
1387	    font_data->xlfd_name = NULL;
1388	}
1389	if(font_data->font){				/* ADD 1996.01.7 */
1390	    if(font_data->font->fid)			/* Add 1996.01.23 */
1391		XFreeFont(dpy,font_data->font);		/* ADD 1996.01.7 */
1392	    else					/* Add 1996.01.23 */
1393		XFreeFontInfo(NULL, font_data->font, 1);/* Add 1996.01.23 */
1394	    font_data->font = NULL;
1395	}
1396/*
1397 * font_data->name and font_data->scopes belong to the OM not OC.
1398 * To save space this data is shared between OM and OC. We are
1399 * not allowed to free it here.
1400 * It has been moved to free_fontdataOM()
1401 */
1402/*
1403	if(font_data->scopes){
1404	    Xfree(font_data->scopes);
1405	    font_data->scopes = NULL;
1406	}
1407	if(font_data->name){
1408	    Xfree(font_data->name);
1409	    font_data->name = NULL;
1410	}
1411*/
1412    }
1413}
1414
1415static void destroy_fontdata(
1416    XOCGenericPart *gen,
1417    Display *dpy)
1418{
1419    FontSet	font_set = (FontSet) NULL;
1420    int		font_set_num = 0;
1421
1422    if (gen->font_set) {
1423	font_set = gen->font_set;
1424	font_set_num = gen->font_set_num;
1425	for( ; font_set_num-- ; font_set++) {
1426	    if (font_set->font) {
1427		if(font_set->font->fid)
1428		    XFreeFont(dpy,font_set->font);
1429		else
1430		    XFreeFontInfo(NULL, font_set->font, 1);
1431		font_set->font = NULL;
1432	    }
1433	    if(font_set->font_data) {
1434		if (font_set->info)
1435		    XFreeFontInfo(NULL, font_set->info, 1);
1436		free_fontdataOC(dpy,
1437			font_set->font_data, font_set->font_data_count);
1438		Xfree(font_set->font_data);
1439		font_set->font_data = NULL;
1440	    }
1441	    if(font_set->substitute) {
1442		free_fontdataOC(dpy,
1443			font_set->substitute, font_set->substitute_num);
1444		Xfree(font_set->substitute);
1445		font_set->substitute = NULL;
1446	    }
1447	    if(font_set->vmap) {
1448		free_fontdataOC(dpy,
1449			font_set->vmap, font_set->vmap_num);
1450		Xfree(font_set->vmap);
1451		font_set->vmap = NULL;
1452	    }
1453	    if(font_set->vrotate) {
1454		free_fontdataOC(dpy,
1455			(FontData)font_set->vrotate,
1456			      font_set->vrotate_num);
1457		Xfree(font_set->vrotate);
1458		font_set->vrotate = NULL;
1459	    }
1460	}
1461	Xfree(gen->font_set);
1462	gen->font_set = NULL;
1463    }
1464}
1465/* For VW/UDC end */
1466
1467static void
1468destroy_oc(
1469    XOC oc)
1470{
1471    Display *dpy = oc->core.om->core.display;
1472    XOCGenericPart *gen = XOC_GENERIC(oc);
1473
1474    if (gen->mbs_to_cs)
1475	_XlcCloseConverter(gen->mbs_to_cs);
1476
1477    if (gen->wcs_to_cs)
1478	_XlcCloseConverter(gen->wcs_to_cs);
1479
1480    if (gen->utf8_to_cs)
1481	_XlcCloseConverter(gen->utf8_to_cs);
1482
1483/* For VW/UDC start */ /* Change 1996.01.8 */
1484    destroy_fontdata(gen,dpy);
1485/*
1486*/
1487/* For VW/UDC end */
1488
1489    if (oc->core.base_name_list)
1490	Xfree(oc->core.base_name_list);
1491
1492    if (oc->core.font_info.font_name_list)
1493	XFreeStringList(oc->core.font_info.font_name_list);
1494
1495    if (oc->core.font_info.font_struct_list) {
1496	Xfree(oc->core.font_info.font_struct_list);
1497    }
1498
1499    if (oc->core.missing_list.charset_list)
1500	XFreeStringList(oc->core.missing_list.charset_list);
1501
1502#ifdef notdef
1503    if (oc->core.res_name)
1504	Xfree(oc->core.res_name);
1505    if (oc->core.res_class)
1506	Xfree(oc->core.res_class);
1507#endif
1508
1509    Xfree(oc);
1510}
1511
1512static char *
1513set_oc_values(
1514    XOC oc,
1515    XlcArgList args,
1516    int num_args)
1517{
1518    XOCGenericPart *gen = XOC_GENERIC(oc);
1519    FontSet font_set = gen->font_set;
1520    char *ret;
1521    int num = gen->font_set_num;
1522
1523    if (oc->core.resources == NULL)
1524	return NULL;
1525
1526    ret = _XlcSetValues((XPointer) oc, oc->core.resources,
1527			oc->core.num_resources, args, num_args, XlcSetMask);
1528    if(ret != NULL){
1529	return(ret);
1530    } else {
1531	for ( ; num-- > 0; font_set++) {
1532	    if (font_set->font_name == NULL)
1533	        continue;
1534	    if (font_set->vpart_initialize != 0)
1535	        continue;
1536	    if( oc->core.orientation == XOMOrientation_TTB_RTL ||
1537		oc->core.orientation == XOMOrientation_TTB_LTR ){
1538	    	load_fontdata(oc, font_set->vmap, font_set->vmap_num);
1539		load_fontdata(oc, (FontData) font_set->vrotate,
1540			    font_set->vrotate_num);
1541		font_set->vpart_initialize = 1;
1542	    }
1543	}
1544	return(NULL);
1545    }
1546}
1547
1548static char *
1549get_oc_values(
1550    XOC oc,
1551    XlcArgList args,
1552    int num_args)
1553{
1554    if (oc->core.resources == NULL)
1555	return NULL;
1556
1557    return _XlcGetValues((XPointer) oc, oc->core.resources,
1558			 oc->core.num_resources, args, num_args, XlcGetMask);
1559}
1560
1561static XOCMethodsRec oc_default_methods = {
1562    destroy_oc,
1563    set_oc_values,
1564    get_oc_values,
1565    _XmbDefaultTextEscapement,
1566    _XmbDefaultTextExtents,
1567    _XmbDefaultTextPerCharExtents,
1568    _XmbDefaultDrawString,
1569    _XmbDefaultDrawImageString,
1570    _XwcDefaultTextEscapement,
1571    _XwcDefaultTextExtents,
1572    _XwcDefaultTextPerCharExtents,
1573    _XwcDefaultDrawString,
1574    _XwcDefaultDrawImageString,
1575    _Xutf8DefaultTextEscapement,
1576    _Xutf8DefaultTextExtents,
1577    _Xutf8DefaultTextPerCharExtents,
1578    _Xutf8DefaultDrawString,
1579    _Xutf8DefaultDrawImageString
1580};
1581
1582static XOCMethodsRec oc_generic_methods = {
1583    destroy_oc,
1584    set_oc_values,
1585    get_oc_values,
1586    _XmbGenericTextEscapement,
1587    _XmbGenericTextExtents,
1588    _XmbGenericTextPerCharExtents,
1589    _XmbGenericDrawString,
1590    _XmbGenericDrawImageString,
1591    _XwcGenericTextEscapement,
1592    _XwcGenericTextExtents,
1593    _XwcGenericTextPerCharExtents,
1594    _XwcGenericDrawString,
1595    _XwcGenericDrawImageString,
1596    _Xutf8GenericTextEscapement,
1597    _Xutf8GenericTextExtents,
1598    _Xutf8GenericTextPerCharExtents,
1599    _Xutf8GenericDrawString,
1600    _Xutf8GenericDrawImageString
1601};
1602
1603typedef struct _XOCMethodsListRec {
1604    const char *name;
1605    XOCMethods methods;
1606} XOCMethodsListRec, *XOCMethodsList;
1607
1608static XOCMethodsListRec oc_methods_list[] = {
1609    { "default", &oc_default_methods },
1610    { "generic", &oc_generic_methods }
1611};
1612
1613static XlcResource oc_resources[] = {
1614    { XNBaseFontName, NULLQUARK, sizeof(char *),
1615      XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask },
1616    { XNOMAutomatic, NULLQUARK, sizeof(Bool),
1617      XOffsetOf(XOCRec, core.om_automatic), XlcGetMask },
1618    { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList),
1619      XOffsetOf(XOCRec, core.missing_list), XlcGetMask },
1620    { XNDefaultString, NULLQUARK, sizeof(char *),
1621      XOffsetOf(XOCRec, core.default_string), XlcGetMask },
1622    { XNOrientation, NULLQUARK, sizeof(XOrientation),
1623      XOffsetOf(XOCRec, core.orientation), XlcDefaultMask | XlcSetMask | XlcGetMask },
1624    { XNResourceName, NULLQUARK, sizeof(char *),
1625      XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask },
1626    { XNResourceClass, NULLQUARK, sizeof(char *),
1627      XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask },
1628    { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo),
1629      XOffsetOf(XOCRec, core.font_info), XlcGetMask }
1630};
1631
1632static XOC
1633create_oc(
1634    XOM om,
1635    XlcArgList args,
1636    int num_args)
1637{
1638    XOC oc;
1639    XOMGenericPart *gen = XOM_GENERIC(om);
1640    XOCMethodsList methods_list = oc_methods_list;
1641    int count;
1642
1643    oc = Xcalloc(1, sizeof(XOCGenericRec));
1644    if (oc == NULL)
1645	return (XOC) NULL;
1646
1647    oc->core.om = om;
1648
1649    if (oc_resources[0].xrm_name == NULLQUARK)
1650	_XlcCompileResourceList(oc_resources, XlcNumber(oc_resources));
1651
1652    if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources),
1653		      args, num_args, XlcCreateMask | XlcDefaultMask))
1654	goto err;
1655
1656    if (oc->core.base_name_list == NULL)
1657	goto err;
1658
1659    oc->core.resources = oc_resources;
1660    oc->core.num_resources = XlcNumber(oc_resources);
1661
1662    if (create_fontset(oc) == False)
1663	goto err;
1664
1665    oc->methods = &oc_generic_methods;
1666
1667    if (gen->object_name) {
1668	count = XlcNumber(oc_methods_list);
1669
1670	for ( ; count-- > 0; methods_list++) {
1671	    if (!_XlcCompareISOLatin1(gen->object_name, methods_list->name)) {
1672		oc->methods = methods_list->methods;
1673		break;
1674	    }
1675	}
1676    }
1677
1678    return oc;
1679
1680err:
1681    destroy_oc(oc);
1682
1683    return (XOC) NULL;
1684}
1685
1686static void
1687free_fontdataOM(
1688    FontData	font_data,
1689    int		font_data_count)
1690{
1691    for( ; font_data_count-- ; font_data++) {
1692	if(font_data->name){
1693	    Xfree(font_data->name);
1694	    font_data->name = NULL;
1695	}
1696	if(font_data->scopes){
1697	    Xfree(font_data->scopes);
1698	    font_data->scopes = NULL;
1699	}
1700    }
1701}
1702
1703static Status
1704close_om(
1705    XOM om)
1706{
1707    XOMGenericPart *gen = XOM_GENERIC(om);
1708    OMData data;
1709    int count;
1710
1711    if ((data = gen->data)) {
1712	for (count = gen->data_num; count-- > 0; data++) {
1713	    if (data->charset_list){
1714		Xfree(data->charset_list);
1715		data->charset_list = NULL;
1716	    }
1717	    /* free font_data for om */
1718	    if (data->font_data) {
1719		free_fontdataOM(data->font_data,data->font_data_count);
1720		Xfree(data->font_data);
1721		data->font_data = NULL;
1722	    }
1723	    /* free substitute for om */
1724	    if (data->substitute) {
1725		free_fontdataOM(data->substitute,data->substitute_num);
1726		Xfree(data->substitute);
1727		data->substitute = NULL;
1728	    }
1729	    /* free vmap for om */
1730	    if (data->vmap) {
1731		free_fontdataOM(data->vmap,data->vmap_num);
1732		Xfree(data->vmap);
1733		data->vmap = NULL;
1734	    }
1735	    /* free vrotate for om */
1736	    if (data->vrotate) {
1737		Xfree(data->vrotate);
1738		data->vrotate = NULL;
1739	    }
1740	}
1741	Xfree(gen->data);
1742	gen->data = NULL;
1743    }
1744
1745    if (gen->object_name){
1746	Xfree(gen->object_name);
1747	gen->object_name = NULL;
1748    }
1749
1750    if (om->core.res_name){
1751	Xfree(om->core.res_name);
1752	om->core.res_name = NULL;
1753    }
1754    if (om->core.res_class){
1755	Xfree(om->core.res_class);
1756	om->core.res_class = NULL;
1757    }
1758    if (om->core.required_charset.charset_list &&
1759	om->core.required_charset.charset_count > 0){
1760	XFreeStringList(om->core.required_charset.charset_list);
1761	om->core.required_charset.charset_list = NULL;
1762    } else {
1763	Xfree((char*)om->core.required_charset.charset_list);
1764	om->core.required_charset.charset_list = NULL;
1765    }
1766    if (om->core.orientation_list.orientation){
1767	Xfree(om->core.orientation_list.orientation);
1768	om->core.orientation_list.orientation = NULL;
1769    }
1770
1771    Xfree(om);
1772
1773    return 1;
1774}
1775
1776static char *
1777set_om_values(
1778    XOM om,
1779    XlcArgList args,
1780    int num_args)
1781{
1782    if (om->core.resources == NULL)
1783	return NULL;
1784
1785    return _XlcSetValues((XPointer) om, om->core.resources,
1786			 om->core.num_resources, args, num_args, XlcSetMask);
1787}
1788
1789static char *
1790get_om_values(
1791    XOM om,
1792    XlcArgList args,
1793    int num_args)
1794{
1795    if (om->core.resources == NULL)
1796	return NULL;
1797
1798    return _XlcGetValues((XPointer) om, om->core.resources,
1799			 om->core.num_resources, args, num_args, XlcGetMask);
1800}
1801
1802static XOMMethodsRec methods = {
1803    close_om,
1804    set_om_values,
1805    get_om_values,
1806    create_oc
1807};
1808
1809static XlcResource om_resources[] = {
1810    { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList),
1811      XOffsetOf(XOMRec, core.required_charset), XlcGetMask },
1812    { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation),
1813      XOffsetOf(XOMRec, core.orientation_list), XlcGetMask },
1814    { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool),
1815      XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask },
1816    { XNContextualDrawing, NULLQUARK, sizeof(Bool),
1817      XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask }
1818};
1819
1820static XOM
1821create_om(
1822    XLCd lcd,
1823    Display *dpy,
1824    XrmDatabase rdb,
1825    _Xconst char *res_name,
1826    _Xconst char *res_class)
1827{
1828    XOM om;
1829
1830    om = Xcalloc(1, sizeof(XOMGenericRec));
1831    if (om == NULL)
1832	return (XOM) NULL;
1833
1834    om->methods = &methods;
1835    om->core.lcd = lcd;
1836    om->core.display = dpy;
1837    om->core.rdb = rdb;
1838    if (res_name) {
1839	om->core.res_name = strdup(res_name);
1840	if (om->core.res_name == NULL)
1841	    goto err;
1842    }
1843    if (res_class) {
1844	om->core.res_class = strdup(res_class);
1845	if (om->core.res_class == NULL)
1846	    goto err;
1847    }
1848
1849    if (om_resources[0].xrm_name == NULLQUARK)
1850	_XlcCompileResourceList(om_resources, XlcNumber(om_resources));
1851
1852    om->core.resources = om_resources;
1853    om->core.num_resources = XlcNumber(om_resources);
1854
1855    return om;
1856
1857err:
1858    close_om(om);
1859
1860    return (XOM) NULL;
1861}
1862
1863static OMData
1864add_data(
1865    XOM om)
1866{
1867    XOMGenericPart *gen = XOM_GENERIC(om);
1868    OMData new;
1869    int num;
1870
1871    if ((num = gen->data_num))
1872        new = Xrealloc(gen->data, (num + 1) * sizeof(OMDataRec));
1873    else
1874        new = Xmalloc(sizeof(OMDataRec));
1875
1876    if (new == NULL)
1877        return NULL;
1878
1879    gen->data_num = num + 1;
1880    gen->data = new;
1881
1882    new += num;
1883    bzero((char *) new, sizeof(OMDataRec));
1884
1885    return new;
1886}
1887
1888/* For VW/UDC */
1889
1890FontData
1891read_EncodingInfo(
1892    int count,
1893    char **value)
1894{
1895    FontData font_data,ret;
1896    char *buf, *bufptr,*scp;
1897    int len;
1898    font_data = Xcalloc(count, sizeof(FontDataRec));
1899    if (font_data == NULL)
1900        return NULL;
1901
1902    ret = font_data;
1903    for ( ; count-- > 0; font_data++) {
1904/*
1905        strcpy(buf, *value++);
1906*/
1907	buf = *value; value++;
1908        if ((bufptr = strchr(buf, ':'))) {
1909	    len = (int)(bufptr - buf);
1910            bufptr++ ;
1911	} else
1912            len = strlen(buf);
1913        font_data->name = Xmalloc(len + 1);
1914        if (font_data->name == NULL) {
1915            Xfree(font_data);
1916            return NULL;
1917	}
1918        strncpy(font_data->name, buf,len);
1919	font_data->name[len] = 0;
1920        if (bufptr && _XlcCompareISOLatin1(bufptr, "GL") == 0)
1921            font_data->side = XlcGL;
1922        else if (bufptr && _XlcCompareISOLatin1(bufptr, "GR") == 0)
1923            font_data->side = XlcGR;
1924        else
1925            font_data->side = XlcGLGR;
1926
1927        if (bufptr && (scp = strchr(bufptr, '['))){
1928            font_data->scopes = _XlcParse_scopemaps(scp,&(font_data->scopes_num));
1929        }
1930    }
1931    return(ret);
1932}
1933
1934static CodeRange read_vrotate(
1935    int count,
1936    char **value,
1937    int *type,
1938    int *vrotate_num)
1939{
1940    CodeRange   range;
1941    if(!strcmp(value[0],"all")){
1942	*type 	     = VROTATE_ALL ;
1943	*vrotate_num = 0 ;
1944	return (NULL);
1945    } else if(*(value[0]) == '['){
1946	*type 	     = VROTATE_PART ;
1947        range = (CodeRange) _XlcParse_scopemaps(value[0],vrotate_num);
1948	return (range);
1949    } else {
1950	*type 	     = VROTATE_NONE ;
1951	*vrotate_num = 0 ;
1952	return (NULL);
1953    }
1954}
1955
1956static void read_vw(
1957    XLCd    lcd,
1958    OMData  font_set,
1959    int     num)
1960{
1961    char **value, buf[BUFSIZ];
1962    int count;
1963
1964    snprintf(buf, sizeof(buf), "fs%d.font.vertical_map", num);
1965    _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
1966    if (count > 0){
1967        _XlcDbg_printValue(buf,value,count);
1968        font_set->vmap_num = count;
1969        font_set->vmap = read_EncodingInfo(count,value);
1970    }
1971
1972    snprintf(buf, sizeof(buf), "fs%d.font.vertical_rotate", num);
1973    _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
1974    if (count > 0){
1975        _XlcDbg_printValue(buf,value,count);
1976        font_set->vrotate = read_vrotate(count,value,&(font_set->vrotate_type),
1977				&(font_set->vrotate_num));
1978    }
1979}
1980/* VW/UDC end */
1981static Bool
1982init_om(
1983    XOM om)
1984{
1985    XLCd lcd = om->core.lcd;
1986    XOMGenericPart *gen = XOM_GENERIC(om);
1987    OMData data;
1988    XlcCharSet *charset_list;
1989    FontData font_data;
1990    char **required_list;
1991    XOrientation *orientation;
1992    char **value, buf[BUFSIZ], *bufptr;
1993    int count = 0, num = 0, length = 0;
1994
1995    _XlcGetResource(lcd, "XLC_FONTSET", "on_demand_loading", &value, &count);
1996    if (count > 0 && _XlcCompareISOLatin1(*value, "True") == 0)
1997	gen->on_demand_loading = True;
1998
1999    _XlcGetResource(lcd, "XLC_FONTSET", "object_name", &value, &count);
2000    if (count > 0) {
2001	gen->object_name = strdup(*value);
2002	if (gen->object_name == NULL)
2003	    return False;
2004    }
2005
2006    for (num = 0; ; num++) {
2007
2008        snprintf(buf, sizeof(buf), "fs%d.charset.name", num);
2009        _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
2010
2011        if( count < 1){
2012            snprintf(buf, sizeof(buf), "fs%d.charset", num);
2013            _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
2014            if (count < 1)
2015                break;
2016        }
2017
2018	data = add_data(om);
2019	if (data == NULL)
2020	    return False;
2021
2022	charset_list = Xmalloc(sizeof(XlcCharSet) * count);
2023	if (charset_list == NULL)
2024	    return False;
2025	data->charset_list = charset_list;
2026	data->charset_count = count;
2027
2028	while (count-- > 0){
2029	    *charset_list++ = _XlcGetCharSet(*value++);
2030        }
2031        snprintf(buf, sizeof(buf), "fs%d.charset.udc_area", num);
2032        _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
2033        if( count > 0){
2034            UDCArea udc;
2035            int i,flag = 0;
2036            udc = Xmalloc(count * sizeof(UDCAreaRec));
2037	    if (udc == NULL)
2038	        return False;
2039            for(i=0;i<count;i++){
2040                sscanf(value[i],"\\x%lx,\\x%lx", &(udc[i].start),
2041		       &(udc[i].end));
2042            }
2043            for(i=0;i<data->charset_count;i++){
2044		if(data->charset_list[i]->udc_area == NULL){
2045		    data->charset_list[i]->udc_area     = udc;
2046		    data->charset_list[i]->udc_area_num = count;
2047		    flag = 1;
2048		}
2049            }
2050	    if(flag == 0){
2051		Xfree(udc);
2052	    }
2053        }
2054
2055        snprintf(buf, sizeof(buf), "fs%d.font.primary", num);
2056        _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
2057        if (count < 1){
2058            snprintf(buf, sizeof(buf), "fs%d.font", num);
2059            _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
2060            if (count < 1)
2061                return False;
2062        }
2063
2064	font_data = read_EncodingInfo(count,value);
2065	if (font_data == NULL)
2066	    return False;
2067
2068	data->font_data = font_data;
2069	data->font_data_count = count;
2070
2071        snprintf(buf, sizeof(buf), "fs%d.font.substitute", num);
2072        _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
2073        if (count > 0){
2074            font_data = read_EncodingInfo(count,value);
2075            if (font_data == NULL)
2076	        return False;
2077            data->substitute      = font_data;
2078            data->substitute_num = count;
2079        } else {
2080            snprintf(buf, sizeof(buf), "fs%d.font", num);
2081            _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
2082            if (count < 1) {
2083                data->substitute      = NULL;
2084                data->substitute_num = 0;
2085	    } else {
2086                font_data = read_EncodingInfo(count,value);
2087                data->substitute      = font_data;
2088                data->substitute_num = count;
2089	    }
2090	}
2091        read_vw(lcd,data,num);
2092	length += strlen(data->font_data->name) + 1;
2093    }
2094
2095    /* required charset list */
2096    required_list = Xmalloc(sizeof(char *) * gen->data_num);
2097    if (required_list == NULL)
2098	return False;
2099
2100    om->core.required_charset.charset_list = required_list;
2101    om->core.required_charset.charset_count = gen->data_num;
2102
2103    count = gen->data_num;
2104    data = gen->data;
2105
2106    if (count > 0) {
2107	bufptr = Xmalloc(length);
2108	if (bufptr == NULL) {
2109	    Xfree(required_list);
2110	    return False;
2111	}
2112
2113	for ( ; count-- > 0; data++) {
2114	    strcpy(bufptr, data->font_data->name);
2115	    *required_list++ = bufptr;
2116	    bufptr += strlen(bufptr) + 1;
2117	}
2118    }
2119
2120    /* orientation list */
2121    orientation = Xmalloc(sizeof(XOrientation) * 2);
2122    if (orientation == NULL)
2123	return False;
2124
2125    orientation[0] = XOMOrientation_LTR_TTB;
2126    orientation[1] = XOMOrientation_TTB_RTL;
2127    om->core.orientation_list.orientation = orientation;
2128    om->core.orientation_list.num_orientation = 2;
2129
2130    /* directional dependent drawing */
2131    om->core.directional_dependent = False;
2132
2133    /* contexual drawing */
2134    om->core.contextual_drawing = False;
2135
2136    /* context dependent */
2137    om->core.context_dependent = False;
2138
2139    return True;
2140}
2141
2142XOM
2143_XomGenericOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb,
2144		  _Xconst char *res_name, _Xconst char *res_class)
2145{
2146    XOM om;
2147
2148    om = create_om(lcd, dpy, rdb, res_name, res_class);
2149    if (om == NULL)
2150	return (XOM) NULL;
2151
2152    if (init_om(om) == False)
2153	goto err;
2154
2155    return om;
2156
2157err:
2158    close_om(om);
2159
2160    return (XOM) NULL;
2161}
2162
2163Bool
2164_XInitOM(
2165    XLCd lcd)
2166{
2167    lcd->methods->open_om = _XomGenericOpenOM;
2168
2169    return True;
2170}
2171