1 /*
2  * xvroot.c - '-root' related code for XV
3  *
4  *  Contains:
5  *            MakeRootPic()
6  *            ClearRoot()
7  *            SaveRootInfo()
8  *            KillOldRootInfo()
9  */
10 
11 #include "copyright.h"
12 
13 #include "xv.h"
14 
15 #include "bits/root_weave"
16 
17 
18 /* local function pre-definitions */
19 static void killRootPix PARM((void));
20 
21 
22 /***********************************/
MakeRootPic()23 void MakeRootPic()
24 {
25   /* called after 'epic' has been generated (if we're using root).
26      creates the XImage and the pixmap, sets the root to the new
27      pixmap, and refreshes the display */
28 
29   Pixmap       tmpPix;
30   int          i, j, k, rmode;
31   unsigned int rpixw, rpixh;
32 
33   killRootPix();
34 
35   rmode = rootMode;
36   /* if eWIDE,eHIGH == dispWIDE,dispHIGH just use 'normal' mode to save mem */
37   if (rmode>=RM_CENTER && eWIDE==dispWIDE && eHIGH==dispHIGH) rmode=RM_NORMAL;
38 
39   /* determine how big tmpPix should be based on rootMode */
40   switch (rmode) {
41   case RM_NORMAL:
42   case RM_CENTILE:
43   case RM_TILE:    rpixw = eWIDE;    rpixh = eHIGH;    break;
44   case RM_MIRROR:
45   case RM_IMIRROR: rpixw = 2*eWIDE;  rpixh = 2*eHIGH;  break;
46   case RM_CSOLID:
47   case RM_UPLEFT:
48   case RM_CWARP:
49   case RM_CBRICK:  rpixw = dispWIDE; rpixh = dispHIGH; break;
50 
51   case RM_ECENTER:
52   case RM_ECMIRR:  rpixw = dispWIDE; rpixh = dispHIGH;  break;
53 
54   default:         rpixw = eWIDE;    rpixh = eHIGH;    break;
55   }
56   if (nolimits) { RANGE(rpixw, 1, maxWIDE);  RANGE(rpixh, 1, maxHIGH); }
57            else { RANGE(rpixw, 1, dispWIDE);  RANGE(rpixh, 1, dispHIGH); }
58 
59   /* create tmpPix */
60   xerrcode = 0;
61   tmpPix = XCreatePixmap(theDisp, mainW, rpixw, rpixh, dispDEEP);
62   XSync(theDisp, False);
63   if (xerrcode || !tmpPix) {
64     ErrPopUp("Insufficient memory in X server to store root pixmap.",
65 	     "\nDarn!");
66     return;
67   }
68 
69 
70   if (rmode == RM_NORMAL || rmode == RM_TILE) {
71     XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0,
72 	      (u_int) eWIDE, (u_int) eHIGH);
73   }
74 
75   else if (rmode == RM_MIRROR || rmode == RM_IMIRROR) {
76     /* quadrant 2 */
77     XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0,
78 	      (u_int) eWIDE, (u_int) eHIGH);
79     if (epic == NULL) FatalError("epic == NULL in RM_MIRROR code...\n");
80 
81     /* quadrant 1 */
82     FlipPic(epic, eWIDE, eHIGH, 0);   /* flip horizontally */
83     CreateXImage();
84     XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, eWIDE,0,
85 	      (u_int) eWIDE, (u_int) eHIGH);
86 
87     /* quadrant 4 */
88     FlipPic(epic, eWIDE, eHIGH, 1);   /* flip vertically */
89     CreateXImage();
90     XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, eWIDE,eHIGH,
91 	      (u_int) eWIDE, (u_int) eHIGH);
92 
93     /* quadrant 3 */
94     FlipPic(epic, eWIDE, eHIGH, 0);   /* flip horizontally */
95     CreateXImage();
96     XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,eHIGH,
97 	      (u_int) eWIDE, (u_int) eHIGH);
98 
99     FlipPic(epic, eWIDE, eHIGH, 1);   /* flip vertically  (back to orig) */
100     CreateXImage();                   /* put back to original state */
101   }
102 
103 
104   else if (rmode == RM_CENTER || rmode == RM_CENTILE || rmode == RM_CSOLID ||
105 	   rmode == RM_CWARP || rmode == RM_CBRICK || rmode == RM_UPLEFT) {
106     /* do some stuff to set up the border around the picture */
107 
108     if (rmode != RM_CENTILE) {
109       XSetForeground(theDisp, theGC, rootbg);
110       XFillRectangle(theDisp, tmpPix, theGC, 0,0, dispWIDE, dispHIGH);
111     }
112 
113     if (rmode == RM_CENTILE) {    /* hagan-style tiling */
114       int x, y, w, h, ax, ay, w1, h1, offx, offy;
115 
116       w = eWIDE;  h = eHIGH;
117 
118       /* compute anchor pt (top-left coords of top-left-most pic) */
119       ax = (dispWIDE-w)/2;  ay = (dispHIGH-h)/2;
120       while (ax>0) ax = ax - w;
121       while (ay>0) ay = ay - h;
122 
123       for (i=ay; i < (int) eHIGH; i+=h) {
124 	for (j=ax; j < (int) eWIDE; j+=w) {
125 	  /* if image goes off tmpPix, only draw subimage */
126 
127 	  x = j;  y = i;  w1 = w;  h1 = h;  offx = offy = 0;
128 	  if (x<0)           { offx = -x;  w1 -= offx;  x = 0; }
129 	  if (x+w1>eWIDE) { w1 = (eWIDE-x); }
130 
131 	  if (y<0)           { offy = -y;  h1 -= offy;  y = 0; }
132 	  if (y+h1>eHIGH)    { h1 = (eHIGH-y); }
133 
134 	  XPutImage(theDisp, tmpPix, theGC, theImage, offx, offy,
135 		    x, y, (u_int) w1, (u_int) h1);
136 	}
137       }
138     }
139 
140     else if (rmode == RM_CSOLID) { }
141 
142     else if (rmode == RM_UPLEFT) {
143 
144       XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0,
145 		(u_int) eWIDE, (u_int) eHIGH);
146     }
147 
148     else if (rmode == RM_CWARP) {          /* warp effect */
149       XSetForeground(theDisp, theGC, rootfg);
150       for (i=0; i<=dispWIDE; i+=8)
151 	XDrawLine(theDisp,tmpPix,theGC, i,0, (int) dispWIDE-i,(int) dispHIGH);
152       for (i=0; i<=dispHIGH; i+=8)
153 	XDrawLine(theDisp,tmpPix,theGC, 0,i, (int) dispWIDE, (int) dispHIGH-i);
154     }
155 
156     else if (rmode == RM_CBRICK) {         /* brick effect */
157       XSetForeground(theDisp, theGC, rootfg);
158       for (i=k=0; i<dispHIGH; i+=20,k++) {
159 	XDrawLine(theDisp, tmpPix, theGC, 0, i, (int) dispWIDE, i);
160 	for (j=(k&1) * 20 + 10; j<dispWIDE; j+=40)
161 	  XDrawLine(theDisp, tmpPix, theGC, j,i,j,i+20);
162       }
163     }
164 
165 
166     /* draw the image centered on top of the background */
167     if ((rmode != RM_CENTILE) && (rmode != RM_UPLEFT))
168       XPutImage(theDisp, tmpPix, theGC, theImage, 0,0,
169 		((int) dispWIDE-eWIDE)/2, ((int) dispHIGH-eHIGH)/2,
170 		(u_int) eWIDE, (u_int) eHIGH);
171   }
172 
173 
174   else if (rmode == RM_ECENTER || rmode == RM_ECMIRR) {
175     int fliph, flipv;
176 
177     fliph = 0;  flipv = 0;
178 
179     if (dispWIDE == eWIDE) {
180       /* horizontal center line */
181       int y, ay;
182 
183       y = eHIGH - ((dispHIGH/2)%eHIGH); /* Starting point in picture to copy */
184       ay = 0;    /* Vertical anchor point */
185       while (ay < dispHIGH) {
186 	XPutImage(theDisp, tmpPix, theGC, theImage, 0,y,
187 		  0,ay, (u_int) eWIDE, (u_int) eHIGH);
188 	ay += eHIGH - y;
189 	y = 0;
190 	if (rmode == RM_ECMIRR) {
191 	  FlipPic(epic, eWIDE, eHIGH, 1);   flipv = !flipv;
192 	  CreateXImage();
193 	}
194       }
195     }
196     else if (dispHIGH == eHIGH) {
197       /* vertical centerline */
198       int x, ax;
199 
200       x = eWIDE - ((dispWIDE/2)%eWIDE); /* Starting point in picture to copy */
201       ax = 0;    /* Horizontal anchor point */
202       while (ax < dispWIDE) {
203 	XPutImage(theDisp, tmpPix, theGC, theImage, x,0,
204 		  ax,0, (u_int) eWIDE, (u_int) eHIGH);
205 	ax += eWIDE - x;
206 	x = 0;
207 	if (rmode == RM_ECMIRR) {
208 	  FlipPic(epic, eWIDE, eHIGH, 0);   fliph = !fliph;
209 	  CreateXImage();
210 	}
211       }
212     }
213     else {
214       /* vertical and horizontal centerlines */
215       int x,y, ax,ay;
216 
217       y = eHIGH - ((dispHIGH/2)%eHIGH); /* Starting point in picture to copy */
218       ay = 0;    /* Vertical anchor point */
219 
220       while (ay < dispHIGH) {
221 	x = eWIDE - ((dispWIDE/2)%eWIDE);/* Starting point in picture to cpy */
222 	ax = 0;    /* Horizontal anchor point */
223 	while (ax < dispWIDE) {
224 	  XPutImage(theDisp, tmpPix, theGC, theImage, x,y,
225 		    ax,ay, (u_int) eWIDE, (u_int) eHIGH);
226 	  if (rmode == RM_ECMIRR) {
227 	    FlipPic(epic, eWIDE, eHIGH, 0);  fliph = !fliph;
228 	    CreateXImage();
229 	  }
230 	  ax += eWIDE - x;
231 	  x = 0;
232 	}
233 	if (rmode == RM_ECMIRR) {
234 	  FlipPic(epic, eWIDE, eHIGH, 1);   flipv = !flipv;
235 	  if (fliph) {   /* leftmost image is always non-hflipped */
236 	    FlipPic(epic, eWIDE, eHIGH, 0);   fliph = !fliph;
237 	  }
238 	  CreateXImage();
239 	}
240 	ay += eHIGH - y;
241 	y = 0;
242       }
243     }
244 
245     /* put epic back to normal */
246     if (fliph) FlipPic(epic, eWIDE, eHIGH, 0);
247     if (flipv) FlipPic(epic, eWIDE, eHIGH, 1);
248   }
249 
250 
251   XSetWindowBackgroundPixmap(theDisp, mainW, tmpPix);
252   XFreePixmap(theDisp, tmpPix);
253 
254   XClearWindow(theDisp, mainW);
255 }
256 
257 
258 
259 /************************************************************************/
ClearRoot()260 void ClearRoot()
261 {
262   killRootPix();
263   XClearWindow(theDisp, vrootW);
264   XFlush(theDisp);
265 }
266 
267 
268 /************************************************************************/
killRootPix()269 static void killRootPix()
270 {
271   Pixmap pix, bitmap;
272   GC gc;
273   XGCValues gc_init;
274 
275   if (vrootW == rootW) {
276     XSetWindowBackgroundPixmap(theDisp, rootW, None);
277   }
278 
279   else {
280     bitmap = XCreateBitmapFromData(theDisp, vrootW, (char *) root_weave_bits,
281 				   root_weave_width, root_weave_height);
282 
283     gc_init.foreground = BlackPixel(theDisp, theScreen);
284     gc_init.background = WhitePixel(theDisp, theScreen);
285     gc = XCreateGC(theDisp, vrootW, GCForeground|GCBackground, &gc_init);
286     pix = XCreatePixmap(theDisp, vrootW, root_weave_width,
287 			root_weave_height,
288 			(unsigned int) DefaultDepth(theDisp, theScreen));
289 
290     XCopyPlane(theDisp, bitmap, pix, gc, 0,0, root_weave_width,
291 	       root_weave_height, 0,0, (unsigned long) 1);
292     XSetWindowBackgroundPixmap(theDisp, vrootW, pix);
293 
294     XFreeGC(theDisp, gc);
295     XFreePixmap(theDisp, bitmap);
296     XFreePixmap(theDisp, pix);
297   }
298 }
299 
300 
301 
302 /***********************************/
SaveRootInfo()303 void SaveRootInfo()
304 {
305   /* called when using root window.  stores the pixmap ID used to draw the
306      root window in a property.  This will be used later to free all resources
307      allocated by this instantiation of xv (ie, the alloc'd colors).  These
308      resources are kept alloc'ed after client exits so that rainbow effect
309      is avoided */
310 
311   Atom          prop;
312   static Pixmap riPix = (Pixmap) NULL;
313 
314   if ( !(theVisual->class & 1)) return;  /* no colormap to worry about */
315   if (riPix) return;                     /* it's already been saved once */
316 
317   riPix = XCreatePixmap(theDisp, vrootW, 1, 1, 1);
318   if (!riPix) return;   /* unable to save.  thankfully, unlikely to happen */
319 
320   prop = XInternAtom(theDisp, "_XSETROOT_ID", False);
321   if (!prop) FatalError("couldn't create _XSETROOT_ID atom");
322 
323   XChangeProperty(theDisp, vrootW, prop, XA_PIXMAP, 32, PropModeReplace,
324 		  (unsigned char *) &riPix, 1);
325 
326   XSetCloseDownMode(theDisp, RetainPermanent);
327 }
328 
329 
330 /***********************************/
KillOldRootInfo()331 void KillOldRootInfo()
332 {
333   /* get the pixmap ID from the _XSETROOT_ID property, and kill it */
334 
335   Atom           prop, type;
336   int            format;
337   unsigned long  length, after;
338   unsigned char *data;
339 
340   prop = XInternAtom(theDisp, "_XSETROOT_ID", True);
341   if (prop == None) return;    /* no old pixmap to kill */
342 
343   if (XGetWindowProperty(theDisp, vrootW, prop, 0L, 1L, True,
344 			 AnyPropertyType, &type, &format, &length,
345 			 &after, &data) == Success) {
346 
347     if (type==XA_PIXMAP && format==32 && length==1 && after==0 && data) {
348       XKillClient(theDisp, *((Pixmap *)data));
349       XDeleteProperty(theDisp, vrootW, prop);
350     }
351 
352     if (data) XFree((char *) data);
353   }
354 }
355 
356 
357 
358 
359