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