4.4BSD/usr/src/contrib/X11R5-lib/lib/X/Xsi/XCrFntSet.c

Compare this file to the similar file:
Show the results in this format:

/*
 * $XConsortium: XCrFntSet.c,v 1.48 92/09/10 17:06:53 rws Exp $
 */

/*
 * Copyright 1990, 1991 by OMRON Corporation, NTT Software Corporation,
 *                      and Nippon Telegraph and Telephone Corporation
 * Copyright 1991 by the Massachusetts Institute of Technology
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the names of OMRON, NTT Software, NTT, and M.I.T.
 * not be used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission. OMRON, NTT Software,
 * NTT, and M.I.T. make no representations about the suitability of this
 * software for any purpose.  It is provided "as is" without express or
 * implied warranty.
 *
 * OMRON, NTT SOFTWARE, NTT, AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD
 * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS, IN NO EVENT SHALL OMRON, NTT SOFTWARE, NTT, OR M.I.T. BE
 * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 * 
 *	Authors: Li Yuhong		OMRON Corporation
 *		 Tatsuya Kato		NTT Software Corporation
 *		 Hiroshi Kuribayashi	OMRON Coproration
 *		 Muneiyoshi Suzuki	Nippon Telegraph and Telephone Co.
 *   
 */

/*
 * _XsiCreateFontSet()
 * XmlCreateFontSet()
 * _XsiQueryFontSetFromId()
 * _XsiQueryFontSetWithName()
 *
 */
#include <X11/Xatom.h>
#include "Xlibint.h"
#include "Xi18nint.h"
#include <X11/Xos.h>

#ifdef DEBUG
#include <stdio.h>
#endif
#include <ctype.h>

#define PRELOAD                 1      /* preload fonts if locale exists */ 

#ifdef DEBUG
#define dbg_printf(f, p1, p2)   fprintf(stderr, f, p1, p2)
#else
#define dbg_printf(f, p1, p2)
#endif

#define XFNEXT_PREFIX	'+'     /* XLFD External prefix */
#define XFNDELIM	'-'     /* XLFD Delimiter */
#define DELIM_COUNT	13      /* Number of delimiters */
#define CSETPOS		13      /* CHARSET-REGISTRY position */

#if __STDC__ && !defined(NORCONST)
#define RConst const
#else
#define RConst /**/
#endif

/*ARGSUSED*/
static void
_XsiFreeFontSet(dpy, font_set)
    Display        *dpy;
    XFontSet        font_set;
{
    if (((XsiFontSet)font_set)->xlc)
	_XlcFreeLocale(((XsiFontSet)font_set)->xlc);
    if (font_set->core.num_of_fonts > 0)
	Xfree((char *) ((XsiFontSet)font_set)->ctid);
}

static RConst XFontSetMethodsRec fs_methods = {
    _XsiFreeFontSet,
    _XsimbTextEscapement,
    _XsimbTextExtents,
    _XsimbTextPerCharExtents,
    _XsimbDrawString,
    _XsimbDrawImageString,
    _XsiwcTextEscapement,
    _XsiwcTextExtents,
    _XsiwcTextPerCharExtents,
    _XsiwcDrawString,
    _XsiwcDrawImageString
};

static RConst XFontSetMethodsRec fs8_methods = {
    _XsiFreeFontSet,
    _Xsimb8TextEscapement,
    _Xsimb8TextExtents,
    _XsimbTextPerCharExtents,
    _Xsimb8DrawString,
    _Xsimb8DrawImageString,
    _XsiwcTextEscapement,
    _XsiwcTextExtents,
    _XsiwcTextPerCharExtents,
    _XsiwcDrawString,
    _XsiwcDrawImageString
};

#define lowercase(c)        ((isalpha(c) && isupper(c)) ? tolower(c) : c)

#if defined(MUSTCOPY)
static void
SetFontInfo(des, src)
XFontStruct *des, *src ;
{
    des->ext_data = src->ext_data;    
    des->fid = src->fid;              
    des->direction = src->direction;  
    des->min_char_or_byte2 = src->min_char_or_byte2;
    des->max_char_or_byte2 = src->max_char_or_byte2;
    des->min_byte1 = src->min_byte1;     
    des->max_byte1 = src->max_byte1;     
    des->all_chars_exist = src->all_chars_exist;  
    des->default_char = src->default_char;
    des->n_properties = src->n_properties;
    des->properties = src->properties;
    des->min_bounds = src->min_bounds;
    des->max_bounds = src->max_bounds;
    des->per_char = src->per_char; 
    des->ascent = src->ascent;  
    des->descent = src->descent;
}
#endif

static int
compareLowercase(s1, s2)
char    *s1;
char    *s2;
{
    register char c1, c2;

    while ((c1 = *s1) && (c2 = *s2)) {
        c1 = lowercase(c1);
        c2 = lowercase(c2);
        if (c1 != c2)
            break;
        s1++, s2++;
    }
    /*
     * do not use c1 and c2 here.
     */
    return (*s1 - *s2);
}

static int
compareNLowercase(s1, s2, n)
char    *s1;
char    *s2;
int      n;
{
    register char c1, c2;

    while ((n > 0) && (c1 = *s1) && (c2 = *s2)) {
        c1 = lowercase(c1);
        c2 = lowercase(c2);
        if (c1 != c2)
            break;
        s1++, s2++, n--;
    }
    /*
     * do not use c1 and c2 here.
     * in the case, if (c1 = *s1) is NULL, stop while, so no value of c2.
     */
    return (n == 0)? 0: (*s1 - *s2);
}

#ifdef XML
static char *
copyLowercase(s1, s2)
char    *s1, *s2;
{
    register char c;

    while (c = *s2++)
        *s1++ = lowercase(c);
    *s1 = 0;
    return s1;
}
#endif


static char **
reallocList(list, count)
char           *list[];
int             count;
{
    char          **ret;
    int             i, j;
    int		    datalen;
    char	   *data;

    ret = (char **) Xmalloc((unsigned)sizeof(char *) * (count + 1));
    if (!ret) return NULL;

    datalen = 0;
    for (i = 0, j = 0; j < count; i++) {
	if (list[i]) {
	    datalen += strlen(list[i]);
	    j++;
	}
    }
    data = (char *) Xmalloc ((unsigned)(datalen + count) * sizeof (char));
    if (!data) {
	Xfree ((char *) ret);
	return NULL;
    }
    for (i = 0, j = 0; j < count; i++) {
	if (list[i]) {
	    ret[j] = data;
	    strcpy(data, list[i]);
	    data += strlen(list[i]) + 1;
	    j++;
	}
    }
    ret[j] = NULL;

    return ret;
}

static XFontStruct **
reallocFontStruct(font, count)
XFontStruct    *font[];
int             count;
{
    XFontStruct   **ret;
    int             i, j;
#if !defined(PRELOAD) || defined(XML)
    XFontStruct	   *data;
#endif

    ret = (XFontStruct **) Xmalloc((unsigned)sizeof(XFontStruct *) * count);
    if (!ret) return NULL;
#if defined(PRELOAD) && !defined(XML)
    for (i = 0, j = 0; j < count; i++) {
	if (font[i]) {
	    if (font[i]->fid > 0) {
		ret[j] = font[i];
		j++;
	    }
	}
    }
#else
    for (i = 0, j = 0; j < count; i++) {
	if (font[i]) {
	    if (font[i]->fid > 0) {
		ret[j] = font[i];
	    } else {
		data = (XFontStruct *) Xmalloc (sizeof(XFontStruct));
		if (!data) {
		    for (j--; j >= 0; j--) {
			if (ret[j])
			    Xfree ((char *) ret[j]);
		    }
		    Xfree ((char *) ret);
		    return NULL;
		}
		ret[j] = data;
		bcopy((char *)font[i], (char *)data, sizeof (XFontStruct));
	    }
	    j++;
	}
    }
#endif
    return ret;
}

static int *
reallocCtidList(fn, list, count)
char   *fn[];
int	list[];
int	count;
{
    int		*ret;
    int		i, j;

    ret = (int *) Xmalloc((unsigned)sizeof(int) * count);
    if (!ret) return NULL;

    for (i = 0, j = 0; j < count; i++) {
	if (fn[i]) {
	    ret[j] = list[i];
	    j++;
	}
    }

    return ret;
}

static          Bool
isXLFDname(font_name)
char           *font_name;
{
    int             i;
    char           *ptr = font_name;

    if (*ptr == XFNEXT_PREFIX) {
        if ((ptr = index(ptr, XFNDELIM)) == NULL) {
            return False;
        }
    }
    if (*ptr != XFNDELIM) {
        return False;
    }
    for (i = 0; i < DELIM_COUNT; i++) {
        if ((ptr = index(ptr + 1, XFNDELIM)) == NULL) {
            return False;
        }
    }
    return True;
}


static Bool
isBaseFontName(font_name)
    char           *font_name;
{
    int             i;
    char           *ptr = font_name;

    if (*ptr == XFNEXT_PREFIX) {
        if ((ptr = index(ptr, XFNDELIM)) == NULL) {
            return False;
        }
    }
    if (*ptr != XFNDELIM) {
        return False;
    }
    for (i = 0; i < DELIM_COUNT-2; i++) {
        if ((ptr = index(ptr + 1, XFNDELIM)) == NULL) {
            return False;
        }
    }
    if ((ptr = index(ptr + 1, XFNDELIM)) == NULL) {
	return True;
    }
    return False;
}

static char    *
getXLFDName(dpy, info)
Display        *dpy;
XFontStruct    *info;
{
    char           *return_value;
    unsigned long   val;

    if (XGetFontProperty(info, XA_FONT, &val) == False) {
        dbg_printf("getXLFD: XGetFontProperty == False\n", 0, 0);
        return NULL;
    }
    return_value = XGetAtomName(dpy, val);
    if (isXLFDname(return_value)) {
        return return_value;
    } else {
        dbg_printf("getXLFD: isXLFDname == Not XLFD\n", 0, 0);
        Xfree(return_value);
        return NULL;
    }
}

static Bool
matchCharset(font_name, cset, GLorGR)
    char       *font_name,
               *cset;
    _CSID	GLorGR;
{
    char	*start = font_name;
    int		i;

    for (i = 0; i < CSETPOS; i++) {
        start = index(start, XFNDELIM);
        if (start == NULL) {
            return False;
        }
        start++;
    }
    if (compareLowercase(start, cset) == 0)
	return (True);

    /* jisx0208.1990-0 is super set of jisx0208.1983-0 */
    if (strlen(cset) == 15 && strlen(start) == 15 &&
	*(cset+14) == *(start+14) &&
	!strncmp(cset, "jisx0208.1983", 13)) {
         return ((compareNLowercase(start, "jisx0208.1990", 13) == 0) ? True : False);
    }
    /* GL of ISO8859.* is same as GL of ISO8859.1 */
    if (GLorGR == GL && !strncmp(cset, "iso8859-", 8)) {
         return ((compareNLowercase(start, cset, 8) == 0) ? True : False);
    }
    return (False);
}

static int
findFont(dpy, fname, xlocale, f_tmp, s_tmp, id_tmp)
    Display	*dpy;
    char        *fname;
    XLocale	 xlocale;
    char        *f_tmp[];
    XFontStruct *s_tmp[];
    int		 id_tmp[];
{
    XFontStruct	*info = NULL;
    char       **list;
    int		 count;
    int		 cset_count;
    char	*fn = NULL;
    int		 ret = 0;
    _CSID	 i;

    if (isXLFDname(fname)) {
	if(! (fn = Xmalloc((unsigned)strlen(fname) + 1)))
	    return 0;
	strcpy(fn, fname);
    } else {
	list = XListFontsWithInfo(dpy, fname, 1, &count, &info);
	if (count != 1) {
	    /* never go to here. */
	    goto _err_return;
	}
	if ((fn = getXLFDName(dpy, &info[0])) == NULL) {
	    goto _err_return;
	}
    }
    dbg_printf("findFont: %s\n", fn, 0);

    cset_count = _Xmbfsnum(xlocale);
    for (i = CODESET0; (int)i < cset_count; i++) {
	if (s_tmp[i] == NULL) {
	    Charset	*cset = _Xmbfscs(xlocale, i);
	    dbg_printf("findFont: charset[%d] = %s\n", i, cset->cs_name);

	    if (matchCharset(fn, cset->cs_name, cset->cs_GLorGR) == True) {
		dbg_printf("findFont: matched\n", 0, 0);
		ret++;
#ifdef PRELOAD
		if (!(s_tmp[i] = XLoadQueryFont(dpy, fn))) ret--;
#else /* PRELOAD */
		if (!info)
		    list = XListFontsWithInfo(dpy, fname, 1, &count, &info);
		    if (count != 1) {
			/* never go to here. */
			goto _err_return;
		    }
		if(! (s_tmp[i] = (XFontStruct *) Xmalloc(sizeof(XFontStruct)))){
		    goto _err_return;
		}
# ifndef MUSTCOPY
		s_tmp[i] = info[0];
# else /* MUSTCOPY */
		SetFontInfo(&s_tmp[i], &info[0]);
# endif /* MUSTCOPY */
		/* indicate the font has not loaded, only info. */
		s_tmp[i]->fid = 0;
#endif /* PRELOAD */
		id_tmp[i] = cset->cs_id;
		if(! (f_tmp[i] = (char *) Xmalloc(strlen(fn) + 1))) {
		    --ret;
		    goto _err_return;
		}
		strcpy(f_tmp[i], fn);
	    } else {
		f_tmp[i] = NULL;
	    }
	}
    }
_err_return:
    if (info) {
	XFreeFontInfo(list, info, count);
    }
    if (fn) Xfree((char *)fn);
    return ret;

}

#undef  MIN
#undef  MAX
#define MIN(a, b)   ((a) = (((a) > (b))? (b): (a)))
#define MAX(a, b)   ((a) = (((a) < (b))? (b): (a)))

/* _MinBounds: if any element of src XCharStruct is less than           */
/*             that of des, replace the des XCharStruct's               */
/*             corresponding element with that of src                   */
/*       des:  destination min_bound                                    */
/*       src:  source min_bound                                         */

static void
_MinBounds(des, src)
XCharStruct    *des;
XCharStruct    *src;
{
    MIN(des->lbearing, src->lbearing);
    MIN(des->rbearing, src->rbearing);
    MIN(des->width, src->width);
    MIN(des->ascent, src->ascent);
    MIN(des->descent, src->descent);
    MIN(des->attributes, src->attributes);
}

/* _MinBounds: if any element of src XCharStruct is greater than        */
/*             that of des, replace the des XCharStruct's               */
/*             corresponding element with that of src                   */
/*       des:  destination min_bound                                    */
/*       src:  source min_bound                                         */

static void
_MaxBounds(des, src)
XCharStruct    *des;
XCharStruct    *src;
{
    MAX(des->lbearing, src->lbearing);
    MAX(des->rbearing, src->rbearing);
    MAX(des->width, src->width);
    MAX(des->ascent, src->ascent);
    MAX(des->descent, src->descent);
    MAX(des->attributes, src->attributes);
}

static void
getFontCharStruct(font_strct, font_count,
          min_bounds, max_bounds, ascent, descent)
XFontStruct   **font_strct;
int             font_count;
XCharStruct    *min_bounds,
               *max_bounds;
int            *ascent,
               *descent;
{
    int		i;

    *min_bounds = font_strct[0]->min_bounds;
    *max_bounds = font_strct[0]->max_bounds;
    *ascent = font_strct[0]->ascent;
    *descent = font_strct[0]->descent;
    for (i = 1; i < font_count; i++) {
	_MinBounds(min_bounds, &font_strct[i]->min_bounds);
	_MaxBounds(max_bounds, &font_strct[i]->max_bounds);

	if (*ascent < font_strct[i]->ascent) {
	    *ascent = font_strct[i]->ascent;
	}
	if (*descent < font_strct[i]->descent) {
	    *descent = font_strct[i]->descent;
	}
    }
}


#ifdef XML
static int
AlreadyLoad(id_tmp, found, charset, GLorGR)
int		id_tmp[];
int		found;
char		*charset;
_CSID		GLorGR;
{
    int		i;
    if ((id_tmp[found] = _XcwNameGetGLorGRId(charset, GLorGR)) == ND)
	return 0;
    for (i = 0; i < found; i++) {
	if (id_tmp[i] == id_tmp[found])
	    return 0;
    }
    return 1;
}

static int
TryLoad(s_tmp, id_tmp, found, info, charset, GLorGR)
XFontStruct	*s_tmp[];
int		id_tmp[];
int		found;
XFontStruct     *info;
char		*charset;
_CSID		GLorGR;
{
    if (! (s_tmp[found] = (XFontStruct *)Xmalloc(sizeof(XFontStruct))))
	return 0;
#ifndef MUSTCOPY
    *s_tmp[found] = info[0];
#else /* MUSTCOPY */
    SetFontInfo(s_tmp[found], &info[0]);
#endif /* MUSTCOPY */
    s_tmp[found]->fid = 0;      /* make sure unloaded */
    return 1;
}

XFontSet
_XsimlCreateFontSet(lcd, dpy, base_font_name_list, font_list, font_count,
		    missing_charset_list, missing_charset_count)
    XLCd	    lcd;
    Display        *dpy;
    char           *base_font_name_list;
    char          **font_list;
    int             font_count;
    char         ***missing_charset_list;
    int            *missing_charset_count;
{
    XsiFontSet      font_set;
    char           *m_tmp[MAXCHARSETS],
                   *f_tmp[MAXCHARSETS];
    XFontStruct    *s_tmp[MAXCHARSETS];
    int             id_tmp[MAXCHARSETS];
    int             found = 1, miss = 0, loadASCIIFONT = 0;
    int             count, i, j, notfound;

    for (i = 0; i < font_count; i++) {
        char	**list;
	char	tmp[256];
	if (isBaseFontName(font_list[i])) {
	    strcpy(tmp, font_list[i]);
	    strcat(tmp, "-*-*");
	    list = XListFonts(dpy, tmp, 1024, &count);
	} else {
	    list = XListFonts(dpy, font_list[i], 1024, &count);
	}

        notfound = 1;
        for (j = 0; j < count; j++) {
	    XFontStruct  *info;
	    char	**info_list;
	    int		  count_list;
	    if (found >= (MAXCHARSETS - 1))
		break;
	    info = NULL;
	    if (isXLFDname(list[j]) ) {
		if (! (f_tmp[found] = Xmalloc((unsigned)strlen(list[j]) + 1))) {
		    return NULL;
		}
		strcpy(f_tmp[found], list[j]);
	    } else  {
		info_list = XListFontsWithInfo(dpy, list[j], 1, &count_list, &info);
		if (count_list != 1) {
		    /* never go to here. */
		    continue;
		}
		f_tmp[found] = getXLFDName(dpy, &info[0]);
	    }
	    if (f_tmp[found] != NULL) {
		char	charset[64];
		char	*start = f_tmp[found];
		int	k;

		for (k = 0; k < CSETPOS; k++) {
		    start = index(start, XFNDELIM);
		    if (start == NULL)
			/* not goes here */
			return NULL;
		    start++;
		}
		copyLowercase(charset, start);
		/* If font name is ISO8859.* Treate for ISO8859.1 GL */
		if (strncmp(charset, "iso8859-", 8) == 0) {
		    if(!loadASCIIFONT) {
			f_tmp[0] = f_tmp[found];
			s_tmp[0] = XLoadQueryFont(dpy, f_tmp[0]);
			id_tmp[0] = CODESET0;
			loadASCIIFONT = 1;
		    }
		} else {
		    if (AlreadyLoad(id_tmp, found, charset, GL)) {

			if (!info)
			    info_list = XListFontsWithInfo(dpy, list[j], 1, &count_list, &info);
			if (count_list != 1)
			    /* never go to here. */
			    continue;

			f_tmp[found+1] = f_tmp[found];
			found += TryLoad(s_tmp, id_tmp, found, info, charset, GL);
		    }
		}
		if (AlreadyLoad(id_tmp, found, charset, GR)) {
		    if (!info)
			info_list = XListFontsWithInfo(dpy, list[j], 1, &count_list, &info);
		    if (count_list != 1)
			/* never go to here. */
			continue;
		    found += TryLoad(s_tmp, id_tmp, found, info, charset, GR);
		}
		notfound = 0;
		if (info)
		    XFreeFontInfo(info_list, info, count_list);
	    }
	}
        if (notfound)
            m_tmp[miss++] = font_list[i];
	XFreeFontNames(list);
    }

    *missing_charset_list = reallocList(m_tmp, miss);
    *missing_charset_count = miss;

    if (miss == font_count) {
        return NULL;
    }

    if (!loadASCIIFONT) {
	if(! (f_tmp[0] = (char *)Xmalloc(strlen("fixed") + 1)))
	    return NULL;
	strcpy(f_tmp[0], "fixed");	/* use defalt font */
	s_tmp[0] = XLoadQueryFont(dpy, f_tmp[0]);
    }

    if(! (font_set = (XsiFontSet) Xmalloc(sizeof(XsiFontSetRec)))) {
	if (s_tmp[0] && s_tmp[0]->fid) {
	    XFreeFont(dpy, s_tmp[0]);
	}
	return NULL;
    }    
    XFreeStringList(font_list);

    font_set->methods = (XFontSetMethods) &fs_methods;
    font_set->core.base_name_list = base_font_name_list;
    font_set->core.num_of_fonts = found;
    font_set->core.lcd = lcd;
    font_set->core.font_name_list = reallocList(f_tmp, found);
    font_set->core.font_struct_list = reallocFontStruct(s_tmp, found);
    font_set->core.context_dependent = False;
    font_set->display = dpy;
    font_set->xlc = NULL;
    font_set->ctid = reallocCtidList(f_tmp, id_tmp, found);
    getFontCharStruct(font_set->core.font_struct_list, found,
		      &font_set->min_bounds, &font_set->max_bounds,
		      &font_set->ascent, &font_set->descent);
    font_set->core.default_string = NULL;
    for (i = 0; (int)i < found; i++) {
	Xfree((char *)f_tmp[i]);
    }

    /*
     * set the ink bounding box of font_set.
     */
    font_set->core.font_set_extents.max_ink_extent.x =
            font_set->min_bounds.lbearing;
    font_set->core.font_set_extents.max_ink_extent.y =
            - font_set->max_bounds.ascent;
    font_set->core.font_set_extents.max_ink_extent.width =
            font_set->max_bounds.rbearing - font_set->min_bounds.lbearing;
    font_set->core.font_set_extents.max_ink_extent.height =
            font_set->max_bounds.ascent + font_set->max_bounds.descent;
    /*
     * set the logical bounding box of font_set.
     * suppose the lbearing >= 0;
     */
    font_set->core.font_set_extents.max_logical_extent.x = 0;
    font_set->core.font_set_extents.max_logical_extent.y =
            - font_set->ascent;
    font_set->core.font_set_extents.max_logical_extent.width =
            font_set->max_bounds.width;
    font_set->core.font_set_extents.max_logical_extent.height =
            font_set->ascent + font_set->descent;

    return (XFontSet)font_set;
}

XFontSet
XmlCreateFontSet (dpy, base_font_name_list, missing_charset_list,
		  missing_charset_count, def_string)
    Display        *dpy;
    char           *base_font_name_list;
    char         ***missing_charset_list;
    int            *missing_charset_count;
    char          **def_string;
{
    XLCd lcd = _XlcCurrentLC();
    char *base_name;
    char **name_list;
    int count;
    XFontSet font_set;

    *missing_charset_list = NULL;
    *missing_charset_count = 0;
    if (!lcd)
	return NULL;
    base_name = (char *)Xmalloc(strlen(base_font_name_list) + 1);
    if (!base_name)
	return NULL;
    strcpy(base_name, base_font_name_list);
    name_list = _XParseBaseFontNameList(base_name, &count);
    if (!name_list) {
	Xfree(base_name);
        return NULL;
    }
    font_set = _XsimlCreateFontSet (lcd, dpy, base_name, name_list, count,
				    missing_charset_list,
				    missing_charset_count);
    if (!font_set) {
	XFreeStringList(name_list);
	Xfree(base_name);
    } else if (def_string) {
	*def_string = font_set->core.default_string;
	if (!*def_string)
	    *def_string = "";
    }
    return font_set;
}
#endif /* XML */

XFontSet
_XsiCreateFontSet(lcd, dpy, base_font_name_list, font_list, font_count,
		  missing_charset_list, missing_charset_count)
    XLCd	    lcd;
    Display        *dpy;
    char           *base_font_name_list;
    char          **font_list;
    int             font_count;
    char         ***missing_charset_list;
    int            *missing_charset_count;
{
    XsiFontSet      font_set;
    int             cset_count;
    char           *m_tmp[MAXCHARSETS],
                   *f_tmp[MAXCHARSETS];
    XFontStruct    *s_tmp[MAXCHARSETS];
    int		    id_tmp[MAXCHARSETS];
    int             found = 0, miss = 0, j;
    _CSID	    i;
    XLocale	    xlocale = ((XsiLCd)lcd)->xlc;

    cset_count = _Xmbfsnum(xlocale);
    for (i = 0; (int)i < cset_count; i++) {
	s_tmp[i] = NULL;
    }
    for (j = 0; j < font_count && found < cset_count; j++) {
        char  **list;
        int	k, count;
	char	tmp[256];

	if (isBaseFontName(font_list[j])) {
	    strcpy(tmp, font_list[j]);
	    strcat(tmp, "-*-*");
	    list = XListFonts(dpy, tmp, 1024, &count);
	} else {
	    list = XListFonts(dpy, font_list[j], 1024, &count);
	}
	for (k = 0; k < count && found < cset_count; k++) {
	    dbg_printf("XCreateFontSet: font = %s\n", list[k], 0);
	    found += findFont(dpy, list[k], xlocale, f_tmp, s_tmp, id_tmp);
	}
	XFreeFontNames(list);
    }
    if (found < cset_count) {
	/* find missing charset */
	for (i = 0; (int)i < cset_count; i++) {
	    if (s_tmp[i] == NULL) {
		Charset	*cset = _Xmbfscs(xlocale, i);
		m_tmp[miss] = cset->cs_name;
		dbg_printf("XCreateFontSet: m_tmp[%d] = %s\n",
			   miss, m_tmp[miss]);
		miss++;
	    }
	}
    }

    *missing_charset_list = reallocList(m_tmp, miss);
    *missing_charset_count = miss;

    if (miss == cset_count) {
        return NULL;
    }
    if (! (font_set = (XsiFontSet)Xmalloc(sizeof(XsiFontSetRec)))) {
	for (i = 0; (int)i < found; i++) {
	    if (s_tmp[i] && s_tmp[i]->fid)
		XFreeFont(dpy, s_tmp[i]);
	}
        return NULL;
    }
    XFreeStringList(font_list);

#ifdef PRELOAD
    if (!miss && _Xmbtype(xlocale) == CDS_STATELESS && cset_count <= 2 &&
	xlocale->xlc_db->lc_codeset->cds_mblen[0] == 1 &&
	(cset_count == 1 || xlocale->xlc_db->lc_codeset->cds_mblen[1] == 1) &&
	found <= 2 && (found == 1 || !strcmp(f_tmp[0], f_tmp[1])))
	font_set->methods = (XFontSetMethods) &fs8_methods;
    else
#endif
	font_set->methods = (XFontSetMethods) &fs_methods;
    font_set->core.base_name_list = base_font_name_list;
    font_set->core.num_of_fonts = found;
    font_set->core.lcd = lcd;
    font_set->display = dpy;
    font_set->xlc = _XlcDupLocale(xlocale);
    font_set->core.font_name_list = reallocList(f_tmp, found);
    font_set->core.font_struct_list = reallocFontStruct(s_tmp, found);
    font_set->core.context_dependent = False;
    font_set->ctid = reallocCtidList(f_tmp, id_tmp, found);
    getFontCharStruct(font_set->core.font_struct_list, found,
		      &font_set->min_bounds, &font_set->max_bounds,
		      &font_set->ascent, &font_set->descent);
    font_set->core.default_string = NULL;
    for (i = 0; (int)i < found; i++) {
	if (f_tmp[i]) Xfree((char *)f_tmp[i]);
    }

    /*
     * set the ink bounding box of font_set.
     */
    font_set->core.font_set_extents.max_ink_extent.x = 
            font_set->min_bounds.lbearing;
    font_set->core.font_set_extents.max_ink_extent.y = 
            - font_set->max_bounds.ascent;
    font_set->core.font_set_extents.max_ink_extent.width = 
            font_set->max_bounds.rbearing - font_set->min_bounds.lbearing;
    font_set->core.font_set_extents.max_ink_extent.height = 
            font_set->max_bounds.ascent + font_set->max_bounds.descent;
    /*
     * set the logical bounding box of font_set.
     * suppose the lbearing >= 0;
     */
    font_set->core.font_set_extents.max_logical_extent.x = 0;
    font_set->core.font_set_extents.max_logical_extent.y = 
            - font_set->ascent;
    font_set->core.font_set_extents.max_logical_extent.width = 
            font_set->max_bounds.width;
    font_set->core.font_set_extents.max_logical_extent.height = 
            font_set->ascent + font_set->descent;

    return (XFontSet)font_set;
}


XFontStruct *
_XsiQueryFontSetFromId(font_set, ctid)
    XFontSet   font_set;
    int	       ctid;
{
    XFontStruct *font;
    int          i;

    for (i = 0; i < font_set->core.num_of_fonts; i++) {
	if (((XsiFontSet)font_set)->ctid[i] == ctid)
	    break;
    }
    if (i == font_set->core.num_of_fonts)
	return NULL;

    if (font_set->core.font_struct_list[i]->fid > 0)
        /* already loaded */
        return font_set->core.font_struct_list[i];

    if ((font = XLoadQueryFont(((XsiFontSet)font_set)->display,
			       font_set->core.font_name_list[i])) == NULL)
        return NULL;
    Xfree((char *)font_set->core.font_struct_list[i]);
    font_set->core.font_struct_list[i] = font;
    return font;
}


#ifdef XML
void
_XsiQueryFontSetWithName(font_set, font_name)
    XFontSet	font_set;
    char       *font_name; /* font name or charset name */
{
    Display    *dpy = ((XsiFontSet)font_set)->display;
    char       *fname;
    int		ctid;
    int		count, i;
    char	**list;
    char	tmp[256];
    char	charset[64];

    if (isBaseFontName(font_name)) {
	strcpy(tmp, font_name);
	strcat(tmp, "-*-*");
	list = XListFonts(dpy, tmp, 1024, &count);
    } else {
	list = XListFonts(dpy, font_name, 1024, &count);
    }
    if (count == 0) { /* charset name */
	copyLowercase(charset, font_name);
	if ((ctid = _XcwNameGetGLorGRId(charset, GL)) != ND) {
	    _XsiQueryFontSetFromId(font_set, ctid);
	}
	if ((ctid = _XcwNameGetGLorGRId(charset, GR)) != ND) {
	    _XsiQueryFontSetFromId(font_set, ctid);
	}
    } else {	/* font name */
	for (i = 0; i < count; i++) {
	    if (isXLFDname(list[i])) {
		fname = list[i];
	    } else  {
		char	**info_list;
		XFontStruct *font;
		info_list = XListFontsWithInfo(dpy, list[i],
					       1, &count, &font);
		if (count != 1)
		    /* not goes here */
		    return;
		fname = getXLFDName(dpy, font);
		XFreeFontInfo(info_list, font, count);
	    }
	    if (fname != NULL) {
		char	*start = fname;
		int	k;

		for (k = 0; k < CSETPOS; k++) {
		    start = index(start, XFNDELIM);
		    if (start == NULL)
			/* not goes here */
			return;
		    start++;
		}
		copyLowercase(charset, start);
		if ((ctid = _XcwNameGetGLorGRId(charset, GL)) != ND) {
		    _XsiQueryFontSetFromId(font_set, ctid);
		}
		if ((ctid = _XcwNameGetGLorGRId(charset, GR)) != ND) {
		    _XsiQueryFontSetFromId(font_set, ctid);
		}
	    }
	}
    }
    XFreeFontNames(list);
}
#endif /* XML */