]> git.saurik.com Git - wxWidgets.git/blame - src/xpm/data.c
XPM updates
[wxWidgets.git] / src / xpm / data.c
CommitLineData
cfbe03c9 1/*
e6ed776f 2 * Copyright (C) 1989-95 GROUPE BULL
cfbe03c9
JS
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* data.c: *
28* *
29* XPM library *
30* IO utilities *
31* *
32* Developed by Arnaud Le Hors *
33\*****************************************************************************/
34
e6ed776f 35#ifndef CXPMPROG
cfbe03c9 36/* Official version number */
e6ed776f 37static char *RCS_Version = "$XpmVersion: 3.4k $";
cfbe03c9
JS
38
39/* Internal version number */
40static char *RCS_Id = "$Id$";
41
e6ed776f 42#include "XpmI.h"
cfbe03c9 43#endif
e6ed776f 44#include <ctype.h>
cfbe03c9 45
e6ed776f
GRG
46#ifndef CXPMPROG
47#define Getc(data, file) getc(file)
48#define Ungetc(data, c, file) ungetc(c, file)
49#endif
cfbe03c9 50
ea258ad3
DW
51#ifdef __OS2__
52/* Visual Age cannot deal with old, non-ansi, code */
53static int
54ParseComment(xpmData* data)
55#else
cfbe03c9 56static int
e6ed776f
GRG
57ParseComment(data)
58 xpmData *data;
ea258ad3 59#endif
cfbe03c9 60{
e6ed776f 61 if (data->type == XPMBUFFER) {
cfbe03c9
JS
62 register char c;
63 register unsigned int n = 0;
64 unsigned int notend;
65 char *s, *s2;
66
e6ed776f
GRG
67 s = data->Comment;
68 *s = data->Bcmt[0];
cfbe03c9
JS
69
70 /* skip the string beginning comment */
e6ed776f 71 s2 = data->Bcmt;
cfbe03c9 72 do {
e6ed776f 73 c = *data->cptr++;
cfbe03c9
JS
74 *++s = c;
75 n++;
76 s2++;
e6ed776f 77 } while (c == *s2 && *s2 != '\0' && c);
cfbe03c9
JS
78
79 if (*s2 != '\0') {
80 /* this wasn't the beginning of a comment */
e6ed776f 81 data->cptr -= n;
cfbe03c9
JS
82 return 0;
83 }
84 /* store comment */
e6ed776f
GRG
85 data->Comment[0] = *s;
86 s = data->Comment;
cfbe03c9
JS
87 notend = 1;
88 n = 0;
89 while (notend) {
e6ed776f
GRG
90 s2 = data->Ecmt;
91 while (*s != *s2 && c) {
92 c = *data->cptr++;
93 if (n == XPMMAXCMTLEN - 1) { /* forget it */
94 s = data->Comment;
95 n = 0;
96 }
cfbe03c9
JS
97 *++s = c;
98 n++;
99 }
e6ed776f 100 data->CommentLength = n;
cfbe03c9 101 do {
e6ed776f
GRG
102 c = *data->cptr++;
103 if (n == XPMMAXCMTLEN - 1) { /* forget it */
104 s = data->Comment;
105 n = 0;
106 }
cfbe03c9 107 *++s = c;
e6ed776f 108 n++;
cfbe03c9 109 s2++;
e6ed776f 110 } while (c == *s2 && *s2 != '\0' && c);
cfbe03c9
JS
111 if (*s2 == '\0') {
112 /* this is the end of the comment */
113 notend = 0;
e6ed776f 114 data->cptr--;
cfbe03c9
JS
115 }
116 }
117 return 0;
118 } else {
e6ed776f 119 FILE *file = data->stream.file;
cfbe03c9
JS
120 register int c;
121 register unsigned int n = 0, a;
122 unsigned int notend;
123 char *s, *s2;
124
e6ed776f
GRG
125 s = data->Comment;
126 *s = data->Bcmt[0];
cfbe03c9
JS
127
128 /* skip the string beginning comment */
e6ed776f 129 s2 = data->Bcmt;
cfbe03c9 130 do {
e6ed776f 131 c = Getc(data, file);
cfbe03c9
JS
132 *++s = c;
133 n++;
134 s2++;
e6ed776f 135 } while (c == *s2 && *s2 != '\0' && c != EOF);
cfbe03c9
JS
136
137 if (*s2 != '\0') {
138 /* this wasn't the beginning of a comment */
139 /* put characters back in the order that we got them */
140 for (a = n; a > 0; a--, s--)
e6ed776f 141 Ungetc(data, *s, file);
cfbe03c9
JS
142 return 0;
143 }
144 /* store comment */
e6ed776f
GRG
145 data->Comment[0] = *s;
146 s = data->Comment;
cfbe03c9
JS
147 notend = 1;
148 n = 0;
149 while (notend) {
e6ed776f
GRG
150 s2 = data->Ecmt;
151 while (*s != *s2 && c != EOF) {
152 c = Getc(data, file);
153 if (n == XPMMAXCMTLEN - 1) { /* forget it */
154 s = data->Comment;
155 n = 0;
156 }
cfbe03c9
JS
157 *++s = c;
158 n++;
159 }
e6ed776f 160 data->CommentLength = n;
cfbe03c9 161 do {
e6ed776f
GRG
162 c = Getc(data, file);
163 if (n == XPMMAXCMTLEN - 1) { /* forget it */
164 s = data->Comment;
165 n = 0;
166 }
cfbe03c9 167 *++s = c;
e6ed776f 168 n++;
cfbe03c9 169 s2++;
e6ed776f 170 } while (c == *s2 && *s2 != '\0' && c != EOF);
cfbe03c9
JS
171 if (*s2 == '\0') {
172 /* this is the end of the comment */
173 notend = 0;
e6ed776f 174 Ungetc(data, *s, file);
cfbe03c9
JS
175 }
176 }
177 return 0;
178 }
179}
180
181/*
182 * skip to the end of the current string and the beginning of the next one
183 */
ea258ad3
DW
184#ifdef __OS2__
185/* Visual Age cannot deal with old, non-ansi, code */
186int xpmNextString(xpmData* data)
187#else
cfbe03c9 188int
e6ed776f
GRG
189xpmNextString(data)
190 xpmData *data;
ea258ad3 191#endif
cfbe03c9 192{
e6ed776f
GRG
193 if (!data->type)
194 data->cptr = (data->stream.data)[++data->line];
195 else if (data->type == XPMBUFFER) {
cfbe03c9
JS
196 register char c;
197
198 /* get to the end of the current string */
e6ed776f
GRG
199 if (data->Eos)
200 while ((c = *data->cptr++) && c != data->Eos);
cfbe03c9
JS
201
202 /*
203 * then get to the beginning of the next string looking for possible
204 * comment
205 */
e6ed776f
GRG
206 if (data->Bos) {
207 while ((c = *data->cptr++) && c != data->Bos)
208 if (data->Bcmt && c == data->Bcmt[0])
209 ParseComment(data);
210 } else if (data->Bcmt) { /* XPM2 natural */
211 while ((c = *data->cptr++) == data->Bcmt[0])
212 ParseComment(data);
213 data->cptr--;
cfbe03c9
JS
214 }
215 } else {
216 register int c;
e6ed776f 217 FILE *file = data->stream.file;
cfbe03c9
JS
218
219 /* get to the end of the current string */
e6ed776f
GRG
220 if (data->Eos)
221 while ((c = Getc(data, file)) != data->Eos && c != EOF);
cfbe03c9
JS
222
223 /*
224 * then get to the beginning of the next string looking for possible
225 * comment
226 */
e6ed776f
GRG
227 if (data->Bos) {
228 while ((c = Getc(data, file)) != data->Bos && c != EOF)
229 if (data->Bcmt && c == data->Bcmt[0])
230 ParseComment(data);
231
232 } else if (data->Bcmt) { /* XPM2 natural */
233 while ((c = Getc(data, file)) == data->Bcmt[0])
234 ParseComment(data);
235 Ungetc(data, c, file);
cfbe03c9
JS
236 }
237 }
238 return 0;
239}
240
241
cfbe03c9
JS
242/*
243 * skip whitespace and return the following word
244 */
ea258ad3
DW
245#ifdef __OS2__
246/* Visual Age cannot deal with old, non-ansi, code */
247unsigned int xpmNextWord(
248 xpmData* data
249, char* buf
250, unsigned int buflen
251)
252#else
cfbe03c9 253unsigned int
e6ed776f
GRG
254xpmNextWord(data, buf, buflen)
255 xpmData *data;
256 char *buf;
257 unsigned int buflen;
ea258ad3 258#endif
cfbe03c9
JS
259{
260 register unsigned int n = 0;
261 int c;
262
e6ed776f
GRG
263 if (!data->type || data->type == XPMBUFFER) {
264 while (isspace(c = *data->cptr) && c != data->Eos)
265 data->cptr++;
cfbe03c9 266 do {
e6ed776f 267 c = *data->cptr++;
cfbe03c9
JS
268 *buf++ = c;
269 n++;
e6ed776f 270 } while (!isspace(c) && c != data->Eos && n < buflen);
cfbe03c9 271 n--;
e6ed776f 272 data->cptr--;
cfbe03c9 273 } else {
e6ed776f 274 FILE *file = data->stream.file;
cfbe03c9 275
e6ed776f
GRG
276 while ((c = Getc(data, file)) != EOF && isspace(c) && c != data->Eos);
277 while (!isspace(c) && c != data->Eos && c != EOF && n < buflen) {
cfbe03c9
JS
278 *buf++ = c;
279 n++;
e6ed776f 280 c = Getc(data, file);
cfbe03c9 281 }
e6ed776f 282 Ungetc(data, c, file);
cfbe03c9
JS
283 }
284 return (n);
285}
286
e6ed776f
GRG
287/*
288 * skip whitespace and compute the following unsigned int,
289 * returns 1 if one is found and 0 if not
290 */
ea258ad3
DW
291#ifdef __OS2__
292/* Visual Age cannot deal with old, non-ansi, code */
293int
294xpmNextUI(xpmData* data, unsigned int* ui_return)
295#else
e6ed776f
GRG
296int
297xpmNextUI(data, ui_return)
298 xpmData *data;
299 unsigned int *ui_return;
ea258ad3 300#endif
e6ed776f
GRG
301{
302 char buf[BUFSIZ];
303 int l;
304
305 l = xpmNextWord(data, buf, BUFSIZ);
306 return xpmatoui(buf, l, ui_return);
307}
308
cfbe03c9
JS
309/*
310 * return end of string - WARNING: malloc!
311 */
ea258ad3
DW
312#ifdef __OS2__
313/* Visual Age cannot deal with old, non-ansi, code */
314int xpmGetString(xpmData* data, char** sptr, unsigned int* l)
315#else
cfbe03c9 316int
e6ed776f
GRG
317xpmGetString(data, sptr, l)
318 xpmData *data;
319 char **sptr;
320 unsigned int *l;
ea258ad3 321#endif
cfbe03c9
JS
322{
323 unsigned int i, n = 0;
324 int c;
e6ed776f
GRG
325 char *p = NULL, *q, buf[BUFSIZ];
326
327 if (!data->type || data->type == XPMBUFFER) {
328 if (data->cptr) {
329 char *start = data->cptr;
330 while ((c = *data->cptr) && c != data->Eos)
331 data->cptr++;
332 n = data->cptr - start + 1;
cfbe03c9
JS
333 p = (char *) XpmMalloc(n);
334 if (!p)
335 return (XpmNoMemory);
336 strncpy(p, start, n);
e6ed776f 337 if (data->type) /* XPMBUFFER */
cfbe03c9
JS
338 p[n - 1] = '\0';
339 }
340 } else {
e6ed776f 341 FILE *file = data->stream.file;
cfbe03c9 342
e6ed776f 343 if ((c = Getc(data, file)) == EOF)
cfbe03c9 344 return (XpmFileInvalid);
e6ed776f 345
cfbe03c9
JS
346 i = 0;
347 q = buf;
348 p = (char *) XpmMalloc(1);
e6ed776f 349 while (c != data->Eos && c != EOF) {
cfbe03c9
JS
350 if (i == BUFSIZ) {
351 /* get to the end of the buffer */
352 /* malloc needed memory */
353 q = (char *) XpmRealloc(p, n + i);
354 if (!q) {
355 XpmFree(p);
356 return (XpmNoMemory);
357 }
358 p = q;
359 q += n;
360 /* and copy what we already have */
361 strncpy(q, buf, i);
362 n += i;
363 i = 0;
364 q = buf;
365 }
366 *q++ = c;
367 i++;
e6ed776f 368 c = Getc(data, file);
cfbe03c9
JS
369 }
370 if (c == EOF) {
371 XpmFree(p);
372 return (XpmFileInvalid);
373 }
374 if (n + i != 0) {
375 /* malloc needed memory */
376 q = (char *) XpmRealloc(p, n + i + 1);
377 if (!q) {
378 XpmFree(p);
379 return (XpmNoMemory);
380 }
381 p = q;
382 q += n;
383 /* and copy the buffer */
384 strncpy(q, buf, i);
385 n += i;
386 p[n++] = '\0';
387 } else {
388 *p = '\0';
389 n = 1;
390 }
e6ed776f 391 Ungetc(data, c, file);
cfbe03c9
JS
392 }
393 *sptr = p;
394 *l = n;
395 return (XpmSuccess);
396}
397
398/*
399 * get the current comment line
400 */
ea258ad3
DW
401#ifdef __OS2__
402/* Visual Age cannot deal with old, non-ansi, code */
403int xpmGetCmt(xpmData* data, char** cmt)
404#else
cfbe03c9 405int
e6ed776f
GRG
406xpmGetCmt(data, cmt)
407 xpmData *data;
408 char **cmt;
ea258ad3 409#endif
cfbe03c9 410{
e6ed776f 411 if (!data->type)
cfbe03c9 412 *cmt = NULL;
e6ed776f
GRG
413 else if (data->CommentLength) {
414 *cmt = (char *) XpmMalloc(data->CommentLength + 1);
415 strncpy(*cmt, data->Comment, data->CommentLength);
416 (*cmt)[data->CommentLength] = '\0';
417 data->CommentLength = 0;
cfbe03c9
JS
418 } else
419 *cmt = NULL;
420 return 0;
421}
422
cfbe03c9
JS
423xpmDataType xpmDataTypes[] =
424{
425 "", "!", "\n", '\0', '\n', "", "", "", "", /* Natural type */
426 "C", "/*", "*/", '"', '"', ",\n", "static char *", "[] = {\n", "};\n",
427 "Lisp", ";", "\n", '"', '"', "\n", "(setq ", " '(\n", "))\n",
428#ifdef VMS
429 NULL
430#else
431 NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL
432#endif
433};
434
435/*
436 * parse xpm header
437 */
ea258ad3
DW
438#ifdef __OS2__
439/* Visual Age cannot deal with old, non-ansi, code */
440int xpmParseHeader(xpmData* data)
441#else
cfbe03c9 442int
e6ed776f
GRG
443xpmParseHeader(data)
444 xpmData *data;
ea258ad3 445#endif
cfbe03c9
JS
446{
447 char buf[BUFSIZ];
448 int l, n = 0;
449
e6ed776f
GRG
450 if (data->type) {
451 data->Bos = '\0';
452 data->Eos = '\n';
453 data->Bcmt = data->Ecmt = NULL;
454 l = xpmNextWord(data, buf, BUFSIZ);
cfbe03c9
JS
455 if (l == 7 && !strncmp("#define", buf, 7)) {
456 /* this maybe an XPM 1 file */
457 char *ptr;
458
e6ed776f 459 l = xpmNextWord(data, buf, BUFSIZ);
cfbe03c9
JS
460 if (!l)
461 return (XpmFileInvalid);
e6ed776f
GRG
462 buf[l] = '\0';
463 ptr = rindex(buf, '_');
cfbe03c9
JS
464 if (!ptr || strncmp("_format", ptr, l - (ptr - buf)))
465 return XpmFileInvalid;
466 /* this is definitely an XPM 1 file */
e6ed776f 467 data->format = 1;
cfbe03c9
JS
468 n = 1; /* handle XPM1 as mainly XPM2 C */
469 } else {
470
471 /*
472 * skip the first word, get the second one, and see if this is
473 * XPM 2 or 3
474 */
e6ed776f 475 l = xpmNextWord(data, buf, BUFSIZ);
cfbe03c9
JS
476 if ((l == 3 && !strncmp("XPM", buf, 3)) ||
477 (l == 4 && !strncmp("XPM2", buf, 4))) {
478 if (l == 3)
479 n = 1; /* handle XPM as XPM2 C */
480 else {
481 /* get the type key word */
e6ed776f 482 l = xpmNextWord(data, buf, BUFSIZ);
cfbe03c9
JS
483
484 /*
485 * get infos about this type
486 */
487 while (xpmDataTypes[n].type
488 && strncmp(xpmDataTypes[n].type, buf, l))
489 n++;
490 }
e6ed776f 491 data->format = 0;
cfbe03c9
JS
492 } else
493 /* nope this is not an XPM file */
494 return XpmFileInvalid;
495 }
496 if (xpmDataTypes[n].type) {
497 if (n == 0) { /* natural type */
e6ed776f
GRG
498 data->Bcmt = xpmDataTypes[n].Bcmt;
499 data->Ecmt = xpmDataTypes[n].Ecmt;
500 xpmNextString(data); /* skip the end of the headerline */
501 data->Bos = xpmDataTypes[n].Bos;
502 data->Eos = xpmDataTypes[n].Eos;
cfbe03c9 503 } else {
e6ed776f
GRG
504 data->Bcmt = xpmDataTypes[n].Bcmt;
505 data->Ecmt = xpmDataTypes[n].Ecmt;
506 if (!data->format) { /* XPM 2 or 3 */
507 data->Bos = xpmDataTypes[n].Bos;
508 data->Eos = '\0';
cfbe03c9 509 /* get to the beginning of the first string */
e6ed776f
GRG
510 xpmNextString(data);
511 data->Eos = xpmDataTypes[n].Eos;
cfbe03c9 512 } else /* XPM 1 skip end of line */
e6ed776f 513 xpmNextString(data);
cfbe03c9
JS
514 }
515 } else
516 /* we don't know about that type of XPM file... */
517 return XpmFileInvalid;
518 }
519 return XpmSuccess;
520}