#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <X11/fonts/fontmisc.h>
#include <X11/fonts/fontstruct.h>
#include <X11/fonts/fontxlfd.h>
#include <X11/fonts/fontutil.h>
#include <X11/Xos.h>
#include <math.h>
#include <stdlib.h>
#if defined(sony) && !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV)
#define NO_LOCALE
#endif
#ifndef NO_LOCALE
#include <locale.h>
#endif
#include <ctype.h>
#include <stdio.h>
static char *
GetInt(char *ptr, int *val)
{
if (*ptr == '*') {
*val = -1;
ptr++;
} else
for (*val = 0; *ptr >= '0' && *ptr <= '9';)
*val = *val * 10 + *ptr++ - '0';
if (*ptr == '-')
return ptr;
return (char *) 0;
}
#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8))
#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8))
#ifndef NO_LOCALE
static struct lconv *locale = 0;
#endif
static char *radix = ".", *plus = "+", *minus = "-";
static char *
readreal(char *ptr, double *result)
{
char buffer[80], *p1, *p2;
#ifndef NO_LOCALE
if (!locale)
{
locale = localeconv();
if (locale->decimal_point && *locale->decimal_point)
radix = locale->decimal_point;
if (locale->positive_sign && *locale->positive_sign)
plus = locale->positive_sign;
if (locale->negative_sign && *locale->negative_sign)
minus = locale->negative_sign;
}
#endif
for (p1 = ptr, p2 = buffer;
*p1 && (p2 - buffer) < sizeof(buffer) - 1;
p1++, p2++)
{
switch(*p1)
{
case '~': *p2 = *minus; break;
case '+': *p2 = *plus; break;
case '.': *p2 = *radix; break;
default: *p2 = *p1;
}
}
*p2 = 0;
*result = strtod(buffer, &p1);
return (p1 == buffer) ? (char *)0 : (ptr + (p1 - buffer));
}
static char *
xlfd_double_to_text(double value, char *buffer, int space_required)
{
char formatbuf[40];
register char *p1;
int ndigits, exponent;
#ifndef NO_LOCALE
if (!locale)
{
locale = localeconv();
if (locale->decimal_point && *locale->decimal_point)
radix = locale->decimal_point;
if (locale->positive_sign && *locale->positive_sign)
plus = locale->positive_sign;
if (locale->negative_sign && *locale->negative_sign)
minus = locale->negative_sign;
}
#endif
sprintf(formatbuf, "%%.%dle", XLFD_NDIGITS);
if (space_required)
*buffer++ = ' ';
sprintf(buffer, formatbuf, value);
for (p1 = buffer + strlen(buffer);
*p1-- != 'e' && p1[1] != 'E';);
exponent = atoi(p1 + 2);
if (value == 0.0) exponent = 0;
while (p1 >= buffer && (!isdigit(*p1) || *p1 == '0')) p1--;
ndigits = 0;
while (p1 >= buffer) if (isdigit(*p1--)) ndigits++;
if (exponent >= XLFD_NDIGITS || ndigits - exponent > XLFD_NDIGITS + 1)
{
sprintf(formatbuf, "%%.%dle", ndigits - 1);
sprintf(buffer, formatbuf, value);
}
else
{
ndigits -= exponent + 1;
if (ndigits < 0) ndigits = 0;
sprintf(formatbuf, "%%.%dlf", ndigits);
sprintf(buffer, formatbuf, value);
if (exponent < 0)
{
p1 = buffer;
while (*p1 && *p1 != '0') p1++;
while (*p1++) p1[-1] = *p1;
}
}
for (p1 = buffer; *p1; p1++)
{
if (*p1 == *minus) *p1 = '~';
else if (*p1 == *plus) *p1 = '+';
else if (*p1 == *radix) *p1 = '.';
}
return buffer - space_required;
}
double
xlfd_round_double(double x)
{
#if defined(i386) || defined(__i386__) || \
defined(ia64) || defined(__ia64__) || \
defined(__alpha__) || defined(__alpha) || \
defined(__hppa__) || \
defined(__amd64__) || defined(__amd64) || \
defined(sgi)
#include <float.h>
#if (FLT_RADIX == 2) && (DBL_DIG == 15) && (DBL_MANT_DIG == 53)
#ifndef M_LN2
#define M_LN2 0.69314718055994530942
#endif
#ifndef M_LN10
#define M_LN10 2.30258509299404568402
#endif
#define XLFD_NDIGITS_2 ((int)(XLFD_NDIGITS * M_LN10 / M_LN2 + 0.5))
union conv_d {
double d;
unsigned char b[8];
} d;
int i,j,k,d_exp;
if (x == 0)
return x;
d.d = 1.0;
if (sizeof(double) == 8 && d.b[7] == 0x3f && d.b[6] == 0xf0) {
d.d = x;
d_exp = (d.b[7] << 4) | (d.b[6] >> 4);
i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3;
j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07);
for (; i<7; i++) {
k = d.b[i] + j;
d.b[i] = k;
if (k & 0x100) j = 1;
else break;
}
if ((i==7) && ((d.b[6] & 0xf0) != ((d_exp<<4) & 0xf0))) {
d_exp = (d_exp & 0x800 ) | ((d_exp & 0x7ff) + 1);
d.b[7] = d_exp >> 4;
d.b[6] = (d.b[6] & 0x0f) | (d_exp << 4);
}
i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3;
j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07);
d.b[i] &= ~(j-1);
for (;--i>=0;) d.b[i] = 0;
return d.d;
}
else
#endif
#endif
{
char formatbuf[40], buffer[40];
sprintf(formatbuf, "%%.%dlg", XLFD_NDIGITS);
sprintf(buffer, formatbuf, x);
return atof(buffer);
}
}
static char *
GetMatrix(char *ptr, FontScalablePtr vals, int which)
{
double *matrix;
if (which == PIXELSIZE_MASK)
matrix = vals->pixel_matrix;
else if (which == POINTSIZE_MASK)
matrix = vals->point_matrix;
else return (char *)0;
while (isspace(*ptr)) ptr++;
if (*ptr == '[')
{
if ((ptr = readreal(++ptr, matrix + 0)) &&
(ptr = readreal(ptr, matrix + 1)) &&
(ptr = readreal(ptr, matrix + 2)) &&
(ptr = readreal(ptr, matrix + 3)))
{
while (isspace(*ptr)) ptr++;
if (*ptr != ']')
ptr = (char *)0;
else
{
ptr++;
while (isspace(*ptr)) ptr++;
if (*ptr == '-')
{
if (which == POINTSIZE_MASK)
vals->values_supplied |= POINTSIZE_ARRAY;
else
vals->values_supplied |= PIXELSIZE_ARRAY;
}
else ptr = (char *)0;
}
}
}
else
{
int value;
if ((ptr = GetInt(ptr, &value)))
{
vals->values_supplied &= ~which;
if (value > 0)
{
matrix[3] = (double)value;
if (which == POINTSIZE_MASK)
{
matrix[3] /= 10.0;
vals->values_supplied |= POINTSIZE_SCALAR;
}
else
vals->values_supplied |= PIXELSIZE_SCALAR;
matrix[0] = matrix[3];
matrix[1] = matrix[2] = 0.0;
}
else if (value < 0)
{
if (which == POINTSIZE_MASK)
vals->values_supplied |= POINTSIZE_WILDCARD;
else
vals->values_supplied |= PIXELSIZE_WILDCARD;
}
}
}
return ptr;
}
static void
append_ranges(char *fname, int nranges, fsRange *ranges)
{
if (nranges)
{
int i;
strcat(fname, "[");
for (i = 0; i < nranges && strlen(fname) < 1010; i++)
{
if (i) strcat(fname, " ");
sprintf(fname + strlen(fname), "%d",
minchar(ranges[i]));
if (ranges[i].min_char_low ==
ranges[i].max_char_low &&
ranges[i].min_char_high ==
ranges[i].max_char_high) continue;
sprintf(fname + strlen(fname), "_%d",
maxchar(ranges[i]));
}
strcat(fname, "]");
}
}
Bool
FontParseXLFDName(char *fname, FontScalablePtr vals, int subst)
{
register char *ptr;
register char *ptr1,
*ptr2,
*ptr3,
*ptr4;
register char *ptr5;
FontScalableRec tmpvals;
char replaceChar = '0';
char tmpBuf[1024];
int spacingLen;
int l;
char *p;
bzero(&tmpvals, sizeof(tmpvals));
if (subst != FONT_XLFD_REPLACE_VALUE)
*vals = tmpvals;
if (!(*(ptr = fname) == '-' || (*ptr++ == '*' && *ptr == '-')) ||
!(ptr = strchr(ptr + 1, '-')) ||
!(ptr1 = ptr = strchr(ptr + 1, '-')) ||
!(ptr = strchr(ptr + 1, '-')) ||
!(ptr = strchr(ptr + 1, '-')) ||
!(ptr = strchr(ptr + 1, '-')) ||
!(ptr = strchr(ptr + 1, '-')) ||
!(ptr = GetMatrix(ptr + 1, &tmpvals, PIXELSIZE_MASK)) ||
!(ptr2 = ptr = GetMatrix(ptr + 1, &tmpvals, POINTSIZE_MASK)) ||
!(ptr = GetInt(ptr + 1, &tmpvals.x)) ||
!(ptr3 = ptr = GetInt(ptr + 1, &tmpvals.y)) ||
!(ptr4 = ptr = strchr(ptr + 1, '-')) ||
!(ptr5 = ptr = GetInt(ptr + 1, &tmpvals.width)) ||
!(ptr = strchr(ptr + 1, '-')) ||
strchr(ptr + 1, '-'))
return FALSE;
if (subst != FONT_XLFD_REPLACE_NONE &&
(p = strchr(strrchr(fname, '-'), '[')))
{
tmpvals.values_supplied |= CHARSUBSET_SPECIFIED;
*p = '\0';
}
tmpvals.pixel = (tmpvals.pixel_matrix[3] >= 0) ?
(int)(tmpvals.pixel_matrix[3] + .5) :
(int)(tmpvals.pixel_matrix[3] - .5);
tmpvals.point = (tmpvals.point_matrix[3] >= 0) ?
(int)(tmpvals.point_matrix[3] * 10 + .5) :
(int)(tmpvals.point_matrix[3] * 10 - .5);
spacingLen = ptr4 - ptr3 + 1;
switch (subst) {
case FONT_XLFD_REPLACE_NONE:
*vals = tmpvals;
break;
case FONT_XLFD_REPLACE_STAR:
replaceChar = '*';
case FONT_XLFD_REPLACE_ZERO:
strcpy(tmpBuf, ptr2);
ptr5 = tmpBuf + (ptr5 - ptr2);
ptr3 = tmpBuf + (ptr3 - ptr2);
ptr2 = tmpBuf;
ptr = ptr1 + 1;
ptr = strchr(ptr, '-') + 1;
ptr = strchr(ptr, '-') + 1;
ptr = strchr(ptr, '-') + 1;
ptr = strchr(ptr, '-') + 1;
if ((ptr - fname) + spacingLen + strlen(ptr5) + 10 >= (unsigned)1024)
return FALSE;
*ptr++ = replaceChar;
*ptr++ = '-';
*ptr++ = replaceChar;
*ptr++ = '-';
*ptr++ = '*';
*ptr++ = '-';
*ptr++ = '*';
if (spacingLen > 2)
{
memmove(ptr, ptr3, spacingLen);
ptr += spacingLen;
}
else
{
*ptr++ = '-';
*ptr++ = '*';
*ptr++ = '-';
}
*ptr++ = replaceChar;
strcpy(ptr, ptr5);
*vals = tmpvals;
break;
case FONT_XLFD_REPLACE_VALUE:
if (vals->values_supplied & PIXELSIZE_MASK)
{
tmpvals.values_supplied =
(tmpvals.values_supplied & ~PIXELSIZE_MASK) |
(vals->values_supplied & PIXELSIZE_MASK);
tmpvals.pixel_matrix[0] = vals->pixel_matrix[0];
tmpvals.pixel_matrix[1] = vals->pixel_matrix[1];
tmpvals.pixel_matrix[2] = vals->pixel_matrix[2];
tmpvals.pixel_matrix[3] = vals->pixel_matrix[3];
}
if (vals->values_supplied & POINTSIZE_MASK)
{
tmpvals.values_supplied =
(tmpvals.values_supplied & ~POINTSIZE_MASK) |
(vals->values_supplied & POINTSIZE_MASK);
tmpvals.point_matrix[0] = vals->point_matrix[0];
tmpvals.point_matrix[1] = vals->point_matrix[1];
tmpvals.point_matrix[2] = vals->point_matrix[2];
tmpvals.point_matrix[3] = vals->point_matrix[3];
}
if (vals->x >= 0)
tmpvals.x = vals->x;
if (vals->y >= 0)
tmpvals.y = vals->y;
if (vals->width >= 0)
tmpvals.width = vals->width;
else if (vals->width < -1)
tmpvals.width = -vals->width;
p = ptr1 + 1;
l = strchr(p, '-') - p;
sprintf(tmpBuf, "%*.*s", l, l, p);
p += l + 1;
l = strchr(p, '-') - p;
sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
p += l + 1;
l = strchr(p, '-') - p;
sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
p += l + 1;
l = strchr(p, '-') - p;
sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
strcat(tmpBuf, "-");
if ((tmpvals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY)
{
char buffer[80];
strcat(tmpBuf, "[");
strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[0],
buffer, 0));
strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[1],
buffer, 1));
strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[2],
buffer, 1));
strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[3],
buffer, 1));
strcat(tmpBuf, "]");
}
else
{
sprintf(tmpBuf + strlen(tmpBuf), "%d",
(int)(tmpvals.pixel_matrix[3] + .5));
}
strcat(tmpBuf, "-");
if ((tmpvals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY)
{
char buffer[80];
strcat(tmpBuf, "[");
strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[0],
buffer, 0));
strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[1],
buffer, 1));
strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[2],
buffer, 1));
strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[3],
buffer, 1));
strcat(tmpBuf, "]");
}
else
{
sprintf(tmpBuf + strlen(tmpBuf), "%d",
(int)(tmpvals.point_matrix[3] * 10.0 + .5));
}
sprintf(tmpBuf + strlen(tmpBuf), "-%d-%d%*.*s%d%s",
tmpvals.x, tmpvals.y,
spacingLen, spacingLen, ptr3, tmpvals.width, ptr5);
strcpy(ptr1 + 1, tmpBuf);
if ((vals->values_supplied & CHARSUBSET_SPECIFIED) && !vals->nranges)
strcat(fname, "[]");
else
append_ranges(fname, vals->nranges, vals->ranges);
break;
}
return TRUE;
}
fsRange *FontParseRanges(char *name, int *nranges)
{
int n;
unsigned long l;
char *p1, *p2;
fsRange *result = (fsRange *)0;
name = strchr(name, '-');
for (n = 1; name && n < 14; n++)
name = strchr(name + 1, '-');
*nranges = 0;
if (!name || !(p1 = strchr(name, '['))) return (fsRange *)0;
p1++;
while (*p1 && *p1 != ']')
{
fsRange thisrange;
l = strtol(p1, &p2, 0);
if (p2 == p1 || l > 0xffff) break;
thisrange.max_char_low = thisrange.min_char_low = l & 0xff;
thisrange.max_char_high = thisrange.min_char_high = l >> 8;
p1 = p2;
if (*p1 == ']' || *p1 == ' ')
{
while (*p1 == ' ') p1++;
if (add_range(&thisrange, nranges, &result, TRUE) != Successful)
break;
}
else if (*p1 == '_')
{
l = strtol(++p1, &p2, 0);
if (p2 == p1 || l > 0xffff) break;
thisrange.max_char_low = l & 0xff;
thisrange.max_char_high = l >> 8;
p1 = p2;
if (*p1 == ']' || *p1 == ' ')
{
while (*p1 == ' ') p1++;
if (add_range(&thisrange, nranges, &result, TRUE) != Successful)
break;
}
}
else break;
}
return result;
}