[306] in Zephyr_Bugs

home help back first fref pref prev next nref lref last post

zwgc fix

daemon@ATHENA.MIT.EDU (Marc Horowitz)
Tue Aug 6 01:28:24 1991

To: bugs@ATHENA.MIT.EDU
Cc: testers@ATHENA.MIT.EDU, ckclark@ATHENA.MIT.EDU, jfc@ATHENA.MIT.EDU,
Reply-To: Marc Horowitz <marc@MIT.EDU>
Date: Tue, 06 Aug 91 01:28:20 EDT
From: Marc Horowitz <marc@ATHENA.MIT.EDU>

This patch fixes a previously known, but until now unfound core-dump
bug in zwgc.  Many of you have seen zwgc dump core when you paste from
it occasionally.  First, try this (7.2 or 7.3):

1) press shift
2) press a mouse button
3) drag
4) release mouse
5) release shift
6) paste

Now, that works fine.  Here's the bug:  reverse 4 and 5, and zwgc will
dump core when you do 6.  This is 100% reproducible.

The first patch below fixes a general problem, which is only a symptom
of the real bug.  The second patch fixes the real problem, which was
that zwgc was looking at the shift/control status on button release,
rather than remembering the state on button press.  I can demonstrate
some non-intuitive behavior which the old code caused if someone
wants, but it's hard to describe in email.  This patch really should
go into 7.3 if at all possible.  It is strictly bug-fixing, and does
not change any user-visible behavior (unless someone was using the bug
to quit zwgc :-).

		Marc

*** /mit/zephyr/src/zwgc/xselect.c	Sun Nov  4 10:52:30 1990
--- xselect.c	Tue Aug  6 00:36:44 1991
***************
*** 111,119 ****
     } else if (target==XA_STRING) {
        char *selected;
  
!       selected=getSelectedText();
! 
!       ChangeProp(XA_STRING,8,selected,string_Length(selected));
        XSync(dpy,0);
     }
  
--- 111,127 ----
     } else if (target==XA_STRING) {
        char *selected;
  
!       if (selected = getSelectedText()) {
! 	 ChangeProp(XA_STRING,8,selected,string_Length(selected));
!       } else {
! 	 /* This should only happen if the pasting client is out of
! 	    spec (or if this program is buggy), but it could happen */
! #ifdef DEBUG
! 	 fprintf(stderr,
! 		 "SelectionRequest event received for unowned selection: requestor wid=0x%x", w);
! #endif
! 	 ChangeProp(XA_STRING,8,"",0);
!       }
        XSync(dpy,0);
     }
  
*** /mit/zephyr/src/zwgc/xcut.c	Mon Oct 22 06:25:55 1990
--- xcut.c	Tue Aug  6 01:09:13 1991
***************
*** 133,142 ****
  }
  
  /* This is out here so xdestroygram can get at it */
-      
- static int current_window_in = -1;
- static int current_valid = False;
  
  void xdestroygram(dpy,w,desc_context,gram)
       Display *dpy;
       Window w;
--- 133,148 ----
  }
  
  /* This is out here so xdestroygram can get at it */
  
+ #define PRESSOP_NONE 0	/* nothing */
+ #define PRESSOP_KILL 1	/* normal click */
+ #define PRESSOP_SEL  2	/* shift left */
+ #define PRESSOP_EXT  3  /* shift right */
+ #define PRESSOP_NUKE 4	/* ctrl */
+ #define PRESSOP_STOP 5  /* pressop cancelled by moving out of window */
+ 
+ static int current_pressop = PRESSOP_NONE;
+ 
  void xdestroygram(dpy,w,desc_context,gram)
       Display *dpy;
       Window w;
***************
*** 156,163 ****
  	selecting_in = 0;
  	xmarkClear();
      }
!     current_window_in = -1;
!     current_valid = False;
      XDeleteContext(dpy, w, desc_context);
      XDestroyWindow(dpy, w);
      delete_gram(gram);
--- 162,168 ----
  	selecting_in = 0;
  	xmarkClear();
      }
!     current_pressop = PRESSOP_NONE;
      XDeleteContext(dpy, w, desc_context);
      XDestroyWindow(dpy, w);
      delete_gram(gram);
***************
*** 198,234 ****
  	}
  	break;
  
-      case LeaveNotify:
- 	if (event->xcrossing.window == current_window_in) {
- 	    current_valid = False;
- 	} else {
- 	    /* it left in an unusual way, so give up */
- 	    current_valid = False;
- 	    current_window_in = -1;
- 	}
- 	break;
- 
-      case MotionNotify:
-        if (w == selecting_in) {
- 	  if (event->xmotion.state==(ShiftMask|Button1Mask)) {
- 	     /*	  getLastEvent(dpy,Button1Mask,event); */
- 	     changedbound=xmarkExtendFromFirst(gram,event->xmotion.x,
- 					       event->xmotion.y);
- 	     xmarkRedraw(dpy,w,gram,changedbound);
- 	  } else if (event->xmotion.state==(ShiftMask|Button3Mask)) {
- 	     /*	  getLastEvent(dpy,Button3Mask,event); */
- 	     changedbound=xmarkExtendFromNearest(gram,event->xmotion.x,
- 						 event->xmotion.y);
- 	     xmarkRedraw(dpy,w,gram,changedbound);
- 	  } 
-        }
-        break;
- 
        case ButtonPress:
! 	if ( (event->xbutton.state)&ShiftMask ) {
  	   if (event->xbutton.button==Button1) {
  	      if (selecting_in)
! 		xunmark(dpy,selecting_in,NULL,desc_context);
  	      if (selected_text) free(selected_text);
  	      selected_text = NULL;
  	      if (! xselGetOwnership(dpy,w,event->xbutton.time)) {
--- 203,215 ----
  	}
  	break;
  
        case ButtonPress:
! 	if (current_pressop != PRESSOP_NONE) {
! 	   current_pressop = PRESSOP_STOP;
! 	} else if ( (event->xbutton.state)&ShiftMask ) {
  	   if (event->xbutton.button==Button1) {
  	      if (selecting_in)
! 		 xunmark(dpy,selecting_in,NULL,desc_context);
  	      if (selected_text) free(selected_text);
  	      selected_text = NULL;
  	      if (! xselGetOwnership(dpy,w,event->xbutton.time)) {
***************
*** 235,246 ****
  		 XBell(dpy,0);
  		 ERROR("Unable to get ownership of PRIMARY selection.\n");
  		 selecting_in = 0;
  	      } else {
  		 selecting_in = w;
  		 xmarkStart(gram,event->xbutton.x,event->xbutton.y);
  	      }
! 	   }
! 	   if ((event->xbutton.button==Button3) && (w == selecting_in)) {
  	      if (selected_text) free(selected_text);
  	      selected_text = NULL;
  	      changedbound=xmarkExtendFromNearest(gram,event->xbutton.x,
--- 216,229 ----
  		 XBell(dpy,0);
  		 ERROR("Unable to get ownership of PRIMARY selection.\n");
  		 selecting_in = 0;
+ 		 current_pressop = PRESSOP_STOP;
  	      } else {
  		 selecting_in = w;
  		 xmarkStart(gram,event->xbutton.x,event->xbutton.y);
+ 		 current_pressop = PRESSOP_SEL;
  	      }
! 	   } else if ((event->xbutton.button==Button3) &&
! 		      (w == selecting_in)) {
  	      if (selected_text) free(selected_text);
  	      selected_text = NULL;
  	      changedbound=xmarkExtendFromNearest(gram,event->xbutton.x,
***************
*** 247,288 ****
  						  event->xbutton.y);
  	      xmarkRedraw(dpy,w,gram,changedbound);
  	      selected_text = xmarkGetText();
  	   }
  	} else {
! 	   current_window_in = w;
! 	   current_valid = True;
  	}
  	break;
  
!       case ButtonRelease:
! 	if (w == current_window_in && 
! 	    current_valid &&
! 	    !((event->xbutton.state)&ShiftMask)) {
  
! 	    if ((event->xbutton.state)&ControlMask) {
! 		XWindowAttributes wa;
! 		int gx,gy;
! 		Window temp;
  
! 		for (gram = bottom_gram ; gram ; gram = gram->above) {
! 		    XGetWindowAttributes(dpy,gram->w,&wa);
! 		    XTranslateCoordinates(dpy,gram->w,wa.root,0,0,&gx,&gy,
! 					  &temp);
! 
! 		    if ((wa.map_state == IsViewable) &&
! 			(gx <= event->xbutton.x_root) &&
! 			(event->xbutton.x_root < gx+wa.width) &&
! 			(gy <= event->xbutton.y_root) &&
! 			(event->xbutton.y_root < gy+wa.height))
! 			xdestroygram(dpy,gram->w,desc_context,gram);
! 		}
! 	    } else {
! 		xdestroygram(dpy,w,desc_context,gram);
! 	    }
! 	} else if (w == selecting_in && ((event->xbutton.state)&ShiftMask)) {
  	   if (selected_text) free(selected_text);
  	   selected_text = xmarkGetText();
  	}
  	break;
  
       case SelectionRequest:
--- 230,291 ----
  						  event->xbutton.y);
  	      xmarkRedraw(dpy,w,gram,changedbound);
  	      selected_text = xmarkGetText();
+ 	      /* this is ok, since to get here, the selection must be owned */
+ 	      current_pressop = PRESSOP_EXT;
  	   }
+ 	} else if ( (event->xbutton.state)&ControlMask ) {
+ 	   current_pressop = PRESSOP_NUKE;
  	} else {
! 	   current_pressop = PRESSOP_KILL;
  	}
  	break;
  
!       case LeaveNotify:
! 	if (current_pressop == PRESSOP_KILL ||
! 	    current_pressop == PRESSOP_NUKE)
! 	   current_pressop = PRESSOP_STOP;
! 	break;
  
!       case MotionNotify:
! 	if (current_pressop == PRESSOP_SEL) {
! 	   /*	  getLastEvent(dpy,Button1Mask,event); */
! 	   changedbound=xmarkExtendFromFirst(gram,event->xmotion.x,
! 					     event->xmotion.y);
! 	   xmarkRedraw(dpy,w,gram,changedbound);
! 	} else if (current_pressop == PRESSOP_EXT) {
! 	   /*	  getLastEvent(dpy,Button3Mask,event); */
! 	   changedbound=xmarkExtendFromNearest(gram,event->xmotion.x,
! 					       event->xmotion.y);
! 	   xmarkRedraw(dpy,w,gram,changedbound);
! 	} 
! 	break;
  
!       case ButtonRelease:
! 	if (current_pressop == PRESSOP_KILL) {
! 	   xdestroygram(dpy,w,desc_context,gram);
! 	} else if (current_pressop == PRESSOP_SEL ||
! 		   current_pressop == PRESSOP_EXT) {
  	   if (selected_text) free(selected_text);
  	   selected_text = xmarkGetText();
+ 	} else if (current_pressop == PRESSOP_NUKE) {
+ 	   XWindowAttributes wa;
+ 	   int gx,gy;
+ 	   Window temp;
+ 
+ 	   for (gram = bottom_gram ; gram ; gram = gram->above) {
+ 	      XGetWindowAttributes(dpy,gram->w,&wa);
+ 	      XTranslateCoordinates(dpy,gram->w,wa.root,0,0,&gx,&gy,
+ 				    &temp);
+ 
+ 	      if ((wa.map_state == IsViewable) &&
+ 		  (gx <= event->xbutton.x_root) &&
+ 		  (event->xbutton.x_root < gx+wa.width) &&
+ 		  (gy <= event->xbutton.y_root) &&
+ 		  (event->xbutton.y_root < gy+wa.height))
+ 		 xdestroygram(dpy,gram->w,desc_context,gram);
+ 	   }
  	}
+ 	current_pressop = PRESSOP_NONE;
  	break;
  
       case SelectionRequest:

home help back first fref pref prev next nref lref last post