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