ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.34
Committed: Mon Feb 20 22:42:01 2006 UTC (18 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-7_7, rel-7_8, rel-7_9
Changes since 1.33: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.34 /*----------------------------------------------------------------------*
2 pcg 1.12 * File: xpm.C
3 pcg 1.1 *----------------------------------------------------------------------*
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 root 1.33 * Copyright (c) 2005-2006 Marc Lehmann <pcg@goof.com>
10 pcg 1.1 *
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 root 1.22 static void rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight);
32    
33 pcg 1.1 /*
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 pcg 1.5 rxvt_term::scale_pixmap (const char *geom)
55 pcg 1.1 {
56 root 1.28 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 pcg 1.1
63 root 1.28 #define MAXLEN_GEOM sizeof("[10000x10000+10000+10000]")
64 pcg 1.1
65 pcg 1.7 if (geom == NULL)
66     return 0;
67 root 1.28
68     char str[MAXLEN_GEOM];
69    
70 root 1.17 if (!strcmp (geom, "?"))
71 pcg 1.7 {
72 pcg 1.9 sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */
73 root 1.28 min (bgpixmap->w, 32767), min (bgpixmap->h, 32767),
74     min (bgpixmap->x, 32767), min (bgpixmap->y, 32767));
75 pcg 1.11 process_xterm_seq (XTerm_title, str, CHAR_ST);
76 pcg 1.7 return 0;
77 pcg 1.1 }
78    
79 root 1.17 if ((p = strchr (geom, ';')) == NULL)
80     p = strchr (geom, '\0');
81 root 1.28
82 pcg 1.7 n = (p - geom);
83     if (n <= MAXLEN_GEOM)
84     {
85 root 1.17 strncpy (str, geom, n);
86 pcg 1.7 str[n] = '\0';
87    
88 pcg 1.9 flags = XParseGeometry (str, &x, &y, &w, &h);
89 root 1.28
90 pcg 1.7 if (!flags)
91     {
92     flags |= WidthValue;
93     w = 0;
94     } /* default is tile */
95 root 1.28
96 pcg 1.7 if (flags & WidthValue)
97     {
98 root 1.28 if (!(flags & XValue))
99 pcg 1.7 x = 50;
100 root 1.28
101     if (!(flags & HeightValue))
102 pcg 1.7 h = w;
103 root 1.28
104 pcg 1.7 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 root 1.28
115     min_it (w, 32767);
116     min_it (h, 32767);
117    
118 pcg 1.7 if (bgpixmap->w != (short)w)
119     {
120     bgpixmap->w = (short)w;
121     changed++;
122     }
123 root 1.28
124 pcg 1.7 if (bgpixmap->h != (short)h)
125     {
126     bgpixmap->h = (short)h;
127     changed++;
128     }
129     }
130 root 1.28
131     if (!(flags & YValue))
132 pcg 1.7 {
133     if (flags & XNegative)
134     flags |= YNegative;
135 root 1.28
136 pcg 1.7 y = x;
137     }
138    
139 root 1.28 if (!(flags & WidthValue) && geom[0] != '=')
140 pcg 1.7 {
141     x += bgpixmap->x;
142     y += bgpixmap->y;
143     }
144 root 1.28
145     if (xpmAttr.width && xpmAttr.height)
146 pcg 1.7 {
147 root 1.28 x = MOD(x, xpmAttr.width);
148     y = MOD(y, xpmAttr.height);
149     }
150    
151 pcg 1.7 if (bgpixmap->x != x)
152     {
153     bgpixmap->x = x;
154     changed++;
155     }
156 root 1.28
157 pcg 1.7 if (bgpixmap->y != y)
158     {
159     bgpixmap->y = y;
160     changed++;
161     }
162 pcg 1.1 }
163 root 1.28
164 pcg 1.7 return changed;
165 pcg 1.1 }
166    
167     void
168 pcg 1.5 rxvt_term::resize_pixmap ()
169 pcg 1.1 {
170 root 1.27 XGCValues gcvalue;
171     GC gc;
172 pcg 1.7
173 root 1.24 if (pixmap != None)
174 root 1.31 XFreePixmap (dpy, pixmap);
175 pcg 1.7
176     if (bgPixmap.pixmap == None)
177     { /* So be it: I'm not using pixmaps */
178 root 1.24 pixmap = None;
179 root 1.20
180 root 1.26 if (!OPTION (Opt_transparent) || !am_transparent)
181 root 1.31 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
182 root 1.20
183 pcg 1.7 return;
184 pcg 1.1 }
185    
186 root 1.17 gcvalue.foreground = pix_colors[Color_bg];
187 root 1.31 gc = XCreateGC (dpy, vt, GCForeground, &gcvalue);
188 pcg 1.1
189 pcg 1.7 if (bgPixmap.pixmap != None)
190     { /* we have a specified pixmap */
191 root 1.28 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 pcg 1.7
196     /*
197     * don't zoom pixmap too much nor expand really small pixmaps
198     */
199 root 1.28 if (w > 32767 || h > 32767)
200 pcg 1.7 w = 1;
201     else if (width > (10 * xpmw)
202     || height > (10 * xpmh))
203     w = 0; /* tile */
204    
205 root 1.28 if (!w)
206 pcg 1.7 {
207     /* basic X tiling - let the X server do it */
208 root 1.31 pixmap = XCreatePixmap (dpy, vt, xpmw, xpmh, depth);
209 root 1.28
210 root 1.31 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 pcg 1.7 }
215     else
216     {
217 root 1.27 float incr, p;
218     Pixmap tmp;
219 pcg 1.7
220 root 1.31 pixmap = XCreatePixmap (dpy, vt, width, height, depth);
221 pcg 1.7 /*
222     * horizontal scaling
223     */
224 pcg 1.9 rxvt_pixmap_incr (&w, &x, &incr, &p, width, xpmw);
225 pcg 1.7
226 root 1.31 tmp = XCreatePixmap (dpy, vt, width, xpmh, depth);
227     XFillRectangle (dpy, tmp, gc, 0, 0, width, xpmh);
228 pcg 1.7
229     for ( /*nil */ ; x < w; x++, p += incr)
230     {
231     if (p >= xpmw)
232     p = 0;
233 root 1.28
234 pcg 1.7 /* copy one column from the original pixmap to the tmp pixmap */
235 root 1.31 XCopyArea (dpy, bgPixmap.pixmap, tmp, gc, (int)p, 0, 1, xpmh, (int)x, 0);
236 pcg 1.7 }
237    
238     /*
239     * vertical scaling
240     */
241 pcg 1.9 rxvt_pixmap_incr (&h, &y, &incr, &p, height, xpmh);
242 pcg 1.7
243     if (y > 0)
244 root 1.31 XFillRectangle (dpy, pixmap, gc, 0, 0, width, y);
245 root 1.20
246 pcg 1.7 if (h < height)
247 root 1.31 XFillRectangle (dpy, pixmap, gc, 0, (int)h, width, height - h + 1);
248 root 1.20
249 pcg 1.7 for ( /*nil */ ; y < h; y++, p += incr)
250     {
251     if (p >= xpmh)
252     p = 0;
253 root 1.20
254 pcg 1.7 /* copy one row from the tmp pixmap to the main pixmap */
255 root 1.31 XCopyArea (dpy, tmp, pixmap, gc, 0, (int)p, width, 1, 0, (int)y);
256 pcg 1.7 }
257 root 1.20
258 root 1.31 XFreePixmap (dpy, tmp);
259 pcg 1.7 }
260 pcg 1.1 }
261 root 1.14
262 root 1.31 XSetWindowBackgroundPixmap (dpy, vt, pixmap);
263 root 1.28
264 root 1.31 XFreeGC (dpy, gc);
265 pcg 1.7 am_transparent = 0;
266 pcg 1.1 }
267    
268     /*
269     * Calculate tiling sizes and increments
270     * At start, p == 0, incr == xpmwidthheight
271     */
272 pcg 1.6 static void
273 pcg 1.9 rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight)
274 pcg 1.1 {
275 pcg 1.7 unsigned int cwh, cxy;
276     float cincr, cp;
277 pcg 1.1
278 pcg 1.7 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 pcg 1.1 }
297 pcg 1.7 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 pcg 1.1 }
343    
344     Pixmap
345 pcg 1.5 rxvt_term::set_bgPixmap (const char *file)
346 pcg 1.1 {
347 root 1.21 char *f;
348 pcg 1.1
349 pcg 1.9 assert (file != NULL);
350 pcg 1.1
351 pcg 1.7 if (bgPixmap.pixmap != None)
352     {
353 root 1.31 XFreePixmap (dpy, bgPixmap.pixmap);
354 pcg 1.7 bgPixmap.pixmap = None;
355 pcg 1.1 }
356 root 1.19
357 root 1.31 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
358 pcg 1.1
359 pcg 1.7 if (*file != '\0')
360     {
361     /* XWindowAttributes attr; */
362    
363     /*
364     * we already have the required attributes
365     */
366 root 1.31 /* XGetWindowAttributes (dpy, vt, &attr); */
367 pcg 1.7
368     xpmAttr.closeness = 30000;
369 root 1.29 xpmAttr.colormap = cmap;
370     xpmAttr.visual = visual;
371     xpmAttr.depth = depth;
372     xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual
373     | XpmDepth | XpmSize | XpmReturnPixels);
374 pcg 1.7
375     /* search environment variables here too */
376 pcg 1.9 f = (char *)rxvt_File_find (file, ".xpm", rs[Rs_path]);
377 pcg 1.7 if (f == NULL
378 root 1.31 || XpmReadFileToPixmap (dpy, display->root, f,
379 root 1.29 &bgPixmap.pixmap, NULL,
380     &xpmAttr))
381 pcg 1.7 {
382 pcg 1.10 char *p;
383 pcg 1.7
384     /* semi-colon delimited */
385 root 1.17 if ((p = strchr (file, ';')) == NULL)
386     p = strchr (file, '\0');
387 pcg 1.7
388 root 1.19 rxvt_warn ("couldn't load XPM file \"%.*s\", ignoring.\n", (p - file), file);
389 pcg 1.7 }
390 pcg 1.10
391 pcg 1.9 free (f);
392 pcg 1.1 }
393 pcg 1.10
394 pcg 1.7 resize_pixmap ();
395     return bgPixmap.pixmap;
396 pcg 1.1 }
397    
398     #endif /* XPM_BACKGROUND */