(coded-charset-entity-reference-alist): Add setting for
[chise/xemacs-chise.git.1] / src / select-x.c
index d37ff2b..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);
@@ -139,9 +143,7 @@ symbol_to_x_atom (struct device *d, Lisp_Object sym, int only_if_exists)
 
   {
     const char *nameext;
-    TO_EXTERNAL_FORMAT (LISP_STRING, Fsymbol_name (sym),
-                       C_STRING_ALLOCA, nameext,
-                       Qctext);
+    LISP_STRING_TO_EXTERNAL (Fsymbol_name (sym), nameext, Qctext);
     return XInternAtom (display, nameext, only_if_exists ? True : False);
   }
 }
@@ -203,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);
@@ -228,14 +231,14 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
      That assumed equivalence of time_t and Time, which is not
      necessarily the case (e.g. under OSF on the Alphas, where
      Time is a 64-bit quantity and time_t is a 32-bit quantity).
-     
+
      Opaque pointers are the clean way to go here.
   */
   selection_time = make_opaque (&thyme, sizeof (thyme));
 
 #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;
 }
@@ -251,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
@@ -272,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
@@ -286,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
       {
@@ -376,9 +382,9 @@ 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 */
        if (NILP (selection))
          selection = select_convert_out (QCLIPBOARD, QSTRING, Qnil);
@@ -386,7 +392,7 @@ motif_clipboard_cb (Widget widget, int *data_id, int *private_id, int *reason)
          selection = select_convert_out (QCLIPBOARD, QTEXT, Qnil);
        if (NILP (selection))
          selection = select_convert_out (QCLIPBOARD, QCOMPOUND_TEXT, Qnil);
-       
+
        if (CONSP (selection) && SYMBOLP (XCAR (selection))
            && (EQ (XCAR (selection), QSTRING)
                || EQ (XCAR (selection), QTEXT)
@@ -400,8 +406,8 @@ motif_clipboard_cb (Widget widget, int *data_id, int *private_id, int *reason)
        if (!STRINGP (selection))
          signal_error (Qselection_conversion_error,
                        build_string ("couldn't convert selection to string"));
-                              
-       
+
+
        XmClipboardCopyByName (dpy, window, *data_id,
                               (char *) XSTRING_DATA (selection),
                               XSTRING_LENGTH (selection) + 1,
@@ -503,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);
 
@@ -554,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 */
     }
 }
 
@@ -600,7 +637,7 @@ x_handle_selection_request (XSelectionRequestEvent *event)
     }
 
   local_selection_time = * (Time *) XOPAQUE_DATA (temp_obj);
-  
+
   if (event->time != CurrentTime &&
       local_selection_time > event->time)
     {
@@ -632,14 +669,14 @@ x_handle_selection_request (XSelectionRequestEvent *event)
     Atom type;
     lisp_data_to_selection_data (d, converted_selection,
                                 &data, &type, &size, &format);
-    
+
     x_reply_selection_request (event, format, data, size, type);
     successful_p = Qt;
     /* Tell x_selection_request_lisp_error() it's cool. */
     event->type = 0;
     xfree (data);
   }
-  
+
   unbind_to (count, Qnil);
 
  DONE_LABEL:
@@ -682,7 +719,7 @@ x_handle_selection_clear (XSelectionClearEvent *event)
   /* We don't own the selection, so that's fine. */
   if (NILP (local_selection_time_lisp))
     return;
-  
+
   local_selection_time = * (Time *) XOPAQUE_DATA (local_selection_time_lisp);
 
   /* This SelectionClear is for a selection that we no longer own, so we can
@@ -692,7 +729,7 @@ x_handle_selection_clear (XSelectionClearEvent *event)
   if (changed_owner_time != CurrentTime &&
       local_selection_time > changed_owner_time)
     return;
-  
+
   handle_selection_clear (selection_symbol);
 }
 
@@ -950,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;
@@ -985,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)
@@ -1022,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)
 {
@@ -1030,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
@@ -1046,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
@@ -1078,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;
@@ -1099,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);
@@ -1181,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)
@@ -1546,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;
@@ -1588,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;
@@ -1622,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)
        {
@@ -1629,6 +1674,7 @@ Set the value of the named CUTBUFFER (typically CUT_BUFFER0) to STRING.
          ptr += 2;
          continue;
        }
+#endif
 
       chartypes = WORLD;
       break;
@@ -1774,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