ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.36
Committed: Sat Feb 17 16:43:58 2007 UTC (17 years, 3 months ago) by ayin
Content type: text/plain
Branch: MAIN
CVS Tags: rel-8_2
Changes since 1.35: +4 -0 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 root 1.35 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 root 1.35 if (n < MAXLEN_GEOM)
84 pcg 1.7 {
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 ayin 1.36 #ifdef TRANSPARENT
181 root 1.26 if (!OPTION (Opt_transparent) || !am_transparent)
182 ayin 1.36 #endif
183 root 1.31 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
184 root 1.20
185 pcg 1.7 return;
186 pcg 1.1 }
187    
188 root 1.17 gcvalue.foreground = pix_colors[Color_bg];
189 root 1.31 gc = XCreateGC (dpy, vt, GCForeground, &gcvalue);
190 pcg 1.1
191 pcg 1.7 if (bgPixmap.pixmap != None)
192     { /* we have a specified pixmap */
193 root 1.28 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 pcg 1.7
198     /*
199     * don't zoom pixmap too much nor expand really small pixmaps
200     */
201 root 1.28 if (w > 32767 || h > 32767)
202 pcg 1.7 w = 1;
203     else if (width > (10 * xpmw)
204     || height > (10 * xpmh))
205     w = 0; /* tile */
206    
207 root 1.28 if (!w)
208 pcg 1.7 {
209     /* basic X tiling - let the X server do it */
210 root 1.31 pixmap = XCreatePixmap (dpy, vt, xpmw, xpmh, depth);
211 root 1.28
212 root 1.31 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 pcg 1.7 }
217     else
218     {
219 root 1.27 float incr, p;
220     Pixmap tmp;
221 pcg 1.7
222 root 1.31 pixmap = XCreatePixmap (dpy, vt, width, height, depth);
223 pcg 1.7 /*
224     * horizontal scaling
225     */
226 pcg 1.9 rxvt_pixmap_incr (&w, &x, &incr, &p, width, xpmw);
227 pcg 1.7
228 root 1.31 tmp = XCreatePixmap (dpy, vt, width, xpmh, depth);
229     XFillRectangle (dpy, tmp, gc, 0, 0, width, xpmh);
230 pcg 1.7
231     for ( /*nil */ ; x < w; x++, p += incr)
232     {
233     if (p >= xpmw)
234     p = 0;
235 root 1.28
236 pcg 1.7 /* copy one column from the original pixmap to the tmp pixmap */
237 root 1.31 XCopyArea (dpy, bgPixmap.pixmap, tmp, gc, (int)p, 0, 1, xpmh, (int)x, 0);
238 pcg 1.7 }
239    
240     /*
241     * vertical scaling
242     */
243 pcg 1.9 rxvt_pixmap_incr (&h, &y, &incr, &p, height, xpmh);
244 pcg 1.7
245     if (y > 0)
246 root 1.31 XFillRectangle (dpy, pixmap, gc, 0, 0, width, y);
247 root 1.20
248 pcg 1.7 if (h < height)
249 root 1.31 XFillRectangle (dpy, pixmap, gc, 0, (int)h, width, height - h + 1);
250 root 1.20
251 pcg 1.7 for ( /*nil */ ; y < h; y++, p += incr)
252     {
253     if (p >= xpmh)
254     p = 0;
255 root 1.20
256 pcg 1.7 /* copy one row from the tmp pixmap to the main pixmap */
257 root 1.31 XCopyArea (dpy, tmp, pixmap, gc, 0, (int)p, width, 1, 0, (int)y);
258 pcg 1.7 }
259 root 1.20
260 root 1.31 XFreePixmap (dpy, tmp);
261 pcg 1.7 }
262 pcg 1.1 }
263 root 1.14
264 root 1.31 XSetWindowBackgroundPixmap (dpy, vt, pixmap);
265 root 1.28
266 root 1.31 XFreeGC (dpy, gc);
267 ayin 1.36 #ifdef TRANSPARENT
268 pcg 1.7 am_transparent = 0;
269 ayin 1.36 #endif
270 pcg 1.1 }
271    
272     /*
273     * Calculate tiling sizes and increments
274     * At start, p == 0, incr == xpmwidthheight
275     */
276 pcg 1.6 static void
277 pcg 1.9 rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight)
278 pcg 1.1 {
279 pcg 1.7 unsigned int cwh, cxy;
280     float cincr, cp;
281 pcg 1.1
282 pcg 1.7 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 pcg 1.1 }
301 pcg 1.7 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 pcg 1.1 }
347    
348     Pixmap
349 pcg 1.5 rxvt_term::set_bgPixmap (const char *file)
350 pcg 1.1 {
351 root 1.21 char *f;
352 pcg 1.1
353 pcg 1.9 assert (file != NULL);
354 pcg 1.1
355 pcg 1.7 if (bgPixmap.pixmap != None)
356     {
357 root 1.31 XFreePixmap (dpy, bgPixmap.pixmap);
358 pcg 1.7 bgPixmap.pixmap = None;
359 pcg 1.1 }
360 root 1.19
361 root 1.31 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
362 pcg 1.1
363 pcg 1.7 if (*file != '\0')
364     {
365     /* XWindowAttributes attr; */
366    
367     /*
368     * we already have the required attributes
369     */
370 root 1.31 /* XGetWindowAttributes (dpy, vt, &attr); */
371 pcg 1.7
372     xpmAttr.closeness = 30000;
373 root 1.29 xpmAttr.colormap = cmap;
374     xpmAttr.visual = visual;
375     xpmAttr.depth = depth;
376     xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual
377     | XpmDepth | XpmSize | XpmReturnPixels);
378 pcg 1.7
379     /* search environment variables here too */
380 pcg 1.9 f = (char *)rxvt_File_find (file, ".xpm", rs[Rs_path]);
381 pcg 1.7 if (f == NULL
382 root 1.31 || XpmReadFileToPixmap (dpy, display->root, f,
383 root 1.29 &bgPixmap.pixmap, NULL,
384     &xpmAttr))
385 pcg 1.7 {
386 pcg 1.10 char *p;
387 pcg 1.7
388     /* semi-colon delimited */
389 root 1.17 if ((p = strchr (file, ';')) == NULL)
390     p = strchr (file, '\0');
391 pcg 1.7
392 root 1.19 rxvt_warn ("couldn't load XPM file \"%.*s\", ignoring.\n", (p - file), file);
393 pcg 1.7 }
394 pcg 1.10
395 pcg 1.9 free (f);
396 pcg 1.1 }
397 pcg 1.10
398 pcg 1.7 resize_pixmap ();
399     return bgPixmap.pixmap;
400 pcg 1.1 }
401    
402     #endif /* XPM_BACKGROUND */