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