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