ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.37
Committed: Tue May 1 21:30:01 2007 UTC (17 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.36: +1 -1 lines
Log Message:
remove OPTION macro

File Contents

# Content
1 /*----------------------------------------------------------------------*
2 * File: xpm.C
3 *----------------------------------------------------------------------*
4 *
5 * All portions of code are copyright by their respective author/s.
6 * Copyright (c) 1997 Carsten Haitzler <raster@zip.com.au>
7 * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
8 * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
9 * Copyright (c) 2005-2006 Marc Lehmann <pcg@goof.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *---------------------------------------------------------------------*/
25
26 #include "../config.h" /* NECESSARY */
27 #include "rxvt.h" /* NECESSARY */
28
29 #ifdef XPM_BACKGROUND
30
31 static void rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight);
32
33 /*
34 * These GEOM strings indicate absolute size/position:
35 * @ `WxH+X+Y'
36 * @ `WxH+X' -> Y = X
37 * @ `WxH' -> Y = X = 50
38 * @ `W+X+Y' -> H = W
39 * @ `W+X' -> H = W, Y = X
40 * @ `W' -> H = W, X = Y = 50
41 * @ `0xH' -> H *= H/100, X = Y = 50 (W unchanged)
42 * @ `Wx0' -> W *= W/100, X = Y = 50 (H unchanged)
43 * @ `=+X+Y' -> (H, W unchanged)
44 * @ `=+X' -> Y = X (H, W unchanged)
45 *
46 * These GEOM strings adjust position relative to current position:
47 * @ `+X+Y'
48 * @ `+X' -> Y = X
49 *
50 * And this GEOM string is for querying current scale/position:
51 * @ `?'
52 */
53 int
54 rxvt_term::scale_pixmap (const char *geom)
55 {
56 int flags, changed = 0;
57 int x = 0, y = 0;
58 unsigned int w = 0, h = 0;
59 unsigned int n;
60 char *p;
61 bgPixmap_t *bgpixmap = &bgPixmap;
62
63 #define MAXLEN_GEOM sizeof("[10000x10000+10000+10000]")
64
65 if (geom == NULL)
66 return 0;
67
68 char str[MAXLEN_GEOM];
69
70 if (!strcmp (geom, "?"))
71 {
72 sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */
73 min (bgpixmap->w, 32767), min (bgpixmap->h, 32767),
74 min (bgpixmap->x, 32767), min (bgpixmap->y, 32767));
75 process_xterm_seq (XTerm_title, str, CHAR_ST);
76 return 0;
77 }
78
79 if ((p = strchr (geom, ';')) == NULL)
80 p = strchr (geom, '\0');
81
82 n = (p - geom);
83 if (n < MAXLEN_GEOM)
84 {
85 strncpy (str, geom, n);
86 str[n] = '\0';
87
88 flags = XParseGeometry (str, &x, &y, &w, &h);
89
90 if (!flags)
91 {
92 flags |= WidthValue;
93 w = 0;
94 } /* default is tile */
95
96 if (flags & WidthValue)
97 {
98 if (!(flags & XValue))
99 x = 50;
100
101 if (!(flags & HeightValue))
102 h = w;
103
104 if (w && !h)
105 {
106 w = (bgpixmap->w * w) / 100;
107 h = bgpixmap->h;
108 }
109 else if (h && !w)
110 {
111 w = bgpixmap->w;
112 h = (bgpixmap->h * h) / 100;
113 }
114
115 min_it (w, 32767);
116 min_it (h, 32767);
117
118 if (bgpixmap->w != (short)w)
119 {
120 bgpixmap->w = (short)w;
121 changed++;
122 }
123
124 if (bgpixmap->h != (short)h)
125 {
126 bgpixmap->h = (short)h;
127 changed++;
128 }
129 }
130
131 if (!(flags & YValue))
132 {
133 if (flags & XNegative)
134 flags |= YNegative;
135
136 y = x;
137 }
138
139 if (!(flags & WidthValue) && geom[0] != '=')
140 {
141 x += bgpixmap->x;
142 y += bgpixmap->y;
143 }
144
145 if (xpmAttr.width && xpmAttr.height)
146 {
147 x = MOD(x, xpmAttr.width);
148 y = MOD(y, xpmAttr.height);
149 }
150
151 if (bgpixmap->x != x)
152 {
153 bgpixmap->x = x;
154 changed++;
155 }
156
157 if (bgpixmap->y != y)
158 {
159 bgpixmap->y = y;
160 changed++;
161 }
162 }
163
164 return changed;
165 }
166
167 void
168 rxvt_term::resize_pixmap ()
169 {
170 XGCValues gcvalue;
171 GC gc;
172
173 if (pixmap != None)
174 XFreePixmap (dpy, pixmap);
175
176 if (bgPixmap.pixmap == None)
177 { /* So be it: I'm not using pixmaps */
178 pixmap = None;
179
180 #ifdef TRANSPARENT
181 if (!option (Opt_transparent) || !am_transparent)
182 #endif
183 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
184
185 return;
186 }
187
188 gcvalue.foreground = pix_colors[Color_bg];
189 gc = XCreateGC (dpy, vt, GCForeground, &gcvalue);
190
191 if (bgPixmap.pixmap != None)
192 { /* we have a specified pixmap */
193 unsigned int w = bgPixmap.w, h = bgPixmap.h,
194 x = bgPixmap.x, y = bgPixmap.y;
195 unsigned int xpmh = xpmAttr.height,
196 xpmw = xpmAttr.width;
197
198 /*
199 * don't zoom pixmap too much nor expand really small pixmaps
200 */
201 if (w > 32767 || h > 32767)
202 w = 1;
203 else if (width > (10 * xpmw)
204 || height > (10 * xpmh))
205 w = 0; /* tile */
206
207 if (!w)
208 {
209 /* basic X tiling - let the X server do it */
210 pixmap = XCreatePixmap (dpy, vt, xpmw, xpmh, depth);
211
212 XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, x, y, xpmw - x, xpmh - y, 0, 0);
213 XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, x, 0, xpmw - x, y, 0, xpmh - y);
214 XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, 0, y, x, xpmh - y, xpmw - x, 0);
215 XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, 0, 0, x, y, xpmw - x, xpmh - y);
216 }
217 else
218 {
219 float incr, p;
220 Pixmap tmp;
221
222 pixmap = XCreatePixmap (dpy, vt, width, height, depth);
223 /*
224 * horizontal scaling
225 */
226 rxvt_pixmap_incr (&w, &x, &incr, &p, width, xpmw);
227
228 tmp = XCreatePixmap (dpy, vt, width, xpmh, depth);
229 XFillRectangle (dpy, tmp, gc, 0, 0, width, xpmh);
230
231 for ( /*nil */ ; x < w; x++, p += incr)
232 {
233 if (p >= xpmw)
234 p = 0;
235
236 /* copy one column from the original pixmap to the tmp pixmap */
237 XCopyArea (dpy, bgPixmap.pixmap, tmp, gc, (int)p, 0, 1, xpmh, (int)x, 0);
238 }
239
240 /*
241 * vertical scaling
242 */
243 rxvt_pixmap_incr (&h, &y, &incr, &p, height, xpmh);
244
245 if (y > 0)
246 XFillRectangle (dpy, pixmap, gc, 0, 0, width, y);
247
248 if (h < height)
249 XFillRectangle (dpy, pixmap, gc, 0, (int)h, width, height - h + 1);
250
251 for ( /*nil */ ; y < h; y++, p += incr)
252 {
253 if (p >= xpmh)
254 p = 0;
255
256 /* copy one row from the tmp pixmap to the main pixmap */
257 XCopyArea (dpy, tmp, pixmap, gc, 0, (int)p, width, 1, 0, (int)y);
258 }
259
260 XFreePixmap (dpy, tmp);
261 }
262 }
263
264 XSetWindowBackgroundPixmap (dpy, vt, pixmap);
265
266 XFreeGC (dpy, gc);
267 #ifdef TRANSPARENT
268 am_transparent = 0;
269 #endif
270 }
271
272 /*
273 * Calculate tiling sizes and increments
274 * At start, p == 0, incr == xpmwidthheight
275 */
276 static void
277 rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight)
278 {
279 unsigned int cwh, cxy;
280 float cincr, cp;
281
282 cp = 0;
283 cincr = (float)xpmwidthheight;
284 cxy = *xy;
285 cwh = *wh;
286 if (cwh == 1)
287 { /* display one image, no horizontal/vertical scaling */
288 cincr = (float)widthheight;
289 if (xpmwidthheight <= widthheight)
290 {
291 cwh = xpmwidthheight;
292 cxy = (cxy * (widthheight - cwh)) / 100; /* beware! order */
293 cwh += cxy;
294 }
295 else
296 {
297 cxy = 0;
298 cwh = widthheight;
299 }
300 }
301 else if (cwh < 10)
302 { /* fit WH images across/down screen */
303 cincr *= cwh;
304 cxy = 0;
305 cwh = widthheight;
306 }
307 else
308 {
309 cincr *= 100.0 / cwh;
310 if (cwh < 100)
311 { /* contract */
312 float pos;
313
314 cwh = (cwh * widthheight) / 100;
315 pos = (float)cxy / 100 * widthheight - (cwh / 2);
316
317 cxy = (widthheight - cwh);
318 if (pos <= 0)
319 cxy = 0;
320 else if (pos < cxy)
321 cxy = (int) pos;
322 cwh += cxy;
323 }
324 else
325 { /* expand */
326 if (cxy > 0)
327 { /* position */
328 float pos;
329
330 pos = (float)cxy / 100 * xpmwidthheight - (cincr / 2);
331 cp = xpmwidthheight - cincr;
332 if (pos <= 0)
333 cp = 0;
334 else if (pos < cp)
335 cp = pos;
336 }
337 cxy = 0;
338 cwh = widthheight;
339 }
340 }
341 cincr /= widthheight;
342 *wh = cwh;
343 *xy = cxy;
344 *incr = cincr;
345 *p = cp;
346 }
347
348 Pixmap
349 rxvt_term::set_bgPixmap (const char *file)
350 {
351 char *f;
352
353 assert (file != NULL);
354
355 if (bgPixmap.pixmap != None)
356 {
357 XFreePixmap (dpy, bgPixmap.pixmap);
358 bgPixmap.pixmap = None;
359 }
360
361 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
362
363 if (*file != '\0')
364 {
365 /* XWindowAttributes attr; */
366
367 /*
368 * we already have the required attributes
369 */
370 /* XGetWindowAttributes (dpy, vt, &attr); */
371
372 xpmAttr.closeness = 30000;
373 xpmAttr.colormap = cmap;
374 xpmAttr.visual = visual;
375 xpmAttr.depth = depth;
376 xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual
377 | XpmDepth | XpmSize | XpmReturnPixels);
378
379 /* search environment variables here too */
380 f = (char *)rxvt_File_find (file, ".xpm", rs[Rs_path]);
381 if (f == NULL
382 || XpmReadFileToPixmap (dpy, display->root, f,
383 &bgPixmap.pixmap, NULL,
384 &xpmAttr))
385 {
386 char *p;
387
388 /* semi-colon delimited */
389 if ((p = strchr (file, ';')) == NULL)
390 p = strchr (file, '\0');
391
392 rxvt_warn ("couldn't load XPM file \"%.*s\", ignoring.\n", (p - file), file);
393 }
394
395 free (f);
396 }
397
398 resize_pixmap ();
399 return bgPixmap.pixmap;
400 }
401
402 #endif /* XPM_BACKGROUND */