(coded-charset-entity-reference-alist): Add setting for
[chise/xemacs-chise.git.1] / src / select-x.c
index 82470e5..2ab3161 100644 (file)
@@ -46,7 +46,8 @@ Lisp_Object time_to_lisp (time_t);
 static void hack_motif_clipboard_selection (Atom selection_atom,
                                            Lisp_Object selection_value,
                                            Time thyme, Display *display,
-                                           Window selecting_window);
+                                           Window selecting_window,
+                                           int owned_p);
 #endif
 
 #define CUT_BUFFER_SUPPORT
@@ -72,7 +73,10 @@ Lisp_Object Vx_sent_selection_hooks;
 /* If the selection owner takes too long to reply to a selection request,
    we give up on it.  This is in seconds (0 = no timeout).
  */
-int x_selection_timeout;
+Fixnum x_selection_timeout;
+
+/* Enable motif selection optimizations. */
+int x_selection_strict_motif_ownership;
 
 \f
 /* Utility functions */
@@ -84,7 +88,7 @@ static void lisp_data_to_selection_data (struct device *,
                                         unsigned int *size_ret,
                                         int *format_ret);
 static Lisp_Object selection_data_to_lisp_data (struct device *,
-                                               unsigned char *data,
+                                               Extbyte *data,
                                                size_t size,
                                                Atom type,
                                                int format);
@@ -201,7 +205,8 @@ x_atom_to_symbol (struct device *d, Atom atom)
  */
 static Lisp_Object
 x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
-                Lisp_Object how_to_add, Lisp_Object selection_type)
+                Lisp_Object how_to_add, Lisp_Object selection_type,
+                int owned_p)
 {
   struct device *d = decode_x_device (Qnil);
   Display *display = DEVICE_X_DISPLAY (d);
@@ -233,7 +238,7 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
 
 #ifdef MOTIF_CLIPBOARDS
   hack_motif_clipboard_selection (selection_atom, selection_value,
-                                 thyme, display, selecting_window);
+                                 thyme, display, selecting_window, owned_p);
 #endif
   return selection_time;
 }
@@ -249,8 +254,8 @@ hack_motif_clipboard_selection (Atom selection_atom,
                                Lisp_Object selection_value,
                                Time thyme,
                                Display *display,
-                               Window selecting_window)
-     /*                                Bool owned_p)*/
+                               Window selecting_window,
+                               int owned_p)
 {
   struct device *d = get_device_from_display (display);
   /* Those Motif wankers can't be bothered to follow the ICCCM, and do
@@ -270,7 +275,10 @@ hack_motif_clipboard_selection (Atom selection_atom,
         to look up the new value, and you can't Copy from a buffer, Paste
         into a text field, then Copy something else from the buffer and
         paste it into the text field -- it pastes the first thing again. */
-/*      && !owned_p */
+      && (!owned_p 
+         /* Selectively re-enable this because for most users its
+            just too painful - especially over a remote link. */
+         || x_selection_strict_motif_ownership)
       )
     {
 #ifdef MOTIF_INCREMENTAL_CLIPBOARDS_WORK
@@ -284,8 +292,8 @@ hack_motif_clipboard_selection (Atom selection_atom,
 #endif
       XmString fmh;
       String encoding = "STRING";
-      const Extbyte *data  = XSTRING_DATA (selection_value);
-      Extcount bytes = XSTRING_LENGTH (selection_value);
+      const Bufbyte *data  = XSTRING_DATA (selection_value);
+      Bytecount bytes = XSTRING_LENGTH (selection_value);
 
 #ifdef MULE
       {
@@ -374,7 +382,7 @@ motif_clipboard_cb (Widget widget, int *data_id, int *private_id, int *reason)
        Window window = (Window) *private_id;
        Lisp_Object selection = select_convert_out (QCLIPBOARD, Qnil, Qnil);
 
-       /* Whichever lazy git wrote this originally just called abort()
+       /* Whichever lazy git wrote this originally just called ABORT()
           when anything didn't go their way... */
 
        /* Try some other text types */
@@ -501,14 +509,41 @@ x_reply_selection_request (XSelectionRequestEvent *event, int format,
     }
   else
     {
+#ifndef HAVE_XTREGISTERDRAWABLE
+      invalid_operation("Copying that much data requires X11R6.", Qunbound);
+#else
       /* Send an INCR selection. */
       int prop_id;
+      Widget widget = FRAME_X_TEXT_WIDGET (XFRAME(DEVICE_SELECTED_FRAME(d)));
 
       if (x_window_to_frame (d, window)) /* #### debug */
        error ("attempt to transfer an INCR to ourself!");
 #if 0
       stderr_out ("\nINCR %d\n", bytes_remaining);
 #endif
+      /* Tell Xt not to drop PropertyNotify events that arrive for the
+        target window, rather, pass them to us. This would be a hack, but
+        the Xt selection routines are broken for our purposes--we can't
+        pass them callbacks from Lisp, for example. Let's call it a
+        workaround.
+        The call to wait_for_property_change means we can break out of that
+        function, switch to another frame on the same display (which will
+        be another Xt widget), select a huge amount of text, and have the
+        same (foreign) app ask for another incremental selection
+        transfer. Programming like X11 made sense, would mean that, in that
+        case, XtRegisterDrawable is called twice with different widgets.
+        Since the results of calling XtRegisterDrawable when the drawable
+        is already registered with another widget are undefined, we want to
+        avoid that--so, only call it when XtWindowToWidget returns NULL,
+        which it will only do with a valid Window if it's not already
+        registered. */
+      if (NULL == XtWindowToWidget(display, window))
+      {
+       XtRegisterDrawable(display, (Drawable)window, widget);
+      }
+      
       prop_id = expect_property_change (display, window, reply.property,
                                        PropertyDelete);
 
@@ -552,10 +587,14 @@ x_reply_selection_request (XSelectionRequestEvent *event, int format,
       stderr_out ("  INCR done\n");
 #endif
       if (! waiting_for_other_props_on_window (display, window))
-       XSelectInput (display, window, 0L);
+      {
+        XSelectInput (display, window, 0L);
+        XtUnregisterDrawable(display, (Drawable)window);
+      }
 
       XChangeProperty (display, window, reply.property, type, format,
                       PropModeReplace, data, 0);
+#endif /* HAVE_XTREGISTERDRAWABLE */
     }
 }
 
@@ -948,11 +987,11 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type)
 
 static void
 x_get_window_property (Display *display, Window window, Atom property,
-                      unsigned char **data_ret, int *bytes_ret,
+                      Extbyte **data_ret, int *bytes_ret,
                       Atom *actual_type_ret, int *actual_format_ret,
                       unsigned long *actual_size_ret, int delete_p)
 {
-  int total_size;
+  size_t total_size;
   unsigned long bytes_remaining;
   int offset = 0;
   unsigned char *tmp_data = 0;
@@ -983,7 +1022,7 @@ x_get_window_property (Display *display, Window window, Atom property,
     }
 
   total_size = bytes_remaining + 1;
-  *data_ret = (unsigned char *) xmalloc (total_size);
+  *data_ret = (Extbyte *) xmalloc (total_size);
 
   /* Now read, until we've gotten it all. */
   while (bytes_remaining)
@@ -1020,7 +1059,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
                               /* this one is for error messages only */
                               Lisp_Object target_type,
                               unsigned int min_size_bytes,
-                              unsigned char **data_ret, int *size_bytes_ret,
+                              Extbyte **data_ret, int *size_bytes_ret,
                               Atom *type_ret, int *format_ret,
                               unsigned long *size_ret)
 {
@@ -1028,7 +1067,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
   int offset = 0;
   int prop_id;
   *size_bytes_ret = min_size_bytes;
-  *data_ret = (unsigned char *) xmalloc (*size_bytes_ret);
+  *data_ret = (Extbyte *) xmalloc (*size_bytes_ret);
 #if 0
   stderr_out ("\nread INCR %d\n", min_size_bytes);
 #endif
@@ -1044,7 +1083,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
                                    PropertyNewValue);
   while (1)
     {
-      unsigned char *tmp_data;
+      Extbyte *tmp_data;
       int tmp_size_bytes;
       wait_for_property_change (prop_id);
       /* expect it again immediately, because x_get_window_property may
@@ -1076,7 +1115,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
                   *size_bytes_ret, offset + tmp_size_bytes);
 #endif
          *size_bytes_ret = offset + tmp_size_bytes;
-         *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret);
+         *data_ret = (Extbyte *) xrealloc (*data_ret, *size_bytes_ret);
        }
       memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes);
       offset += tmp_size_bytes;
@@ -1097,7 +1136,7 @@ x_get_window_property_as_lisp_data (Display *display,
   Atom actual_type;
   int actual_format;
   unsigned long actual_size;
-  unsigned char *data = NULL;
+  Extbyte *data = NULL;
   int bytes = 0;
   Lisp_Object val;
   struct device *d = get_device_from_display (display);
@@ -1179,7 +1218,7 @@ x_get_window_property_as_lisp_data (Display *display,
 
 static Lisp_Object
 selection_data_to_lisp_data (struct device *d,
-                            unsigned char *data,
+                            Extbyte *data,
                             size_t size,
                             Atom type,
                             int format)
@@ -1544,7 +1583,7 @@ Return the value of the named CUTBUFFER (typically CUT_BUFFER0).
   Display *display = DEVICE_X_DISPLAY (d);
   Window window = RootWindow (display, 0); /* Cutbuffers are on frame 0 */
   Atom cut_buffer_atom;
-  unsigned char *data;
+  Extbyte *data;
   int bytes;
   Atom type;
   int format;
@@ -1586,9 +1625,9 @@ Set the value of the named CUTBUFFER (typically CUT_BUFFER0) to STRING.
   Display *display = DEVICE_X_DISPLAY (d);
   Window window = RootWindow (display, 0); /* Cutbuffers are on frame 0 */
   Atom cut_buffer_atom;
-  const Extbyte *data  = XSTRING_DATA (string);
-  Extcount bytes = XSTRING_LENGTH (string);
-  Extcount bytes_remaining;
+  const Bufbyte *data  = XSTRING_DATA (string);
+  Bytecount bytes = XSTRING_LENGTH (string);
+  Bytecount bytes_remaining;
   int max_bytes = SELECTION_QUANTUM (display);
 #ifdef MULE
   const Bufbyte *ptr, *end;
@@ -1620,6 +1659,14 @@ Set the value of the named CUTBUFFER (typically CUT_BUFFER0) to STRING.
          continue;
        }
 
+#ifdef UTF2000
+      if ((*ptr) <= 0xC3)
+       {
+         chartypes = LATIN_1;
+         ptr += 2;
+         continue;
+       }
+#else
       if ((*ptr) == LEADING_BYTE_LATIN_ISO8859_1 ||
          (*ptr) == LEADING_BYTE_CONTROL_1)
        {
@@ -1627,6 +1674,7 @@ Set the value of the named CUTBUFFER (typically CUT_BUFFER0) to STRING.
          ptr += 2;
          continue;
        }
+#endif
 
       chartypes = WORLD;
       break;
@@ -1772,6 +1820,17 @@ A value of 0 means wait as long as necessary.  This is initialized from the
 \"*selectionTimeout\" resource (which is expressed in milliseconds).
 */ );
   x_selection_timeout = 0;
+
+  DEFVAR_BOOL ("x-selection-strict-motif-ownership", &x_selection_strict_motif_ownership /*
+*If nil and XEmacs already owns the clipboard, don't own it again in the
+Motif way. Owning the selection on the Motif way does a huge amount of
+X protocol, and it makes killing text incredibly slow when using an
+X terminal.  However, when enabled Motif text fields don't bother to look up
+the new value, and you can't Copy from a buffer, Paste into a text
+field, then Copy something else from the buffer and paste it into the
+text field; it pastes the first thing again.
+*/ );
+  x_selection_strict_motif_ownership = 1;
 }
 
 void