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