1 /****************************************************************************
2  * This module is based on Twm, but has been siginificantly modified
3  * by Rob Nation
4  *
5  * later modified for BowMan
6  * by Bo Yang
7  *
8  * again modified for AfterStep
9  * by Frank Fejes
10  ****************************************************************************/
11 /*****************************************************************************/
12 /**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
13 /**                          Salt Lake City, Utah                           **/
14 /**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
15 /**                        Cambridge, Massachusetts                         **/
16 /**                                                                         **/
17 /**                           All Rights Reserved                           **/
18 /**                                                                         **/
19 /**    Permission to use, copy, modify, and distribute this software and    **/
20 /**    its documentation  for  any  purpose  and  without  fee is hereby    **/
21 /**    granted, provided that the above copyright notice appear  in  all    **/
22 /**    copies and that both  that  copyright  notice  and  this  permis-    **/
23 /**    sion  notice appear in supporting  documentation,  and  that  the    **/
24 /**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
25 /**    in publicity pertaining to distribution of the  software  without    **/
26 /**    specific, written prior permission.                                  **/
27 /**                                                                         **/
28 /**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
29 /**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
30 /**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
31 /**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
32 /**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
33 /**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
34 /**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
35 /**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
36 /*****************************************************************************/
37 
38 
39 /***********************************************************************
40  *
41  * afterstep event handling
42  *
43  ***********************************************************************/
44 
45 #include "../configure.h"
46 
47 #ifdef ISC
48 #include <sys/bsdtypes.h>
49 #endif
50 
51 #include <stdio.h>
52 #include <string.h>
53 #include <sys/types.h>
54 #include <sys/time.h>
55 #include <unistd.h>
56 #include <signal.h>
57 #include <limits.h>
58 /* Some people say that AIX and AIXV3 need 3 preceding underscores, other say
59  * no. I'll do both */
60 #if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_
61 #include <sys/select.h>
62 #endif
63 
64 #include "afterstep.h"
65 #include <X11/Xatom.h>
66 #include "menus.h"
67 #include "misc.h"
68 #include "parse.h"
69 #include "screen.h"
70 #ifdef SHAPE
71 #include <X11/extensions/shape.h>
72 #endif /* SHAPE */
73 #include "module.h"
74 
75 #ifndef NO_PAGER
76 extern ASWindow *FindCounterpart(Window target);
77 #endif /* NO_PAGER */
78 
79 extern int menuFromFrameOrWindowOrTitlebar;
80 
81 static void ChangeIcon();
82 
83 int Context = C_NO_CONTEXT;	/* current button press context */
84 int Button = 0;
85 ASWindow *ButtonWindow;	/* button press window structure */
86 XEvent Event;			/* the current event */
87 ASWindow *Tmp_win;		/* the current afterstep window */
88 
89 int last_event_type=0;
90 Window last_event_window=0;
91 
92 #ifdef SHAPE
93 extern int ShapeEventBase;
94 void HandleShapeNotify(void);
95 #endif /* SHAPE */
96 
97 Window PressedW;
98 
99 /***********************************************************************
100  *
101  *  Procedure:
102  *	DispatchEvent - handle a single X event stored in global var Event
103  *
104  ************************************************************************/
DispatchEvent()105 void DispatchEvent()
106 {
107   Window w = Event.xany.window;
108 
109   StashEventTime(&Event);
110 
111   if (XFindContext (dpy, w, ASContext, (caddr_t *) &Tmp_win) == XCNOENT)
112     Tmp_win = NULL;
113   last_event_type = Event.type;
114   last_event_window = w;
115 
116   switch(Event.type)
117     {
118     case Expose:
119       HandleExpose();
120       break;
121     case DestroyNotify:
122       HandleDestroyNotify();
123       break;
124     case MapRequest:
125       HandleMapRequest();
126       break;
127     case MapNotify:
128       HandleMapNotify();
129       break;
130     case UnmapNotify:
131       HandleUnmapNotify();
132       break;
133     case MotionNotify:
134       HandleMotionNotify();
135       break;
136     case ButtonPress:
137       HandleButtonPress();
138       break;
139     case ButtonRelease:
140       HandleButtonRelease();
141       break;
142     case EnterNotify:
143       HandleEnterNotify();
144       break;
145     case LeaveNotify:
146       HandleLeaveNotify();
147       break;
148     case FocusIn:
149       HandleFocusIn();
150       break;
151     case ConfigureRequest:
152       HandleConfigureRequest();
153       break;
154     case ClientMessage:
155       HandleClientMessage();
156       break;
157     case PropertyNotify:
158       HandlePropertyNotify();
159       break;
160     case KeyPress:
161       HandleKeyPress();
162       break;
163     case ColormapNotify:
164       HandleColormapNotify();
165       break;
166     default:
167 #ifdef SHAPE
168       if(Event.type == (ShapeEventBase + ShapeNotify))
169 	HandleShapeNotify();
170 #endif /* SHAPE */
171 
172       break;
173     }
174   return;
175 }
176 
177 
178 /***********************************************************************
179  *
180  *  Procedure:
181  *	HandleEvents - handle X events
182  *
183  ************************************************************************/
HandleEvents()184 void HandleEvents()
185 {
186   while (TRUE)
187     {
188       last_event_type = 0;
189       if(My_XNextEvent(dpy, &Event))
190 	{
191 	  DispatchEvent ();
192 	}
193     }
194 }
195 
196 /***********************************************************************
197  *
198  *  Procedure:
199  *	Find the AS context for the Event.
200  *
201  ************************************************************************/
GetContext(ASWindow * t,XEvent * e,Window * w)202 int GetContext(ASWindow *t, XEvent *e, Window *w)
203 {
204   int i;
205 
206   if (t == NULL)
207       return C_ROOT;
208 
209   *w= e->xany.window;
210 
211   if ((*w == Scr.NoFocusWin) || (*w == Scr.Root))
212       return C_ROOT;
213 
214   /* Since key presses and button presses are grabbed in the frame
215    * when we have re-parented windows, we need to find out the real
216    * window where the event occured */
217   if (! (t->flags & ICONIFIED))
218     {
219       if (e->type == KeyPress)
220         {
221 	  if (e->xkey.subwindow != None)
222 	      *w = e->xany.window = e->xkey.subwindow;
223 	}
224       else if (e->type == ButtonPress)
225         {
226 	  if (e->xbutton.subwindow != None)
227 	      *w = e->xany.window = e->xbutton.subwindow;
228 	  else if ((*w == t->frame) && (e->xbutton.y < NS_TITLE_HEIGHT+2))
229 	      return C_TITLE;
230 	}
231     }
232 
233   if (*w == t->title_w)  return C_TITLE;
234   if ((*w == t->icon_pixmap_w) || (t->flags & ICONIFIED))  return C_ICON;
235   if ((*w == t->frame) || (*w == t->side))  return C_SIDEBAR;
236 
237   for(i = 0; i < 2; i++)
238     {
239       if(*w == t->corners[i])
240       {
241 	  Button = i;
242 	  return C_FRAME;
243       }
244     }
245   for(i = 0; i < Scr.nr_left_buttons; i++)
246     {
247       if(*w == t->left_w[i])
248         {
249 	  Button = i;
250 	  return (1<<i)*C_L1;
251 	}
252     }
253   for(i = 0; i < Scr.nr_right_buttons; i++)
254   {
255       if(*w == t->right_w[i])
256       {
257 	  Button = i;
258 	  return (1<<i)*C_R1;
259       }
260   }
261 
262   *w = t->w;
263   return C_WINDOW;
264 }
265 
266 /***********************************************************************
267  *
268  *  Procedure:
269  *	HandleFocusIn - handles focus in events
270  *
271  ************************************************************************/
HandleFocusIn()272 void HandleFocusIn()
273 {
274   XEvent d;
275   Window w;
276 
277   w= Event.xany.window;
278   while(XCheckTypedEvent(dpy,FocusIn,&d))
279     {
280       w = d.xany.window;
281     }
282   if (XFindContext (dpy, w, ASContext, (caddr_t *) &Tmp_win) == XCNOENT)
283     {
284       Tmp_win = NULL;
285     }
286 
287   if(!Tmp_win)
288     {
289       SetBorder(Scr.Hilite,False,True,True,None);
290       Broadcast(M_FOCUS_CHANGE,3,0,0,0,0,0,0,0);
291     }
292   else if(Tmp_win != Scr.Hilite)
293     {
294       SetBorder(Tmp_win,True,True,True,None);
295       Broadcast(M_FOCUS_CHANGE,3,Tmp_win->w,
296 		Tmp_win->frame,(unsigned long)Tmp_win,0,0,0,0);
297     }
298 }
299 
300 /***********************************************************************
301  *
302  *  Procedure:
303  *	HandleKeyPress - key press event handler
304  *
305  ************************************************************************/
HandleKeyPress()306 void HandleKeyPress()
307 {
308   FuncKey *key;
309   unsigned int modifier;
310   Window dummy;
311 
312   Context = GetContext(Tmp_win,&Event,&dummy);
313 
314   modifier = (Event.xkey.state & Scr.nonlock_mods);
315   for (key = Scr.FuncKeyRoot.next; key != NULL; key = key->next)
316     {
317       ButtonWindow = Tmp_win;
318       /* Here's a real hack - some systems have two keys with the
319        * same keysym and different keycodes. This converts all
320        * the cases to one keycode. */
321       Event.xkey.keycode =
322 	XKeysymToKeycode(dpy,XkbKeycodeToKeysym(dpy,Event.xkey.keycode,0,0));
323       if ((key->keycode == Event.xkey.keycode) &&
324 	  ((key->mods == (modifier&(~LockMask)))||
325 	   (key->mods == AnyModifier)) &&
326 	  (key->cont & Context))
327 	{
328 	  ExecuteFunction(key->func, key->action, Event.xany.window,Tmp_win,
329 			  &Event,Context,key->val1,key->val2,
330 			  key->val1_unit,key->val2_unit,
331 			  key->menu,-1);
332 	  return;
333 	}
334     }
335 
336   /* if we get here, no function key was bound to the key.  Send it
337    * to the client if it was in a window we know about.
338    */
339   if (Tmp_win)
340     {
341       if(Event.xkey.window != Tmp_win->w)
342 	{
343 	  Event.xkey.window = Tmp_win->w;
344 	  XSendEvent(dpy, Tmp_win->w, False, KeyPressMask, &Event);
345 	}
346     }
347   ButtonWindow = NULL;
348 }
349 
350 
351 /***********************************************************************
352  *
353  *  Procedure:
354  *	HandlePropertyNotify - property notify event handler
355  *
356  ***********************************************************************/
357 #define MAX_NAME_LEN 200L		/* truncate to this many */
358 #define MAX_ICON_NAME_LEN 200L		/* ditto */
359 
HandlePropertyNotify()360 void HandlePropertyNotify()
361 {
362   char *prop = NULL;
363   Atom actual = None;
364   int actual_format;
365   unsigned long nitems, bytesafter;
366 
367   if ((!Tmp_win)||(XGetGeometry(dpy, Tmp_win->w, &JunkRoot, &JunkX, &JunkY,
368 				&JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0))
369     return;
370 
371   switch (Event.xproperty.atom)
372     {
373     case XA_WM_NAME:
374       if (XGetWindowProperty (dpy, Tmp_win->w, Event.xproperty.atom, 0L,
375 			      MAX_NAME_LEN, False, XA_STRING, &actual,
376 			      &actual_format, &nitems, &bytesafter,
377 			      (unsigned char **) &prop) != Success ||
378 	  actual == None)
379 	return;
380       if (!prop) prop = NoName;
381       free_window_names (Tmp_win, True, False);
382 
383       Tmp_win->name = prop;
384       BroadcastName(M_WINDOW_NAME,Tmp_win->w,Tmp_win->frame,
385 		    (unsigned long)Tmp_win,Tmp_win->name);
386 
387       /* fix the name in the title bar */
388       if(!(Tmp_win->flags & ICONIFIED))
389 	SetTitleBar(Tmp_win,(Scr.Hilite==Tmp_win),True);
390 	else
391 	  ChangeIcon();
392 
393 /*
394 * if the icon name is NoName, set the name of the icon to be
395 * the same as the window
396        */
397       if (Tmp_win->icon_name == NoName)
398 	{
399 	  Tmp_win->icon_name = Tmp_win->name;
400 	  BroadcastName(M_ICON_NAME,Tmp_win->w,Tmp_win->frame,
401 			(unsigned long)Tmp_win,Tmp_win->icon_name);
402 	}
403       break;
404 
405     case XA_WM_ICON_NAME:
406       if (XGetWindowProperty (dpy, Tmp_win->w, Event.xproperty.atom, 0,
407 			      MAX_ICON_NAME_LEN, False, XA_STRING, &actual,
408 			      &actual_format, &nitems, &bytesafter,
409 			      (unsigned char **) &prop) != Success ||
410 	  actual == None)
411 	return;
412       if (!prop) prop = NoName;
413       free_window_names (Tmp_win, False, True);
414       Tmp_win->icon_name = prop;
415       BroadcastName(M_ICON_NAME,Tmp_win->w,Tmp_win->frame,
416 		    (unsigned long)Tmp_win,Tmp_win->icon_name);
417 	  if((Tmp_win->flags & ICONIFIED))
418 		  ChangeIcon();
419       break;
420 
421     case XA_WM_HINTS:
422       if (Tmp_win->wmhints)
423 	XFree ((char *) Tmp_win->wmhints);
424       Tmp_win->wmhints = XGetWMHints(dpy, Event.xany.window);
425 
426       if(Tmp_win->wmhints == NULL)
427 	return;
428 
429       if((Tmp_win->wmhints->flags & IconPixmapHint)||
430 	 (Tmp_win->wmhints->flags & IconWindowHint))
431 	if(Tmp_win->icon_bitmap_file == Scr.DefaultIcon)
432 	  Tmp_win->icon_bitmap_file = (char *)0;
433 
434       if((Tmp_win->wmhints->flags & IconPixmapHint)||
435          (Tmp_win->wmhints->flags & IconWindowHint))
436 	{
437 	  if (!(Tmp_win->flags & SUPPRESSICON))
438 	    {
439 	      if(Tmp_win->flags & ICON_OURS)
440 		{
441 		  if(Tmp_win->icon_pixmap_w != None)
442 		    {
443 		      XDestroyWindow(dpy,Tmp_win->icon_pixmap_w);
444 		      XDeleteContext(dpy, Tmp_win->icon_pixmap_w, ASContext);
445 		    }
446 		}
447 	      else
448 		XUnmapWindow(dpy,Tmp_win->icon_pixmap_w);
449 	    }
450           Tmp_win->icon_pixmap_w = None;
451 	  Tmp_win->iconPixmap = (Window)NULL;
452 	  if(Tmp_win->flags & ICONIFIED)
453 	    {
454 	      Tmp_win->flags &= ~ICONIFIED;
455 	      Tmp_win->flags &= ~ICON_UNMAPPED;
456 	      CreateIconWindow(Tmp_win,Tmp_win->icon_x_loc,Tmp_win->icon_y_loc);
457 	      Broadcast(M_ICONIFY,7,Tmp_win->w,Tmp_win->frame,
458 			(unsigned long)Tmp_win,
459 			Tmp_win->icon_x_loc,
460 			Tmp_win->icon_y_loc,
461 			Tmp_win->icon_p_width,
462 			Tmp_win->icon_p_height);
463 	      BroadcastConfig(M_CONFIGURE_WINDOW,Tmp_win);
464 
465 	      if (!(Tmp_win->flags & SUPPRESSICON))
466 		{
467 		  LowerWindow(Tmp_win);
468 		  AutoPlace(Tmp_win);
469 		  if(Tmp_win->Desk == Scr.CurrentDesk)
470 		    {
471 		      if(Tmp_win->icon_pixmap_w != None)
472 			XMapWindow(dpy, Tmp_win->icon_pixmap_w);
473 		    }
474 		}
475 	      Tmp_win->flags |= ICONIFIED;
476 	      DrawIconWindow(Tmp_win);
477 	    }
478 	}
479       break;
480 
481     case XA_WM_NORMAL_HINTS:
482       GetWindowSizeHints (Tmp_win);
483       BroadcastConfig(M_CONFIGURE_WINDOW,Tmp_win);
484       break;
485 
486     default:
487       if(Event.xproperty.atom == _XA_WM_PROTOCOLS)
488 	FetchWmProtocols (Tmp_win);
489       else if (Event.xproperty.atom == _XA_WM_COLORMAP_WINDOWS)
490 	{
491 	  FetchWmColormapWindows (Tmp_win);	/* frees old data */
492 	  ReInstallActiveColormap();
493 	}
494       else if(Event.xproperty.atom == _XA_WM_STATE)
495 	{
496 	  if((Scr.flags & ClickToFocus)&&(Tmp_win == Scr.Focus)&&
497 	     (Tmp_win != NULL))
498 	    {
499 	      Scr.Focus = NULL;
500 	      SetFocus(Tmp_win->w,Tmp_win,False);
501 	    }
502 	}
503       break;
504     }
505 }
506 
507 
508 /***********************************************************************
509  *
510  *  Procedure:
511  *	HandleClientMessage - client message event handler
512  *
513  ************************************************************************/
HandleClientMessage()514 void HandleClientMessage()
515 {
516   XEvent button;
517 
518   if ((Event.xclient.message_type == _XA_WM_CHANGE_STATE)&&
519       (Tmp_win)&&(Event.xclient.data.l[0]==IconicState)&&
520       !(Tmp_win->flags & ICONIFIED))
521     {
522       XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild,
523 		    &(button.xmotion.x_root),
524 		    &(button.xmotion.y_root),
525 		    &JunkX, &JunkY, &JunkMask);
526       button.type = 0;
527       ExecuteFunction(F_ICONIFY, NULLSTR, Event.xany.window,
528 		      Tmp_win, &button, C_FRAME,0,0, 0,0,
529 		      (MenuRoot *)0,-1);
530 #ifdef ENABLE_DND
531 	/* Pass the event to the client window */
532 	if (Event.xclient.window != Tmp_win->w)
533 	{
534 	    Event.xclient.window = Tmp_win->w;
535 	    XSendEvent(dpy,Tmp_win->w,True,NoEventMask,&Event);
536 	}
537 #endif
538     }
539 }
540 
541 /***********************************************************************
542  *
543  *  Procedure:
544  *	HandleExpose - expose event handler
545  *
546  ***********************************************************************/
HandleExpose()547 void HandleExpose()
548 {
549   if (Event.xexpose.count != 0)
550     return;
551 
552   if (Tmp_win)
553     {
554 #ifndef NO_PAGER
555       if((Tmp_win->w == Scr.Pager_w)||
556 	 (Tmp_win->w == Scr.CPagerWin))
557 	{
558 	  ReallyRedrawPager();
559 	}
560 #endif
561       if (Event.xany.window == Tmp_win->title_w)
562 	{
563 	  SetTitleBar(Tmp_win,(Scr.Hilite == Tmp_win),False);
564 	}
565       else
566 	{
567 	  SetBorder(Tmp_win,(Scr.Hilite == Tmp_win),True,True,Event.xany.window);
568 	}
569     }
570 #ifndef NO_PAGER
571   else
572     {
573       if(FindCounterpart(Event.xany.window))
574 	ReallyRedrawPager();
575     }
576 #endif
577   return;
578 }
579 
580 
581 
582 /***********************************************************************
583  *
584  *  Procedure:
585  *	HandleDestroyNotify - DestroyNotify event handler
586  *
587  ***********************************************************************/
HandleDestroyNotify()588 void HandleDestroyNotify()
589 {
590   if (Tmp_win) {
591     Destroy(Tmp_win);
592     UpdateVisibility();
593   }
594 }
595 
596 
597 
598 
599 /***********************************************************************
600  *
601  *  Procedure:
602  *	HandleMapRequest - MapRequest event handler
603  *
604  ************************************************************************/
HandleMapRequest()605 void HandleMapRequest()
606 {
607   extern long isIconicState;
608 
609   Event.xany.window = Event.xmaprequest.window;
610 
611   if(XFindContext(dpy, Event.xany.window, ASContext,
612 		  (caddr_t *)&Tmp_win)==XCNOENT)
613     Tmp_win = NULL;
614 
615   XFlush(dpy);
616 
617   /* If the window has never been mapped before ... */
618   if(!Tmp_win)
619     {
620       /* Add decorations. */
621       Tmp_win = AddWindow(Event.xany.window);
622       if (Tmp_win == NULL)
623 	return;
624     }
625 
626   /* If it's not merely iconified, and we have hints, use them. */
627   if (!(Tmp_win->flags & ICONIFIED))
628     {
629       int state;
630 
631       if(Tmp_win->wmhints && (Tmp_win->wmhints->flags & StateHint))
632 	state = Tmp_win->wmhints->initial_state;
633       else
634 	state = NormalState;
635 
636       if(Tmp_win->flags & STARTICONIC)
637 	state = IconicState;
638 
639       if(isIconicState != DontCareState)
640 	state = isIconicState;
641 
642       XGrabServer (dpy);
643       switch (state)
644 	{
645 	case DontCareState:
646 	case NormalState:
647 	case InactiveState:
648 	default:
649 	  if (Tmp_win->Desk == Scr.CurrentDesk)
650 	    {
651 	      XMapWindow(dpy, Tmp_win->w);
652 	      XMapWindow(dpy, Tmp_win->frame);
653 	      Tmp_win->flags |= MAP_PENDING;
654 	      SetMapStateProp(Tmp_win, NormalState);
655 	      if(Scr.flags & ClickToFocus)
656 		{
657 		  SetFocus(Tmp_win->w,Tmp_win,False);
658 		}
659 	    }
660 	  else
661 	    {
662 	      XMapWindow(dpy, Tmp_win->w);
663 	      SetMapStateProp(Tmp_win, NormalState);
664 	    }
665 	  break;
666 
667 	case IconicState:
668 	  Iconify(Tmp_win, 0, 0);
669 	  break;
670 
671 	case ZoomState:
672 	  Shade(Tmp_win);
673 	  break;
674 	}
675       XSync(dpy,0);
676       XUngrabServer(dpy);
677     }
678   /* If no hints, or currently an icon, just "deiconify" */
679   else
680     {
681       DeIconify(Tmp_win);
682     }
683 }
684 
685 
686 /***********************************************************************
687  *
688  *  Procedure:
689  *	HandleMapNotify - MapNotify event handler
690  *
691  ***********************************************************************/
HandleMapNotify()692 void HandleMapNotify()
693 {
694   if (!Tmp_win || (Event.xmap.event == Scr.ASRoot.w))
695     {
696       return;
697     }
698 
699   /*
700    * Need to do the grab to avoid race condition of having server send
701    * MapNotify to client before the frame gets mapped; this is bad because
702    * the client would think that the window has a chance of being viewable
703    * when it really isn't.
704    */
705   XGrabServer (dpy);
706   if(Tmp_win->icon_pixmap_w != None)
707     XUnmapWindow(dpy, Tmp_win->icon_pixmap_w);
708   XMapSubwindows(dpy, Tmp_win->frame);
709 
710   if(Tmp_win->Desk == Scr.CurrentDesk)
711     {
712       XMapWindow(dpy, Tmp_win->frame);
713     }
714 
715   if(Tmp_win->flags & ICONIFIED)
716     Broadcast(M_DEICONIFY,3,Tmp_win->w,Tmp_win->frame,
717 	      (unsigned long)Tmp_win,0,0,0,0);
718   else
719     {
720       Broadcast(M_MAP,3,Tmp_win->w,Tmp_win->frame,
721 		(unsigned long)Tmp_win,0,0,0,0);
722     }
723 
724   if(Scr.flags & ClickToFocus)
725       SetFocus(Tmp_win->w,Tmp_win,False);
726 
727   if((!(Tmp_win->flags &(BORDER|TITLE)))&&(Tmp_win->boundary_width <2))
728     {
729       SetBorder(Tmp_win,False,True,True,Tmp_win->frame);
730     }
731   XSync(dpy,0);
732   XUngrabServer (dpy);
733   XFlush (dpy);
734   Tmp_win->flags |= MAPPED;
735   Tmp_win->flags &= ~MAP_PENDING;
736   Tmp_win->flags &= ~ICONIFIED;
737   Tmp_win->flags &= ~ICON_UNMAPPED;
738   UpdateVisibility();
739 }
740 
741 
742 /***********************************************************************
743  *
744  *  Procedure:
745  *	HandleUnmapNotify - UnmapNotify event handler
746  *
747  ************************************************************************/
HandleUnmapNotify()748 void HandleUnmapNotify()
749 {
750   int dstx, dsty;
751   Window dumwin;
752   XEvent dummy;
753   extern ASWindow *colormap_win;
754 
755   /*
756    * The July 27, 1988 ICCCM spec states that a client wishing to switch
757    * to WithdrawnState should send a synthetic UnmapNotify with the
758    * event field set to (pseudo-)root, in case the window is already
759    * unmapped (which is the case for afterstep for IconicState).  Unfortunately,
760    * we looked for the ASContext using that field, so try the window
761    * field also.
762    */
763   if (!Tmp_win)
764     {
765       Event.xany.window = Event.xunmap.window;
766       if (XFindContext(dpy, Event.xany.window,
767 		       ASContext, (caddr_t *)&Tmp_win) == XCNOENT)
768 	Tmp_win = NULL;
769     }
770 
771   if (Event.xunmap.event == Scr.ASRoot.w) return;
772 
773   if(!Tmp_win)
774     return;
775 
776   if(Tmp_win ==  Scr.Hilite)
777     Scr.Hilite = NULL;
778 
779   if(Scr.PreviousFocus == Tmp_win)
780     Scr.PreviousFocus = NULL;
781 
782   if((Tmp_win == Scr.Focus)&&(Scr.flags & ClickToFocus))
783     {
784       ASWindow *t, *tn = NULL;
785       long best = LONG_MIN;
786       for (t = Scr.ASRoot.next; t != NULL; t = t->next)
787         {
788 	  if ((t->focus_sequence > best) && (t != Tmp_win))
789 	    {
790 	      best = t->focus_sequence;
791 	      tn = t;
792 	    }
793 	}
794       if (tn)
795 	SetFocus(tn->w, tn, False);
796       else
797 	SetFocus(Scr.NoFocusWin, NULL, False);
798     }
799 
800   if(Scr.Focus == Tmp_win)
801     SetFocus(Scr.NoFocusWin, NULL, False);
802 
803   if(Tmp_win == Scr.pushed_window)
804     Scr.pushed_window = NULL;
805 
806   if(Tmp_win == colormap_win)
807     colormap_win = NULL;
808 
809   if ((!(Tmp_win->flags & MAPPED)&&!(Tmp_win->flags&ICONIFIED)))
810     {
811       return;
812     }
813 
814   XGrabServer(dpy);
815 
816   if(XCheckTypedWindowEvent (dpy, Event.xunmap.window, DestroyNotify,&dummy))
817     {
818       Destroy(Tmp_win);
819       XUngrabServer (dpy);
820       UpdateVisibility();
821       return;
822     }
823 
824   /*
825    * The program may have unmapped the client window, from either
826    * NormalState or IconicState.  Handle the transition to WithdrawnState.
827    *
828    * We need to reparent the window back to the root (so that afterstep exiting
829    * won't cause it to get mapped) and then throw away all state (pretend
830    * that we've received a DestroyNotify).
831    */
832   if (XTranslateCoordinates (dpy, Event.xunmap.window, Scr.Root,
833 			     0, 0, &dstx, &dsty, &dumwin))
834     {
835       XEvent ev;
836       Bool reparented;
837 
838       reparented = XCheckTypedWindowEvent (dpy, Event.xunmap.window,
839 					   ReparentNotify, &ev);
840       SetMapStateProp (Tmp_win, WithdrawnState);
841       if (reparented)
842 	{
843 	  if (Tmp_win->old_bw)
844 	    XSetWindowBorderWidth (dpy, Event.xunmap.window, Tmp_win->old_bw);
845 	  if((!(Tmp_win->flags & SUPPRESSICON))&&
846 	     (Tmp_win->wmhints && (Tmp_win->wmhints->flags & IconWindowHint)))
847 	    XUnmapWindow (dpy, Tmp_win->wmhints->icon_window);
848 	}
849       else
850 	{
851 	  RestoreWithdrawnLocation (Tmp_win,False);
852 	}
853       XRemoveFromSaveSet (dpy, Event.xunmap.window);
854       XSelectInput (dpy, Event.xunmap.window, NoEventMask);
855       Destroy(Tmp_win);		/* do not need to mash event before */
856       /*
857        * Flush any pending events for the window.
858        */
859       /* Bzzt! it could be about to re-map */
860 /*      while(XCheckWindowEvent(dpy, Event.xunmap.window,
861 			      StructureNotifyMask | PropertyChangeMask |
862 			      ColormapChangeMask |
863 			      EnterWindowMask | LeaveWindowMask, &dummy));
864       */
865     } /* else window no longer exists and we'll get a destroy notify */
866   XUngrabServer (dpy);
867   UpdateVisibility();
868   XFlush (dpy);
869 }
870 
871 
872 /***********************************************************************
873  *
874  *  Procedure:
875  *	HandleMotionNotify - MotionNotify event handler
876  *
877  **********************************************************************/
HandleMotionNotify()878 void HandleMotionNotify()
879 {
880 #ifndef NO_PAGER
881   extern Bool EnablePagerRedraw;
882 
883   /* here is the code for dragging the viewport around within the pager.*/
884   if((Tmp_win)&&(Tmp_win->w == Scr.Pager_w)&&
885      (!(Tmp_win->flags & ICONIFIED)))
886     {
887       if(Event.xmotion.state == Button3MotionMask)
888 	{
889 	  EnablePagerRedraw = False;
890 	  SwitchPages(FALSE,FALSE);
891 	}
892     }
893 #endif
894 }
895 
896 /***********************************************************************
897  *
898  *  Procedure:
899  *	HandleButtonPress - ButtonPress event handler
900  *
901  ***********************************************************************/
HandleButtonPress()902 void HandleButtonPress()
903 {
904 #ifndef NO_PAGER
905   extern Bool EnablePagerRedraw;
906 #endif
907   unsigned int modifier;
908   MouseButton *MouseEntry;
909   char *Action;
910   Window xPressedW;
911   int LocalContext;
912 
913   Context = GetContext(Tmp_win,&Event, &PressedW);
914   LocalContext = Context;
915   xPressedW= PressedW;
916 
917   /* click to focus stuff goes here */
918   if (Scr.flags & ClickToFocus)
919     {
920       if (Tmp_win && (Tmp_win != Scr.Ungrabbed)
921 	  && ((Event.xbutton.state & Scr.nonlock_mods) == 0))
922         {
923 	  Bool focusAccepted = SetFocus(Tmp_win->w,Tmp_win,False);
924 
925 	  if (! (Tmp_win->flags & VISIBLE))
926 	    {
927 	      if ((Scr.flags & ClickToRaise) && (Context == C_WINDOW)
928 		  && (Scr.RaiseButtons & (1<<Event.xbutton.button)))
929 		 RaiseWindow(Tmp_win);
930 	      else
931 	        {
932 		  if(Scr.AutoRaiseDelay > 0)
933 		    {
934 		      SetTimer(Scr.AutoRaiseDelay);
935 		    }
936 		  else
937 		    {
938 #ifdef CLICKY_MODE_1
939 		      if((Event.xany.window != Tmp_win->w)&&
940 			 (Event.xbutton.subwindow != Tmp_win->w)&&
941 			 (Event.xany.window != Tmp_win->Parent)&&
942 			 (Event.xbutton.subwindow != Tmp_win->Parent))
943 #endif
944 		        {
945 			  if(Scr.AutoRaiseDelay == 0)
946 			      RaiseWindow(Tmp_win);
947 			}
948 		    }
949 		}
950 	    }
951 	  if(!(Tmp_win->flags & ICONIFIED) && focusAccepted)
952 	    {
953 	      XSync(dpy,0);
954 	      if ((Scr.flags & EatFocusClick) && (Context == C_WINDOW))
955 		  XAllowEvents(dpy, AsyncPointer, CurrentTime);
956 	      else
957 		  XAllowEvents(dpy,ReplayPointer,CurrentTime);
958 
959 	      XSync(dpy,0);
960 	      return;
961 	    }
962 	}
963     }
964   else if((Scr.flags & ClickToRaise) && Tmp_win && (Context == C_WINDOW)
965           && (Scr.RaiseButtons & (1<<Event.xbutton.button))
966           && ((Event.xbutton.state & Scr.nonlock_mods) == 0)
967           && ((Tmp_win->flags & VISIBLE) == 0))
968    {
969          RaiseWindow(Tmp_win);
970          if(!(Tmp_win->flags & ICONIFIED))
971            {
972              XSync(dpy,0);
973              XAllowEvents(dpy,AsyncPointer,CurrentTime);
974              XSync(dpy,0);
975              return;
976            }
977    }
978   XSync(dpy,0);
979   XAllowEvents(dpy, (Context == C_WINDOW) ? ReplayPointer : AsyncPointer,
980 	       CurrentTime);
981   XSync(dpy,0);
982 
983   /* here is the code for moving windows in the pager.*/
984 #ifndef NO_PAGER
985   if((Tmp_win)&&(Tmp_win->w == Event.xbutton.window)&&
986      (Tmp_win->w == Scr.Pager_w)&&(Event.xbutton.button == Button2))
987     {
988       PagerMoveWindow();
989       return;
990     }
991   if((Tmp_win)&&(Tmp_win->w == Scr.Pager_w)&&
992      (!(Tmp_win->flags & ICONIFIED))&&
993      (Event.xbutton.button == Button3)&&
994      (Event.xany.window == Scr.Pager_w))
995     {
996 #ifndef NO_PAGER
997       EnablePagerRedraw = False;
998 #endif
999       SwitchPages(FALSE,FALSE);
1000     }
1001 #endif
1002 
1003   if(Context == C_TITLE)
1004     SetTitleBar(Tmp_win,(Scr.Hilite == Tmp_win),False);
1005   else
1006     SetBorder(Tmp_win,(Scr.Hilite == Tmp_win),True,True,PressedW);
1007 
1008   ButtonWindow = Tmp_win;
1009 
1010   /* we have to execute a function or pop up a menu
1011    */
1012 
1013   modifier = (Event.xbutton.state & Scr.nonlock_mods);
1014   /* need to search for an appropriate mouse binding */
1015   MouseEntry = Scr.MouseButtonRoot;
1016   while(MouseEntry != (MouseButton *)0)
1017     {
1018       if(((MouseEntry->Button == Event.xbutton.button)||(MouseEntry->Button == 0))&&
1019 	 (MouseEntry->Context & Context)&&
1020 	 ((MouseEntry->Modifier == AnyModifier)||
1021 	  (MouseEntry->Modifier == modifier)))
1022 	{
1023 	  /* got a match, now process it */
1024 	  if (MouseEntry->func != (int)NULL)
1025  	    {
1026 	      Action = MouseEntry->item ? MouseEntry->item->action : NULL;
1027 	      ExecuteFunction(MouseEntry->func, Action, Event.xany.window,
1028 			      Tmp_win, &Event, Context,MouseEntry->val1,
1029 			      MouseEntry->val2,
1030 			      MouseEntry->val1_unit,MouseEntry->val2_unit,
1031 			      MouseEntry->menu,-1);
1032 	      break;
1033 	    }
1034 	}
1035       MouseEntry = MouseEntry->NextButton;
1036     }
1037   PressedW = None;
1038 
1039   if(LocalContext!=C_TITLE)
1040     SetBorder(ButtonWindow,(Scr.Hilite == ButtonWindow),True,True,xPressedW);
1041   else
1042     SetTitleBar(ButtonWindow,(Scr.Hilite==ButtonWindow),False);
1043 
1044   ButtonWindow = NULL;
1045 }
1046 
1047 /***********************************************************************
1048  *
1049  *  Procedure:
1050  *	HandleButtonRelease - ButtonRelease event handler
1051  *
1052  ***********************************************************************/
HandleButtonRelease()1053 void HandleButtonRelease()
1054 {
1055 #ifndef NO_PAGER
1056   extern Bool EnablePagerRedraw;
1057   if((Tmp_win)&&(Event.xany.window == Scr.Pager_w)&&
1058      (!(Tmp_win->flags & ICONIFIED)))
1059     {
1060       switch(Event.xbutton.button)
1061 	{
1062 	default:
1063 	case Button1:
1064 	  SwitchPages(TRUE,TRUE);
1065 	  break;
1066 	case Button3:
1067 	  EnablePagerRedraw = True;
1068 	  SwitchPages(FALSE,FALSE);
1069 	  RedrawPager();
1070 	  break;
1071 	}
1072     }
1073 #endif
1074 }
1075 
1076 
1077 /***********************************************************************
1078  *
1079  *  Procedure:
1080  *	HandleEnterNotify - EnterNotify event handler
1081  *
1082  ************************************************************************/
HandleEnterNotify()1083 void HandleEnterNotify()
1084 {
1085   XEnterWindowEvent *ewp = &Event.xcrossing;
1086   XEvent d;
1087 
1088   /* look for a matching leaveNotify which would nullify this enterNotify */
1089   if(XCheckTypedWindowEvent (dpy, ewp->window, LeaveNotify, &d))
1090     {
1091       StashEventTime(&d);
1092       if((d.xcrossing.mode==NotifyNormal)&&
1093 	 (d.xcrossing.detail!=NotifyInferior))
1094 	return;
1095     }
1096 
1097 /* an EnterEvent in one of the PanFrameWindows activates the Paging */
1098 #ifndef NON_VIRTUAL
1099   if (ewp->window==Scr.PanFrameTop.win
1100       || ewp->window==Scr.PanFrameLeft.win
1101       || ewp->window==Scr.PanFrameRight.win
1102       || ewp->window==Scr.PanFrameBottom.win )
1103     {
1104       int delta_x=0, delta_y=0;
1105       /* this was in the HandleMotionNotify before, HEDU */
1106       HandlePaging(Scr.EdgeScrollX,Scr.EdgeScrollY,
1107                    &Event.xcrossing.x_root,&Event.xcrossing.y_root,
1108                    &delta_x,&delta_y,True);
1109       return;
1110     }
1111 #endif /* NON_VIRTUAL */
1112 
1113   if(Event.xany.window == Scr.Root)
1114     {
1115       if((!(Scr.flags & ClickToFocus))&&(!(Scr.flags & SloppyFocus)))
1116 	{
1117 	  SetFocus(Scr.NoFocusWin,NULL,False);
1118 	}
1119       InstallWindowColormaps(NULL);
1120       return;
1121     }
1122 
1123   /* make sure its for one of our windows */
1124   if (!Tmp_win)
1125     return;
1126 
1127 if (Tmp_win->focus_var == 0)
1128 {
1129   if(!(Scr.flags & ClickToFocus))
1130     {
1131       if(Scr.Focus != Tmp_win)
1132 	{
1133 	  if((Scr.AutoRaiseDelay > 0)&&(!(Tmp_win->flags & VISIBLE)))
1134 	    SetTimer(Scr.AutoRaiseDelay);
1135 	  SetFocus(Tmp_win->w,Tmp_win,False);
1136 	}
1137       else
1138 	SetFocus(Tmp_win->w,Tmp_win, True);  /* don't affect the circ.seq. */
1139     }
1140   if((!(Tmp_win->flags & ICONIFIED))&&(Event.xany.window == Tmp_win->w))
1141     InstallWindowColormaps(Tmp_win);
1142   else
1143     InstallWindowColormaps(NULL);
1144 }
1145   return;
1146 }
1147 
1148 
1149 /***********************************************************************
1150  *
1151  *  Procedure:
1152  *	HandleLeaveNotify - LeaveNotify event handler
1153  *
1154  ************************************************************************/
HandleLeaveNotify()1155 void HandleLeaveNotify()
1156 {
1157   /* If we leave the root window, then we're really moving
1158    * another screen on a multiple screen display, and we
1159    * need to de-focus and unhighlight to make sure that we
1160    * don't end up with more than one highlighted window at a time */
1161   if(Event.xcrossing.window == Scr.Root)
1162     {
1163       if(Event.xcrossing.mode == NotifyNormal)
1164 	{
1165 	  if (Event.xcrossing.detail != NotifyInferior)
1166 	    {
1167 	      if(Scr.Focus != NULL)
1168 		{
1169 		  SetFocus(Scr.NoFocusWin,NULL,False);
1170 		}
1171 	      if(Scr.Hilite != NULL)
1172 		SetBorder(Scr.Hilite,False,True,True,None);
1173 	    }
1174 	}
1175     }
1176 }
1177 
1178 
1179 /***********************************************************************
1180  *
1181  *  Procedure:
1182  *	HandleConfigureRequest - ConfigureRequest event handler
1183  *
1184  ************************************************************************/
HandleConfigureRequest()1185 void HandleConfigureRequest()
1186 {
1187   XWindowChanges xwc;
1188   unsigned long xwcm;
1189   int x, y, width, height;
1190   XConfigureRequestEvent *cre = &Event.xconfigurerequest;
1191 
1192   /*
1193    * Event.xany.window is Event.xconfigurerequest.parent, so Tmp_win will
1194    * be wrong
1195    */
1196   Event.xany.window = cre->window;	/* mash parent field */
1197   if (XFindContext (dpy, cre->window, ASContext, (caddr_t *) &Tmp_win) ==
1198       XCNOENT)
1199     Tmp_win = NULL;
1200 
1201   /*
1202    * According to the July 27, 1988 ICCCM draft, we should ignore size and
1203    * position fields in the WM_NORMAL_HINTS property when we map a window.
1204    * Instead, we'll read the current geometry.  Therefore, we should respond
1205    * to configuration requests for windows which have never been mapped.
1206    */
1207   if (!Tmp_win )
1208     {
1209       xwcm = cre->value_mask &
1210 	(CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
1211       xwc.x = cre->x;
1212       xwc.y = cre->y;
1213       xwc.width = cre->width;
1214       xwc.height = cre->height;
1215       xwc.border_width = cre->border_width;
1216       XConfigureWindow(dpy, Event.xany.window, xwcm, &xwc);
1217 
1218       if(Tmp_win)
1219 	{
1220 	  xwc.x = Tmp_win->icon_x_loc;
1221 	  xwc.y = Tmp_win->icon_y_loc - Tmp_win->icon_p_height;
1222 	  xwcm = cre->value_mask & (CWX | CWY);
1223 	  if(Tmp_win->icon_pixmap_w != None)
1224 	    XConfigureWindow(dpy, Tmp_win->icon_pixmap_w, xwcm, &xwc);
1225 	  xwc.x = Tmp_win->icon_x_loc;
1226 	  xwc.y = Tmp_win->icon_y_loc;
1227 	  xwcm = cre->value_mask & (CWX | CWY);
1228 	}
1229       return;
1230     }
1231 
1232   if (cre->value_mask & CWStackMode)
1233     {
1234       ASWindow *otherwin;
1235 
1236       xwc.sibling = (((cre->value_mask & CWSibling) &&
1237 		      (XFindContext (dpy, cre->above, ASContext,
1238 				     (caddr_t *) &otherwin) == XCSUCCESS))
1239 		     ? otherwin->frame : cre->above);
1240       xwc.stack_mode = cre->detail;
1241       XConfigureWindow (dpy, Tmp_win->frame,
1242 			cre->value_mask & (CWSibling | CWStackMode), &xwc);
1243       XSync(dpy, False);
1244       CorrectStackOrder();
1245     }
1246 
1247 #ifdef SHAPE
1248   {
1249     int xws, yws, xbs, ybs;
1250     unsigned wws, hws, wbs, hbs;
1251     int boundingShaped, clipShaped;
1252 
1253     XShapeQueryExtents (dpy, Tmp_win->w,&boundingShaped, &xws, &yws, &wws,
1254 			&hws,&clipShaped, &xbs, &ybs, &wbs, &hbs);
1255     Tmp_win->wShaped = boundingShaped;
1256   }
1257 #endif /* SHAPE */
1258 
1259   /* Don't modify frame_XXX fields before calling SetupWindow! */
1260   x = Tmp_win->frame_x;
1261   y = Tmp_win->frame_y;
1262   width = Tmp_win->frame_width;
1263   height = Tmp_win->frame_height;
1264 
1265   /* for restoring */
1266   if (cre->value_mask & CWBorderWidth)
1267     {
1268       Tmp_win->old_bw = cre->border_width;
1269     }
1270   /* override even if border change */
1271 
1272   if (cre->value_mask & CWX)
1273     x = cre->x - Tmp_win->boundary_width - Tmp_win->bw;
1274   if (cre->value_mask & CWY)
1275     y = cre->y - Tmp_win->title_height - Tmp_win->bw;
1276   if (cre->value_mask & CWWidth)
1277     width = cre->width + 2*Tmp_win->boundary_width;
1278   if (cre->value_mask & CWHeight)
1279     height = cre->height+Tmp_win->title_height+Tmp_win->boundary_height;
1280 
1281   /*
1282    * SetupWindow (x,y) are the location of the upper-left outer corner and
1283    * are passed directly to XMoveResizeWindow (frame).  The (width,height)
1284    * are the inner size of the frame.  The inner width is the same as the
1285    * requested client window width; the inner height is the same as the
1286    * requested client window height plus any title bar slop.
1287    */
1288   SetupFrame (Tmp_win, x, y, width, height,FALSE);
1289   UpdateVisibility();
1290 
1291 #ifndef NO_PAGER
1292   RedrawPager();
1293 #endif
1294 }
1295 
1296 /***********************************************************************
1297  *
1298  *  Procedure:
1299  *      HandleShapeNotify - shape notification event handler
1300  *
1301  ***********************************************************************/
1302 #ifdef SHAPE
HandleShapeNotify(void)1303 void HandleShapeNotify (void)
1304 {
1305   XShapeEvent *sev = (XShapeEvent *) &Event;
1306 
1307   if (!Tmp_win)
1308     return;
1309   if (sev->kind != ShapeBounding)
1310     return;
1311   Tmp_win->wShaped = sev->shaped;
1312   SetShape(Tmp_win,Tmp_win->frame_width);
1313 }
1314 #endif  /* SHAPE*/
1315 
1316 /**************************************************************************
1317  *
1318  * For auto-raising windows, this routine is called
1319  *
1320  *************************************************************************/
1321 volatile int alarmed;
enterAlarm(int nonsense)1322 void enterAlarm(int nonsense)
1323 {
1324   alarmed = True;
1325   signal(SIGALRM, enterAlarm);
1326 }
1327 
1328 
1329 /***************************************************************************
1330  *
1331  * Waits for next X event, or for an auto-raise timeout.
1332  *
1333  ****************************************************************************/
My_XNextEvent(Display * dpy,XEvent * event)1334 int My_XNextEvent(Display *dpy, XEvent *event)
1335 {
1336   extern int fd_width, x_fd;
1337   struct itimerval value;
1338   fd_set in_fdset,out_fdset;
1339   Window child;
1340   Window targetWindow;
1341   int i,count;
1342   int retval;
1343 
1344   /* Do this prior to the select() call, in case the timer already expired,
1345    * in which case the select would never return. */
1346   if(alarmed)
1347     {
1348       alarmed = False;
1349       XQueryPointer(dpy,Scr.Root,&JunkRoot,&child,&JunkX,&JunkY,&JunkX,
1350 		    &JunkY,&JunkMask );
1351       if((Scr.Focus != NULL)&&(child == Scr.Focus->frame))
1352 	{
1353 	  if(!(Scr.Focus->flags & VISIBLE))
1354 	    {
1355 	      RaiseWindow(Scr.Focus);
1356 #ifndef NO_PAGER
1357 	      RedrawPager();
1358 #endif
1359 	    }
1360 	}
1361       return 0;
1362     }
1363 
1364 #ifndef HAVE_GETITIMER
1365   value.it_value.tv_usec = 0;
1366   value.it_value.tv_sec = 0;
1367 #else
1368   getitimer(ITIMER_REAL,&value);
1369 #endif
1370 
1371   FD_ZERO(&in_fdset);
1372   FD_SET(x_fd,&in_fdset);
1373   FD_ZERO(&out_fdset);
1374   for(i=0; i<npipes; i++)
1375     {
1376       if(readPipes[i]>=0)
1377 	{
1378 	  FD_SET(readPipes[i], &in_fdset);
1379 	}
1380     }
1381 
1382   for(i=0; i<npipes; i++)
1383     {
1384       if(pipeQueue[i]!= NULL)
1385 	{
1386 	  FD_SET(writePipes[i], &out_fdset);
1387 	}
1388     }
1389 
1390 
1391   /* Do this IMMEDIATELY prior to select, to prevent any nasty
1392    * queued up X events from just hanging around waiting to be
1393    * flushed */
1394   XFlush(dpy);
1395   if(XPending(dpy))
1396     {
1397       XNextEvent(dpy,event);
1398       StashEventTime(event);
1399       return 1;
1400     }
1401 
1402   /* Zap all those zombies! */
1403   /* If we get to here, then there are no X events waiting to be processed.
1404    * Just take a moment to check for dead children. */
1405   ReapChildren();
1406 
1407   XFlush(dpy);
1408   if((value.it_value.tv_usec != 0)||
1409      (value.it_value.tv_sec != 0))
1410 #ifdef __hpux
1411     retval=select(fd_width,(int *)&in_fdset, 0, 0, &value.it_value);
1412 #else
1413     retval=select(fd_width,&in_fdset, 0, 0, &value.it_value);
1414 #endif
1415   else
1416 #ifdef __hpux
1417     retval=select(fd_width,(int *)&in_fdset, (int *)&out_fdset,
1418 		  0, NULL);
1419 #else
1420     retval=select(fd_width,&in_fdset, &out_fdset, 0, NULL);
1421 #endif
1422 
1423   /* Check for module input. */
1424   for(i=0;i<npipes;i++)
1425     {
1426       if(readPipes[i] >= 0)
1427 	{
1428 	  if((retval>0)&&(FD_ISSET(readPipes[i], &in_fdset)))
1429 	    {
1430 	      if((count =
1431 		  read(readPipes[i],&targetWindow, sizeof(Window))) >0)
1432 		{
1433 		  HandleModuleInput(targetWindow,i);
1434 		}
1435 	      if(count <= 0)
1436 		{
1437 		  KillModule(i,10);
1438 		}
1439 	    }
1440 	}
1441       if(writePipes[i] >= 0)
1442 	{
1443 	  if((retval>0)&&(FD_ISSET(writePipes[i], &out_fdset)))
1444 	    {
1445 	      FlushQueue(i);
1446 	    }
1447 	}
1448     }
1449   return 0;
1450 }
1451 
1452 	/* Change the icon, bugs for that to wiz@iol.it */
ChangeIcon()1453 void ChangeIcon()
1454 {
1455 	char *cp;
1456 	if (!(Tmp_win->flags & SUPPRESSICON) && (Tmp_win->flags & ICON_OURS)) {
1457 		SearchIcon(Tmp_win,&cp);
1458 		if(cp && !( Tmp_win->icon_bitmap_file && cp == Tmp_win->icon_bitmap_file ))
1459 			Tmp_win->icon_bitmap_file=cp;
1460 		else
1461 			return;
1462 	}
1463 	GetIcon(Tmp_win);
1464 	DrawIconWindow(Tmp_win);
1465 }
1466 
SearchIcon(ASWindow * tmp_win,char ** value)1467 void SearchIcon(ASWindow *tmp_win, char**value)
1468 {
1469 	name_list *nptr=Scr.TheList;
1470 	*value = NULL;
1471 		/* Start from the last element, because we are looking for
1472 		   an icon name and it is the last match that should win,
1473 		   I think better to start from the end of the list...;)
1474 		   */
1475 
1476 	if(!nptr)
1477 		return;
1478 	nptr=nptr->prev;
1479 	do{
1480 		if(nptr->value){
1481 			if (matchWildcards(nptr->name,tmp_win->icon_name) == TRUE){
1482 				*value = nptr->value;
1483 				return;
1484 			}
1485 			if (matchWildcards(nptr->name,tmp_win->name) == TRUE){
1486 				*value = nptr->value;
1487 				return;
1488 			}
1489 			if (matchWildcards(nptr->name,tmp_win->class.res_name) == TRUE ){
1490 				*value = nptr->value;
1491 				return;
1492 			}
1493 			if (matchWildcards(nptr->name,tmp_win->class.res_class) == TRUE){
1494 				*value = nptr->value;
1495 				return;
1496 			}
1497 
1498 		}
1499 		nptr=nptr->prev;
1500 	} while(nptr != Scr.TheList);
1501 
1502 }
1503