| 1 | /* |
| 2 | * Copyright (C) 1989-95 GROUPE BULL |
| 3 | * |
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 5 | * of this software and associated documentation files (the "Software"), to |
| 6 | * deal in the Software without restriction, including without limitation the |
| 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| 8 | * sell copies of the Software, and to permit persons to whom the Software is |
| 9 | * furnished to do so, subject to the following conditions: |
| 10 | * |
| 11 | * The above copyright notice and this permission notice shall be included in |
| 12 | * all copies or substantial portions of the Software. |
| 13 | * |
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 17 | * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
| 18 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 20 | * |
| 21 | * Except as contained in this notice, the name of GROUPE BULL shall not be |
| 22 | * used in advertising or otherwise to promote the sale, use or other dealings |
| 23 | * in this Software without prior written authorization from GROUPE BULL. |
| 24 | */ |
| 25 | |
| 26 | /*****************************************************************************\ |
| 27 | * parse.c: * |
| 28 | * * |
| 29 | * XPM library * |
| 30 | * Parse an XPM file or array and store the found informations * |
| 31 | * in the given XpmImage structure. * |
| 32 | * * |
| 33 | * Developed by Arnaud Le Hors * |
| 34 | \*****************************************************************************/ |
| 35 | |
| 36 | /* |
| 37 | * The code related to FOR_MSW has been added by |
| 38 | * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 |
| 39 | */ |
| 40 | |
| 41 | #include "XpmI.h" |
| 42 | #include <ctype.h> |
| 43 | |
| 44 | LFUNC(ParsePixels, int, (xpmData *data, unsigned int width, |
| 45 | unsigned int height, unsigned int ncolors, |
| 46 | unsigned int cpp, XpmColor *colorTable, |
| 47 | xpmHashTable *hashtable, unsigned int **pixels)); |
| 48 | |
| 49 | char *xpmColorKeys[] = { |
| 50 | "s", /* key #1: symbol */ |
| 51 | "m", /* key #2: mono visual */ |
| 52 | "g4", /* key #3: 4 grays visual */ |
| 53 | "g", /* key #4: gray visual */ |
| 54 | "c", /* key #5: color visual */ |
| 55 | }; |
| 56 | |
| 57 | int |
| 58 | xpmParseValues(data, width, height, ncolors, cpp, |
| 59 | x_hotspot, y_hotspot, hotspot, extensions) |
| 60 | xpmData *data; |
| 61 | unsigned int *width, *height, *ncolors, *cpp; |
| 62 | unsigned int *x_hotspot, *y_hotspot, *hotspot; |
| 63 | unsigned int *extensions; |
| 64 | { |
| 65 | unsigned int l; |
| 66 | char buf[BUFSIZ]; |
| 67 | |
| 68 | if (!data->format) { /* XPM 2 or 3 */ |
| 69 | |
| 70 | /* |
| 71 | * read values: width, height, ncolors, chars_per_pixel |
| 72 | */ |
| 73 | if (!(xpmNextUI(data, width) && xpmNextUI(data, height) |
| 74 | && xpmNextUI(data, ncolors) && xpmNextUI(data, cpp))) |
| 75 | return (XpmFileInvalid); |
| 76 | |
| 77 | /* |
| 78 | * read optional information (hotspot and/or XPMEXT) if any |
| 79 | */ |
| 80 | l = xpmNextWord(data, buf, BUFSIZ); |
| 81 | if (l) { |
| 82 | *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6)); |
| 83 | if (*extensions) |
| 84 | *hotspot = (xpmNextUI(data, x_hotspot) |
| 85 | && xpmNextUI(data, y_hotspot)); |
| 86 | else { |
| 87 | *hotspot = (xpmatoui(buf, l, x_hotspot) |
| 88 | && xpmNextUI(data, y_hotspot)); |
| 89 | l = xpmNextWord(data, buf, BUFSIZ); |
| 90 | *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6)); |
| 91 | } |
| 92 | } |
| 93 | } else { |
| 94 | |
| 95 | /* |
| 96 | * XPM 1 file read values: width, height, ncolors, chars_per_pixel |
| 97 | */ |
| 98 | int i; |
| 99 | char *ptr; |
| 100 | Bool got_one, saw_width = False, saw_height = False; |
| 101 | Bool saw_ncolors = False, saw_chars_per_pixel = False; |
| 102 | |
| 103 | for (i = 0; i < 4; i++) { |
| 104 | l = xpmNextWord(data, buf, BUFSIZ); |
| 105 | if (l != 7 || strncmp("#define", buf, 7)) |
| 106 | return (XpmFileInvalid); |
| 107 | l = xpmNextWord(data, buf, BUFSIZ); |
| 108 | if (!l) |
| 109 | return (XpmFileInvalid); |
| 110 | buf[l] = '\0'; |
| 111 | ptr = buf; |
| 112 | got_one = False; |
| 113 | while (!got_one) { |
| 114 | #if defined(macintosh) || defined(__APPLE__) |
| 115 | // we have a strange parameter problem here |
| 116 | ptr = strchr(ptr, '_'); // index |
| 117 | #else |
| 118 | ptr = index(ptr, '_'); |
| 119 | #endif |
| 120 | if (!ptr) |
| 121 | return (XpmFileInvalid); |
| 122 | switch (l - (ptr - buf)) { |
| 123 | case 6: |
| 124 | if (saw_width || strncmp("_width", ptr, 6) |
| 125 | || !xpmNextUI(data, width)) |
| 126 | return (XpmFileInvalid); |
| 127 | else |
| 128 | saw_width = True; |
| 129 | got_one = True; |
| 130 | break; |
| 131 | case 7: |
| 132 | if (saw_height || strncmp("_height", ptr, 7) |
| 133 | || !xpmNextUI(data, height)) |
| 134 | return (XpmFileInvalid); |
| 135 | else |
| 136 | saw_height = True; |
| 137 | got_one = True; |
| 138 | break; |
| 139 | case 8: |
| 140 | if (saw_ncolors || strncmp("_ncolors", ptr, 8) |
| 141 | || !xpmNextUI(data, ncolors)) |
| 142 | return (XpmFileInvalid); |
| 143 | else |
| 144 | saw_ncolors = True; |
| 145 | got_one = True; |
| 146 | break; |
| 147 | case 16: |
| 148 | if (saw_chars_per_pixel |
| 149 | || strncmp("_chars_per_pixel", ptr, 16) |
| 150 | || !xpmNextUI(data, cpp)) |
| 151 | return (XpmFileInvalid); |
| 152 | else |
| 153 | saw_chars_per_pixel = True; |
| 154 | got_one = True; |
| 155 | break; |
| 156 | default: |
| 157 | ptr++; |
| 158 | } |
| 159 | } |
| 160 | /* skip the end of line */ |
| 161 | xpmNextString(data); |
| 162 | } |
| 163 | if (!saw_width || !saw_height || !saw_ncolors || !saw_chars_per_pixel) |
| 164 | return (XpmFileInvalid); |
| 165 | |
| 166 | *hotspot = 0; |
| 167 | *extensions = 0; |
| 168 | } |
| 169 | return (XpmSuccess); |
| 170 | } |
| 171 | |
| 172 | int |
| 173 | xpmParseColors(data, ncolors, cpp, colorTablePtr, hashtable) |
| 174 | xpmData *data; |
| 175 | unsigned int ncolors; |
| 176 | unsigned int cpp; |
| 177 | XpmColor **colorTablePtr; |
| 178 | xpmHashTable *hashtable; |
| 179 | { |
| 180 | unsigned int key, l, a, b; |
| 181 | unsigned int curkey; /* current color key */ |
| 182 | unsigned int lastwaskey; /* key read */ |
| 183 | char buf[BUFSIZ]; |
| 184 | char curbuf[BUFSIZ]; /* current buffer */ |
| 185 | char **sptr, *s; |
| 186 | XpmColor *color; |
| 187 | XpmColor *colorTable; |
| 188 | char **defaults; |
| 189 | int ErrorStatus; |
| 190 | |
| 191 | colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor)); |
| 192 | if (!colorTable) |
| 193 | return (XpmNoMemory); |
| 194 | |
| 195 | if (!data->format) { /* XPM 2 or 3 */ |
| 196 | for (a = 0, color = colorTable; a < ncolors; a++, color++) { |
| 197 | xpmNextString(data); /* skip the line */ |
| 198 | |
| 199 | /* |
| 200 | * read pixel value |
| 201 | */ |
| 202 | color->string = (char *) XpmMalloc(cpp + 1); |
| 203 | if (!color->string) { |
| 204 | xpmFreeColorTable(colorTable, ncolors); |
| 205 | return (XpmNoMemory); |
| 206 | } |
| 207 | for (b = 0, s = color->string; b < cpp; b++, s++) |
| 208 | *s = xpmGetC(data); |
| 209 | *s = '\0'; |
| 210 | |
| 211 | /* |
| 212 | * store the string in the hashtable with its color index number |
| 213 | */ |
| 214 | if (USE_HASHTABLE) { |
| 215 | ErrorStatus = |
| 216 | xpmHashIntern(hashtable, color->string, HashAtomData(a)); |
| 217 | if (ErrorStatus != XpmSuccess) { |
| 218 | xpmFreeColorTable(colorTable, ncolors); |
| 219 | return (ErrorStatus); |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | /* |
| 224 | * read color keys and values |
| 225 | */ |
| 226 | defaults = (char **) color; |
| 227 | curkey = 0; |
| 228 | lastwaskey = 0; |
| 229 | *curbuf = '\0'; /* init curbuf */ |
| 230 | while ((l = xpmNextWord(data, buf, BUFSIZ))!=NULL ) { |
| 231 | if (!lastwaskey) { |
| 232 | for (key = 0, sptr = xpmColorKeys; key < NKEYS; key++, |
| 233 | sptr++) |
| 234 | if ((strlen(*sptr) == l) && (!strncmp(*sptr, buf, l))) |
| 235 | break; |
| 236 | } |
| 237 | if (!lastwaskey && key < NKEYS) { /* open new key */ |
| 238 | if (curkey) { /* flush string */ |
| 239 | s = (char *) XpmMalloc(strlen(curbuf) + 1); |
| 240 | if (!s) { |
| 241 | xpmFreeColorTable(colorTable, ncolors); |
| 242 | return (XpmNoMemory); |
| 243 | } |
| 244 | defaults[curkey] = s; |
| 245 | strcpy(s, curbuf); |
| 246 | } |
| 247 | curkey = key + 1; /* set new key */ |
| 248 | *curbuf = '\0'; /* reset curbuf */ |
| 249 | lastwaskey = 1; |
| 250 | } else { |
| 251 | if (!curkey) { /* key without value */ |
| 252 | xpmFreeColorTable(colorTable, ncolors); |
| 253 | return (XpmFileInvalid); |
| 254 | } |
| 255 | if (!lastwaskey) |
| 256 | strcat(curbuf, " "); /* append space */ |
| 257 | buf[l] = '\0'; |
| 258 | strcat(curbuf, buf);/* append buf */ |
| 259 | lastwaskey = 0; |
| 260 | } |
| 261 | } |
| 262 | if (!curkey) { /* key without value */ |
| 263 | xpmFreeColorTable(colorTable, ncolors); |
| 264 | return (XpmFileInvalid); |
| 265 | } |
| 266 | s = defaults[curkey] = (char *) XpmMalloc(strlen(curbuf) + 1); |
| 267 | if (!s) { |
| 268 | xpmFreeColorTable(colorTable, ncolors); |
| 269 | return (XpmNoMemory); |
| 270 | } |
| 271 | strcpy(s, curbuf); |
| 272 | } |
| 273 | } else { /* XPM 1 */ |
| 274 | /* get to the beginning of the first string */ |
| 275 | data->Bos = '"'; |
| 276 | data->Eos = '\0'; |
| 277 | xpmNextString(data); |
| 278 | data->Eos = '"'; |
| 279 | for (a = 0, color = colorTable; a < ncolors; a++, color++) { |
| 280 | |
| 281 | /* |
| 282 | * read pixel value |
| 283 | */ |
| 284 | color->string = (char *) XpmMalloc(cpp + 1); |
| 285 | if (!color->string) { |
| 286 | xpmFreeColorTable(colorTable, ncolors); |
| 287 | return (XpmNoMemory); |
| 288 | } |
| 289 | for (b = 0, s = color->string; b < cpp; b++, s++) |
| 290 | *s = xpmGetC(data); |
| 291 | *s = '\0'; |
| 292 | |
| 293 | /* |
| 294 | * store the string in the hashtable with its color index number |
| 295 | */ |
| 296 | if (USE_HASHTABLE) { |
| 297 | ErrorStatus = |
| 298 | xpmHashIntern(hashtable, color->string, HashAtomData(a)); |
| 299 | if (ErrorStatus != XpmSuccess) { |
| 300 | xpmFreeColorTable(colorTable, ncolors); |
| 301 | return (ErrorStatus); |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | /* |
| 306 | * read color values |
| 307 | */ |
| 308 | xpmNextString(data); /* get to the next string */ |
| 309 | *curbuf = '\0'; /* init curbuf */ |
| 310 | while ((l = xpmNextWord(data, buf, BUFSIZ))!=NULL ) { |
| 311 | if (*curbuf != '\0') |
| 312 | strcat(curbuf, " ");/* append space */ |
| 313 | buf[l] = '\0'; |
| 314 | strcat(curbuf, buf); /* append buf */ |
| 315 | } |
| 316 | s = (char *) XpmMalloc(strlen(curbuf) + 1); |
| 317 | if (!s) { |
| 318 | xpmFreeColorTable(colorTable, ncolors); |
| 319 | return (XpmNoMemory); |
| 320 | } |
| 321 | strcpy(s, curbuf); |
| 322 | color->c_color = s; |
| 323 | *curbuf = '\0'; /* reset curbuf */ |
| 324 | if (a < ncolors - 1) |
| 325 | xpmNextString(data); /* get to the next string */ |
| 326 | } |
| 327 | } |
| 328 | *colorTablePtr = colorTable; |
| 329 | return (XpmSuccess); |
| 330 | } |
| 331 | |
| 332 | static int |
| 333 | ParsePixels(data, width, height, ncolors, cpp, colorTable, hashtable, pixels) |
| 334 | xpmData *data; |
| 335 | unsigned int width; |
| 336 | unsigned int height; |
| 337 | unsigned int ncolors; |
| 338 | unsigned int cpp; |
| 339 | XpmColor *colorTable; |
| 340 | xpmHashTable *hashtable; |
| 341 | unsigned int **pixels; |
| 342 | { |
| 343 | unsigned int *iptr, *iptr2; |
| 344 | unsigned int a, x, y; |
| 345 | |
| 346 | #ifndef FOR_MSW |
| 347 | iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height); |
| 348 | #else |
| 349 | |
| 350 | /* |
| 351 | * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!! |
| 352 | * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary |
| 353 | */ |
| 354 | iptr2 = (unsigned int *) |
| 355 | XpmMalloc((long) sizeof(unsigned int) * (long) width * (long) height); |
| 356 | #endif |
| 357 | if (!iptr2) |
| 358 | return (XpmNoMemory); |
| 359 | |
| 360 | iptr = iptr2; |
| 361 | |
| 362 | switch (cpp) { |
| 363 | |
| 364 | case (1): /* Optimize for single character |
| 365 | * colors */ |
| 366 | { |
| 367 | unsigned short colidx[256]; |
| 368 | |
| 369 | bzero((char *)colidx, 256 * sizeof(short)); |
| 370 | for (a = 0; a < ncolors; a++) |
| 371 | colidx[(unsigned char)colorTable[a].string[0]] = a + 1; |
| 372 | |
| 373 | for (y = 0; y < height; y++) { |
| 374 | xpmNextString(data); |
| 375 | for (x = 0; x < width; x++, iptr++) { |
| 376 | int c = xpmGetC(data); |
| 377 | |
| 378 | if (c > 0 && c < 256 && colidx[c] != 0) |
| 379 | *iptr = colidx[c] - 1; |
| 380 | else { |
| 381 | XpmFree(iptr2); |
| 382 | return (XpmFileInvalid); |
| 383 | } |
| 384 | } |
| 385 | } |
| 386 | } |
| 387 | break; |
| 388 | |
| 389 | case (2): /* Optimize for double character |
| 390 | * colors */ |
| 391 | { |
| 392 | |
| 393 | /* free all allocated pointers at all exits */ |
| 394 | #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \ |
| 395 | if (cidx[f]) XpmFree(cidx[f]);} |
| 396 | |
| 397 | /* array of pointers malloced by need */ |
| 398 | unsigned short *cidx[256]; |
| 399 | int char1; |
| 400 | |
| 401 | bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */ |
| 402 | for (a = 0; a < ncolors; a++) { |
| 403 | char1 = colorTable[a].string[0]; |
| 404 | if (cidx[char1] == NULL) { /* get new memory */ |
| 405 | cidx[char1] = (unsigned short *) |
| 406 | XpmCalloc(256, sizeof(unsigned short)); |
| 407 | if (cidx[char1] == NULL) { /* new block failed */ |
| 408 | FREE_CIDX; |
| 409 | XpmFree(iptr2); |
| 410 | return (XpmNoMemory); |
| 411 | } |
| 412 | } |
| 413 | cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1; |
| 414 | } |
| 415 | |
| 416 | for (y = 0; y < height; y++) { |
| 417 | xpmNextString(data); |
| 418 | for (x = 0; x < width; x++, iptr++) { |
| 419 | int cc1 = xpmGetC(data); |
| 420 | if (cc1 > 0 && cc1 < 256) { |
| 421 | int cc2 = xpmGetC(data); |
| 422 | if (cc2 > 0 && cc2 < 256 && |
| 423 | cidx[cc1] && cidx[cc1][cc2] != 0) |
| 424 | *iptr = cidx[cc1][cc2] - 1; |
| 425 | else { |
| 426 | FREE_CIDX; |
| 427 | XpmFree(iptr2); |
| 428 | return (XpmFileInvalid); |
| 429 | } |
| 430 | } else { |
| 431 | FREE_CIDX; |
| 432 | XpmFree(iptr2); |
| 433 | return (XpmFileInvalid); |
| 434 | } |
| 435 | } |
| 436 | } |
| 437 | FREE_CIDX; |
| 438 | } |
| 439 | break; |
| 440 | |
| 441 | default: /* Non-optimized case of long color |
| 442 | * names */ |
| 443 | { |
| 444 | char *s; |
| 445 | char buf[BUFSIZ]; |
| 446 | |
| 447 | buf[cpp] = '\0'; |
| 448 | if (USE_HASHTABLE) { |
| 449 | xpmHashAtom *slot; |
| 450 | |
| 451 | for (y = 0; y < height; y++) { |
| 452 | xpmNextString(data); |
| 453 | for (x = 0; x < width; x++, iptr++) { |
| 454 | for (a = 0, s = buf; a < cpp; a++, s++) |
| 455 | *s = xpmGetC(data); |
| 456 | slot = xpmHashSlot(hashtable, buf); |
| 457 | if (!*slot) { /* no color matches */ |
| 458 | XpmFree(iptr2); |
| 459 | return (XpmFileInvalid); |
| 460 | } |
| 461 | *iptr = HashColorIndex(slot); |
| 462 | } |
| 463 | } |
| 464 | } else { |
| 465 | for (y = 0; y < height; y++) { |
| 466 | xpmNextString(data); |
| 467 | for (x = 0; x < width; x++, iptr++) { |
| 468 | for (a = 0, s = buf; a < cpp; a++, s++) |
| 469 | *s = xpmGetC(data); |
| 470 | for (a = 0; a < ncolors; a++) |
| 471 | if (!strcmp(colorTable[a].string, buf)) |
| 472 | break; |
| 473 | if (a == ncolors) { /* no color matches */ |
| 474 | XpmFree(iptr2); |
| 475 | return (XpmFileInvalid); |
| 476 | } |
| 477 | *iptr = a; |
| 478 | } |
| 479 | } |
| 480 | } |
| 481 | } |
| 482 | break; |
| 483 | } |
| 484 | *pixels = iptr2; |
| 485 | return (XpmSuccess); |
| 486 | } |
| 487 | |
| 488 | int |
| 489 | xpmParseExtensions(data, extensions, nextensions) |
| 490 | xpmData *data; |
| 491 | XpmExtension **extensions; |
| 492 | unsigned int *nextensions; |
| 493 | { |
| 494 | XpmExtension *exts = NULL, *ext; |
| 495 | unsigned int num = 0; |
| 496 | unsigned int nlines, a, l, notstart, notend = 0; |
| 497 | int status; |
| 498 | char *string, *s, *s2, **sp; |
| 499 | |
| 500 | xpmNextString(data); |
| 501 | exts = (XpmExtension *) XpmMalloc(sizeof(XpmExtension)); |
| 502 | /* get the whole string */ |
| 503 | status = xpmGetString(data, &string, &l); |
| 504 | if (status != XpmSuccess) { |
| 505 | XpmFree(exts); |
| 506 | return (status); |
| 507 | } |
| 508 | /* look for the key word XPMEXT, skip lines before this */ |
| 509 | while ((notstart = strncmp("XPMEXT", string, 6))!=NULL |
| 510 | && (notend = strncmp("XPMENDEXT", string, 9))!=NULL ) { |
| 511 | XpmFree(string); |
| 512 | xpmNextString(data); |
| 513 | status = xpmGetString(data, &string, &l); |
| 514 | if (status != XpmSuccess) { |
| 515 | XpmFree(exts); |
| 516 | return (status); |
| 517 | } |
| 518 | } |
| 519 | if (!notstart) |
| 520 | notend = strncmp("XPMENDEXT", string, 9); |
| 521 | while (!notstart && notend) { |
| 522 | /* there starts an extension */ |
| 523 | ext = (XpmExtension *) |
| 524 | XpmRealloc(exts, (num + 1) * sizeof(XpmExtension)); |
| 525 | if (!ext) { |
| 526 | XpmFree(string); |
| 527 | XpmFreeExtensions(exts, num); |
| 528 | return (XpmNoMemory); |
| 529 | } |
| 530 | exts = ext; |
| 531 | ext += num; |
| 532 | /* skip whitespace and store its name */ |
| 533 | s2 = s = string + 6; |
| 534 | while (isspace(*s2)) |
| 535 | s2++; |
| 536 | a = s2 - s; |
| 537 | ext->name = (char *) XpmMalloc(l - a - 6); |
| 538 | if (!ext->name) { |
| 539 | XpmFree(string); |
| 540 | ext->lines = NULL; |
| 541 | ext->nlines = 0; |
| 542 | XpmFreeExtensions(exts, num + 1); |
| 543 | return (XpmNoMemory); |
| 544 | } |
| 545 | strncpy(ext->name, s + a, l - a - 6); |
| 546 | XpmFree(string); |
| 547 | /* now store the related lines */ |
| 548 | xpmNextString(data); |
| 549 | status = xpmGetString(data, &string, &l); |
| 550 | if (status != XpmSuccess) { |
| 551 | ext->lines = NULL; |
| 552 | ext->nlines = 0; |
| 553 | XpmFreeExtensions(exts, num + 1); |
| 554 | return (status); |
| 555 | } |
| 556 | ext->lines = (char **) XpmMalloc(sizeof(char *)); |
| 557 | nlines = 0; |
| 558 | while ((notstart = strncmp("XPMEXT", string, 6))!=NULL |
| 559 | && (notend = strncmp("XPMENDEXT", string, 9))!=NULL ) { |
| 560 | sp = (char **) |
| 561 | XpmRealloc(ext->lines, (nlines + 1) * sizeof(char *)); |
| 562 | if (!sp) { |
| 563 | XpmFree(string); |
| 564 | ext->nlines = nlines; |
| 565 | XpmFreeExtensions(exts, num + 1); |
| 566 | return (XpmNoMemory); |
| 567 | } |
| 568 | ext->lines = sp; |
| 569 | ext->lines[nlines] = string; |
| 570 | nlines++; |
| 571 | xpmNextString(data); |
| 572 | status = xpmGetString(data, &string, &l); |
| 573 | if (status != XpmSuccess) { |
| 574 | ext->nlines = nlines; |
| 575 | XpmFreeExtensions(exts, num + 1); |
| 576 | return (status); |
| 577 | } |
| 578 | } |
| 579 | if (!nlines) { |
| 580 | XpmFree(ext->lines); |
| 581 | ext->lines = NULL; |
| 582 | } |
| 583 | ext->nlines = nlines; |
| 584 | num++; |
| 585 | } |
| 586 | if (!num) { |
| 587 | XpmFree(string); |
| 588 | XpmFree(exts); |
| 589 | exts = NULL; |
| 590 | } else if (!notend) |
| 591 | XpmFree(string); |
| 592 | *nextensions = num; |
| 593 | *extensions = exts; |
| 594 | return (XpmSuccess); |
| 595 | } |
| 596 | |
| 597 | |
| 598 | /* function call in case of error */ |
| 599 | #undef RETURN |
| 600 | #define RETURN(status) \ |
| 601 | { \ |
| 602 | goto error; \ |
| 603 | } |
| 604 | |
| 605 | /* |
| 606 | * This function parses an Xpm file or data and store the found informations |
| 607 | * in an an XpmImage structure which is returned. |
| 608 | */ |
| 609 | int |
| 610 | xpmParseData(data, image, info) |
| 611 | xpmData *data; |
| 612 | XpmImage *image; |
| 613 | XpmInfo *info; |
| 614 | { |
| 615 | /* variables to return */ |
| 616 | unsigned int width, height, ncolors, cpp; |
| 617 | unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0; |
| 618 | XpmColor *colorTable = NULL; |
| 619 | unsigned int *pixelindex = NULL; |
| 620 | char *hints_cmt = NULL; |
| 621 | char *colors_cmt = NULL; |
| 622 | char *pixels_cmt = NULL; |
| 623 | |
| 624 | unsigned int cmts; |
| 625 | int ErrorStatus; |
| 626 | xpmHashTable hashtable; |
| 627 | |
| 628 | cmts = info && (info->valuemask & XpmReturnComments); |
| 629 | |
| 630 | /* |
| 631 | * parse the header |
| 632 | */ |
| 633 | ErrorStatus = xpmParseHeader(data); |
| 634 | if (ErrorStatus != XpmSuccess) |
| 635 | return (ErrorStatus); |
| 636 | |
| 637 | /* |
| 638 | * read values |
| 639 | */ |
| 640 | ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp, |
| 641 | &x_hotspot, &y_hotspot, &hotspot, |
| 642 | &extensions); |
| 643 | if (ErrorStatus != XpmSuccess) |
| 644 | return (ErrorStatus); |
| 645 | |
| 646 | /* |
| 647 | * store the hints comment line |
| 648 | */ |
| 649 | if (cmts) |
| 650 | xpmGetCmt(data, &hints_cmt); |
| 651 | |
| 652 | /* |
| 653 | * init the hastable |
| 654 | */ |
| 655 | if (USE_HASHTABLE) { |
| 656 | ErrorStatus = xpmHashTableInit(&hashtable); |
| 657 | if (ErrorStatus != XpmSuccess) |
| 658 | return (ErrorStatus); |
| 659 | } |
| 660 | |
| 661 | /* |
| 662 | * read colors |
| 663 | */ |
| 664 | ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable); |
| 665 | if (ErrorStatus != XpmSuccess) { |
| 666 | if (USE_HASHTABLE) |
| 667 | xpmHashTableFree(&hashtable); |
| 668 | RETURN(ErrorStatus); |
| 669 | } |
| 670 | |
| 671 | /* |
| 672 | * store the colors comment line |
| 673 | */ |
| 674 | if (cmts) |
| 675 | xpmGetCmt(data, &colors_cmt); |
| 676 | |
| 677 | /* |
| 678 | * read pixels and index them on color number |
| 679 | */ |
| 680 | ErrorStatus = ParsePixels(data, width, height, ncolors, cpp, colorTable, |
| 681 | &hashtable, &pixelindex); |
| 682 | |
| 683 | /* |
| 684 | * free the hastable |
| 685 | */ |
| 686 | if (USE_HASHTABLE) |
| 687 | xpmHashTableFree(&hashtable); |
| 688 | |
| 689 | if (ErrorStatus != XpmSuccess) |
| 690 | RETURN(ErrorStatus); |
| 691 | |
| 692 | /* |
| 693 | * store the pixels comment line |
| 694 | */ |
| 695 | if (cmts) |
| 696 | xpmGetCmt(data, &pixels_cmt); |
| 697 | |
| 698 | /* |
| 699 | * parse extensions |
| 700 | */ |
| 701 | if (info && (info->valuemask & XpmReturnExtensions)) |
| 702 | if (extensions) { |
| 703 | ErrorStatus = xpmParseExtensions(data, &info->extensions, |
| 704 | &info->nextensions); |
| 705 | if (ErrorStatus != XpmSuccess) |
| 706 | RETURN(ErrorStatus); |
| 707 | } else { |
| 708 | info->extensions = NULL; |
| 709 | info->nextensions = 0; |
| 710 | } |
| 711 | |
| 712 | /* |
| 713 | * store found informations in the XpmImage structure |
| 714 | */ |
| 715 | image->width = width; |
| 716 | image->height = height; |
| 717 | image->cpp = cpp; |
| 718 | image->ncolors = ncolors; |
| 719 | image->colorTable = colorTable; |
| 720 | image->data = pixelindex; |
| 721 | |
| 722 | if (info) { |
| 723 | if (cmts) { |
| 724 | info->hints_cmt = hints_cmt; |
| 725 | info->colors_cmt = colors_cmt; |
| 726 | info->pixels_cmt = pixels_cmt; |
| 727 | } |
| 728 | if (hotspot) { |
| 729 | info->x_hotspot = x_hotspot; |
| 730 | info->y_hotspot = y_hotspot; |
| 731 | info->valuemask |= XpmHotspot; |
| 732 | } |
| 733 | } |
| 734 | return (XpmSuccess); |
| 735 | |
| 736 | /* exit point in case of error, free only locally allocated variables */ |
| 737 | error: |
| 738 | if (colorTable) |
| 739 | xpmFreeColorTable(colorTable, ncolors); |
| 740 | if (pixelindex) |
| 741 | XpmFree(pixelindex); |
| 742 | if (hints_cmt) |
| 743 | XpmFree(hints_cmt); |
| 744 | if (colors_cmt) |
| 745 | XpmFree(colors_cmt); |
| 746 | if (pixels_cmt) |
| 747 | XpmFree(pixels_cmt); |
| 748 | |
| 749 | return(ErrorStatus); |
| 750 | } |