]> git.saurik.com Git - wxWidgets.git/blob - src/mac/xpm/data.c
Fix for the wrong painting rectangle being set.
[wxWidgets.git] / src / mac / 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 /* Official version number */
37 static char *RCS_Version = "$XpmVersion: 3.4k $";
38
39 /* Internal version number */
40 static char *RCS_Id = "$Id$";
41
42 #include "XpmI.h"
43 #endif
44 #include <ctype.h>
45
46 #ifndef CXPMPROG
47 #define Getc(data, file) getc(file)
48 #define Ungetc(data, c, file) ungetc(c, file)
49 #endif
50
51 static int
52 ParseComment(data)
53 xpmData *data;
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 int
179 xpmNextString(data)
180 xpmData *data;
181 {
182 if (!data->type)
183 data->cptr = (data->stream.data)[++data->line];
184 else if (data->type == XPMBUFFER) {
185 register char c;
186
187 /* get to the end of the current string */
188 if (data->Eos)
189 while ((c = *data->cptr++)!=NULL && c != data->Eos)
190 {}
191
192 /*
193 * then get to the beginning of the next string looking for possible
194 * comment
195 */
196 if (data->Bos) {
197 while ((c = *data->cptr++)!=NULL && c != data->Bos)
198 if (data->Bcmt && c == data->Bcmt[0])
199 ParseComment(data);
200 } else if (data->Bcmt) { /* XPM2 natural */
201 while ((c = *data->cptr++) == data->Bcmt[0])
202 ParseComment(data);
203 data->cptr--;
204 }
205 } else {
206 register int c;
207 FILE *file = data->stream.file;
208
209 /* get to the end of the current string */
210 if (data->Eos)
211 while ((c = Getc(data, file))!=NULL != data->Eos && c != EOF)
212 {}
213
214 /*
215 * then get to the beginning of the next string looking for possible
216 * comment
217 */
218 if (data->Bos) {
219 while ((c = Getc(data, file)) != data->Bos && c != EOF)
220 if (data->Bcmt && c == data->Bcmt[0])
221 ParseComment(data);
222
223 } else if (data->Bcmt) { /* XPM2 natural */
224 while ((c = Getc(data, file)) == data->Bcmt[0])
225 ParseComment(data);
226 Ungetc(data, c, file);
227 }
228 }
229 return 0;
230 }
231
232
233 /*
234 * skip whitespace and return the following word
235 */
236 unsigned int
237 xpmNextWord(data, buf, buflen)
238 xpmData *data;
239 char *buf;
240 unsigned int buflen;
241 {
242 register unsigned int n = 0;
243 int c;
244
245 if (!data->type || data->type == XPMBUFFER) {
246 while (isspace(c = *data->cptr) && c != data->Eos)
247 data->cptr++;
248 do {
249 c = *data->cptr++;
250 *buf++ = c;
251 n++;
252 } while (!isspace(c) && c != data->Eos && n < buflen);
253 n--;
254 data->cptr--;
255 } else {
256 FILE *file = data->stream.file;
257
258 while ((c = Getc(data, file)) != EOF && isspace(c) && c != data->Eos)
259 {
260 }
261 while (!isspace(c) && c != data->Eos && c != EOF && n < buflen) {
262 *buf++ = c;
263 n++;
264 c = Getc(data, file);
265 }
266 Ungetc(data, c, file);
267 }
268 return (n);
269 }
270
271 /*
272 * skip whitespace and compute the following unsigned int,
273 * returns 1 if one is found and 0 if not
274 */
275 int
276 xpmNextUI(data, ui_return)
277 xpmData *data;
278 unsigned int *ui_return;
279 {
280 char buf[BUFSIZ];
281 int l;
282
283 l = xpmNextWord(data, buf, BUFSIZ);
284 return xpmatoui(buf, l, ui_return);
285 }
286
287 /*
288 * return end of string - WARNING: malloc!
289 */
290 int
291 xpmGetString(data, sptr, l)
292 xpmData *data;
293 char **sptr;
294 unsigned int *l;
295 {
296 unsigned int i, n = 0;
297 int c;
298 char *p = NULL, *q, buf[BUFSIZ];
299
300 if (!data->type || data->type == XPMBUFFER) {
301 if (data->cptr) {
302 char *start = data->cptr;
303 while ((c = *data->cptr)!=NULL && c != data->Eos)
304 data->cptr++;
305 n = data->cptr - start + 1;
306 p = (char *) XpmMalloc(n);
307 if (!p)
308 return (XpmNoMemory);
309 strncpy(p, start, n);
310 if (data->type) /* XPMBUFFER */
311 p[n - 1] = '\0';
312 }
313 } else {
314 FILE *file = data->stream.file;
315
316 if ((c = Getc(data, file)) == EOF)
317 return (XpmFileInvalid);
318
319 i = 0;
320 q = buf;
321 p = (char *) XpmMalloc(1);
322 while (c != data->Eos && c != EOF) {
323 if (i == BUFSIZ) {
324 /* get to the end of the buffer */
325 /* malloc needed memory */
326 q = (char *) XpmRealloc(p, n + i);
327 if (!q) {
328 XpmFree(p);
329 return (XpmNoMemory);
330 }
331 p = q;
332 q += n;
333 /* and copy what we already have */
334 strncpy(q, buf, i);
335 n += i;
336 i = 0;
337 q = buf;
338 }
339 *q++ = c;
340 i++;
341 c = Getc(data, file);
342 }
343 if (c == EOF) {
344 XpmFree(p);
345 return (XpmFileInvalid);
346 }
347 if (n + i != 0) {
348 /* malloc needed memory */
349 q = (char *) XpmRealloc(p, n + i + 1);
350 if (!q) {
351 XpmFree(p);
352 return (XpmNoMemory);
353 }
354 p = q;
355 q += n;
356 /* and copy the buffer */
357 strncpy(q, buf, i);
358 n += i;
359 p[n++] = '\0';
360 } else {
361 *p = '\0';
362 n = 1;
363 }
364 Ungetc(data, c, file);
365 }
366 *sptr = p;
367 *l = n;
368 return (XpmSuccess);
369 }
370
371 /*
372 * get the current comment line
373 */
374 int
375 xpmGetCmt(data, cmt)
376 xpmData *data;
377 char **cmt;
378 {
379 if (!data->type)
380 *cmt = NULL;
381 else if (data->CommentLength) {
382 *cmt = (char *) XpmMalloc(data->CommentLength + 1);
383 strncpy(*cmt, data->Comment, data->CommentLength);
384 (*cmt)[data->CommentLength] = '\0';
385 data->CommentLength = 0;
386 } else
387 *cmt = NULL;
388 return 0;
389 }
390
391 xpmDataType xpmDataTypes[] =
392 {
393 "", "!", "\n", '\0', '\n', "", "", "", "", /* Natural type */
394 "C", "/*", "*/", '"', '"', ",\n", "static char *", "[] = {\n", "};\n",
395 "Lisp", ";", "\n", '"', '"', "\n", "(setq ", " '(\n", "))\n",
396 #ifdef VMS
397 NULL
398 #else
399 NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL
400 #endif
401 };
402
403 /*
404 * parse xpm header
405 */
406 int
407 xpmParseHeader(data)
408 xpmData *data;
409 {
410 char buf[BUFSIZ];
411 int l, n = 0;
412
413 if (data->type) {
414 data->Bos = '\0';
415 data->Eos = '\n';
416 data->Bcmt = data->Ecmt = NULL;
417 l = xpmNextWord(data, buf, BUFSIZ);
418 if (l == 7 && !strncmp("#define", buf, 7)) {
419 /* this maybe an XPM 1 file */
420 char *ptr;
421
422 l = xpmNextWord(data, buf, BUFSIZ);
423 if (!l)
424 return (XpmFileInvalid);
425 buf[l] = '\0';
426 #ifdef macintosh
427 ptr = strrchr(buf, '_');
428 #else
429 ptr = rindex(buf, '_');
430 #endif
431 if (!ptr || strncmp("_format", ptr, l - (ptr - buf)))
432 return XpmFileInvalid;
433 /* this is definitely an XPM 1 file */
434 data->format = 1;
435 n = 1; /* handle XPM1 as mainly XPM2 C */
436 } else {
437
438 /*
439 * skip the first word, get the second one, and see if this is
440 * XPM 2 or 3
441 */
442 l = xpmNextWord(data, buf, BUFSIZ);
443 if ((l == 3 && !strncmp("XPM", buf, 3)) ||
444 (l == 4 && !strncmp("XPM2", buf, 4))) {
445 if (l == 3)
446 n = 1; /* handle XPM as XPM2 C */
447 else {
448 /* get the type key word */
449 l = xpmNextWord(data, buf, BUFSIZ);
450
451 /*
452 * get infos about this type
453 */
454 while (xpmDataTypes[n].type
455 && strncmp(xpmDataTypes[n].type, buf, l))
456 n++;
457 }
458 data->format = 0;
459 } else
460 /* nope this is not an XPM file */
461 return XpmFileInvalid;
462 }
463 if (xpmDataTypes[n].type) {
464 if (n == 0) { /* natural type */
465 data->Bcmt = xpmDataTypes[n].Bcmt;
466 data->Ecmt = xpmDataTypes[n].Ecmt;
467 xpmNextString(data); /* skip the end of the headerline */
468 data->Bos = xpmDataTypes[n].Bos;
469 data->Eos = xpmDataTypes[n].Eos;
470 } else {
471 data->Bcmt = xpmDataTypes[n].Bcmt;
472 data->Ecmt = xpmDataTypes[n].Ecmt;
473 if (!data->format) { /* XPM 2 or 3 */
474 data->Bos = xpmDataTypes[n].Bos;
475 data->Eos = '\0';
476 /* get to the beginning of the first string */
477 xpmNextString(data);
478 data->Eos = xpmDataTypes[n].Eos;
479 } else /* XPM 1 skip end of line */
480 xpmNextString(data);
481 }
482 } else
483 /* we don't know about that type of XPM file... */
484 return XpmFileInvalid;
485 }
486 return XpmSuccess;
487 }