CTWM
Loading...
Searching...
No Matches
/usr/src/RPM/BUILD/ctwm-4.1.0/image.c
Go to the documentation of this file.
1/*
2 * Image handling functions
3 *
4 * This provides some general and hub stuff. Details of different image
5 * type functions, and generation of builtins, go in their own files.
6 */
7
8#include "ctwm.h"
9
10#include <stdio.h>
11#include <string.h>
12#include <unistd.h>
13
14#include "list.h"
15#include "screen.h"
16
17#include "image.h"
18#include "image_bitmap.h"
20#include "image_xwd.h"
21#ifdef JPEG
22#include "image_jpeg.h"
23#endif
24#if defined (XPM)
25#include "image_xpm.h"
26#endif
27
28/* Flag (maybe should be retired */
29bool reportfilenotfound = false;
31
32
33/*
34 * Find (load/generate) an image by name
35 */
36Image *
37GetImage(const char *name, ColorPair cp)
38{
40#define GIFNLEN 256
41 char fullname[GIFNLEN];
42 Image *image;
43
44 if(name == NULL) {
45 return NULL;
46 }
47 if(dpy == NULL) {
48 // May happen in special cases like --cfgchk with no $DISPLAY
49 return NULL;
50 }
51 image = NULL;
52
53 list = &Scr->ImageCache;
54 if(0) {
55 /* dummy */ ;
56 }
57 else if((name [0] == '@') || (strncmp(name, "xpm:", 4) == 0)) {
58#ifdef XPM
59 snprintf(fullname, GIFNLEN, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
60
61 if((image = LookInNameList(*list, fullname)) == NULL) {
62 int startn = (name [0] == '@') ? 1 : 4;
63 if((image = GetXpmImage(name + startn, cp)) != NULL) {
64 AddToList(list, fullname, image);
65 }
66 }
67#else
68 fprintf(stderr, "XPM support disabled, ignoring image %s\n", name);
69 return NULL;
70#endif
71 }
72 else if(strncmp(name, "jpeg:", 5) == 0) {
73#ifdef JPEG
74 if((image = LookInNameList(*list, name)) == NULL) {
75 if((image = GetJpegImage(&name [5])) != NULL) {
76 AddToList(list, name, image);
77 }
78 }
79#else
80 fprintf(stderr, "JPEG support disabled, ignoring image %s\n", name);
81 return NULL;
82#endif
83 }
84 else if((strncmp(name, "xwd:", 4) == 0) || (name [0] == '|')) {
85 int startn = (name [0] == '|') ? 0 : 4;
86 if((image = LookInNameList(*list, name)) == NULL) {
87 if((image = GetXwdImage(&name [startn], cp)) != NULL) {
88 AddToList(list, name, image);
89 }
90 }
91 }
92 else if(strncmp(name, ":xpm:", 5) == 0) {
93 snprintf(fullname, GIFNLEN, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
94 if((image = LookInNameList(*list, fullname)) == NULL) {
95 image = get_builtin_scalable_pixmap(name, cp);
96 if(image == NULL) {
97 /* g_b_s_p() already warned */
98 return NULL;
99 }
100 AddToList(list, fullname, image);
101 }
102 }
103 else if(strncmp(name, "%xpm:", 5) == 0) {
104 snprintf(fullname, GIFNLEN, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
105 if((image = LookInNameList(*list, fullname)) == NULL) {
106 image = get_builtin_animated_pixmap(name, cp);
107 if(image == NULL) {
108 /* g_b_a_p() already warned */
109 return NULL;
110 }
111 AddToList(list, fullname, image);
112 }
113 }
114 else if(name [0] == ':') {
115 unsigned int width, height;
116 Pixmap pm = 0;
118
119 snprintf(fullname, GIFNLEN, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
120 if((image = LookInNameList(*list, fullname)) == NULL) {
121 pm = get_builtin_plain_pixmap(name, &width, &height);
122 if(pm == None) {
123 /* g_b_p_p() already warned */
124 return NULL;
125 }
126 image = AllocImage();
127 image->pixmap = XCreatePixmap(dpy, Scr->Root, width, height, Scr->d_depth);
128 if(Scr->rootGC == (GC) 0) {
129 Scr->rootGC = XCreateGC(dpy, Scr->Root, 0, &gcvalues);
130 }
131 gcvalues.background = cp.back;
132 gcvalues.foreground = cp.fore;
134 XCopyPlane(dpy, pm, image->pixmap, Scr->rootGC, 0, 0, width, height, 0, 0,
135 (unsigned long) 1);
136 image->width = width;
137 image->height = height;
138 AddToList(list, fullname, image);
139 }
140 }
141 else {
142 snprintf(fullname, GIFNLEN, "%s%dx%d", name, (int) cp.fore, (int) cp.back);
143 if((image = LookInNameList(*list, fullname)) == NULL) {
144 if((image = GetBitmapImage(name, cp)) != NULL) {
145 AddToList(list, fullname, image);
146 }
147 }
148 }
149 return image;
150#undef GIFNLEN
151}
152
153
154/*
155 * Creation/cleanup of Image structs
156 */
157Image *
159{
160 return calloc(1, sizeof(Image));
161}
162
163void
165{
166 Image *im, *im2;
167
168 im = image;
169 while(im != NULL) {
170 /* Cleanup sub-bits */
171 if(im->pixmap) {
172 XFreePixmap(dpy, im->pixmap);
173 }
174 if(im->mask) {
175 XFreePixmap(dpy, im->mask);
176 }
177
178 /* Cleanup self */
179 im2 = im->next;
180 im->next = NULL;
181 free(im);
182
183 /*
184 * Loop back around, unless we hit the original. e.g.,
185 * "foo%.xpm" animations load the images into a closed loop, so
186 * FreeImage() would do Very Bad Things running around the track
187 * until it segfaults or the like.
188 */
189 if(im2 == image) {
190 break;
191 }
192 im = im2;
193 }
194}
195
196
197
198/*
199 * Utils for image*
200 */
201
202/*
203 * Expand out the real pathname for an image. Turn ~ into $HOME if
204 * it's there, and look under the entries in PixmapDirectory if the
205 * result isn't a full path.
206 */
207char *
208ExpandPixmapPath(const char *name)
209{
210 char *ret;
211
212 ret = NULL;
213
214 /* If it starts with '~/', replace it with our homedir */
215 if(name[0] == '~' && name[1] == '/') {
216 asprintf(&ret, "%s/%s", Home, name + 2);
217 return ret;
218 }
219
220 /*
221 * If it starts with /, it's an absolute path, so just pass it
222 * through.
223 */
224 if(name[0] == '/') {
225 return strdup(name);
226 }
227
228 /*
229 * If we got here, it's some sort of relative path (or a bare
230 * filename), so search for it under PixmapDirectory if we have it.
231 */
232 if(Scr->PixmapDirectory) {
233 char *colon;
234 char *p = Scr->PixmapDirectory;
235
236 /* PixmapDirectory is a colon-separated list */
237 while((colon = strchr(p, ':'))) {
238 *colon = '\0';
239 asprintf(&ret, "%s/%s", p, name);
240 *colon = ':';
241 if(!access(ret, R_OK)) {
242 return (ret);
243 }
244 free(ret);
245 p = colon + 1;
246 }
247
248 asprintf(&ret, "%s/%s", p, name);
249 if(!access(ret, R_OK)) {
250 return (ret);
251 }
252 free(ret);
253 }
254
255
256 /*
257 * If we get here, we have no idea. For simplicity and consistency
258 * for our callers, just return what we were given.
259 */
260 return strdup(name);
261}
262
263
264/*
265 * Generalized loader for animations.
266 *
267 * These are specified with a '%' in the filename, which is replaced by a
268 * series of numbers. So e.g.
269 *
270 * "foo%.xpm" -> [ "foo1.xpm", "foo2.xpm", ...]
271 *
272 * These then turn into a looped-linked-list of Image's. We support
273 * these for all types of images, so write it up into a central handler
274 * once to centralize the logic.
275 */
276Image *
277get_image_anim_cp(const char *name,
278 ColorPair cp, Image * (*imgloader)(const char *, ColorPair))
279{
280 Image *head, *tail;
281 char *pref, *suff, *stmp;
282 int i;
283
284 /* This shouldn't get called for non-animations */
285 if((stmp = strchr(name, '%')) == NULL) {
286 fprintf(stderr, "%s() called for non-animation '%s'\n", __func__, name);
287 return NULL;
288 }
289 if(stmp[1] == '\0') {
290 fprintf(stderr, "%s(): nothing after %% in '%s'\n", __func__, name);
291 return NULL;
292 }
293 stmp = NULL;
294
295 /*
296 * For animated requests, we load a series of files, replacing the %
297 * with numbers in series.
298 */
299 tail = head = NULL;
300
301 /* Working copy of the filename split to before/after the % */
302 pref = strdup(name);
303 suff = strchr(pref, '%');
304 *suff++ = '\0';
305
306 /* "foo%.xpm" -> [ "foo1.xpm", "foo2.xpm", ...] */
307 for(i = 1 ; ; i++) {
308#define ANIM_PATHLEN 256
309 char path[ANIM_PATHLEN];
310 Image *tmp;
311
312 if(snprintf(path, ANIM_PATHLEN, "%s%d%s", pref, i,
313 suff) >= (ANIM_PATHLEN - 1)) {
314 fprintf(stderr, "%s(): generated filename for '%s' #%d longer than %d.\n",
315 __func__, name, i, ANIM_PATHLEN);
316 FreeImage(head);
317 free(pref);
318 return NULL;
319 }
320#undef ANIM_PATHLEN
321
322 /*
323 * Load this image, and set ->next so it's explicitly the
324 * [current] tail of the list.
325 */
326 tmp = imgloader(path, cp);
327 if(tmp == NULL) {
328 break;
329 }
330 tmp->next = NULL;
331
332 /*
333 * If it's the first, it's the head (image) we return, as well as
334 * our current tail marker (s). Else, append to that tail.
335 */
336 if(head == NULL) {
337 tail = head = tmp;
338 }
339 else {
340 tail->next = tmp;
341 tail = tmp;
342 }
343 }
344 free(pref);
345
346 /* Set the tail to loop back to the head */
347 if(tail != NULL) {
348 tail->next = head;
349 }
350
351 /* Warn if we got nothing */
352 if(head == NULL) {
353 fprintf(stderr, "Cannot find any image frames for '%s'\n", name);
354 }
355
356 return head;
357}
static int PlaceX
Definition add_window.c:82
char * Home
Definition ctwm_main.c:128
Display * dpy
Definition ctwm_main.c:84
#define Scr
Colormap AlternateCmap
Definition image.c:30
#define ANIM_PATHLEN
bool reportfilenotfound
Definition image.c:29
Image * GetImage(const char *name, ColorPair cp)
Definition image.c:37
Image * get_image_anim_cp(const char *name, ColorPair cp, Image *(*imgloader)(const char *, ColorPair))
Definition image.c:277
#define GIFNLEN
Image * AllocImage(void)
Definition image.c:158
char * ExpandPixmapPath(const char *name)
Definition image.c:208
void FreeImage(Image *image)
Definition image.c:164
Image * GetBitmapImage(const char *name, ColorPair cp)
Pixmap get_builtin_plain_pixmap(const char *name, unsigned int *widthp, unsigned int *heightp)
Image * get_builtin_scalable_pixmap(const char *name, ColorPair cp)
Image * get_builtin_animated_pixmap(const char *name, ColorPair cp)
Image * GetJpegImage(const char *name)
Definition image_jpeg.c:46
Image * GetXpmImage(const char *name, ColorPair cp)
Definition image_xpm.c:28
Image * GetXwdImage(const char *name, ColorPair cp)
Definition image_xwd.c:30
void * LookInNameList(name_list *list_head, const char *name)
Definition list.c:130
void AddToList(name_list **list_head, const char *name, void *ptr)
Definition list.c:63
Pixel back
Definition ctwm.h:141
Pixel fore
Definition ctwm.h:141
Definition image.h:9
int height
Definition image.h:13
Pixmap pixmap
Definition image.h:10
Image * next
Definition image.h:14
int width
Definition image.h:12