1/*
2 * XPM image handling functions
3 */
4
5#include "ctwm.h"
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include <X11/xpm.h>
12
13#include "screen.h"
14
15#include "image.h"
16#include "image_xpm.h"
17
18static Image *LoadXpmImage(const char  *name, ColorPair cp);
19static void xpmErrorMessage(int status, const char *name, const char *fullname);
20
21static int reportxpmerror = 1;
22
23
24/*
25 * External entry point
26 */
27Image *
28GetXpmImage(const char *name, ColorPair cp)
29{
30	/* For non-animated requests, just load the file */
31	if(! strchr(name, '%')) {
32		return LoadXpmImage(name, cp);
33	}
34
35	/* Else it's animated, so load/return the series */
36	return get_image_anim_cp(name, cp, LoadXpmImage);
37}
38
39
40
41/*
42 * Internal backend
43 */
44static Image *
45LoadXpmImage(const char *name, ColorPair cp)
46{
47	char        *fullname;
48	Image       *image;
49	int         status;
50	Colormap    stdcmap = Scr->RootColormaps.cwins[0]->colormap->c;
51	XpmAttributes attributes;
52	static XpmColorSymbol overrides[] = {
53		{"Foreground", NULL, 0},
54		{"Background", NULL, 0},
55		{"HiShadow", NULL, 0},
56		{"LoShadow", NULL, 0}
57	};
58
59	fullname = ExpandPixmapPath(name);
60	if(! fullname) {
61		return NULL;
62	}
63
64	image = AllocImage();
65	if(image == NULL) {
66		free(fullname);
67		return NULL;
68	}
69
70	attributes.valuemask  = 0;
71	attributes.valuemask |= XpmSize;
72	attributes.valuemask |= XpmReturnPixels;
73	attributes.valuemask |= XpmColormap;
74	attributes.valuemask |= XpmDepth;
75	attributes.valuemask |= XpmVisual;
76	attributes.valuemask |= XpmCloseness;
77	attributes.valuemask |= XpmColorSymbols;
78
79	attributes.numsymbols = 4;
80	attributes.colorsymbols = overrides;
81	overrides[0].pixel = cp.fore;
82	overrides[1].pixel = cp.back;
83	overrides[2].pixel = cp.shadd;
84	overrides[3].pixel = cp.shadc;
85
86
87	attributes.colormap  = AlternateCmap ? AlternateCmap : stdcmap;
88	attributes.depth     = Scr->d_depth;
89	attributes.visual    = Scr->d_visual;
90	attributes.closeness = 65535; /* Never fail */
91	status = XpmReadFileToPixmap(dpy, Scr->Root, fullname,
92	                             &(image->pixmap), &(image->mask), &attributes);
93	if(status != XpmSuccess) {
94		xpmErrorMessage(status, name, fullname);
95		free(fullname);
96		free(image);
97		return NULL;
98	}
99	free(fullname);
100	image->width  = attributes.width;
101	image->height = attributes.height;
102	return image;
103}
104
105static void
106xpmErrorMessage(int status, const char *name, const char *fullname)
107{
108	switch(status) {
109		case XpmSuccess:
110			/* No error */
111			return;
112
113		case XpmColorError:
114			if(reportxpmerror)
115				fprintf(stderr,
116				        "Could not parse or alloc requested color : %s\n",
117				        fullname);
118			return;
119
120		case XpmOpenFailed:
121			if(reportxpmerror && reportfilenotfound) {
122				fprintf(stderr, "unable to locate XPM file : %s\n", fullname);
123			}
124			return;
125
126		case XpmFileInvalid:
127			fprintf(stderr, "invalid XPM file : %s\n", fullname);
128			return;
129
130		case XpmNoMemory:
131			if(reportxpmerror) {
132				fprintf(stderr, "Not enough memory for XPM file : %s\n", fullname);
133			}
134			return;
135
136		case XpmColorFailed:
137			if(reportxpmerror) {
138				fprintf(stderr, "Color not found in : %s\n", fullname);
139			}
140			return;
141
142		default :
143			fprintf(stderr, "Unknown error in : %s\n", fullname);
144			return;
145	}
146}
147