ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.28
Committed: Wed Jan 18 17:49:47 2006 UTC (18 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-7_2, rel-7_1
Changes since 1.27: +56 -40 lines
Log Message:
*** empty log message ***

File Contents

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