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