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