fontxlfd.c revision 23a0898a
123a0898aSmrg/* $Xorg: fontxlfd.c,v 1.4 2001/02/09 02:04:04 xorgcvs Exp $ */
223a0898aSmrg
323a0898aSmrg/*
423a0898aSmrg
523a0898aSmrgCopyright 1990, 1998  The Open Group
623a0898aSmrg
723a0898aSmrgPermission to use, copy, modify, distribute, and sell this software and its
823a0898aSmrgdocumentation for any purpose is hereby granted without fee, provided that
923a0898aSmrgthe above copyright notice appear in all copies and that both that
1023a0898aSmrgcopyright notice and this permission notice appear in supporting
1123a0898aSmrgdocumentation.
1223a0898aSmrg
1323a0898aSmrgThe above copyright notice and this permission notice shall be included
1423a0898aSmrgin all copies or substantial portions of the Software.
1523a0898aSmrg
1623a0898aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1723a0898aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1823a0898aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1923a0898aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
2023a0898aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2123a0898aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2223a0898aSmrgOTHER DEALINGS IN THE SOFTWARE.
2323a0898aSmrg
2423a0898aSmrgExcept as contained in this notice, the name of The Open Group shall
2523a0898aSmrgnot be used in advertising or otherwise to promote the sale, use or
2623a0898aSmrgother dealings in this Software without prior written authorization
2723a0898aSmrgfrom The Open Group.
2823a0898aSmrg
2923a0898aSmrg*/
3023a0898aSmrg/* $XFree86: xc/lib/font/util/fontxlfd.c,v 3.16tsi Exp $ */
3123a0898aSmrg
3223a0898aSmrg/*
3323a0898aSmrg * Author:  Keith Packard, MIT X Consortium
3423a0898aSmrg */
3523a0898aSmrg
3623a0898aSmrg#ifdef HAVE_CONFIG_H
3723a0898aSmrg#include <config.h>
3823a0898aSmrg#endif
3923a0898aSmrg#include	<X11/fonts/fontmisc.h>
4023a0898aSmrg#include	<X11/fonts/fontstruct.h>
4123a0898aSmrg#include	<X11/fonts/fontxlfd.h>
4223a0898aSmrg#include	<X11/fonts/fontutil.h>
4323a0898aSmrg#include	<X11/Xos.h>
4423a0898aSmrg#include	<math.h>
4523a0898aSmrg#include	<stdlib.h>
4623a0898aSmrg#if defined(sony) && !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV)
4723a0898aSmrg#define NO_LOCALE
4823a0898aSmrg#endif
4923a0898aSmrg#ifndef NO_LOCALE
5023a0898aSmrg#include	<locale.h>
5123a0898aSmrg#endif
5223a0898aSmrg#include	<ctype.h>
5323a0898aSmrg#include	<stdio.h>	/* for sprintf() */
5423a0898aSmrg
5523a0898aSmrgstatic char *
5623a0898aSmrgGetInt(char *ptr, int *val)
5723a0898aSmrg{
5823a0898aSmrg    if (*ptr == '*') {
5923a0898aSmrg	*val = -1;
6023a0898aSmrg	ptr++;
6123a0898aSmrg    } else
6223a0898aSmrg	for (*val = 0; *ptr >= '0' && *ptr <= '9';)
6323a0898aSmrg	    *val = *val * 10 + *ptr++ - '0';
6423a0898aSmrg    if (*ptr == '-')
6523a0898aSmrg	return ptr;
6623a0898aSmrg    return (char *) 0;
6723a0898aSmrg}
6823a0898aSmrg
6923a0898aSmrg#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8))
7023a0898aSmrg#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8))
7123a0898aSmrg
7223a0898aSmrg
7323a0898aSmrg#ifndef NO_LOCALE
7423a0898aSmrgstatic struct lconv *locale = 0;
7523a0898aSmrg#endif
7623a0898aSmrgstatic char *radix = ".", *plus = "+", *minus = "-";
7723a0898aSmrg
7823a0898aSmrgstatic char *
7923a0898aSmrgreadreal(char *ptr, double *result)
8023a0898aSmrg{
8123a0898aSmrg    char buffer[80], *p1, *p2;
8223a0898aSmrg
8323a0898aSmrg#ifndef NO_LOCALE
8423a0898aSmrg    /* Figure out what symbols apply in this locale */
8523a0898aSmrg
8623a0898aSmrg    if (!locale)
8723a0898aSmrg    {
8823a0898aSmrg	locale = localeconv();
8923a0898aSmrg	if (locale->decimal_point && *locale->decimal_point)
9023a0898aSmrg	    radix = locale->decimal_point;
9123a0898aSmrg	if (locale->positive_sign && *locale->positive_sign)
9223a0898aSmrg	    plus = locale->positive_sign;
9323a0898aSmrg	if (locale->negative_sign && *locale->negative_sign)
9423a0898aSmrg	    minus = locale->negative_sign;
9523a0898aSmrg    }
9623a0898aSmrg#endif
9723a0898aSmrg    /* Copy the first 80 chars of ptr into our local buffer, changing
9823a0898aSmrg       symbols as needed. */
9923a0898aSmrg    for (p1 = ptr, p2 = buffer;
10023a0898aSmrg	 *p1 && (p2 - buffer) < sizeof(buffer) - 1;
10123a0898aSmrg	 p1++, p2++)
10223a0898aSmrg    {
10323a0898aSmrg	switch(*p1)
10423a0898aSmrg	{
10523a0898aSmrg	    case '~': *p2 = *minus; break;
10623a0898aSmrg	    case '+': *p2 = *plus; break;
10723a0898aSmrg	    case '.': *p2 = *radix; break;
10823a0898aSmrg	    default: *p2 = *p1;
10923a0898aSmrg	}
11023a0898aSmrg    }
11123a0898aSmrg    *p2 = 0;
11223a0898aSmrg
11323a0898aSmrg    /* Now we have something that strtod() can interpret... do it. */
11423a0898aSmrg    *result = strtod(buffer, &p1);
11523a0898aSmrg    /* Return NULL if failure, pointer past number if success */
11623a0898aSmrg    return (p1 == buffer) ? (char *)0 : (ptr + (p1 - buffer));
11723a0898aSmrg}
11823a0898aSmrg
11923a0898aSmrgstatic char *
12023a0898aSmrgxlfd_double_to_text(double value, char *buffer, int space_required)
12123a0898aSmrg{
12223a0898aSmrg    char formatbuf[40];
12323a0898aSmrg    register char *p1;
12423a0898aSmrg    int ndigits, exponent;
12523a0898aSmrg
12623a0898aSmrg#ifndef NO_LOCALE
12723a0898aSmrg    if (!locale)
12823a0898aSmrg    {
12923a0898aSmrg	locale = localeconv();
13023a0898aSmrg	if (locale->decimal_point && *locale->decimal_point)
13123a0898aSmrg	    radix = locale->decimal_point;
13223a0898aSmrg	if (locale->positive_sign && *locale->positive_sign)
13323a0898aSmrg	    plus = locale->positive_sign;
13423a0898aSmrg	if (locale->negative_sign && *locale->negative_sign)
13523a0898aSmrg	    minus = locale->negative_sign;
13623a0898aSmrg    }
13723a0898aSmrg#endif
13823a0898aSmrg    /* Compute a format to use to render the number */
13923a0898aSmrg    sprintf(formatbuf, "%%.%dle", XLFD_NDIGITS);
14023a0898aSmrg
14123a0898aSmrg    if (space_required)
14223a0898aSmrg	*buffer++ = ' ';
14323a0898aSmrg
14423a0898aSmrg    /* Render the number using printf's idea of formatting */
14523a0898aSmrg    sprintf(buffer, formatbuf, value);
14623a0898aSmrg
14723a0898aSmrg    /* Find and read the exponent value */
14823a0898aSmrg    for (p1 = buffer + strlen(buffer);
14923a0898aSmrg	*p1-- != 'e' && p1[1] != 'E';);
15023a0898aSmrg    exponent = atoi(p1 + 2);
15123a0898aSmrg    if (value == 0.0) exponent = 0;
15223a0898aSmrg
15323a0898aSmrg    /* Figure out how many digits are significant */
15423a0898aSmrg    while (p1 >= buffer && (!isdigit(*p1) || *p1 == '0')) p1--;
15523a0898aSmrg    ndigits = 0;
15623a0898aSmrg    while (p1 >= buffer) if (isdigit(*p1--)) ndigits++;
15723a0898aSmrg
15823a0898aSmrg    /* Figure out notation to use */
15923a0898aSmrg    if (exponent >= XLFD_NDIGITS || ndigits - exponent > XLFD_NDIGITS + 1)
16023a0898aSmrg    {
16123a0898aSmrg	/* Scientific */
16223a0898aSmrg	sprintf(formatbuf, "%%.%dle", ndigits - 1);
16323a0898aSmrg	sprintf(buffer, formatbuf, value);
16423a0898aSmrg    }
16523a0898aSmrg    else
16623a0898aSmrg    {
16723a0898aSmrg	/* Fixed */
16823a0898aSmrg	ndigits -= exponent + 1;
16923a0898aSmrg	if (ndigits < 0) ndigits = 0;
17023a0898aSmrg	sprintf(formatbuf, "%%.%dlf", ndigits);
17123a0898aSmrg	sprintf(buffer, formatbuf, value);
17223a0898aSmrg	if (exponent < 0)
17323a0898aSmrg	{
17423a0898aSmrg	    p1 = buffer;
17523a0898aSmrg	    while (*p1 && *p1 != '0') p1++;
17623a0898aSmrg	    while (*p1++) p1[-1] = *p1;
17723a0898aSmrg	}
17823a0898aSmrg    }
17923a0898aSmrg
18023a0898aSmrg    /* Last step, convert the locale-specific sign and radix characters
18123a0898aSmrg       to our own. */
18223a0898aSmrg    for (p1 = buffer; *p1; p1++)
18323a0898aSmrg    {
18423a0898aSmrg	if (*p1 == *minus) *p1 = '~';
18523a0898aSmrg	else if (*p1 == *plus) *p1 = '+';
18623a0898aSmrg	else if (*p1 == *radix) *p1 = '.';
18723a0898aSmrg    }
18823a0898aSmrg
18923a0898aSmrg    return buffer - space_required;
19023a0898aSmrg}
19123a0898aSmrg
19223a0898aSmrgdouble
19323a0898aSmrgxlfd_round_double(double x)
19423a0898aSmrg{
19523a0898aSmrg   /* Utility for XLFD users to round numbers to XLFD_NDIGITS
19623a0898aSmrg      significant digits.  How do you round to n significant digits on
19723a0898aSmrg      a binary machine?  */
19823a0898aSmrg
19923a0898aSmrg#if defined(i386) || defined(__i386__) || \
20023a0898aSmrg    defined(ia64) || defined(__ia64__) || \
20123a0898aSmrg    defined(__alpha__) || defined(__alpha) || \
20223a0898aSmrg    defined(__hppa__) || \
20323a0898aSmrg    defined(__amd64__) || defined(__amd64) || \
20423a0898aSmrg    defined(sgi)
20523a0898aSmrg#if !defined(__UNIXOS2__)
20623a0898aSmrg#include <float.h>
20723a0898aSmrg
20823a0898aSmrg/* if we have IEEE 754 fp, we can round to binary digits... */
20923a0898aSmrg
21023a0898aSmrg#if (FLT_RADIX == 2) && (DBL_DIG == 15) && (DBL_MANT_DIG == 53)
21123a0898aSmrg
21223a0898aSmrg#ifndef M_LN2
21323a0898aSmrg#define M_LN2       0.69314718055994530942
21423a0898aSmrg#endif
21523a0898aSmrg#ifndef M_LN10
21623a0898aSmrg#define M_LN10      2.30258509299404568402
21723a0898aSmrg#endif
21823a0898aSmrg
21923a0898aSmrg/* convert # of decimal digits to # of binary digits */
22023a0898aSmrg#define XLFD_NDIGITS_2 ((int)(XLFD_NDIGITS * M_LN10 / M_LN2 + 0.5))
22123a0898aSmrg
22223a0898aSmrg   union conv_d {
22323a0898aSmrg      double d;
22423a0898aSmrg      unsigned char b[8];
22523a0898aSmrg   } d;
22623a0898aSmrg   int i,j,k,d_exp;
22723a0898aSmrg
22823a0898aSmrg   if (x == 0)
22923a0898aSmrg      return x;
23023a0898aSmrg
23123a0898aSmrg   /* do minor sanity check for IEEE 754 fp and correct byte order */
23223a0898aSmrg   d.d = 1.0;
23323a0898aSmrg   if (sizeof(double) == 8 && d.b[7] == 0x3f && d.b[6] == 0xf0) {
23423a0898aSmrg
23523a0898aSmrg      /*
23623a0898aSmrg       * this code will round IEEE 754 double to XLFD_NDIGITS_2 binary digits
23723a0898aSmrg       */
23823a0898aSmrg
23923a0898aSmrg      d.d = x;
24023a0898aSmrg      d_exp = (d.b[7] << 4) | (d.b[6] >> 4);
24123a0898aSmrg
24223a0898aSmrg      i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3;
24323a0898aSmrg      j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07);
24423a0898aSmrg      for (; i<7; i++) {
24523a0898aSmrg	 k = d.b[i] + j;
24623a0898aSmrg	 d.b[i] = k;
24723a0898aSmrg	 if (k & 0x100) j = 1;
24823a0898aSmrg	 else break;
24923a0898aSmrg      }
25023a0898aSmrg      if ((i==7) && ((d.b[6] & 0xf0) != ((d_exp<<4) & 0xf0))) {
25123a0898aSmrg	 /* mantissa overflow: increment exponent */
25223a0898aSmrg	 d_exp = (d_exp & 0x800 ) | ((d_exp & 0x7ff) + 1);
25323a0898aSmrg	 d.b[7] = d_exp >> 4;
25423a0898aSmrg	 d.b[6] = (d.b[6] & 0x0f) | (d_exp << 4);
25523a0898aSmrg      }
25623a0898aSmrg
25723a0898aSmrg      i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3;
25823a0898aSmrg      j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07);
25923a0898aSmrg      d.b[i] &= ~(j-1);
26023a0898aSmrg      for (;--i>=0;) d.b[i] = 0;
26123a0898aSmrg
26223a0898aSmrg      return d.d;
26323a0898aSmrg   }
26423a0898aSmrg   else
26523a0898aSmrg#endif
26623a0898aSmrg#endif /* !__UNIXOS2__ */
26723a0898aSmrg#endif /* i386 || __i386__ */
26823a0898aSmrg    {
26923a0898aSmrg	/*
27023a0898aSmrg	 * If not IEEE 754:  Let printf() do it for you.
27123a0898aSmrg	 */
27223a0898aSmrg
27323a0898aSmrg	char formatbuf[40], buffer[40];
27423a0898aSmrg
27523a0898aSmrg	sprintf(formatbuf, "%%.%dlg", XLFD_NDIGITS);
27623a0898aSmrg	sprintf(buffer, formatbuf, x);
27723a0898aSmrg	return atof(buffer);
27823a0898aSmrg    }
27923a0898aSmrg}
28023a0898aSmrg
28123a0898aSmrgstatic char *
28223a0898aSmrgGetMatrix(char *ptr, FontScalablePtr vals, int which)
28323a0898aSmrg{
28423a0898aSmrg    double *matrix;
28523a0898aSmrg
28623a0898aSmrg    if (which == PIXELSIZE_MASK)
28723a0898aSmrg	matrix = vals->pixel_matrix;
28823a0898aSmrg    else if (which == POINTSIZE_MASK)
28923a0898aSmrg	matrix = vals->point_matrix;
29023a0898aSmrg    else return (char *)0;
29123a0898aSmrg
29223a0898aSmrg    while (isspace(*ptr)) ptr++;
29323a0898aSmrg    if (*ptr == '[')
29423a0898aSmrg    {
29523a0898aSmrg	/* This is a matrix containing real numbers.  It would be nice
29623a0898aSmrg	   to use strtod() or sscanf() to read the numbers, but those
29723a0898aSmrg	   don't handle '~' for minus and we cannot force them to use a
29823a0898aSmrg	   "."  for the radix.  We'll have to do the hard work ourselves
29923a0898aSmrg	   (in readreal()).  */
30023a0898aSmrg
30123a0898aSmrg	if ((ptr = readreal(++ptr, matrix + 0)) &&
30223a0898aSmrg	    (ptr = readreal(ptr, matrix + 1)) &&
30323a0898aSmrg	    (ptr = readreal(ptr, matrix + 2)) &&
30423a0898aSmrg	    (ptr = readreal(ptr, matrix + 3)))
30523a0898aSmrg	{
30623a0898aSmrg	    while (isspace(*ptr)) ptr++;
30723a0898aSmrg	    if (*ptr != ']')
30823a0898aSmrg		ptr = (char *)0;
30923a0898aSmrg	    else
31023a0898aSmrg	    {
31123a0898aSmrg		ptr++;
31223a0898aSmrg		while (isspace(*ptr)) ptr++;
31323a0898aSmrg		if (*ptr == '-')
31423a0898aSmrg		{
31523a0898aSmrg		    if (which == POINTSIZE_MASK)
31623a0898aSmrg			vals->values_supplied |= POINTSIZE_ARRAY;
31723a0898aSmrg		    else
31823a0898aSmrg			vals->values_supplied |= PIXELSIZE_ARRAY;
31923a0898aSmrg		}
32023a0898aSmrg		else ptr = (char *)0;
32123a0898aSmrg	    }
32223a0898aSmrg	}
32323a0898aSmrg    }
32423a0898aSmrg    else
32523a0898aSmrg    {
32623a0898aSmrg	int value;
32723a0898aSmrg	if ((ptr = GetInt(ptr, &value)))
32823a0898aSmrg	{
32923a0898aSmrg	    vals->values_supplied &= ~which;
33023a0898aSmrg	    if (value > 0)
33123a0898aSmrg	    {
33223a0898aSmrg		matrix[3] = (double)value;
33323a0898aSmrg		if (which == POINTSIZE_MASK)
33423a0898aSmrg		{
33523a0898aSmrg		    matrix[3] /= 10.0;
33623a0898aSmrg		    vals->values_supplied |= POINTSIZE_SCALAR;
33723a0898aSmrg		}
33823a0898aSmrg		else
33923a0898aSmrg		    vals->values_supplied |= PIXELSIZE_SCALAR;
34023a0898aSmrg		/* If we're concocting the pixelsize array from a scalar,
34123a0898aSmrg		   we will need to normalize element 0 for the pixel shape.
34223a0898aSmrg		   This is done in FontFileCompleteXLFD(). */
34323a0898aSmrg		matrix[0] = matrix[3];
34423a0898aSmrg		matrix[1] = matrix[2] = 0.0;
34523a0898aSmrg	    }
34623a0898aSmrg	    else if (value < 0)
34723a0898aSmrg	    {
34823a0898aSmrg		if (which == POINTSIZE_MASK)
34923a0898aSmrg		    vals->values_supplied |= POINTSIZE_WILDCARD;
35023a0898aSmrg		else
35123a0898aSmrg		    vals->values_supplied |= PIXELSIZE_WILDCARD;
35223a0898aSmrg	    }
35323a0898aSmrg	}
35423a0898aSmrg    }
35523a0898aSmrg    return ptr;
35623a0898aSmrg}
35723a0898aSmrg
35823a0898aSmrg
35923a0898aSmrgstatic void
36023a0898aSmrgappend_ranges(char *fname, int nranges, fsRange *ranges)
36123a0898aSmrg{
36223a0898aSmrg    if (nranges)
36323a0898aSmrg    {
36423a0898aSmrg        int i;
36523a0898aSmrg
36623a0898aSmrg        strcat(fname, "[");
36723a0898aSmrg        for (i = 0; i < nranges && strlen(fname) < 1010; i++)
36823a0898aSmrg        {
36923a0898aSmrg	    if (i) strcat(fname, " ");
37023a0898aSmrg	    sprintf(fname + strlen(fname), "%d",
37123a0898aSmrg		    minchar(ranges[i]));
37223a0898aSmrg	    if (ranges[i].min_char_low ==
37323a0898aSmrg		ranges[i].max_char_low &&
37423a0898aSmrg		ranges[i].min_char_high ==
37523a0898aSmrg		ranges[i].max_char_high) continue;
37623a0898aSmrg	    sprintf(fname + strlen(fname), "_%d",
37723a0898aSmrg		    maxchar(ranges[i]));
37823a0898aSmrg        }
37923a0898aSmrg        strcat(fname, "]");
38023a0898aSmrg    }
38123a0898aSmrg}
38223a0898aSmrg
38323a0898aSmrgBool
38423a0898aSmrgFontParseXLFDName(char *fname, FontScalablePtr vals, int subst)
38523a0898aSmrg{
38623a0898aSmrg    register char *ptr;
38723a0898aSmrg    register char *ptr1,
38823a0898aSmrg               *ptr2,
38923a0898aSmrg               *ptr3,
39023a0898aSmrg               *ptr4;
39123a0898aSmrg    register char *ptr5;
39223a0898aSmrg    FontScalableRec tmpvals;
39323a0898aSmrg    char        replaceChar = '0';
39423a0898aSmrg    char        tmpBuf[1024];
39523a0898aSmrg    int         spacingLen;
39623a0898aSmrg    int		l;
39723a0898aSmrg    char	*p;
39823a0898aSmrg
39923a0898aSmrg    bzero(&tmpvals, sizeof(tmpvals));
40023a0898aSmrg    if (subst != FONT_XLFD_REPLACE_VALUE)
40123a0898aSmrg	*vals = tmpvals;
40223a0898aSmrg
40323a0898aSmrg    if (!(*(ptr = fname) == '-' || (*ptr++ == '*' && *ptr == '-')) ||  /* fndry */
40423a0898aSmrg	    !(ptr = strchr(ptr + 1, '-')) ||	/* family_name */
40523a0898aSmrg	    !(ptr1 = ptr = strchr(ptr + 1, '-')) ||	/* weight_name */
40623a0898aSmrg	    !(ptr = strchr(ptr + 1, '-')) ||	/* slant */
40723a0898aSmrg	    !(ptr = strchr(ptr + 1, '-')) ||	/* setwidth_name */
40823a0898aSmrg	    !(ptr = strchr(ptr + 1, '-')) ||	/* add_style_name */
40923a0898aSmrg	    !(ptr = strchr(ptr + 1, '-')) ||	/* pixel_size */
41023a0898aSmrg	    !(ptr = GetMatrix(ptr + 1, &tmpvals, PIXELSIZE_MASK)) ||
41123a0898aSmrg	    !(ptr2 = ptr = GetMatrix(ptr + 1, &tmpvals, POINTSIZE_MASK)) ||
41223a0898aSmrg	    !(ptr = GetInt(ptr + 1, &tmpvals.x)) ||	/* resolution_x */
41323a0898aSmrg	    !(ptr3 = ptr = GetInt(ptr + 1, &tmpvals.y)) ||  /* resolution_y */
41423a0898aSmrg	    !(ptr4 = ptr = strchr(ptr + 1, '-')) ||	/* spacing */
41523a0898aSmrg	    !(ptr5 = ptr = GetInt(ptr + 1, &tmpvals.width)) || /* average_width */
41623a0898aSmrg	    !(ptr = strchr(ptr + 1, '-')) ||	/* charset_registry */
41723a0898aSmrg	    strchr(ptr + 1, '-'))/* charset_encoding */
41823a0898aSmrg	return FALSE;
41923a0898aSmrg
42023a0898aSmrg    /* Lop off HP charset subsetting enhancement.  Interpreting this
42123a0898aSmrg       field requires allocating some space in which to return the
42223a0898aSmrg       results.  So, to prevent memory leaks, this procedure will simply
42323a0898aSmrg       lop off and ignore charset subsetting, and initialize the
42423a0898aSmrg       relevant vals fields to zero.  It's up to the caller to make its
42523a0898aSmrg       own call to FontParseRanges() if it's interested in the charset
42623a0898aSmrg       subsetting.  */
42723a0898aSmrg
42823a0898aSmrg    if (subst != FONT_XLFD_REPLACE_NONE &&
42923a0898aSmrg	(p = strchr(strrchr(fname, '-'), '[')))
43023a0898aSmrg    {
43123a0898aSmrg	tmpvals.values_supplied |= CHARSUBSET_SPECIFIED;
43223a0898aSmrg	*p = '\0';
43323a0898aSmrg    }
43423a0898aSmrg
43523a0898aSmrg    /* Fill in deprecated fields for the benefit of rasterizers that care
43623a0898aSmrg       about them. */
43723a0898aSmrg    tmpvals.pixel = (tmpvals.pixel_matrix[3] >= 0) ?
43823a0898aSmrg		    (int)(tmpvals.pixel_matrix[3] + .5) :
43923a0898aSmrg		    (int)(tmpvals.pixel_matrix[3] - .5);
44023a0898aSmrg    tmpvals.point = (tmpvals.point_matrix[3] >= 0) ?
44123a0898aSmrg                    (int)(tmpvals.point_matrix[3] * 10 + .5) :
44223a0898aSmrg                    (int)(tmpvals.point_matrix[3] * 10 - .5);
44323a0898aSmrg
44423a0898aSmrg    spacingLen = ptr4 - ptr3 + 1;
44523a0898aSmrg
44623a0898aSmrg    switch (subst) {
44723a0898aSmrg    case FONT_XLFD_REPLACE_NONE:
44823a0898aSmrg	*vals = tmpvals;
44923a0898aSmrg	break;
45023a0898aSmrg    case FONT_XLFD_REPLACE_STAR:
45123a0898aSmrg	replaceChar = '*';
45223a0898aSmrg    case FONT_XLFD_REPLACE_ZERO:
45323a0898aSmrg	strcpy(tmpBuf, ptr2);
45423a0898aSmrg	ptr5 = tmpBuf + (ptr5 - ptr2);
45523a0898aSmrg	ptr3 = tmpBuf + (ptr3 - ptr2);
45623a0898aSmrg	ptr2 = tmpBuf;
45723a0898aSmrg	ptr = ptr1 + 1;
45823a0898aSmrg
45923a0898aSmrg	ptr = strchr(ptr, '-') + 1;		/* skip weight */
46023a0898aSmrg	ptr = strchr(ptr, '-') + 1;		/* skip slant */
46123a0898aSmrg	ptr = strchr(ptr, '-') + 1;		/* skip setwidth_name */
46223a0898aSmrg	ptr = strchr(ptr, '-') + 1;		/* skip add_style_name */
46323a0898aSmrg
46423a0898aSmrg	if ((ptr - fname) + spacingLen + strlen(ptr5) + 10 >= (unsigned)1024)
46523a0898aSmrg	    return FALSE;
46623a0898aSmrg	*ptr++ = replaceChar;
46723a0898aSmrg	*ptr++ = '-';
46823a0898aSmrg	*ptr++ = replaceChar;
46923a0898aSmrg	*ptr++ = '-';
47023a0898aSmrg	*ptr++ = '*';
47123a0898aSmrg	*ptr++ = '-';
47223a0898aSmrg	*ptr++ = '*';
47323a0898aSmrg	if (spacingLen > 2)
47423a0898aSmrg	{
47523a0898aSmrg	    memmove(ptr, ptr3, spacingLen);
47623a0898aSmrg	    ptr += spacingLen;
47723a0898aSmrg	}
47823a0898aSmrg	else
47923a0898aSmrg	{
48023a0898aSmrg	    *ptr++ = '-';
48123a0898aSmrg	    *ptr++ = '*';
48223a0898aSmrg	    *ptr++ = '-';
48323a0898aSmrg	}
48423a0898aSmrg	*ptr++ = replaceChar;
48523a0898aSmrg	strcpy(ptr, ptr5);
48623a0898aSmrg	*vals = tmpvals;
48723a0898aSmrg	break;
48823a0898aSmrg    case FONT_XLFD_REPLACE_VALUE:
48923a0898aSmrg	if (vals->values_supplied & PIXELSIZE_MASK)
49023a0898aSmrg	{
49123a0898aSmrg	    tmpvals.values_supplied =
49223a0898aSmrg		(tmpvals.values_supplied & ~PIXELSIZE_MASK) |
49323a0898aSmrg		(vals->values_supplied & PIXELSIZE_MASK);
49423a0898aSmrg	    tmpvals.pixel_matrix[0] = vals->pixel_matrix[0];
49523a0898aSmrg	    tmpvals.pixel_matrix[1] = vals->pixel_matrix[1];
49623a0898aSmrg	    tmpvals.pixel_matrix[2] = vals->pixel_matrix[2];
49723a0898aSmrg	    tmpvals.pixel_matrix[3] = vals->pixel_matrix[3];
49823a0898aSmrg	}
49923a0898aSmrg	if (vals->values_supplied & POINTSIZE_MASK)
50023a0898aSmrg	{
50123a0898aSmrg	    tmpvals.values_supplied =
50223a0898aSmrg		(tmpvals.values_supplied & ~POINTSIZE_MASK) |
50323a0898aSmrg		(vals->values_supplied & POINTSIZE_MASK);
50423a0898aSmrg	    tmpvals.point_matrix[0] = vals->point_matrix[0];
50523a0898aSmrg	    tmpvals.point_matrix[1] = vals->point_matrix[1];
50623a0898aSmrg	    tmpvals.point_matrix[2] = vals->point_matrix[2];
50723a0898aSmrg	    tmpvals.point_matrix[3] = vals->point_matrix[3];
50823a0898aSmrg	}
50923a0898aSmrg	if (vals->x >= 0)
51023a0898aSmrg	    tmpvals.x = vals->x;
51123a0898aSmrg	if (vals->y >= 0)
51223a0898aSmrg	    tmpvals.y = vals->y;
51323a0898aSmrg	if (vals->width >= 0)
51423a0898aSmrg	    tmpvals.width = vals->width;
51523a0898aSmrg	else if (vals->width < -1)	/* overload: -1 means wildcard */
51623a0898aSmrg	    tmpvals.width = -vals->width;
51723a0898aSmrg
51823a0898aSmrg
51923a0898aSmrg	p = ptr1 + 1;				/* weight field */
52023a0898aSmrg	l = strchr(p, '-') - p;
52123a0898aSmrg	sprintf(tmpBuf, "%*.*s", l, l, p);
52223a0898aSmrg
52323a0898aSmrg	p += l + 1;				/* slant field */
52423a0898aSmrg	l = strchr(p, '-') - p;
52523a0898aSmrg	sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
52623a0898aSmrg
52723a0898aSmrg	p += l + 1;				/* setwidth_name */
52823a0898aSmrg	l = strchr(p, '-') - p;
52923a0898aSmrg	sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
53023a0898aSmrg
53123a0898aSmrg	p += l + 1;				/* add_style_name field */
53223a0898aSmrg	l = strchr(p, '-') - p;
53323a0898aSmrg	sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
53423a0898aSmrg
53523a0898aSmrg	strcat(tmpBuf, "-");
53623a0898aSmrg	if ((tmpvals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY)
53723a0898aSmrg	{
53823a0898aSmrg	    char buffer[80];
53923a0898aSmrg	    strcat(tmpBuf, "[");
54023a0898aSmrg	    strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[0],
54123a0898aSmrg		   buffer, 0));
54223a0898aSmrg	    strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[1],
54323a0898aSmrg		   buffer, 1));
54423a0898aSmrg	    strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[2],
54523a0898aSmrg		   buffer, 1));
54623a0898aSmrg	    strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[3],
54723a0898aSmrg		   buffer, 1));
54823a0898aSmrg	    strcat(tmpBuf, "]");
54923a0898aSmrg	}
55023a0898aSmrg	else
55123a0898aSmrg	{
55223a0898aSmrg	    sprintf(tmpBuf + strlen(tmpBuf), "%d",
55323a0898aSmrg		    (int)(tmpvals.pixel_matrix[3] + .5));
55423a0898aSmrg	}
55523a0898aSmrg	strcat(tmpBuf, "-");
55623a0898aSmrg	if ((tmpvals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY)
55723a0898aSmrg	{
55823a0898aSmrg	    char buffer[80];
55923a0898aSmrg	    strcat(tmpBuf, "[");
56023a0898aSmrg	    strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[0],
56123a0898aSmrg		   buffer, 0));
56223a0898aSmrg	    strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[1],
56323a0898aSmrg		   buffer, 1));
56423a0898aSmrg	    strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[2],
56523a0898aSmrg		   buffer, 1));
56623a0898aSmrg	    strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[3],
56723a0898aSmrg		   buffer, 1));
56823a0898aSmrg	    strcat(tmpBuf, "]");
56923a0898aSmrg	}
57023a0898aSmrg	else
57123a0898aSmrg	{
57223a0898aSmrg	    sprintf(tmpBuf + strlen(tmpBuf), "%d",
57323a0898aSmrg		    (int)(tmpvals.point_matrix[3] * 10.0 + .5));
57423a0898aSmrg	}
57523a0898aSmrg	sprintf(tmpBuf + strlen(tmpBuf), "-%d-%d%*.*s%d%s",
57623a0898aSmrg		tmpvals.x, tmpvals.y,
57723a0898aSmrg		spacingLen, spacingLen, ptr3, tmpvals.width, ptr5);
57823a0898aSmrg	strcpy(ptr1 + 1, tmpBuf);
57923a0898aSmrg	if ((vals->values_supplied & CHARSUBSET_SPECIFIED) && !vals->nranges)
58023a0898aSmrg	    strcat(fname, "[]");
58123a0898aSmrg	else
58223a0898aSmrg	    append_ranges(fname, vals->nranges, vals->ranges);
58323a0898aSmrg	break;
58423a0898aSmrg    }
58523a0898aSmrg    return TRUE;
58623a0898aSmrg}
58723a0898aSmrg
58823a0898aSmrgfsRange *FontParseRanges(char *name, int *nranges)
58923a0898aSmrg{
59023a0898aSmrg    int n;
59123a0898aSmrg    unsigned long l;
59223a0898aSmrg    char *p1, *p2;
59323a0898aSmrg    fsRange *result = (fsRange *)0;
59423a0898aSmrg
59523a0898aSmrg    name = strchr(name, '-');
59623a0898aSmrg    for (n = 1; name && n < 14; n++)
59723a0898aSmrg	name = strchr(name + 1, '-');
59823a0898aSmrg
59923a0898aSmrg    *nranges = 0;
60023a0898aSmrg    if (!name || !(p1 = strchr(name, '['))) return (fsRange *)0;
60123a0898aSmrg    p1++;
60223a0898aSmrg
60323a0898aSmrg    while (*p1 && *p1 != ']')
60423a0898aSmrg    {
60523a0898aSmrg	fsRange thisrange;
60623a0898aSmrg
60723a0898aSmrg	l = strtol(p1, &p2, 0);
60823a0898aSmrg	if (p2 == p1 || l > 0xffff) break;
60923a0898aSmrg	thisrange.max_char_low = thisrange.min_char_low = l & 0xff;
61023a0898aSmrg	thisrange.max_char_high = thisrange.min_char_high = l >> 8;
61123a0898aSmrg
61223a0898aSmrg	p1 = p2;
61323a0898aSmrg	if (*p1 == ']' || *p1 == ' ')
61423a0898aSmrg	{
61523a0898aSmrg	    while (*p1 == ' ') p1++;
61623a0898aSmrg	    if (add_range(&thisrange, nranges, &result, TRUE) != Successful)
61723a0898aSmrg		break;
61823a0898aSmrg	}
61923a0898aSmrg	else if (*p1 == '_')
62023a0898aSmrg	{
62123a0898aSmrg	    l = strtol(++p1, &p2, 0);
62223a0898aSmrg	    if (p2 == p1 || l > 0xffff) break;
62323a0898aSmrg	    thisrange.max_char_low = l & 0xff;
62423a0898aSmrg	    thisrange.max_char_high = l >> 8;
62523a0898aSmrg	    p1 = p2;
62623a0898aSmrg	    if (*p1 == ']' || *p1 == ' ')
62723a0898aSmrg	    {
62823a0898aSmrg		while (*p1 == ' ') p1++;
62923a0898aSmrg		if (add_range(&thisrange, nranges, &result, TRUE) != Successful)
63023a0898aSmrg		    break;
63123a0898aSmrg	    }
63223a0898aSmrg	}
63323a0898aSmrg	else break;
63423a0898aSmrg    }
63523a0898aSmrg
63623a0898aSmrg    return result;
63723a0898aSmrg}
638