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