ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.4
Committed: Thu Dec 18 02:07:12 2003 UTC (20 years, 5 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1-3, rel-1-2
Changes since 1.3: +3 -3 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*--------------------------------*-C-*---------------------------------*
2     * File: xpm.c
3     *----------------------------------------------------------------------*
4 pcg 1.4 * $Id: xpm.C,v 1.3 2003/11/25 11:52:42 pcg Exp $
5 pcg 1.1 *
6     * All portions of code are copyright by their respective author/s.
7     * Copyright (c) 1997 Carsten Haitzler <raster@zip.com.au>
8     * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
9     * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.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     #include "xpm.intpro" /* PROTOS for internal routines */
29    
30     #ifdef XPM_BACKGROUND
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     /* EXTPROTO */
53     int
54     rxvt_scale_pixmap(pR_ 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, *str;
61 pcg 1.3 bgPixmap_t *bgpixmap = &(R->bgPixmap);
62 pcg 1.1
63     #define MAXLEN_GEOM sizeof("[1000x1000+1000+1000]")
64    
65     if (geom == NULL)
66     return 0;
67 pcg 1.4 str = (char *)rxvt_malloc (MAXLEN_GEOM + 1);
68 pcg 1.1 if (!STRCMP(geom, "?")) {
69     sprintf(str, "[%dx%d+%d+%d]", /* can't presume snprintf() ! */
70     min(bgpixmap->w, 9999), min(bgpixmap->h, 9999),
71     min(bgpixmap->x, 9999), min(bgpixmap->y, 9999));
72     rxvt_xterm_seq(aR_ XTerm_title, str, CHAR_ST);
73     free(str);
74     return 0;
75     }
76    
77     if ((p = STRCHR(geom, ';')) == NULL)
78     p = STRCHR(geom, '\0');
79     n = (p - geom);
80     if (n <= MAXLEN_GEOM) {
81     STRNCPY(str, geom, n);
82     str[n] = '\0';
83    
84     flags = XParseGeometry(str, &x, &y, &w, &h);
85     if (!flags) {
86     flags |= WidthValue;
87     w = 0;
88     } /* default is tile */
89     if (flags & WidthValue) {
90     if (!(flags & XValue))
91     x = 50;
92     if (!(flags & HeightValue))
93     h = w;
94     if (w && !h) {
95     w = (bgpixmap->w * w) / 100;
96     h = bgpixmap->h;
97     } else if (h && !w) {
98     w = bgpixmap->w;
99     h = (bgpixmap->h * h) / 100;
100     }
101     if (w > 1000)
102     w = 1000;
103     if (h > 1000)
104     h = 1000;
105     if (bgpixmap->w != (short)w) {
106     bgpixmap->w = (short)w;
107     changed++;
108     }
109     if (bgpixmap->h != (short)h) {
110     bgpixmap->h = (short)h;
111     changed++;
112     }
113     }
114     if (!(flags & YValue)) {
115     if (flags & XNegative)
116     flags |= YNegative;
117     y = x;
118     }
119    
120     if (!(flags & WidthValue) && geom[0] != '=') {
121     x += bgpixmap->x;
122     y += bgpixmap->y;
123     } else {
124     if (flags & XNegative)
125     x += 100;
126     if (flags & YNegative)
127     y += 100;
128     }
129     MIN_IT(x, 100);
130     MIN_IT(y, 100);
131     MAX_IT(x, 0);
132     MAX_IT(y, 0);
133     if (bgpixmap->x != x) {
134     bgpixmap->x = x;
135     changed++;
136     }
137     if (bgpixmap->y != y) {
138     bgpixmap->y = y;
139     changed++;
140     }
141     }
142     free(str);
143     return changed;
144     }
145    
146     /* EXTPROTO */
147     void
148     rxvt_resize_pixmap(pR)
149     {
150     XGCValues gcvalue;
151     GC gc;
152     unsigned int width = TermWin_TotalWidth();
153     unsigned int height = TermWin_TotalHeight();
154    
155     if (R->TermWin.pixmap != None)
156     XFreePixmap(R->Xdisplay, R->TermWin.pixmap);
157    
158 pcg 1.3 if (R->bgPixmap.pixmap == None) { /* So be it: I'm not using pixmaps */
159 pcg 1.1 R->TermWin.pixmap = None;
160 pcg 1.3 if (!(R->Options & Opt_transparent) || R->am_transparent == 0)
161 pcg 1.1 XSetWindowBackground(R->Xdisplay, R->TermWin.vt,
162     R->PixColors[Color_bg]);
163     return;
164     }
165    
166     gcvalue.foreground = R->PixColors[Color_bg];
167     gc = XCreateGC(R->Xdisplay, R->TermWin.vt, GCForeground, &gcvalue);
168    
169 pcg 1.3 if (R->bgPixmap.pixmap != None) { /* we have a specified pixmap */
170     unsigned int w = R->bgPixmap.w, h = R->bgPixmap.h,
171     x = R->bgPixmap.x, y = R->bgPixmap.y;
172     unsigned int xpmh = R->xpmAttr.height,
173     xpmw = R->xpmAttr.width;
174 pcg 1.1
175     /*
176     * don't zoom pixmap too much nor expand really small pixmaps
177     */
178     if (w > 1000 || h > 1000)
179     w = 1;
180     else if (width > (10 * xpmw)
181     || height > (10 * xpmh))
182     w = 0; /* tile */
183    
184     if (w == 0) {
185     /* basic X tiling - let the X server do it */
186     R->TermWin.pixmap = XCreatePixmap(R->Xdisplay, R->TermWin.vt,
187     xpmw, xpmh,
188     (unsigned int)XDEPTH);
189 pcg 1.3 XCopyArea(R->Xdisplay, R->bgPixmap.pixmap, R->TermWin.pixmap, gc,
190 pcg 1.1 0, 0, xpmw, xpmh, 0, 0);
191     } else {
192     float incr, p;
193     Pixmap tmp;
194    
195     R->TermWin.pixmap = XCreatePixmap(R->Xdisplay, R->TermWin.vt,
196     width, height,
197     (unsigned int)XDEPTH);
198     /*
199     * horizontal scaling
200     */
201     rxvt_pixmap_incr(&w, &x, &incr, &p, width, xpmw);
202    
203     tmp = XCreatePixmap(R->Xdisplay, R->TermWin.vt,
204     width, xpmh, (unsigned int)XDEPTH);
205     XFillRectangle(R->Xdisplay, tmp, gc, 0, 0, width,
206     xpmh);
207    
208     for ( /*nil */ ; x < w; x++, p += incr) {
209     if (p >= xpmw)
210     p = 0;
211     /* copy one column from the original pixmap to the tmp pixmap */
212 pcg 1.3 XCopyArea(R->Xdisplay, R->bgPixmap.pixmap, tmp, gc,
213 pcg 1.1 (int)p, 0, 1, xpmh, (int)x, 0);
214     }
215    
216     /*
217     * vertical scaling
218     */
219     rxvt_pixmap_incr(&h, &y, &incr, &p, height, xpmh);
220    
221     if (y > 0)
222     XFillRectangle(R->Xdisplay, R->TermWin.pixmap, gc, 0, 0, width,
223     y);
224     if (h < height)
225     XFillRectangle(R->Xdisplay, R->TermWin.pixmap, gc, 0, (int)h,
226     width, height - h + 1);
227     for ( /*nil */ ; y < h; y++, p += incr) {
228     if (p >= xpmh)
229     p = 0;
230     /* copy one row from the tmp pixmap to the main pixmap */
231     XCopyArea(R->Xdisplay, tmp, R->TermWin.pixmap, gc,
232     0, (int)p, width, 1, 0, (int)y);
233     }
234     XFreePixmap(R->Xdisplay, tmp);
235     }
236     }
237     XSetWindowBackgroundPixmap(R->Xdisplay, R->TermWin.vt, R->TermWin.pixmap);
238     XFreeGC(R->Xdisplay, gc);
239 pcg 1.3 R->am_transparent = 0;
240 pcg 1.1
241     XClearWindow(R->Xdisplay, R->TermWin.vt);
242    
243     XSync(R->Xdisplay, False);
244     }
245    
246     /*
247     * Calculate tiling sizes and increments
248     * At start, p == 0, incr == xpmwidthheight
249     */
250     /* INTPROTO */
251     void
252     rxvt_pixmap_incr(unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight)
253     {
254     unsigned int cwh, cxy;
255     float cincr, cp;
256    
257     cp = 0;
258     cincr = (float)xpmwidthheight;
259     cxy = *xy;
260     cwh = *wh;
261     if (cwh == 1) { /* display one image, no horizontal/vertical scaling */
262     cincr = (float)widthheight;
263     if (xpmwidthheight <= widthheight) {
264     cwh = xpmwidthheight;
265     cxy = (cxy * (widthheight - cwh)) / 100; /* beware! order */
266     cwh += cxy;
267     } else {
268     cxy = 0;
269     cwh = widthheight;
270     }
271     } else if (cwh < 10) { /* fit WH images across/down screen */
272     cincr *= cwh;
273     cxy = 0;
274     cwh = widthheight;
275     } else {
276     cincr *= 100.0 / cwh;
277     if (cwh < 100) { /* contract */
278     float pos;
279    
280     cwh = (cwh * widthheight) / 100;
281     pos = (float)cxy / 100 * widthheight - (cwh / 2);
282    
283     cxy = (widthheight - cwh);
284     if (pos <= 0)
285     cxy = 0;
286     else if (pos < cxy)
287 pcg 1.4 cxy = (int) pos;
288 pcg 1.1 cwh += cxy;
289     } else { /* expand */
290     if (cxy > 0) { /* position */
291     float pos;
292    
293     pos = (float)cxy / 100 * xpmwidthheight - (cincr / 2);
294     cp = xpmwidthheight - cincr;
295     if (pos <= 0)
296     cp = 0;
297     else if (pos < cp)
298     cp = pos;
299     }
300     cxy = 0;
301     cwh = widthheight;
302     }
303     }
304     cincr /= widthheight;
305     *wh = cwh;
306     *xy = cxy;
307     *incr = cincr;
308     *p = cp;
309     }
310    
311     /* EXTPROTO */
312     Pixmap
313     rxvt_set_bgPixmap(pR_ const char *file)
314     {
315     char *f;
316    
317     assert(file != NULL);
318    
319 pcg 1.3 if (R->bgPixmap.pixmap != None) {
320     XFreePixmap(R->Xdisplay, R->bgPixmap.pixmap);
321     R->bgPixmap.pixmap = None;
322 pcg 1.1 }
323     XSetWindowBackground(R->Xdisplay, R->TermWin.vt, R->PixColors[Color_bg]);
324    
325     if (*file != '\0') {
326     /* XWindowAttributes attr; */
327    
328     /*
329     * we already have the required attributes
330     */
331     /* XGetWindowAttributes(R->Xdisplay, R->TermWin.vt, &attr); */
332    
333 pcg 1.3 R->xpmAttr.closeness = 30000;
334     R->xpmAttr.colormap = XCMAP;
335     R->xpmAttr.visual = XVISUAL;
336     R->xpmAttr.depth = XDEPTH;
337     R->xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual |
338 pcg 1.1 XpmDepth | XpmSize | XpmReturnPixels);
339    
340     /* search environment variables here too */
341 pcg 1.3 f = (char *)rxvt_File_find(file, ".xpm", R->rs[Rs_path]);
342 pcg 1.1 if (f == NULL
343     || XpmReadFileToPixmap(R->Xdisplay, Xroot, f,
344 pcg 1.3 &R->bgPixmap.pixmap, NULL,
345     &R->xpmAttr)) {
346 pcg 1.1 char *p;
347    
348     /* semi-colon delimited */
349     if ((p = STRCHR(file, ';')) == NULL)
350     p = STRCHR(file, '\0');
351    
352     rxvt_print_error("couldn't load XPM file \"%.*s\"", (p - file),
353     file);
354     }
355     free(f);
356     }
357     rxvt_resize_pixmap(aR);
358 pcg 1.3 return R->bgPixmap.pixmap;
359 pcg 1.1 }
360    
361     #endif /* XPM_BACKGROUND */