2 ac33a34a 2005-07-13 devnull * Window management.
5 038e9089 2004-03-21 devnull /* Copyright (c) 1994-1996 David Hogan, see README for licence details */
6 038e9089 2004-03-21 devnull #include <stdio.h>
7 e62ba5ec 2004-03-21 devnull #include <stdlib.h>
8 c9ee9e62 2006-04-20 devnull #include <inttypes.h>
9 038e9089 2004-03-21 devnull #include <X11/X.h>
10 038e9089 2004-03-21 devnull #include <X11/Xos.h>
11 038e9089 2004-03-21 devnull #include <X11/Xlib.h>
12 038e9089 2004-03-21 devnull #include <X11/Xutil.h>
13 038e9089 2004-03-21 devnull #include <X11/Xatom.h>
14 038e9089 2004-03-21 devnull #include <X11/extensions/shape.h>
15 038e9089 2004-03-21 devnull #include "dat.h"
16 038e9089 2004-03-21 devnull #include "fns.h"
18 e62ba5ec 2004-03-21 devnull int isNew;
21 038e9089 2004-03-21 devnull manage(Client *c, int mapped)
23 038e9089 2004-03-21 devnull int fixsize, dohide, doreshape, state;
24 038e9089 2004-03-21 devnull long msize;
25 038e9089 2004-03-21 devnull XClassHint class;
26 038e9089 2004-03-21 devnull XWMHints *hints;
27 c005568a 2004-03-30 devnull XSetWindowAttributes attrs;
29 038e9089 2004-03-21 devnull trace("manage", c, 0);
30 df03d60c 2005-07-13 devnull XSelectInput(dpy, c->window, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | FocusChangeMask | KeyPressMask);
32 038e9089 2004-03-21 devnull /* Get loads of hints */
34 ac33a34a 2005-07-13 devnull if(XGetClassHint(dpy, c->window, &class) != 0){ /* ``Success'' */
35 038e9089 2004-03-21 devnull c->instance = class.res_name;
36 038e9089 2004-03-21 devnull c->class = class.res_class;
37 e62ba5ec 2004-03-21 devnull c->is9term = 0;
38 e62ba5ec 2004-03-21 devnull if(isNew){
39 e62ba5ec 2004-03-21 devnull c->is9term = strstr(c->class, "term") || strstr(c->class, "Term");
40 e62ba5ec 2004-03-21 devnull isNew = 0;
44 038e9089 2004-03-21 devnull c->instance = 0;
45 038e9089 2004-03-21 devnull c->class = 0;
46 038e9089 2004-03-21 devnull c->is9term = 0;
48 038e9089 2004-03-21 devnull c->iconname = getprop(c->window, XA_WM_ICON_NAME);
49 038e9089 2004-03-21 devnull c->name = getprop(c->window, XA_WM_NAME);
50 038e9089 2004-03-21 devnull setlabel(c);
52 038e9089 2004-03-21 devnull hints = XGetWMHints(dpy, c->window);
53 ac33a34a 2005-07-13 devnull if(XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0)
54 038e9089 2004-03-21 devnull c->size.flags = PSize; /* not specified - punt */
56 038e9089 2004-03-21 devnull getcmaps(c);
57 038e9089 2004-03-21 devnull getproto(c);
58 038e9089 2004-03-21 devnull gettrans(c);
59 ac33a34a 2005-07-13 devnull if(c->is9term)
60 aa808685 2004-04-19 devnull c->hold = getiprop(c->window, _rio_hold_mode);
62 038e9089 2004-03-21 devnull /* Figure out what to do with the window from hints */
64 ac33a34a 2005-07-13 devnull if(!getstate(c->window, &state))
65 038e9089 2004-03-21 devnull state = hints ? hints->initial_state : NormalState;
66 038e9089 2004-03-21 devnull dohide = (state == IconicState);
68 038e9089 2004-03-21 devnull fixsize = 0;
69 ac33a34a 2005-07-13 devnull if((c->size.flags & (USSize|PSize)))
70 038e9089 2004-03-21 devnull fixsize = 1;
71 ac33a34a 2005-07-13 devnull if((c->size.flags & (PMinSize|PMaxSize)) == (PMinSize|PMaxSize) && c->size.min_width == c->size.max_width && c->size.min_height == c->size.max_height)
72 038e9089 2004-03-21 devnull fixsize = 1;
73 038e9089 2004-03-21 devnull doreshape = !mapped;
74 ac33a34a 2005-07-13 devnull if(fixsize){
75 ac33a34a 2005-07-13 devnull if(c->size.flags & USPosition)
76 038e9089 2004-03-21 devnull doreshape = 0;
77 ac33a34a 2005-07-13 devnull if(dohide && (c->size.flags & PPosition))
78 038e9089 2004-03-21 devnull doreshape = 0;
79 ac33a34a 2005-07-13 devnull if(c->trans != None)
80 038e9089 2004-03-21 devnull doreshape = 0;
82 ac33a34a 2005-07-13 devnull if(c->is9term)
83 038e9089 2004-03-21 devnull fixsize = 0;
84 ac33a34a 2005-07-13 devnull if(c->size.flags & PBaseSize){
85 038e9089 2004-03-21 devnull c->min_dx = c->size.base_width;
86 038e9089 2004-03-21 devnull c->min_dy = c->size.base_height;
88 ac33a34a 2005-07-13 devnull else if(c->size.flags & PMinSize){
89 038e9089 2004-03-21 devnull c->min_dx = c->size.min_width;
90 038e9089 2004-03-21 devnull c->min_dy = c->size.min_height;
92 ac33a34a 2005-07-13 devnull else if(c->is9term){
93 038e9089 2004-03-21 devnull c->min_dx = 100;
94 038e9089 2004-03-21 devnull c->min_dy = 50;
97 038e9089 2004-03-21 devnull c->min_dx = c->min_dy = 0;
99 ac33a34a 2005-07-13 devnull if(hints)
100 038e9089 2004-03-21 devnull XFree(hints);
102 038e9089 2004-03-21 devnull /* Now do it!!! */
104 ac33a34a 2005-07-13 devnull if(doreshape){
105 cc3c704c 2004-04-05 devnull if(0) fprintf(stderr, "in doreshape is9term=%d fixsize=%d, x=%d, y=%d, min_dx=%d, min_dy=%d, dx=%d, dy=%d\n",
106 cc3c704c 2004-04-05 devnull c->is9term, fixsize, c->x, c->y, c->min_dx, c->min_dy, c->dx, c->dy);
107 ac33a34a 2005-07-13 devnull if(current && current->screen == c->screen)
108 038e9089 2004-03-21 devnull cmapnofocus(c->screen);
109 ac33a34a 2005-07-13 devnull if(!c->is9term && c->x==0 && c->y==0){
110 038e9089 2004-03-21 devnull static int nwin;
112 038e9089 2004-03-21 devnull c->x = 20*nwin+BORDER;
113 038e9089 2004-03-21 devnull c->y = 20*nwin+BORDER;
115 038e9089 2004-03-21 devnull nwin %= 10;
118 ac33a34a 2005-07-13 devnull if(c->is9term && !(fixsize ? drag(c, Button3) : sweep(c, Button3))){
119 038e9089 2004-03-21 devnull XKillClient(dpy, c->window);
120 038e9089 2004-03-21 devnull rmclient(c);
121 ac33a34a 2005-07-13 devnull if(current && current->screen == c->screen)
122 038e9089 2004-03-21 devnull cmapfocus(current);
123 038e9089 2004-03-21 devnull return 0;
127 c005568a 2004-03-30 devnull attrs.border_pixel = c->screen->black;
128 c005568a 2004-03-30 devnull attrs.background_pixel = c->screen->white;
129 c005568a 2004-03-30 devnull attrs.colormap = c->screen->def_cmap;
130 c005568a 2004-03-30 devnull c->parent = XCreateWindow(dpy, c->screen->root,
131 038e9089 2004-03-21 devnull c->x - BORDER, c->y - BORDER,
132 038e9089 2004-03-21 devnull c->dx + 2*BORDER, c->dy + 2*BORDER,
134 c005568a 2004-03-30 devnull c->screen->depth,
135 c005568a 2004-03-30 devnull CopyFromParent,
136 c005568a 2004-03-30 devnull c->screen->vis,
137 c005568a 2004-03-30 devnull CWBackPixel | CWBorderPixel | CWColormap,
138 c005568a 2004-03-30 devnull &attrs);
140 df03d60c 2005-07-13 devnull XSelectInput(dpy, c->parent, SubstructureRedirectMask | SubstructureNotifyMask|ButtonPressMask| PointerMotionMask|LeaveWindowMask|KeyPressMask);
141 ac33a34a 2005-07-13 devnull if(mapped)
142 038e9089 2004-03-21 devnull c->reparenting = 1;
143 ac33a34a 2005-07-13 devnull if(doreshape && !fixsize)
144 038e9089 2004-03-21 devnull XResizeWindow(dpy, c->window, c->dx, c->dy);
145 038e9089 2004-03-21 devnull XSetWindowBorderWidth(dpy, c->window, 0);
148 c005568a 2004-03-30 devnull * To have something more than only a big white or black border
149 c005568a 2004-03-30 devnull * XXX should replace this by a pattern in the white or black
150 c005568a 2004-03-30 devnull * such that we can see the border also if all our
151 c005568a 2004-03-30 devnull * windows are black and/or white
152 c005568a 2004-03-30 devnull * (black (or white) border around black (or white) window
153 c005568a 2004-03-30 devnull * is not very helpful.
155 ac33a34a 2005-07-13 devnull if(c->screen->depth <= 8){
156 1cb3fa80 2004-03-29 devnull XSetWindowBorderWidth(dpy, c->parent, 1);
159 038e9089 2004-03-21 devnull XReparentWindow(dpy, c->window, c->parent, BORDER, BORDER);
160 038e9089 2004-03-21 devnull #ifdef SHAPE
161 ac33a34a 2005-07-13 devnull if(shape){
162 038e9089 2004-03-21 devnull XShapeSelectInput(dpy, c->window, ShapeNotifyMask);
163 038e9089 2004-03-21 devnull ignore_badwindow = 1; /* magic */
164 038e9089 2004-03-21 devnull setshape(c);
165 038e9089 2004-03-21 devnull ignore_badwindow = 0;
168 038e9089 2004-03-21 devnull XAddToSaveSet(dpy, c->window);
169 ac33a34a 2005-07-13 devnull if(dohide)
170 038e9089 2004-03-21 devnull hide(c);
172 038e9089 2004-03-21 devnull XMapWindow(dpy, c->window);
173 038e9089 2004-03-21 devnull XMapWindow(dpy, c->parent);
174 038e9089 2004-03-21 devnull XUnmapWindow(dpy, c->screen->sweepwin);
175 ac33a34a 2005-07-13 devnull if(nostalgia || doreshape)
176 038e9089 2004-03-21 devnull active(c);
177 ac33a34a 2005-07-13 devnull else if(c->trans != None && current && current->window == c->trans)
178 038e9089 2004-03-21 devnull active(c);
180 038e9089 2004-03-21 devnull setactive(c, 0);
181 038e9089 2004-03-21 devnull setstate(c, NormalState);
183 ac33a34a 2005-07-13 devnull if(current && (current != c))
184 038e9089 2004-03-21 devnull cmapfocus(current);
185 038e9089 2004-03-21 devnull c->init = 1;
188 c005568a 2004-03-30 devnull * If we swept the window, let's send a resize event to the
189 c005568a 2004-03-30 devnull * guy who just got resized. It's not clear whether the apps
190 c005568a 2004-03-30 devnull * should notice their new size via other means. Try as I might,
191 c005568a 2004-03-30 devnull * I can't find a way to have them notice during initdraw, so
192 c005568a 2004-03-30 devnull * I solve the problem this way instead. -rsc
194 c005568a 2004-03-30 devnull if(c->is9term)
195 c005568a 2004-03-30 devnull sendconfig(c);
196 038e9089 2004-03-21 devnull return 1;
200 038e9089 2004-03-21 devnull scanwins(ScreenInfo *s)
202 038e9089 2004-03-21 devnull unsigned int i, nwins;
203 038e9089 2004-03-21 devnull Client *c;
204 038e9089 2004-03-21 devnull Window dw1, dw2, *wins;
205 038e9089 2004-03-21 devnull XWindowAttributes attr;
207 038e9089 2004-03-21 devnull XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins);
208 ac33a34a 2005-07-13 devnull for(i = 0; i < nwins; i++){
209 038e9089 2004-03-21 devnull XGetWindowAttributes(dpy, wins[i], &attr);
210 ac33a34a 2005-07-13 devnull if(attr.override_redirect || wins[i] == s->menuwin)
211 038e9089 2004-03-21 devnull continue;
212 038e9089 2004-03-21 devnull c = getclient(wins[i], 1);
213 ac33a34a 2005-07-13 devnull if(c != 0 && c->window == wins[i] && !c->init){
214 038e9089 2004-03-21 devnull c->x = attr.x;
215 038e9089 2004-03-21 devnull c->y = attr.y;
216 038e9089 2004-03-21 devnull c->dx = attr.width;
217 038e9089 2004-03-21 devnull c->dy = attr.height;
218 038e9089 2004-03-21 devnull c->border = attr.border_width;
219 038e9089 2004-03-21 devnull c->screen = s;
220 038e9089 2004-03-21 devnull c->parent = s->root;
221 ac33a34a 2005-07-13 devnull if(attr.map_state == IsViewable)
222 038e9089 2004-03-21 devnull manage(c, 1);
225 038e9089 2004-03-21 devnull XFree((void *) wins); /* cast is to shut stoopid compiler up */
229 038e9089 2004-03-21 devnull gettrans(Client *c)
231 038e9089 2004-03-21 devnull Window trans;
233 038e9089 2004-03-21 devnull trans = None;
234 ac33a34a 2005-07-13 devnull if(XGetTransientForHint(dpy, c->window, &trans) != 0)
235 038e9089 2004-03-21 devnull c->trans = trans;
237 038e9089 2004-03-21 devnull c->trans = None;
241 038e9089 2004-03-21 devnull withdraw(Client *c)
243 038e9089 2004-03-21 devnull XUnmapWindow(dpy, c->parent);
244 038e9089 2004-03-21 devnull XReparentWindow(dpy, c->window, c->screen->root, c->x, c->y);
245 038e9089 2004-03-21 devnull XRemoveFromSaveSet(dpy, c->window);
246 038e9089 2004-03-21 devnull setstate(c, WithdrawnState);
248 038e9089 2004-03-21 devnull /* flush any errors */
249 038e9089 2004-03-21 devnull ignore_badwindow = 1;
250 038e9089 2004-03-21 devnull XSync(dpy, False);
251 038e9089 2004-03-21 devnull ignore_badwindow = 0;
254 038e9089 2004-03-21 devnull static void
255 038e9089 2004-03-21 devnull installcmap(ScreenInfo *s, Colormap cmap)
257 ac33a34a 2005-07-13 devnull if(cmap == None)
258 038e9089 2004-03-21 devnull XInstallColormap(dpy, s->def_cmap);
260 038e9089 2004-03-21 devnull XInstallColormap(dpy, cmap);
264 038e9089 2004-03-21 devnull cmapfocus(Client *c)
266 038e9089 2004-03-21 devnull int i, found;
267 038e9089 2004-03-21 devnull Client *cc;
269 ac33a34a 2005-07-13 devnull if(c == 0)
271 ac33a34a 2005-07-13 devnull else if(c->ncmapwins != 0){
272 038e9089 2004-03-21 devnull found = 0;
273 ac33a34a 2005-07-13 devnull for(i = c->ncmapwins-1; i >= 0; i--){
274 038e9089 2004-03-21 devnull installcmap(c->screen, c->wmcmaps[i]);
275 ac33a34a 2005-07-13 devnull if(c->cmapwins[i] == c->window)
276 038e9089 2004-03-21 devnull found++;
278 ac33a34a 2005-07-13 devnull if(!found)
279 038e9089 2004-03-21 devnull installcmap(c->screen, c->cmap);
281 ac33a34a 2005-07-13 devnull else if(c->trans != None && (cc = getclient(c->trans, 0)) != 0 && cc->ncmapwins != 0)
282 038e9089 2004-03-21 devnull cmapfocus(cc);
284 038e9089 2004-03-21 devnull installcmap(c->screen, c->cmap);
288 038e9089 2004-03-21 devnull cmapnofocus(ScreenInfo *s)
290 038e9089 2004-03-21 devnull installcmap(s, None);
294 038e9089 2004-03-21 devnull getcmaps(Client *c)
296 038e9089 2004-03-21 devnull int n, i;
297 038e9089 2004-03-21 devnull Window *cw;
298 038e9089 2004-03-21 devnull XWindowAttributes attr;
300 ac33a34a 2005-07-13 devnull if(!c->init){
301 78802e69 2004-04-24 devnull ignore_badwindow = 1;
302 038e9089 2004-03-21 devnull XGetWindowAttributes(dpy, c->window, &attr);
303 038e9089 2004-03-21 devnull c->cmap = attr.colormap;
304 78802e69 2004-04-24 devnull XSync(dpy, False);
305 78802e69 2004-04-24 devnull ignore_badwindow = 0;
308 1cb3fa80 2004-03-29 devnull n = _getprop(c->window, wm_colormaps, XA_WINDOW, 100L, (void*)&cw);
309 ac33a34a 2005-07-13 devnull if(c->ncmapwins != 0){
310 038e9089 2004-03-21 devnull XFree((char *)c->cmapwins);
311 038e9089 2004-03-21 devnull free((char *)c->wmcmaps);
313 ac33a34a 2005-07-13 devnull if(n <= 0){
314 038e9089 2004-03-21 devnull c->ncmapwins = 0;
318 038e9089 2004-03-21 devnull c->ncmapwins = n;
319 038e9089 2004-03-21 devnull c->cmapwins = cw;
321 038e9089 2004-03-21 devnull c->wmcmaps = (Colormap*)malloc(n*sizeof(Colormap));
322 ac33a34a 2005-07-13 devnull for(i = 0; i < n; i++){
323 ac33a34a 2005-07-13 devnull if(cw[i] == c->window)
324 038e9089 2004-03-21 devnull c->wmcmaps[i] = c->cmap;
326 78802e69 2004-04-24 devnull /* flush any errors (e.g., caused by mozilla tabs) */
327 78802e69 2004-04-24 devnull ignore_badwindow = 1;
328 038e9089 2004-03-21 devnull XSelectInput(dpy, cw[i], ColormapChangeMask);
329 038e9089 2004-03-21 devnull XGetWindowAttributes(dpy, cw[i], &attr);
330 038e9089 2004-03-21 devnull c->wmcmaps[i] = attr.colormap;
331 78802e69 2004-04-24 devnull XSync(dpy, False);
332 78802e69 2004-04-24 devnull ignore_badwindow = 0;
338 038e9089 2004-03-21 devnull setlabel(Client *c)
340 038e9089 2004-03-21 devnull char *label, *p;
342 ac33a34a 2005-07-13 devnull if(c->iconname != 0)
343 038e9089 2004-03-21 devnull label = c->iconname;
344 ac33a34a 2005-07-13 devnull else if(c->name != 0)
345 038e9089 2004-03-21 devnull label = c->name;
346 ac33a34a 2005-07-13 devnull else if(c->instance != 0)
347 038e9089 2004-03-21 devnull label = c->instance;
348 ac33a34a 2005-07-13 devnull else if(c->class != 0)
349 038e9089 2004-03-21 devnull label = c->class;
351 038e9089 2004-03-21 devnull label = "no label";
352 ac33a34a 2005-07-13 devnull if((p = index(label, ':')) != 0)
353 038e9089 2004-03-21 devnull *p = '\0';
354 038e9089 2004-03-21 devnull c->label = label;
357 038e9089 2004-03-21 devnull #ifdef SHAPE
359 038e9089 2004-03-21 devnull setshape(Client *c)
361 038e9089 2004-03-21 devnull int n, order;
362 038e9089 2004-03-21 devnull XRectangle *rect;
364 038e9089 2004-03-21 devnull /* don't try to add a border if the window is non-rectangular */
365 038e9089 2004-03-21 devnull rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order);
366 ac33a34a 2005-07-13 devnull if(n > 1)
367 038e9089 2004-03-21 devnull XShapeCombineShape(dpy, c->parent, ShapeBounding, BORDER, BORDER,
368 038e9089 2004-03-21 devnull c->window, ShapeBounding, ShapeSet);
369 038e9089 2004-03-21 devnull XFree((void*)rect);
374 038e9089 2004-03-21 devnull _getprop(Window w, Atom a, Atom type, long len, unsigned char **p)
376 038e9089 2004-03-21 devnull Atom real_type;
377 038e9089 2004-03-21 devnull int format;
378 038e9089 2004-03-21 devnull unsigned long n, extra;
379 038e9089 2004-03-21 devnull int status;
381 038e9089 2004-03-21 devnull status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p);
382 ac33a34a 2005-07-13 devnull if(status != Success || *p == 0)
383 038e9089 2004-03-21 devnull return -1;
384 ac33a34a 2005-07-13 devnull if(n == 0)
385 038e9089 2004-03-21 devnull XFree((void*) *p);
386 038e9089 2004-03-21 devnull /* could check real_type, format, extra here... */
387 038e9089 2004-03-21 devnull return n;
391 038e9089 2004-03-21 devnull getprop(Window w, Atom a)
393 038e9089 2004-03-21 devnull unsigned char *p;
395 ac33a34a 2005-07-13 devnull if(_getprop(w, a, XA_STRING, 100L, &p) <= 0)
396 038e9089 2004-03-21 devnull return 0;
397 038e9089 2004-03-21 devnull return (char *)p;
401 038e9089 2004-03-21 devnull get1prop(Window w, Atom a, Atom type)
403 038e9089 2004-03-21 devnull char **p, *x;
405 ac33a34a 2005-07-13 devnull if(_getprop(w, a, type, 1L, (void*)&p) <= 0)
406 038e9089 2004-03-21 devnull return 0;
408 038e9089 2004-03-21 devnull XFree((void*) p);
409 c9ee9e62 2006-04-20 devnull return (int)(uintptr_t)x;
413 038e9089 2004-03-21 devnull getwprop(Window w, Atom a)
415 038e9089 2004-03-21 devnull return get1prop(w, a, XA_WINDOW);
419 038e9089 2004-03-21 devnull getiprop(Window w, Atom a)
421 038e9089 2004-03-21 devnull return get1prop(w, a, XA_INTEGER);
425 038e9089 2004-03-21 devnull setstate(Client *c, int state)
427 038e9089 2004-03-21 devnull long data[2];
429 038e9089 2004-03-21 devnull data[0] = (long) state;
430 038e9089 2004-03-21 devnull data[1] = (long) None;
432 038e9089 2004-03-21 devnull c->state = state;
433 038e9089 2004-03-21 devnull XChangeProperty(dpy, c->window, wm_state, wm_state, 32,
434 038e9089 2004-03-21 devnull PropModeReplace, (unsigned char *)data, 2);
438 038e9089 2004-03-21 devnull getstate(Window w, int *state)
440 038e9089 2004-03-21 devnull long *p = 0;
442 ac33a34a 2005-07-13 devnull if(_getprop(w, wm_state, wm_state, 2L, (void*)&p) <= 0)
443 038e9089 2004-03-21 devnull return 0;
445 038e9089 2004-03-21 devnull *state = (int) *p;
446 038e9089 2004-03-21 devnull XFree((char *) p);
447 038e9089 2004-03-21 devnull return 1;
451 038e9089 2004-03-21 devnull getproto(Client *c)
453 038e9089 2004-03-21 devnull Atom *p;
456 038e9089 2004-03-21 devnull Window w;
458 038e9089 2004-03-21 devnull w = c->window;
459 038e9089 2004-03-21 devnull c->proto = 0;
460 ac33a34a 2005-07-13 devnull if((n = _getprop(w, wm_protocols, XA_ATOM, 20L, (void*)&p)) <= 0)
463 ac33a34a 2005-07-13 devnull for(i = 0; i < n; i++)
464 ac33a34a 2005-07-13 devnull if(p[i] == wm_delete)
465 038e9089 2004-03-21 devnull c->proto |= Pdelete;
466 ac33a34a 2005-07-13 devnull else if(p[i] == wm_take_focus)
467 038e9089 2004-03-21 devnull c->proto |= Ptakefocus;
468 ac33a34a 2005-07-13 devnull else if(p[i] == wm_lose_focus)
469 c005568a 2004-03-30 devnull c->proto |= Plosefocus;
471 038e9089 2004-03-21 devnull XFree((char *) p);