]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/util/fontxlfd.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / lib / font / util / fontxlfd.c
1 /* $XConsortium: fontxlfd.c /main/20 1996/09/28 16:49:26 rws $ */
2 /* $XFree86: xc/lib/font/util/fontxlfd.c,v 3.5 1996/12/23 06:02:34 dawes Exp $ */
3
4 /*
5
6 Copyright (c) 1990  X Consortium
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice shall be included
17 in all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 OTHER DEALINGS IN THE SOFTWARE.
26
27 Except as contained in this notice, the name of the X Consortium shall
28 not be used in advertising or otherwise to promote the sale, use or
29 other dealings in this Software without prior written authorization
30 from the X Consortium.
31
32 */
33
34 /*
35  * Author:  Keith Packard, MIT X Consortium
36  */
37
38 #include        "fontmisc.h"
39 #include        "fontstruct.h"
40 #include        "fontxlfd.h"
41 #include        <X11/Xos.h>
42 #include        <math.h>
43 #if !defined(X_NOT_STDC_ENV) || defined(SCO)
44 #include        <stdlib.h>
45 #endif
46 #if defined(X_NOT_STDC_ENV) || (defined(sony) && !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV))
47 #define NO_LOCALE
48 #endif
49 #ifndef NO_LOCALE
50 #include        <locale.h>
51 #endif
52 #include        <ctype.h>
53 #include        <stdio.h>       /* for sprintf() */
54
55 static char *
56 GetInt(ptr, val)
57     char       *ptr;
58     int        *val;
59 {
60     if (*ptr == '*') {
61         *val = -1;
62         ptr++;
63     } else
64         for (*val = 0; *ptr >= '0' && *ptr <= '9';)
65             *val = *val * 10 + *ptr++ - '0';
66     if (*ptr == '-')
67         return ptr;
68     return (char *) 0;
69 }
70
71 #define minchar(p) ((p).min_char_low + ((p).min_char_high << 8))
72 #define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8))
73
74
75 #ifndef NO_LOCALE
76 static struct lconv *locale = 0;
77 #endif
78 static char *radix = ".", *plus = "+", *minus = "-";
79
80 static char *
81 readreal(ptr, result)
82 char *ptr;
83 double *result;
84 {
85     char buffer[80], *p1, *p2;
86     int count;
87
88 #ifndef NO_LOCALE
89     /* Figure out what symbols apply in this locale */
90
91     if (!locale)
92     {
93         locale = localeconv();
94         if (locale->decimal_point && *locale->decimal_point)
95             radix = locale->decimal_point;
96         if (locale->positive_sign && *locale->positive_sign)
97             plus = locale->positive_sign;
98         if (locale->negative_sign && *locale->negative_sign)
99             minus = locale->negative_sign;
100     }
101 #endif
102     /* Copy the first 80 chars of ptr into our local buffer, changing
103        symbols as needed. */
104     for (p1 = ptr, p2 = buffer;
105          *p1 && (p2 - buffer) < sizeof(buffer) - 1;
106          p1++, p2++)
107     {
108         switch(*p1)
109         {
110             case '~': *p2 = *minus; break;
111             case '+': *p2 = *plus; break;
112             case '.': *p2 = *radix; break;
113             default: *p2 = *p1;
114         }
115     }
116     *p2 = 0;
117
118     /* Now we have something that strtod() can interpret... do it. */
119 #ifndef X_NOT_STDC_ENV
120     *result = strtod(buffer, &p1);
121     /* Return NULL if failure, pointer past number if success */
122     return (p1 == buffer) ? (char *)0 : (ptr + (p1 - buffer));
123 #else
124     for (p1 = buffer; isspace(*p1); p1++)
125         ;
126     if (sscanf(p1, "%lf", result) != 1)
127         return (char *)0;
128     while (!isspace(*p1))
129         p1++;
130     return ptr + (p1 - buffer);
131 #endif
132 }
133
134 static char *
135 xlfd_double_to_text(value, buffer, space_required)
136 double value;
137 char *buffer;
138 int space_required;
139 {
140     char formatbuf[40];
141     register char *p1;
142     int ndigits, exponent;
143
144 #ifndef NO_LOCALE
145     if (!locale)
146     {
147         locale = localeconv();
148         if (locale->decimal_point && *locale->decimal_point)
149             radix = locale->decimal_point;
150         if (locale->positive_sign && *locale->positive_sign)
151             plus = locale->positive_sign;
152         if (locale->negative_sign && *locale->negative_sign)
153             minus = locale->negative_sign;
154     }
155 #endif
156     /* Compute a format to use to render the number */
157     sprintf(formatbuf, "%%.%dle", XLFD_NDIGITS);
158
159     if (space_required)
160         *buffer++ = ' ';
161
162     /* Render the number using printf's idea of formatting */
163     sprintf(buffer, formatbuf, value);
164
165     /* Find and read the exponent value */
166     for (p1 = buffer + strlen(buffer);
167         *p1-- != 'e' && p1[1] != 'E';);
168     exponent = atoi(p1 + 2);
169     if (value == 0.0) exponent = 0;
170
171     /* Figure out how many digits are significant */
172     while (p1 >= buffer && (!isdigit(*p1) || *p1 == '0')) p1--;
173     ndigits = 0;
174     while (p1 >= buffer) if (isdigit(*p1--)) ndigits++;
175
176     /* Figure out notation to use */
177     if (exponent >= XLFD_NDIGITS || ndigits - exponent > XLFD_NDIGITS + 1)
178     {
179         /* Scientific */
180         sprintf(formatbuf, "%%.%dle", ndigits - 1);
181         sprintf(buffer, formatbuf, value);
182     }
183     else
184     {
185         /* Fixed */
186         ndigits -= exponent + 1;
187         if (ndigits < 0) ndigits = 0;
188         sprintf(formatbuf, "%%.%dlf", ndigits);
189         sprintf(buffer, formatbuf, value);
190         if (exponent < 0)
191         {
192             p1 = buffer;
193             while (*p1 && *p1 != '0') p1++;
194             while (*p1++) p1[-1] = *p1;
195         }
196     }
197
198     /* Last step, convert the locale-specific sign and radix characters
199        to our own. */
200     for (p1 = buffer; *p1; p1++)
201     {
202         if (*p1 == *minus) *p1 = '~';
203         else if (*p1 == *plus) *p1 = '+';
204         else if (*p1 == *radix) *p1 = '.';
205     }
206
207     return buffer - space_required;
208 }
209
210 double
211 xlfd_round_double(x)
212 double x;
213 {
214    /* Utility for XLFD users to round numbers to XLFD_NDIGITS
215       significant digits.  How do you round to n significant digits on
216       a binary machine?  */
217
218 #if defined(i386) || defined(__i386__) || defined(__alpha__)
219 #if !defined(__EMX__)
220 #include <float.h>
221
222 /* if we have IEEE 754 fp, we can round to binary digits... */
223
224 #if (FLT_RADIX == 2) && (DBL_DIG == 15) && (DBL_MANT_DIG == 53)
225
226 #ifndef M_LN2
227 #define M_LN2       0.69314718055994530942
228 #endif
229 #ifndef M_LN10
230 #define M_LN10      2.30258509299404568402
231 #endif
232
233 /* convert # of decimal digits to # of binary digits */
234 #define XLFD_NDIGITS_2 ((int)(XLFD_NDIGITS * M_LN10 / M_LN2 + 0.5))
235    
236    union conv_d {
237       double d;
238       unsigned char b[8];
239    } d;
240    int i,j,k,d_exp;
241    
242    if (x == 0) 
243       return x;
244
245    /* do minor sanity check for IEEE 754 fp and correct byte order */
246    d.d = 1.0;
247    if (sizeof(double) == 8 && d.b[7] == 0x3f && d.b[6] == 0xf0) {
248       
249       /* 
250        * this code will round IEEE 754 double to XLFD_NDIGITS_2 binary digits
251        */
252       
253       d.d = x;
254       d_exp = (d.b[7] << 4) | (d.b[6] >> 4);
255       
256       i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3;
257       j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07);
258       for (; i<7; i++) {
259          k = d.b[i] + j;
260          d.b[i] = k;
261          if (k & 0x100) j = 1;
262          else break;
263       }
264       if ((i==7) && ((d.b[6] & 0xf0) != ((d_exp<<4) & 0xf0))) {
265          /* mantissa overflow: increment exponent */
266          d_exp = (d_exp & 0x800 ) | ((d_exp & 0x7ff) + 1);
267          d.b[7] = d_exp >> 4;
268          d.b[6] = (d.b[6] & 0x0f) | (d_exp << 4);
269       }
270       
271       i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3;
272       j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07);      
273       d.b[i] &= ~(j-1);
274       for (;--i>=0;) d.b[i] = 0;
275
276       return d.d;
277    }
278    else 
279 #endif
280 #endif /* !__EMX__ */
281 #endif /* i386 || __i386__ */
282     {
283         /*
284          * If not IEEE 754:  Let printf() do it for you.  
285          */
286          
287         char formatbuf[40], buffer[40];
288          
289         sprintf(formatbuf, "%%.%dlg", XLFD_NDIGITS);
290         sprintf(buffer, formatbuf, x);
291         return atof(buffer);
292     }
293 }
294
295 static char *
296 GetMatrix(ptr, vals, which)
297 char *ptr;
298 FontScalablePtr vals;
299 int which;
300 {
301     double *matrix;
302
303     if (which == PIXELSIZE_MASK)
304         matrix = vals->pixel_matrix;
305     else if (which == POINTSIZE_MASK)
306         matrix = vals->point_matrix;
307     else return (char *)0;
308
309     while (isspace(*ptr)) ptr++;
310     if (*ptr == '[')
311     {
312         /* This is a matrix containing real numbers.  It would be nice
313            to use strtod() or sscanf() to read the numbers, but those
314            don't handle '~' for minus and we cannot force them to use a
315            "."  for the radix.  We'll have to do the hard work ourselves
316            (in readreal()).  */
317
318         if ((ptr = readreal(++ptr, matrix + 0)) &&
319             (ptr = readreal(ptr, matrix + 1)) &&
320             (ptr = readreal(ptr, matrix + 2)) &&
321             (ptr = readreal(ptr, matrix + 3)))
322         {
323             while (isspace(*ptr)) ptr++;
324             if (*ptr != ']')
325                 ptr = (char *)0;
326             else
327             {
328                 ptr++;
329                 while (isspace(*ptr)) ptr++;
330                 if (*ptr == '-')
331                 {
332                     if (which == POINTSIZE_MASK)
333                         vals->values_supplied |= POINTSIZE_ARRAY;
334                     else
335                         vals->values_supplied |= PIXELSIZE_ARRAY;
336                 }
337                 else ptr = (char *)0;
338             }
339         }
340     }
341     else
342     {
343         int value;
344         if (ptr = GetInt(ptr, &value))
345         {
346             vals->values_supplied &= ~which;
347             if (value > 0)
348             {
349                 matrix[3] = (double)value;
350                 if (which == POINTSIZE_MASK)
351                 {
352                     matrix[3] /= 10.0;
353                     vals->values_supplied |= POINTSIZE_SCALAR;
354                 }
355                 else
356                     vals->values_supplied |= PIXELSIZE_SCALAR;
357                 /* If we're concocting the pixelsize array from a scalar,
358                    we will need to normalize element 0 for the pixel shape.
359                    This is done in FontFileCompleteXLFD(). */
360                 matrix[0] = matrix[3];
361                 matrix[1] = matrix[2] = 0.0;
362             }
363             else if (value < 0)
364             {
365                 if (which == POINTSIZE_MASK)
366                     vals->values_supplied |= POINTSIZE_WILDCARD;
367                 else
368                     vals->values_supplied |= PIXELSIZE_WILDCARD;
369             }
370         }
371     }
372     return ptr;
373 }
374
375
376 static void append_ranges(fname, nranges, ranges)
377 char *fname;
378 int nranges;
379 fsRange *ranges;
380 {
381     if (nranges)
382     {
383         int i;
384
385         strcat(fname, "[");
386         for (i = 0; i < nranges && strlen(fname) < 1010; i++)
387         {
388             if (i) strcat(fname, " ");
389             sprintf(fname + strlen(fname), "%d",
390                     minchar(ranges[i]));
391             if (ranges[i].min_char_low ==
392                 ranges[i].max_char_low &&
393                 ranges[i].min_char_high ==
394                 ranges[i].max_char_high) continue;
395             sprintf(fname + strlen(fname), "_%d",
396                     maxchar(ranges[i]));
397         }
398         strcat(fname, "]");
399     }
400 }
401
402 Bool
403 FontParseXLFDName(fname, vals, subst)
404     char       *fname;
405     FontScalablePtr vals;
406     int         subst;
407 {
408     register char *ptr;
409     register char *ptr1,
410                *ptr2,
411                *ptr3,
412                *ptr4;
413     register char *ptr5;
414     FontScalableRec tmpvals;
415     char        replaceChar = '0';
416     char        tmpBuf[1024];
417     int         spacingLen;
418     int         l;
419     char        *p;
420
421     bzero(&tmpvals, sizeof(tmpvals));
422     if (subst != FONT_XLFD_REPLACE_VALUE)
423         *vals = tmpvals;
424
425     if (!(*(ptr = fname) == '-' || *ptr++ == '*' && *ptr == '-') ||  /* fndry */
426             !(ptr = strchr(ptr + 1, '-')) ||    /* family_name */
427             !(ptr1 = ptr = strchr(ptr + 1, '-')) ||     /* weight_name */
428             !(ptr = strchr(ptr + 1, '-')) ||    /* slant */
429             !(ptr = strchr(ptr + 1, '-')) ||    /* setwidth_name */
430             !(ptr = strchr(ptr + 1, '-')) ||    /* add_style_name */
431             !(ptr = strchr(ptr + 1, '-')) ||    /* pixel_size */
432             !(ptr = GetMatrix(ptr + 1, &tmpvals, PIXELSIZE_MASK)) ||
433             !(ptr2 = ptr = GetMatrix(ptr + 1, &tmpvals, POINTSIZE_MASK)) ||
434             !(ptr = GetInt(ptr + 1, &tmpvals.x)) ||     /* resolution_x */
435             !(ptr3 = ptr = GetInt(ptr + 1, &tmpvals.y)) ||  /* resolution_y */
436             !(ptr4 = ptr = strchr(ptr + 1, '-')) ||     /* spacing */
437             !(ptr5 = ptr = GetInt(ptr + 1, &tmpvals.width)) || /* average_width */
438             !(ptr = strchr(ptr + 1, '-')) ||    /* charset_registry */
439             strchr(ptr + 1, '-'))/* charset_encoding */
440         return FALSE;
441
442     /* Lop off HP charset subsetting enhancement.  Interpreting this
443        field requires allocating some space in which to return the
444        results.  So, to prevent memory leaks, this procedure will simply
445        lop off and ignore charset subsetting, and initialize the
446        relevant vals fields to zero.  It's up to the caller to make its
447        own call to FontParseRanges() if it's interested in the charset
448        subsetting.  */
449
450     if (subst != FONT_XLFD_REPLACE_NONE &&
451         (p = strchr(strrchr(fname, '-'), '[')))
452     {
453         tmpvals.values_supplied |= CHARSUBSET_SPECIFIED;
454         *p = '\0';
455     }
456
457     /* Fill in deprecated fields for the benefit of rasterizers that care
458        about them. */
459     tmpvals.pixel = (tmpvals.pixel_matrix[3] >= 0) ?
460                     (int)(tmpvals.pixel_matrix[3] + .5) :
461                     (int)(tmpvals.pixel_matrix[3] - .5);
462     tmpvals.point = (tmpvals.point_matrix[3] >= 0) ?
463                     (int)(tmpvals.point_matrix[3] * 10 + .5) :
464                     (int)(tmpvals.point_matrix[3] * 10 - .5);
465
466     spacingLen = ptr4 - ptr3 + 1;
467
468     switch (subst) {
469     case FONT_XLFD_REPLACE_NONE:
470         *vals = tmpvals;
471         break;
472     case FONT_XLFD_REPLACE_STAR:
473         replaceChar = '*';
474     case FONT_XLFD_REPLACE_ZERO:
475         strcpy(tmpBuf, ptr2);
476         ptr5 = tmpBuf + (ptr5 - ptr2);
477         ptr3 = tmpBuf + (ptr3 - ptr2);
478         ptr2 = tmpBuf;
479         ptr = ptr1 + 1;
480
481         ptr = strchr(ptr, '-') + 1;             /* skip weight */
482         ptr = strchr(ptr, '-') + 1;             /* skip slant */
483         ptr = strchr(ptr, '-') + 1;             /* skip setwidth_name */
484         ptr = strchr(ptr, '-') + 1;             /* skip add_style_name */
485
486         if ((ptr - fname) + spacingLen + strlen(ptr5) + 10 >= (unsigned)1024)
487             return FALSE;
488         *ptr++ = replaceChar;
489         *ptr++ = '-';
490         *ptr++ = replaceChar;
491         *ptr++ = '-';
492         *ptr++ = '*';
493         *ptr++ = '-';
494         *ptr++ = '*';
495         if (spacingLen > 2)
496         {
497             memmove(ptr, ptr3, spacingLen);
498             ptr += spacingLen;
499         }
500         else
501         {
502             *ptr++ = '-';
503             *ptr++ = '*';
504             *ptr++ = '-';
505         }
506         *ptr++ = replaceChar;
507         strcpy(ptr, ptr5);
508         *vals = tmpvals;
509         break;
510     case FONT_XLFD_REPLACE_VALUE:
511         if (vals->values_supplied & PIXELSIZE_MASK)
512         {
513             tmpvals.values_supplied =
514                 (tmpvals.values_supplied & ~PIXELSIZE_MASK) |
515                 (vals->values_supplied & PIXELSIZE_MASK);
516             tmpvals.pixel_matrix[0] = vals->pixel_matrix[0];
517             tmpvals.pixel_matrix[1] = vals->pixel_matrix[1];
518             tmpvals.pixel_matrix[2] = vals->pixel_matrix[2];
519             tmpvals.pixel_matrix[3] = vals->pixel_matrix[3];
520         }
521         if (vals->values_supplied & POINTSIZE_MASK)
522         {
523             tmpvals.values_supplied =
524                 (tmpvals.values_supplied & ~POINTSIZE_MASK) |
525                 (vals->values_supplied & POINTSIZE_MASK);
526             tmpvals.point_matrix[0] = vals->point_matrix[0];
527             tmpvals.point_matrix[1] = vals->point_matrix[1];
528             tmpvals.point_matrix[2] = vals->point_matrix[2];
529             tmpvals.point_matrix[3] = vals->point_matrix[3];
530         }
531         if (vals->x >= 0)
532             tmpvals.x = vals->x;
533         if (vals->y >= 0)
534             tmpvals.y = vals->y;
535         if (vals->width >= 0)
536             tmpvals.width = vals->width;
537         else if (vals->width < -1)      /* overload: -1 means wildcard */
538             tmpvals.width = -vals->width;
539
540
541         p = ptr1 + 1;                           /* weight field */
542         l = strchr(p, '-') - p;
543         sprintf(tmpBuf, "%*.*s", l, l, p);
544
545         p += l + 1;                             /* slant field */
546         l = strchr(p, '-') - p;
547         sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
548
549         p += l + 1;                             /* setwidth_name */
550         l = strchr(p, '-') - p;
551         sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
552
553         p += l + 1;                             /* add_style_name field */
554         l = strchr(p, '-') - p;
555         sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
556
557         strcat(tmpBuf, "-");
558         if ((tmpvals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY)
559         {
560             char buffer[80];
561             strcat(tmpBuf, "[");
562             strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[0],
563                    buffer, 0));
564             strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[1],
565                    buffer, 1));
566             strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[2],
567                    buffer, 1));
568             strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[3],
569                    buffer, 1));
570             strcat(tmpBuf, "]");
571         }
572         else
573         {
574             sprintf(tmpBuf + strlen(tmpBuf), "%d",
575                     (int)(tmpvals.pixel_matrix[3] + .5));
576         }
577         strcat(tmpBuf, "-");
578         if ((tmpvals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY)
579         {
580             char buffer[80];
581             strcat(tmpBuf, "[");
582             strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[0],
583                    buffer, 0));
584             strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[1],
585                    buffer, 1));
586             strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[2],
587                    buffer, 1));
588             strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[3],
589                    buffer, 1));
590             strcat(tmpBuf, "]");
591         }
592         else
593         {
594             sprintf(tmpBuf + strlen(tmpBuf), "%d",
595                     (int)(tmpvals.point_matrix[3] * 10.0 + .5));
596         }
597         sprintf(tmpBuf + strlen(tmpBuf), "-%d-%d%*.*s%d%s",
598                 tmpvals.x, tmpvals.y,
599                 spacingLen, spacingLen, ptr3, tmpvals.width, ptr5);
600         strcpy(ptr1 + 1, tmpBuf);
601         if ((vals->values_supplied & CHARSUBSET_SPECIFIED) && !vals->nranges)
602             strcat(fname, "[]");
603         else
604             append_ranges(fname, vals->nranges, vals->ranges);
605         break;
606     }
607     return TRUE;
608 }
609
610 fsRange *FontParseRanges(name, nranges)
611 char *name;
612 int *nranges;
613 {
614     int n;
615     unsigned long l;
616     char *p1, *p2;
617     fsRange *result = (fsRange *)0;
618
619     name = strchr(name, '-');
620     for (n = 1; name && n < 14; n++)
621         name = strchr(name + 1, '-');
622
623     *nranges = 0;
624     if (!name || !(p1 = strchr(name, '['))) return (fsRange *)0;
625     p1++;
626
627     while (*p1 && *p1 != ']')
628     {
629         fsRange thisrange;
630
631         l = strtol(p1, &p2, 0);
632         if (p2 == p1 || l > 0xffff) break;
633         thisrange.max_char_low = thisrange.min_char_low = l & 0xff;
634         thisrange.max_char_high = thisrange.min_char_high = l >> 8;
635
636         p1 = p2;
637         if (*p1 == ']' || *p1 == ' ')
638         {
639             while (*p1 == ' ') p1++;
640             if (add_range(&thisrange, nranges, &result, TRUE) != Successful)
641                 break;
642         }
643         else if (*p1 == '_')
644         {
645             l = strtol(++p1, &p2, 0);
646             if (p2 == p1 || l > 0xffff) break;
647             thisrange.max_char_low = l & 0xff;
648             thisrange.max_char_high = l >> 8;
649             p1 = p2;
650             if (*p1 == ']' || *p1 == ' ')
651             {
652                 while (*p1 == ' ') p1++;
653                 if (add_range(&thisrange, nranges, &result, TRUE) != Successful)
654                     break;
655             }
656         }
657         else break;
658     }
659
660     return result;
661 }