[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

X Selection



If anyone wants to try out X selections apply the following patch and
add "-DSELECTION" to the DEFS in the Makefile.  I don't know if I'm going
to keep the old method around.  In particular I'd like to know if it
solves the SCO cut and paste problems.

Dennis Payne
dulsi@identicalsoftware.com


--- WeXterm.h.orig	Thu Nov 18 22:06:05 1999
+++ WeXterm.h	Thu Dec 16 20:43:25 1999
@@ -33,11 +33,12 @@
  Window window;
  GC gc;
  XFontStruct *font;
- Atom delete_atom, protocol_atom;
+ Atom delete_atom, protocol_atom, selection_atom, text_atom, property_atom;
  int font_height, font_width;
  int altmask;
  int colors[16];
  WpeMouseShape shape_list[2];
+ char *selection;
 } WpeXStruct;
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\
--- WeXterm.c.orig	Thu Nov 18 22:06:05 1999
+++ WeXterm.c	Thu Dec 16 20:43:25 1999
@@ -458,6 +458,10 @@
                  atom_num + 1);
  WpeFree(new_atom_list);
 
+ WpeXInfo.selection_atom = XInternAtom(WpeXInfo.display, "PRIMARY", False);
+ WpeXInfo.text_atom = XInternAtom(WpeXInfo.display, "STRING", False);
+ WpeXInfo.property_atom = XInternAtom(WpeXInfo.display, "GTK_SELECTION", False);
+ WpeXInfo.selection = NULL;
  WpeXGCSetup();
 
  XMapWindow(WpeXInfo.display, WpeXInfo.window);
 
--- we_xterm.c.orig	Thu Nov 18 22:06:05 1999
+++ we_xterm.c	Thu Dec 16 20:43:32 1999
@@ -435,15 +435,17 @@
    KeySym keysym;
    XComposeStatus compose;
    unsigned char buffer[BUFSIZE];
-   int root_x, root_y, x, y, charcount;
+ int charcount;
    unsigned int key_b;
    XSizeHints size_hints;
 
    expose_report = (XExposeEvent *)&report;
    while (XCheckMaskEvent(WpeXInfo.display, KeyPressMask | ButtonPressMask |
 		ExposureMask | StructureNotifyMask, &report) == True)
-   {  switch(report.type)
-      {  case Expose:
+ {
+  switch(report.type)
+  {
+   case Expose:
             /* Reason for +2 : Assumes extra character on either side. */
             e_refresh_area(expose_report->x/WpeXInfo.font_width,
                            expose_report->y/WpeXInfo.font_height,
@@ -453,36 +455,34 @@
 	    e_refresh();
 	    break;
 	 case ConfigureNotify:
-            {  size_hints.width = (report.xconfigure.width / WpeXInfo.font_width) * WpeXInfo.font_width;
+    size_hints.width = (report.xconfigure.width / WpeXInfo.font_width) * WpeXInfo.font_width;
 	       size_hints.height = (report.xconfigure.height / WpeXInfo.font_height) * WpeXInfo.font_height;
 	       if(size_hints.width != MAXSCOL * WpeXInfo.font_width ||
                   size_hints.height != MAXSLNS * WpeXInfo.font_height)
-	       {  extern struct EXT h_error;
+    {
+     extern struct EXT h_error;
                   MAXSCOL = size_hints.width / WpeXInfo.font_width;
                   MAXSLNS = size_hints.height / WpeXInfo.font_height;
                   e_x_repaint_desk(h_error.cn->f[h_error.cn->mxedt]);
 	       }
-	    }
-	    while (XCheckMaskEvent(WpeXInfo.display,
-		   	StructureNotifyMask, &report) == True);
 	    break;
 	 case KeyPress:
-	    charcount = XLookupString(&report.xkey, buffer, BUFSIZE,
-				&keysym, &compose);
+    charcount = XLookupString(&report.xkey, buffer, BUFSIZE, &keysym, &compose);
 	    if(charcount == 1 && *buffer == CtrlC) return(CtrlC);
 	    break;
 	 case ButtonPress:
-	    if(!pic) break;
-	    XQueryPointer(WpeXInfo.display, WpeXInfo.window, &tmp_root, &tmp_win,
-				      &root_x, &root_y, &x, &y, &key_b);
+    if (!pic)
+     break;
+    key_b = report.xbutton.state;
 	    if(report.xbutton.button == 1)
-	    {  e_mouse.k = (key_b & ShiftMask) ? 3 : 0 +
+    {
+     e_mouse.k = (key_b & ShiftMask) ? 3 : 0 +
 		         (key_b & ControlMask) ? 4 : 0 +
 		         (key_b & WpeXInfo.altmask) ? 8 : 0;
 	       e_mouse.x = report.xbutton.x/WpeXInfo.font_width;
 	       e_mouse.y = report.xbutton.y/WpeXInfo.font_height;
-	       if(e_mouse.x > (pic->e.x + pic->a.x - 10)/2
-		&& e_mouse.x < (pic->e.x + pic->a.x + 6)/2 )
+     if (e_mouse.x > (pic->e.x + pic->a.x - 10)/2 &&
+       e_mouse.x < (pic->e.x + pic->a.x + 6)/2 )
 	       return(CtrlC);
 	    }
 	    break;
@@ -495,7 +495,7 @@
 {
    Window tmp_win, tmp_root;
    XEvent report;
-   XExposeEvent *expose_report;
+ XSelectionEvent se;
    KeySym keysym;
    XComposeStatus compose;
    int charcount;
@@ -504,13 +504,13 @@
    unsigned int key_b;
    XSizeHints size_hints;
    
-   expose_report = (XExposeEvent *)&report;
    e_refresh();
    
    XQueryPointer(WpeXInfo.display, WpeXInfo.window, &tmp_root, &tmp_win,
 				&root_x, &root_y, &x, &y, &key_b);
    if(key_b & (Button1Mask | Button2Mask | Button3Mask))
-   {  e_mouse.x = x/WpeXInfo.font_width;
+ {
+  e_mouse.x = x / WpeXInfo.font_width;
       e_mouse.y = y/WpeXInfo.font_height;
       c = 0;
       if(key_b & Button1Mask) c |= 1;
@@ -519,76 +519,79 @@
       return(-c);
    }
    
-   while(1)  {
-      
+ while (1)
+ {
       XNextEvent(WpeXInfo.display, &report);
       
       switch(report.type)
-      {  case Expose:
-            do {
+  {
+   case Expose:
+    do
+    {
              /* Reason for +2 : Assumes extra character on either side. */
-             e_refresh_area(expose_report->x/WpeXInfo.font_width,
-                            expose_report->y/WpeXInfo.font_height,
-                            expose_report->width/WpeXInfo.font_width+2,
-                            expose_report->height/WpeXInfo.font_height+2);
-            }
-            while (XCheckMaskEvent(WpeXInfo.display,
-		   ExposureMask, &report) == True);
+     e_refresh_area(report.xexpose.x / WpeXInfo.font_width,
+       report.xexpose.y / WpeXInfo.font_height,
+       report.xexpose.width / WpeXInfo.font_width + 2,
+       report.xexpose.height / WpeXInfo.font_height + 2);
+    } while (XCheckMaskEvent(WpeXInfo.display, ExposureMask, &report) == True);
 	    e_refresh();
 	    break;
 	 case ConfigureNotify:
-            {  size_hints.width = (report.xconfigure.width / WpeXInfo.font_width) * WpeXInfo.font_width;
+    size_hints.width = (report.xconfigure.width / WpeXInfo.font_width) * WpeXInfo.font_width;
 	       size_hints.height = (report.xconfigure.height / WpeXInfo.font_height) * WpeXInfo.font_height;
 	       if(size_hints.width != MAXSCOL * WpeXInfo.font_width ||
                   size_hints.height != MAXSLNS * WpeXInfo.font_height)
-	       {  extern struct EXT h_error;
+    {
+     extern struct EXT h_error;
                   MAXSCOL = size_hints.width / WpeXInfo.font_width;
                   MAXSLNS = size_hints.height / WpeXInfo.font_height;
                   e_x_repaint_desk(h_error.cn->f[h_error.cn->mxedt]);
 	       }
-	    }
-	    while (XCheckMaskEvent(WpeXInfo.display,
-		   	StructureNotifyMask, &report) == True);
 	    break;
 	 case ClientMessage:
-	    if(report.xclient.message_type == WpeXInfo.protocol_atom
-		    && ((report.xclient.format == 8
-			&& report.xclient.data.b[0] == WpeXInfo.delete_atom)
-		     || (report.xclient.format == 16
-			&& report.xclient.data.s[0] == WpeXInfo.delete_atom)
-		     || (report.xclient.format == 32
-			&& report.xclient.data.l[0] == WpeXInfo.delete_atom)))
-	    {  extern struct EXT h_error;
+    if (report.xclient.message_type == WpeXInfo.protocol_atom &&
+      ((report.xclient.format == 8 &&
+        report.xclient.data.b[0] == WpeXInfo.delete_atom) ||
+      (report.xclient.format == 16 &&
+        report.xclient.data.s[0] == WpeXInfo.delete_atom) ||
+      (report.xclient.format == 32 &&
+        report.xclient.data.l[0] == WpeXInfo.delete_atom)))
+    {
+     extern struct EXT h_error;
 	       e_quit(h_error.cn->f[h_error.cn->mxedt]);
 	    }
 	    break;
 	 case KeyPress:
-	    charcount = XLookupString(&report.xkey, buffer, BUFSIZE,
-				&keysym, &compose);
+    charcount = XLookupString(&report.xkey, buffer, BUFSIZE, &keysym,
+      &compose);
+    key_b = report.xkey.state;
 	    if(charcount == 1)
 	    {
-	       XQueryPointer(WpeXInfo.display, WpeXInfo.window, &tmp_root, &tmp_win,
-				      &root_x, &root_y, &x, &y, &key_b);
 	       if(*buffer == 127)
-	       {  if(key_b & ControlMask) return(CENTF);
-		  else if(key_b & ShiftMask) return(ShiftDel);
-		  else if(key_b & WpeXInfo.altmask) return(AltDel);
-		  else return(ENTF);
+     {
+      if (key_b & ControlMask)
+       return(CENTF);
+      else if (key_b & ShiftMask)
+       return(ShiftDel);
+      else if (key_b & WpeXInfo.altmask)
+       return(AltDel);
+      else
+       return(ENTF);
 	       }
                if((key_b & ShiftMask) && (*buffer == '\t'))
                  return(WPE_BTAB);
 
 	       if(key_b & WpeXInfo.altmask)
-	       c = e_tast_sim(key_b & ShiftMask ?
-					toupper(*buffer) : *buffer);
-	       else return(*buffer);
+      c = e_tast_sim(key_b & ShiftMask ? toupper(*buffer) : *buffer);
+     else
+      return(*buffer);
 	    }
 	    else
-	    {  c = 0;
-	       XQueryPointer(WpeXInfo.display, WpeXInfo.window, &tmp_root, &tmp_win,
-				      &root_x, &root_y, &x, &y, &key_b);
+    {
+     c = 0;
 	       if(key_b & ControlMask)
-	       {  if(keysym == XK_Left) c = CCLE;
+     {
+      if (keysym == XK_Left) c = CCLE;
 		  else if(keysym == XK_Right) c = CCRI;
 		  else if(keysym == XK_Home) c = CPS1;
 		  else if(keysym == XK_End) c = CEND;
@@ -657,13 +662,14 @@
 	       }
 	    }
 	    if(c != 0)
-	    {  if(key_b & ShiftMask) c = c + 512;
+    {
+     if (key_b & ShiftMask)
+      c = c + 512;
 	       return(c);
 	    }
 	    break;
 	 case ButtonPress:
-	    XQueryPointer(WpeXInfo.display, WpeXInfo.window, &tmp_root, &tmp_win,
-				      &root_x, &root_y, &x, &y, &key_b);
+    key_b = report.xbutton.state;
 	    e_mouse.k = (key_b & ShiftMask) ? 3 : 0 +
 			    (key_b & ControlMask) ? 4 : 0 +
 			    (key_b & WpeXInfo.altmask) ? 8 : 0;
@@ -674,9 +680,40 @@
 	    if(report.xbutton.button == 2) c |= 2;
 	    if(report.xbutton.button == 3) c |= 4;
 	    return(-c);
+   case SelectionRequest:
+    if (WpeXInfo.selection)
+    {
+     se.type = SelectionNotify;
+     se.display = report.xselectionrequest.display;
+     se.requestor = report.xselectionrequest.requestor;
+     se.selection = report.xselectionrequest.selection;
+     se.time = report.xselectionrequest.time;
+     se.target = report.xselectionrequest.target;
+     if (report.xselectionrequest.property == None)
+      report.xselectionrequest.property = report.xselectionrequest.target;
+     /* Xt asks for TARGETS.  Should probably support that. */
+     if (report.xselectionrequest.target == WpeXInfo.text_atom)
+     {
+      se.property = report.xselectionrequest.property;
+      XChangeProperty(se.display, se.requestor, se.property, se.target, 8,
+        PropModeReplace, WpeXInfo.selection, strlen(WpeXInfo.selection));
+     }
+     else
+      se.property = None;
+     XSendEvent(WpeXInfo.display, se.requestor, False, 0, (XEvent *)&se);
+    }
+    break;
+   case SelectionClear:
+    if (WpeXInfo.selection)
+    {
+     WpeFree(WpeXInfo.selection);
+     WpeXInfo.selection = NULL;
+    }
+    break;
 	 default:
 	    break;
-      }  }
+  }
+ }
    return(0);
 }
 
@@ -688,7 +725,7 @@
    XComposeStatus compose;
    int charcount;
    unsigned char buffer[BUFSIZE];
-   int c, root_x, root_y, x, y;
+ int c;
    unsigned int key_b;
    
    e_refresh();
@@ -697,8 +734,8 @@
    return(0);
    
    if(report.type == ButtonPress)
-   {  XQueryPointer(WpeXInfo.display, WpeXInfo.window, &tmp_root, &tmp_win,
-				      &root_x, &root_y, &x, &y, &key_b);
+ {
+  key_b = report.xbutton.state;
       e_mouse.k = (key_b & ShiftMask) ? 3 : 0;
       e_mouse.x = report.xbutton.x/WpeXInfo.font_width;
       e_mouse.y = report.xbutton.y/WpeXInfo.font_height;
@@ -709,7 +746,8 @@
       return(-c);
    }
    else
-   {  charcount = XLookupString(&report.xkey, buffer, BUFSIZE,
+ {
+  charcount = XLookupString(&report.xkey, buffer, BUFSIZE,
 						&keysym, &compose);
       if(charcount == 1) return(*buffer);
       else return(0);
@@ -881,7 +918,11 @@
    BUFFER *b0 = f->ed->f[0]->b;
    SCHIRM *s0 = f->ed->f[0]->s;
    int i, j, k, n;
-   char *str;
+ unsigned char *str;
+ XEvent report;
+ Atom type;
+ int format;
+ long nitems, bytes_left;
 
    for(i = 1; i < b0->mxlines; i++)
    FREE(b0->bf[i].s);
@@ -889,29 +930,62 @@
    *(b0->bf[0].s) = WPE_WR;
    *(b0->bf[0].s+1) = '\0';
    b0->bf[0].len = 0;
+#if SELECTION
+ if (WpeXInfo.selection)
+ {
+  str = WpeStrdup(WpeXInfo.selection);
+  n = strlen(str);
+ }
+ else
+ {
+  /* Should check for errors especially failure to send SelectionNotify */
+  XConvertSelection(WpeXInfo.display, WpeXInfo.selection_atom,
+    WpeXInfo.text_atom, WpeXInfo.property_atom, WpeXInfo.window, CurrentTime);
+  while (!XCheckTypedEvent(WpeXInfo.display, SelectionNotify, &report))
+   ;
+  if (WpeXInfo.property_atom == None)
+   return 0;
+  XGetWindowProperty(WpeXInfo.display, WpeXInfo.window, WpeXInfo.property_atom,
+    0, 1000000, FALSE, WpeXInfo.text_atom, &type, &format, &nitems, &bytes_left,
+    &str);
+  n = strlen(str);
+ }
+#else
    str = XFetchBytes(WpeXInfo.display, &n);
+#endif
    for(i = k = 0; i < n; i++, k++)
-   {  for(j = 0; i < n && str[i] != '\n' && j < b0->mx.x-1; j++, i++)
+ {
+  for (j = 0; i < n && str[i] != '\n' && j < b0->mx.x-1; j++, i++)
 					       b0->bf[k].s[j] = str[i];
       if(i < n)
-      {  e_new_line(k+1, b0);
+  {
+   e_new_line(k+1, b0);
          if(str[i] == '\n')
-	 {  b0->bf[k].s[j] = WPE_WR;
+   {
+    b0->bf[k].s[j] = WPE_WR;
 	    b0->bf[k].nrc = j+1;
 	 }
-	 else b0->bf[k].nrc = j;
+   else
+    b0->bf[k].nrc = j;
 	 b0->bf[k].s[j+1] = '\0';
 	 b0->bf[k].len = j;
       }
       else
-      {  b0->bf[k].s[j] = '\0';
+  {
+   b0->bf[k].s[j] = '\0';
 	 b0->bf[k].nrc = b0->bf[k].len = j;
       }
    }
    s0->mark_begin.x = s0->mark_begin.y = 0;
    s0->mark_end.y = b0->mxlines-1;
    s0->mark_end.x = b0->bf[b0->mxlines-1].len;
-   return(0);
+#if SELECTION
+ if (WpeXInfo.selection)
+  WpeFree(str);
+ else
+#endif
+  XFree(str);
+ return 0;
 }
 
 int e_x_copy_X_buffer(FENSTER *f)
@@ -926,9 +1000,15 @@
  BUFFER *b0 = f->ed->f[0]->b;
  SCHIRM *s0 = f->ed->f[0]->s;
  int i, j, n;
- char *str;
 
  e_edt_copy(f);
+#if SELECTION
+ if (WpeXInfo.selection)
+ {
+  WpeFree(WpeXInfo.selection);
+  WpeXInfo.selection = NULL;
+ }
+#endif
  if ((s0->mark_end.y == 0 && s0->mark_end.x == 0) ||
    s0->mark_end.y < s0->mark_begin.y)
   return(0);
@@ -937,24 +1017,40 @@
   if (s0->mark_end.x < s0->mark_begin.x)
    return(0);
   n = s0->mark_end.x - s0->mark_begin.x;
+#if SELECTION
+  WpeXInfo.selection = WpeMalloc(n + 1);
+  strncpy(WpeXInfo.selection, b0->bf[s0->mark_begin.y].s+s0->mark_begin.x,
+    n);
+  WpeXInfo.selection[n] = 0;
+  XSetSelectionOwner(WpeXInfo.display, WpeXInfo.selection_atom,
+    WpeXInfo.window, CurrentTime);
+#else
   XStoreBytes(WpeXInfo.display, b0->bf[s0->mark_begin.y].s+s0->mark_begin.x,
     n);
+#endif
   return(0);
  }
- str = MALLOC(b0->bf[s0->mark_begin.y].nrc * sizeof(char));
+ WpeXInfo.selection = WpeMalloc(b0->bf[s0->mark_begin.y].nrc * sizeof(char));
  for (n = 0, j = s0->mark_begin.x; j < b0->bf[s0->mark_begin.y].nrc; j++, n++)
-  str[n] = b0->bf[s0->mark_begin.y].s[j];
+  WpeXInfo.selection[n] = b0->bf[s0->mark_begin.y].s[j];
  for (i = s0->mark_begin.y+1; i < s0->mark_end.y; i++)
  {
-  str = REALLOC(str, (n + b0->bf[i].nrc)*sizeof(char));
+  WpeXInfo.selection = WpeRealloc(WpeXInfo.selection, (n + b0->bf[i].nrc)*sizeof(char));
   for (j = 0; j < b0->bf[i].nrc; j++, n++)
-   str[n] = b0->bf[i].s[j];
+   WpeXInfo.selection[n] = b0->bf[i].s[j];
  }
- str = REALLOC(str, (n + s0->mark_end.x)*sizeof(char));
+ WpeXInfo.selection = WpeRealloc(WpeXInfo.selection, (n + s0->mark_end.x + 1)*sizeof(char));
  for (j = 0; j < s0->mark_end.x; j++, n++)
-  str[n] = b0->bf[i].s[j];
- XStoreBytes(WpeXInfo.display, str, n);
- FREE(str);
+  WpeXInfo.selection[n] = b0->bf[i].s[j];
+ WpeXInfo.selection[n] = 0;
+#if SELECTION
+ XSetSelectionOwner(WpeXInfo.display, WpeXInfo.selection_atom,
+   WpeXInfo.window, CurrentTime);
+#else
+ XStoreBytes(WpeXInfo.display, WpeXInfo.selection, n);
+ WpeFree(WpeXInfo.selection);
+ WpeXInfo.selection = NULL;
+#endif
  return(0);
 }