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