ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.35
Committed: Fri Aug 18 23:03:31 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-8_0, rel-8_1
Changes since 1.34: +2 -2 lines
Log Message:
*** empty log message ***

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 if (!OPTION (Opt_transparent) || !am_transparent)
181 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
182
183 return;
184 }
185
186 gcvalue.foreground = pix_colors[Color_bg];
187 gc = XCreateGC (dpy, vt, GCForeground, &gcvalue);
188
189 if (bgPixmap.pixmap != None)
190 { /* we have a specified pixmap */
191 unsigned int w = bgPixmap.w, h = bgPixmap.h,
192 x = bgPixmap.x, y = bgPixmap.y;
193 unsigned int xpmh = xpmAttr.height,
194 xpmw = xpmAttr.width;
195
196 /*
197 * don't zoom pixmap too much nor expand really small pixmaps
198 */
199 if (w > 32767 || h > 32767)
200 w = 1;
201 else if (width > (10 * xpmw)
202 || height > (10 * xpmh))
203 w = 0; /* tile */
204
205 if (!w)
206 {
207 /* basic X tiling - let the X server do it */
208 pixmap = XCreatePixmap (dpy, vt, xpmw, xpmh, depth);
209
210 XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, x, y, xpmw - x, xpmh - y, 0, 0);
211 XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, x, 0, xpmw - x, y, 0, xpmh - y);
212 XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, 0, y, x, xpmh - y, xpmw - x, 0);
213 XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, 0, 0, x, y, xpmw - x, xpmh - y);
214 }
215 else
216 {
217 float incr, p;
218 Pixmap tmp;
219
220 pixmap = XCreatePixmap (dpy, vt, width, height, depth);
221 /*
222 * horizontal scaling
223 */
224 rxvt_pixmap_incr (&w, &x, &incr, &p, width, xpmw);
225
226 tmp = XCreatePixmap (dpy, vt, width, xpmh, depth);
227 XFillRectangle (dpy, tmp, gc, 0, 0, width, xpmh);
228
229 for ( /*nil */ ; x < w; x++, p += incr)
230 {
231 if (p >= xpmw)
232 p = 0;
233
234 /* copy one column from the original pixmap to the tmp pixmap */
235 XCopyArea (dpy, bgPixmap.pixmap, tmp, gc, (int)p, 0, 1, xpmh, (int)x, 0);
236 }
237
238 /*
239 * vertical scaling
240 */
241 rxvt_pixmap_incr (&h, &y, &incr, &p, height, xpmh);
242
243 if (y > 0)
244 XFillRectangle (dpy, pixmap, gc, 0, 0, width, y);
245
246 if (h < height)
247 XFillRectangle (dpy, pixmap, gc, 0, (int)h, width, height - h + 1);
248
249 for ( /*nil */ ; y < h; y++, p += incr)
250 {
251 if (p >= xpmh)
252 p = 0;
253
254 /* copy one row from the tmp pixmap to the main pixmap */
255 XCopyArea (dpy, tmp, pixmap, gc, 0, (int)p, width, 1, 0, (int)y);
256 }
257
258 XFreePixmap (dpy, tmp);
259 }
260 }
261
262 XSetWindowBackgroundPixmap (dpy, vt, pixmap);
263
264 XFreeGC (dpy, gc);
265 am_transparent = 0;
266 }
267
268 /*
269 * Calculate tiling sizes and increments
270 * At start, p == 0, incr == xpmwidthheight
271 */
272 static void
273 rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight)
274 {
275 unsigned int cwh, cxy;
276 float cincr, cp;
277
278 cp = 0;
279 cincr = (float)xpmwidthheight;
280 cxy = *xy;
281 cwh = *wh;
282 if (cwh == 1)
283 { /* display one image, no horizontal/vertical scaling */
284 cincr = (float)widthheight;
285 if (xpmwidthheight <= widthheight)
286 {
287 cwh = xpmwidthheight;
288 cxy = (cxy * (widthheight - cwh)) / 100; /* beware! order */
289 cwh += cxy;
290 }
291 else
292 {
293 cxy = 0;
294 cwh = widthheight;
295 }
296 }
297 else if (cwh < 10)
298 { /* fit WH images across/down screen */
299 cincr *= cwh;
300 cxy = 0;
301 cwh = widthheight;
302 }
303 else
304 {
305 cincr *= 100.0 / cwh;
306 if (cwh < 100)
307 { /* contract */
308 float pos;
309
310 cwh = (cwh * widthheight) / 100;
311 pos = (float)cxy / 100 * widthheight - (cwh / 2);
312
313 cxy = (widthheight - cwh);
314 if (pos <= 0)
315 cxy = 0;
316 else if (pos < cxy)
317 cxy = (int) pos;
318 cwh += cxy;
319 }
320 else
321 { /* expand */
322 if (cxy > 0)
323 { /* position */
324 float pos;
325
326 pos = (float)cxy / 100 * xpmwidthheight - (cincr / 2);
327 cp = xpmwidthheight - cincr;
328 if (pos <= 0)
329 cp = 0;
330 else if (pos < cp)
331 cp = pos;
332 }
333 cxy = 0;
334 cwh = widthheight;
335 }
336 }
337 cincr /= widthheight;
338 *wh = cwh;
339 *xy = cxy;
340 *incr = cincr;
341 *p = cp;
342 }
343
344 Pixmap
345 rxvt_term::set_bgPixmap (const char *file)
346 {
347 char *f;
348
349 assert (file != NULL);
350
351 if (bgPixmap.pixmap != None)
352 {
353 XFreePixmap (dpy, bgPixmap.pixmap);
354 bgPixmap.pixmap = None;
355 }
356
357 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
358
359 if (*file != '\0')
360 {
361 /* XWindowAttributes attr; */
362
363 /*
364 * we already have the required attributes
365 */
366 /* XGetWindowAttributes (dpy, vt, &attr); */
367
368 xpmAttr.closeness = 30000;
369 xpmAttr.colormap = cmap;
370 xpmAttr.visual = visual;
371 xpmAttr.depth = depth;
372 xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual
373 | XpmDepth | XpmSize | XpmReturnPixels);
374
375 /* search environment variables here too */
376 f = (char *)rxvt_File_find (file, ".xpm", rs[Rs_path]);
377 if (f == NULL
378 || XpmReadFileToPixmap (dpy, display->root, f,
379 &bgPixmap.pixmap, NULL,
380 &xpmAttr))
381 {
382 char *p;
383
384 /* semi-colon delimited */
385 if ((p = strchr (file, ';')) == NULL)
386 p = strchr (file, '\0');
387
388 rxvt_warn ("couldn't load XPM file \"%.*s\", ignoring.\n", (p - file), file);
389 }
390
391 free (f);
392 }
393
394 resize_pixmap ();
395 return bgPixmap.pixmap;
396 }
397
398 #endif /* XPM_BACKGROUND */