]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1989-94 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 | * misc.c: * | |
28 | * * | |
29 | * XPM library * | |
30 | * Miscellaneous utilities * | |
31 | * * | |
32 | * Developed by Arnaud Le Hors * | |
33 | \*****************************************************************************/ | |
34 | ||
35 | /* | |
36 | * The code related to FOR_MSW has been added by | |
37 | * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 | |
38 | */ | |
39 | ||
40 | #include "xpm34p.h" | |
41 | #ifdef VMS | |
42 | #include "sys$library:stat.h" | |
43 | #include "sys$library:fcntl.h" | |
44 | #else | |
45 | #include <sys/types.h> | |
46 | #include <sys/stat.h> | |
47 | #include <fcntl.h> | |
48 | #include <stdio.h> | |
49 | #ifdef FOR_MSW | |
50 | #include <io.h> | |
51 | #else | |
52 | #include <unistd.h> | |
53 | #endif | |
54 | #endif | |
55 | ||
56 | /* 3.2 backward compatibility code */ | |
57 | LFUNC(CreateOldColorTable, int, (XpmColor *ct, int ncolors, | |
58 | XpmColor ***oldct)); | |
59 | ||
60 | LFUNC(FreeOldColorTable, void, (XpmColor **colorTable, int ncolors)); | |
61 | ||
62 | /* | |
63 | * Create a colortable compatible with the old style colortable | |
64 | */ | |
65 | static int | |
66 | CreateOldColorTable(XpmColor *ct, int ncolors, XpmColor ***oldct) | |
67 | { | |
68 | XpmColor **colorTable, **color; | |
69 | int a; | |
70 | ||
71 | colorTable = (XpmColor **) XpmMalloc(ncolors * sizeof(XpmColor *)); | |
72 | if (!colorTable) { | |
73 | *oldct = NULL; | |
74 | return (XpmNoMemory); | |
75 | } | |
76 | for (a = 0, color = colorTable; a < ncolors; a++, color++, ct++) | |
77 | *color = ct; | |
78 | *oldct = colorTable; | |
79 | return (XpmSuccess); | |
80 | } | |
81 | ||
82 | static void | |
83 | FreeOldColorTable(XpmColor **colorTable, int ncolors) | |
84 | { | |
85 | int a, b; | |
86 | XpmColor **color; | |
87 | char **sptr; | |
88 | ||
89 | if (colorTable) { | |
90 | for (a = 0, color = colorTable; a < ncolors; a++, color++) { | |
91 | for (b = 0, sptr = (char **) *color; b <= NKEYS; b++, sptr++) | |
92 | if (*sptr) | |
93 | XpmFree(*sptr); | |
94 | } | |
95 | XpmFree(*colorTable); | |
96 | XpmFree(colorTable); | |
97 | } | |
98 | } | |
99 | ||
100 | /* end 3.2 bc */ | |
101 | ||
102 | ||
103 | /* | |
104 | * Free the computed color table | |
105 | */ | |
106 | void | |
107 | xpmFreeColorTable(XpmColor *colorTable, int ncolors) | |
108 | { | |
109 | int a, b; | |
110 | XpmColor *color; | |
111 | char **sptr; | |
112 | ||
113 | if (colorTable) { | |
114 | for (a = 0, color = colorTable; a < ncolors; a++, color++) { | |
115 | for (b = 0, sptr = (char **) color; b <= NKEYS; b++, sptr++) | |
116 | if (*sptr) | |
117 | XpmFree(*sptr); | |
118 | } | |
119 | XpmFree(colorTable); | |
120 | } | |
121 | } | |
122 | ||
123 | /* | |
124 | * Free array of extensions | |
125 | */ | |
126 | void | |
127 | XpmFreeExtensions(XpmExtension *extensions, int nextensions) | |
128 | { | |
129 | unsigned int i, j, nlines; | |
130 | XpmExtension *ext; | |
131 | char **sptr; | |
132 | ||
133 | if (extensions) { | |
134 | for (i = 0, ext = extensions; i < nextensions; i++, ext++) { | |
135 | if (ext->name) | |
136 | XpmFree(ext->name); | |
137 | nlines = ext->nlines; | |
138 | for (j = 0, sptr = ext->lines; j < nlines; j++, sptr++) | |
139 | if (*sptr) | |
140 | XpmFree(*sptr); | |
141 | if (ext->lines) | |
142 | XpmFree(ext->lines); | |
143 | } | |
144 | XpmFree(extensions); | |
145 | } | |
146 | } | |
147 | ||
148 | ||
149 | /* | |
150 | * Return the XpmAttributes structure size | |
151 | */ | |
152 | ||
153 | int | |
154 | XpmAttributesSize() | |
155 | { | |
156 | return sizeof(XpmAttributes); | |
157 | } | |
158 | ||
159 | /* | |
160 | * Init returned data to free safely later on | |
161 | */ | |
162 | void | |
163 | xpmInitAttributes(XpmAttributes *attributes) | |
164 | { | |
165 | if (attributes) { | |
166 | attributes->pixels = NULL; | |
167 | attributes->npixels = 0; | |
168 | attributes->colorTable = NULL; | |
169 | attributes->ncolors = 0; | |
170 | /* 3.2 backward compatibility code */ | |
171 | attributes->hints_cmt = NULL; | |
172 | attributes->colors_cmt = NULL; | |
173 | attributes->pixels_cmt = NULL; | |
174 | /* end 3.2 bc */ | |
175 | attributes->extensions = NULL; | |
176 | attributes->nextensions = 0; | |
177 | } | |
178 | } | |
179 | ||
180 | /* | |
181 | * Fill in the XpmAttributes with the XpmImage and the XpmInfo | |
182 | */ | |
183 | void | |
184 | xpmSetAttributes(XpmAttributes *attributes, XpmImage *image, XpmInfo *info) | |
185 | { | |
186 | if (attributes->valuemask & XpmReturnColorTable) { | |
187 | attributes->colorTable = image->colorTable; | |
188 | attributes->ncolors = image->ncolors; | |
189 | ||
190 | /* avoid deletion of copied data */ | |
191 | image->ncolors = 0; | |
192 | image->colorTable = NULL; | |
193 | } | |
194 | /* 3.2 backward compatibility code */ | |
195 | else if (attributes->valuemask & XpmReturnInfos) { | |
196 | int ErrorStatus; | |
197 | ||
198 | ErrorStatus = CreateOldColorTable(image->colorTable, image->ncolors, | |
199 | (XpmColor ***) | |
200 | &attributes->colorTable); | |
201 | ||
202 | /* if error just say we can't return requested data */ | |
203 | if (ErrorStatus != XpmSuccess) { | |
204 | attributes->valuemask &= ~XpmReturnInfos; | |
205 | if (!(attributes->valuemask & XpmReturnPixels)) { | |
206 | XpmFree(attributes->pixels); | |
207 | attributes->pixels = NULL; | |
208 | attributes->npixels = 0; | |
209 | } | |
210 | attributes->ncolors = 0; | |
211 | } else { | |
212 | attributes->ncolors = image->ncolors; | |
213 | attributes->hints_cmt = info->hints_cmt; | |
214 | attributes->colors_cmt = info->colors_cmt; | |
215 | attributes->pixels_cmt = info->pixels_cmt; | |
216 | ||
217 | /* avoid deletion of copied data */ | |
218 | image->ncolors = 0; | |
219 | image->colorTable = NULL; | |
220 | info->hints_cmt = NULL; | |
221 | info->colors_cmt = NULL; | |
222 | info->pixels_cmt = NULL; | |
223 | } | |
224 | } | |
225 | /* end 3.2 bc */ | |
226 | if (attributes->valuemask & XpmReturnExtensions) { | |
227 | attributes->extensions = info->extensions; | |
228 | attributes->nextensions = info->nextensions; | |
229 | ||
230 | /* avoid deletion of copied data */ | |
231 | info->extensions = NULL; | |
232 | info->nextensions = 0; | |
233 | } | |
234 | if (info->valuemask & XpmHotspot) { | |
235 | attributes->valuemask |= XpmHotspot; | |
236 | attributes->x_hotspot = info->x_hotspot; | |
237 | attributes->y_hotspot = info->y_hotspot; | |
238 | } | |
239 | attributes->valuemask |= XpmCharsPerPixel; | |
240 | attributes->cpp = image->cpp; | |
241 | attributes->valuemask |= XpmSize; | |
242 | attributes->width = image->width; | |
243 | attributes->height = image->height; | |
244 | } | |
245 | ||
246 | /* | |
247 | * Free the XpmAttributes structure members | |
248 | * but the structure itself | |
249 | */ | |
250 | void | |
251 | XpmFreeAttributes(XpmAttributes *attributes) | |
252 | { | |
253 | if (attributes->valuemask & XpmReturnPixels && attributes->npixels) { | |
254 | XpmFree(attributes->pixels); | |
255 | attributes->pixels = NULL; | |
256 | attributes->npixels = 0; | |
257 | } | |
258 | if (attributes->valuemask & XpmReturnColorTable) { | |
259 | xpmFreeColorTable(attributes->colorTable, attributes->ncolors); | |
260 | attributes->colorTable = NULL; | |
261 | attributes->ncolors = 0; | |
262 | } | |
263 | /* 3.2 backward compatibility code */ | |
264 | else if (attributes->valuemask & XpmInfos) { | |
265 | if (attributes->colorTable) { | |
266 | FreeOldColorTable((XpmColor **) attributes->colorTable, | |
267 | attributes->ncolors); | |
268 | attributes->colorTable = NULL; | |
269 | attributes->ncolors = 0; | |
270 | } | |
271 | if (attributes->hints_cmt) { | |
272 | XpmFree(attributes->hints_cmt); | |
273 | attributes->hints_cmt = NULL; | |
274 | } | |
275 | if (attributes->colors_cmt) { | |
276 | XpmFree(attributes->colors_cmt); | |
277 | attributes->colors_cmt = NULL; | |
278 | } | |
279 | if (attributes->pixels_cmt) { | |
280 | XpmFree(attributes->pixels_cmt); | |
281 | attributes->pixels_cmt = NULL; | |
282 | } | |
283 | if (attributes->pixels) { | |
284 | XpmFree(attributes->pixels); | |
285 | attributes->pixels = NULL; | |
286 | attributes->npixels = 0; | |
287 | } | |
288 | } | |
289 | /* end 3.2 bc */ | |
290 | if (attributes->valuemask & XpmReturnExtensions | |
291 | && attributes->nextensions) { | |
292 | XpmFreeExtensions(attributes->extensions, attributes->nextensions); | |
293 | attributes->extensions = NULL; | |
294 | attributes->nextensions = 0; | |
295 | } | |
296 | attributes->valuemask = 0; | |
297 | } | |
298 | ||
299 | /* | |
300 | * Init returned data to free safely later on | |
301 | */ | |
302 | void | |
303 | xpmInitXpmImage(XpmImage *image) | |
304 | { | |
305 | image->ncolors = 0; | |
306 | image->colorTable = NULL; | |
307 | image->data = NULL; | |
308 | } | |
309 | ||
310 | /* | |
311 | * Free the XpmImage data which have been allocated | |
312 | */ | |
313 | void | |
314 | XpmFreeXpmImage(XpmImage *image) | |
315 | { | |
316 | if (image->colorTable) | |
317 | xpmFreeColorTable(image->colorTable, image->ncolors); | |
318 | XpmFree(image->data); | |
319 | image->data = NULL; | |
320 | } | |
321 | ||
322 | /* | |
323 | * Init returned data to free safely later on | |
324 | */ | |
325 | void | |
326 | xpmInitXpmInfo(XpmInfo *info) | |
327 | { | |
328 | if (info) { | |
329 | info->hints_cmt = NULL; | |
330 | info->colors_cmt = NULL; | |
331 | info->pixels_cmt = NULL; | |
332 | info->extensions = NULL; | |
333 | info->nextensions = 0; | |
334 | } | |
335 | } | |
336 | ||
337 | /* | |
338 | * Free the XpmInfo data which have been allocated | |
339 | */ | |
340 | void | |
341 | XpmFreeXpmInfo(XpmInfo *info) | |
342 | { | |
343 | if (info) { | |
344 | if (info->valuemask & XpmComments) { | |
345 | if (info->hints_cmt) { | |
346 | XpmFree(info->hints_cmt); | |
347 | info->hints_cmt = NULL; | |
348 | } | |
349 | if (info->colors_cmt) { | |
350 | XpmFree(info->colors_cmt); | |
351 | info->colors_cmt = NULL; | |
352 | } | |
353 | if (info->pixels_cmt) { | |
354 | XpmFree(info->pixels_cmt); | |
355 | info->pixels_cmt = NULL; | |
356 | } | |
357 | } | |
358 | if (info->valuemask & XpmReturnExtensions && info->nextensions) { | |
359 | XpmFreeExtensions(info->extensions, info->nextensions); | |
360 | info->extensions = NULL; | |
361 | info->nextensions = 0; | |
362 | } | |
363 | info->valuemask = 0; | |
364 | } | |
365 | } | |
366 | ||
367 | /* | |
368 | * Set the XpmInfo valuemask to retrieve required info | |
369 | */ | |
370 | void | |
371 | xpmSetInfoMask(XpmInfo *info, XpmAttributes *attributes) | |
372 | { | |
373 | info->valuemask = 0; | |
374 | if (attributes->valuemask & XpmReturnInfos) | |
375 | info->valuemask |= XpmReturnComments; | |
376 | if (attributes->valuemask & XpmReturnExtensions) | |
377 | info->valuemask |= XpmReturnExtensions; | |
378 | } | |
379 | ||
380 | /* | |
381 | * Fill in the XpmInfo with the XpmAttributes | |
382 | */ | |
383 | void | |
384 | xpmSetInfo(XpmInfo *info, XpmAttributes *attributes) | |
385 | { | |
386 | info->valuemask = 0; | |
387 | if (attributes->valuemask & XpmInfos) { | |
388 | info->valuemask |= XpmComments | XpmColorTable; | |
389 | info->hints_cmt = attributes->hints_cmt; | |
390 | info->colors_cmt = attributes->colors_cmt; | |
391 | info->pixels_cmt = attributes->pixels_cmt; | |
392 | } | |
393 | if (attributes->valuemask & XpmExtensions) { | |
394 | info->valuemask |= XpmExtensions; | |
395 | info->extensions = attributes->extensions; | |
396 | info->nextensions = attributes->nextensions; | |
397 | } | |
398 | if (attributes->valuemask & XpmHotspot) { | |
399 | info->valuemask |= XpmHotspot; | |
400 | info->x_hotspot = attributes->x_hotspot; | |
401 | info->y_hotspot = attributes->y_hotspot; | |
402 | } | |
403 | } | |
404 | ||
405 | ||
406 | #ifdef NEED_STRDUP | |
407 | /* | |
408 | * in case strdup is not provided by the system here is one | |
409 | * which does the trick | |
410 | */ | |
411 | char * | |
412 | strdup(char *s1) | |
413 | { | |
414 | char *s2; | |
415 | int l = strlen(s1) + 1; | |
416 | ||
417 | if (s2 = (char *) XpmMalloc(l)) | |
418 | strncpy(s2, s1, l); | |
419 | return s2; | |
420 | } | |
421 | ||
422 | #endif | |
423 | ||
424 | unsigned int | |
425 | atoui(register char *p, unsigned int l, unsigned int *ui_return) | |
426 | { | |
427 | register unsigned int n, i; | |
428 | ||
429 | n = 0; | |
430 | for (i = 0; i < l; i++) | |
431 | if (*p >= '0' && *p <= '9') | |
432 | n = n * 10 + *p++ - '0'; | |
433 | else | |
434 | break; | |
435 | ||
436 | if (i != 0 && i == l) { | |
437 | *ui_return = n; | |
438 | return 1; | |
439 | } else | |
440 | return 0; | |
441 | } | |
442 | ||
443 | ||
444 | /* | |
445 | * File / Buffer utilities | |
446 | */ | |
447 | int | |
448 | XpmReadFileToBuffer(char *filename, char **buffer_return) | |
449 | { | |
450 | int fd, fcheck, len; | |
451 | char *ptr; | |
452 | struct stat stats; | |
453 | FILE *fp; | |
454 | ||
455 | *buffer_return = NULL; | |
456 | ||
457 | fd = open(filename, O_RDONLY); | |
458 | if (fd < 0) | |
459 | return XpmOpenFailed; | |
460 | ||
461 | if (fstat(fd, &stats)) { | |
462 | close(fd); | |
463 | return XpmOpenFailed; | |
464 | } | |
465 | fp = fdopen(fd, "r"); | |
466 | if (!fp) { | |
467 | close(fd); | |
468 | return XpmOpenFailed; | |
469 | } | |
470 | len = (int) stats.st_size; | |
471 | ptr = (char *) XpmMalloc(len + 1); | |
472 | if (!ptr) { | |
473 | fclose(fp); | |
474 | return XpmNoMemory; | |
475 | } | |
476 | fcheck = fread(ptr, len, 1, fp); | |
477 | fclose(fp); | |
478 | if (fcheck != 1) { | |
479 | XpmFree(ptr); | |
480 | return XpmOpenFailed; | |
481 | } | |
482 | ptr[len] = '\0'; | |
483 | *buffer_return = ptr; | |
484 | return XpmSuccess; | |
485 | } | |
486 | ||
487 | int | |
488 | XpmWriteFileFromBuffer(char *filename, char *buffer) | |
489 | { | |
490 | int fcheck, len; | |
491 | FILE *fp = fopen(filename, "w"); | |
492 | ||
493 | if (!fp) | |
494 | return XpmOpenFailed; | |
495 | ||
496 | len = strlen(buffer); | |
497 | fcheck = fwrite(buffer, len, 1, fp); | |
498 | fclose(fp); | |
499 | if (fcheck != 1) | |
500 | return XpmOpenFailed; | |
501 | ||
502 | return XpmSuccess; | |
503 | } | |
504 | ||
505 | ||
506 | /* | |
507 | * Small utility function | |
508 | */ | |
509 | char * | |
510 | XpmGetErrorString(int errcode) | |
511 | { | |
512 | switch (errcode) { | |
513 | case XpmColorError: | |
514 | return ("XpmColorError"); | |
515 | case XpmSuccess: | |
516 | return ("XpmSuccess"); | |
517 | case XpmOpenFailed: | |
518 | return ("XpmOpenFailed"); | |
519 | case XpmFileInvalid: | |
520 | return ("XpmFileInvalid"); | |
521 | case XpmNoMemory: | |
522 | return ("XpmNoMemory"); | |
523 | case XpmColorFailed: | |
524 | return ("XpmColorFailed"); | |
525 | default: | |
526 | return ("Invalid XpmError"); | |
527 | } | |
528 | } | |
529 | ||
530 | /* | |
531 | * The following function provides a way to figure out if the linked library is | |
532 | * newer or older than the one with which a program has been first compiled. | |
533 | */ | |
534 | int | |
535 | XpmLibraryVersion() | |
536 | { | |
537 | return XpmIncludeVersion; | |
538 | } | |
539 | ||
540 | ||
541 | #ifndef FOR_MSW | |
542 | void | |
543 | xpmCreatePixmapFromImage(Display *display, Drawable d, XImage *ximage, Pixmap *pixmap_return) | |
544 | { | |
545 | GC gc; | |
546 | ||
547 | *pixmap_return = XCreatePixmap(display, d, ximage->width, | |
548 | ximage->height, ximage->depth); | |
549 | gc = XCreateGC(display, *pixmap_return, 0, NULL); | |
550 | ||
551 | XPutImage(display, *pixmap_return, gc, ximage, 0, 0, 0, 0, | |
552 | ximage->width, ximage->height); | |
553 | ||
554 | XFreeGC(display, gc); | |
555 | } | |
556 | ||
557 | void | |
558 | xpmCreateImageFromPixmap(Display *display, Pixmap pixmap, XImage **ximage_return, unsigned int *width, unsigned int *height) | |
559 | { | |
560 | unsigned int dum; | |
561 | int dummy; | |
562 | Window win; | |
563 | ||
564 | if (*width == 0 && *height == 0) | |
565 | XGetGeometry(display, pixmap, &win, &dummy, &dummy, | |
566 | width, height, &dum, &dum); | |
567 | ||
568 | *ximage_return = XGetImage(display, pixmap, 0, 0, *width, *height, | |
569 | AllPlanes, ZPixmap); | |
570 | } | |
571 | ||
572 | #endif /* FOR_MSW */ |