(sigunblockx): Definitions deleted.
[bpt/emacs.git] / src / xselect.c
index 28b0b8f..053d7f0 100644 (file)
@@ -1,5 +1,5 @@
 /* X Selection processing for Emacs.
-   Copyright (C) 1993, 1994, 1995 Free Software Foundation.
+   Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 /* Rewritten by jwz */
@@ -27,8 +28,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "frame.h"     /* Need this to get the X window of selected_frame */
 #include "blockinput.h"
 
-#define xfree free
-
 #define CUT_BUFFER_SUPPORT
 
 Lisp_Object QPRIMARY, QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
@@ -58,7 +57,8 @@ static Lisp_Object Vx_sent_selection_hooks;
 #endif
 
 /* The timestamp of the last input event Emacs received from the X server.  */
-unsigned long last_event_timestamp;
+/* Defined in keyboard.c.  */
+extern unsigned long last_event_timestamp;
 
 /* This is an association list whose elements are of the form
      ( SELECTION-NAME SELECTION-VALUE SELECTION-TIMESTAMP FRAME)
@@ -210,6 +210,7 @@ x_atom_to_symbol (dpyinfo, display, atom)
   if (! str) return Qnil;
   val = intern (str);
   BLOCK_INPUT;
+  /* This was allocated by Xlib, so use XFree.  */
   XFree (str);
   UNBLOCK_INPUT;
   return val;
@@ -412,7 +413,7 @@ x_decline_selection_request (event)
 static struct input_event *x_selection_current_request;
 
 /* Used as an unwind-protect clause so that, if a selection-converter signals
-   an error, we tell the requestor that we were unable to do what they wanted
+   an error, we tell the requester that we were unable to do what they wanted
    before we throw to top-level or go into the debugger or whatever.  */
 
 static Lisp_Object
@@ -463,6 +464,7 @@ queue_selection_requests_unwind (frame)
 
   if (! NILP (frame))
     x_stop_queuing_selection_requests (FRAME_X_DISPLAY (f));
+  return Qnil;
 }
 
 /* Return some frame whose display info is DPYINFO.
@@ -557,7 +559,7 @@ x_reply_selection_request (event, format, data, size, type)
        }
 
       if (x_window_to_frame (dpyinfo, window)) /* #### debug */
-       error ("attempt to transfer an INCR to ourself!");
+       error ("Attempt to transfer an INCR to ourself!");
 #if 0
       fprintf (stderr, "\nINCR %d\n", bytes_remaining);
 #endif
@@ -575,7 +577,7 @@ x_reply_selection_request (event, format, data, size, type)
       had_errors = x_had_errors_p (display);
       UNBLOCK_INPUT;
 
-      /* First, wait for the requestor to ack by deleting the property.
+      /* First, wait for the requester to ack by deleting the property.
         This can run random lisp code (process handlers) or signal.  */
       if (! had_errors)
        wait_for_property_change (wait_object);
@@ -606,12 +608,12 @@ x_reply_selection_request (event, format, data, size, type)
          if (had_errors)
            break;
 
-         /* Now wait for the requestor to ack this chunk by deleting the
+         /* Now wait for the requester to ack this chunk by deleting the
             property.   This can run random lisp code or signal.
           */
          wait_for_property_change (wait_object);
        }
-      /* Now write a zero-length chunk to the property to tell the requestor
+      /* Now write a zero-length chunk to the property to tell the requester
         that we're done.  */
 #if 0
       fprintf (stderr,"  INCR done\n");
@@ -718,8 +720,10 @@ x_handle_selection_request (event)
       /* Indicate we have successfully processed this event.  */
       x_selection_current_request = 0;
 
+      /* Use free, not XFree, because lisp_data_to_selection_data
+        calls xmalloc itself.  */
       if (!nofree)
-       xfree (data);
+       free (data);
     }
   unbind_to (count, Qnil);
 
@@ -817,6 +821,7 @@ x_clear_frame_selections (f)
   /* Otherwise, we're really honest and truly being told to drop it.
      Don't use Fdelq as that may QUIT;.  */
 
+  /* Delete elements from the beginning of Vselection_alist.  */
   while (!NILP (Vselection_alist)
         && EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (Vselection_alist)))))))
     {
@@ -824,18 +829,23 @@ x_clear_frame_selections (f)
       Lisp_Object hooks, selection_symbol;
 
       hooks = Vx_lost_selection_hooks;
-      selection_symbol = Fcar (Vselection_alist);
+      selection_symbol = Fcar (Fcar (Vselection_alist));
 
       if (!EQ (hooks, Qunbound))
        {
          for (; CONSP (hooks); hooks = Fcdr (hooks))
            call1 (Fcar (hooks), selection_symbol);
+#if 0 /* This can crash when deleting a frame
+        from x_connection_closed.  Anyway, it seems unnecessary;
+        something else should cause a redisplay.  */
          redisplay_preserve_echo_area ();
+#endif
        }
 
       Vselection_alist = Fcdr (Vselection_alist);
     }
 
+  /* Delete elements after the beginning of Vselection_alist.  */
   for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
     if (EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (XCONS (rest)->cdr)))))))
       {
@@ -843,13 +853,15 @@ x_clear_frame_selections (f)
        Lisp_Object hooks, selection_symbol;
 
        hooks = Vx_lost_selection_hooks;
-       selection_symbol = Fcar (XCONS (rest)->cdr);
+       selection_symbol = Fcar (Fcar (XCONS (rest)->cdr));
 
        if (!EQ (hooks, Qunbound))
          {
            for (; CONSP (hooks); hooks = Fcdr (hooks))
              call1 (Fcar (hooks), selection_symbol);
+#if 0 /* See above */
            redisplay_preserve_echo_area ();
+#endif
          }
        XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
        break;
@@ -914,7 +926,7 @@ unexpect_property_change (location)
            prev->next = rest->next;
          else
            property_change_wait_list = rest->next;
-         xfree (rest);
+         free (rest);
          return;
        }
       prev = rest;
@@ -931,6 +943,7 @@ wait_for_property_change_unwind (identifierval)
   unexpect_property_change ((struct prop_location *)
                            (XFASTINT (XCONS (identifierval)->car) << 16
                             | XFASTINT (XCONS (identifierval)->cdr)));
+  return Qnil;
 }
 
 /* Actually wait for a property change.
@@ -963,7 +976,7 @@ wait_for_property_change (location)
       wait_reading_process_input (secs, usecs, property_change_reply, 0);
 
       if (NILP (XCONS (property_change_reply)->car))
-       error ("timed out waiting for property-notify event");
+       error ("Timed out waiting for property-notify event");
     }
 
   unbind_to (count, Qnil);
@@ -1002,7 +1015,7 @@ x_handle_property_notify (event)
            prev->next = rest->next;
          else
            property_change_wait_list = rest->next;
-         xfree (rest);
+         free (rest);
          return;
        }
       prev = rest;
@@ -1134,7 +1147,9 @@ x_get_foreign_selection (selection_symbol, target_type)
   UNBLOCK_INPUT;
 
   if (NILP (XCONS (reading_selection_reply)->car))
-    error ("timed out waiting for reply from selection owner");
+    error ("Timed out waiting for reply from selection owner");
+  if (EQ (XCONS (reading_selection_reply)->car, Qlambda))
+    error ("No `%s' selection", XSYMBOL (selection_symbol)->name->data);
 
   /* Otherwise, the selection is waiting for us on the requested property.  */
   return
@@ -1145,6 +1160,8 @@ x_get_foreign_selection (selection_symbol, target_type)
 \f
 /* Subroutines of x_get_window_property_as_lisp_data */
 
+/* Use free, not XFree, to free the data obtained with this function.  */
+
 static void
 x_get_window_property (display, window, property, data_ret, bytes_ret,
                       actual_type_ret, actual_format_ret, actual_size_ret,
@@ -1181,7 +1198,8 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
       *bytes_ret = 0;
       return;
     }
-  xfree ((char *) tmp_data);
+  /* This was allocated by Xlib, so use XFree.  */
+  XFree ((char *) tmp_data);
   
   if (*actual_type_ret == None || *actual_format_ret == 0)
     {
@@ -1192,7 +1210,7 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
   total_size = bytes_remaining + 1;
   *data_ret = (unsigned char *) xmalloc (total_size);
   
-  /* Now read, until weve gotten it all.  */
+  /* Now read, until we've gotten it all.  */
   while (bytes_remaining)
     {
 #if 0
@@ -1216,7 +1234,8 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
       *actual_size_ret *= *actual_format_ret / 8;
       bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret);
       offset += *actual_size_ret;
-      xfree ((char *) tmp_data);
+      /* This was allocated by Xlib, so use XFree.  */
+      XFree ((char *) tmp_data);
     }
 
   XFlush (display);
@@ -1224,6 +1243,8 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
   *bytes_ret = offset;
 }
 \f
+/* Use free, not XFree, to free the data obtained with this function.  */
+
 static void
 receive_incremental_selection (display, window, property, target_type,
                               min_size_bytes, data_ret, size_bytes_ret,
@@ -1269,7 +1290,7 @@ receive_incremental_selection (display, window, property, target_type,
       int tmp_size_bytes;
       wait_for_property_change (wait_object);
       /* expect it again immediately, because x_get_window_property may
-        .. no it wont, I dont get it.
+        .. no it won't, I don't get it.
         .. Ok, I get it now, the Xt code that implements INCR is broken.
        */
       x_get_window_property (display, window, property,
@@ -1284,7 +1305,9 @@ receive_incremental_selection (display, window, property, target_type,
          if (! waiting_for_other_props_on_window (display, window))
            XSelectInput (display, window, STANDARD_EVENT_SET);
          unexpect_property_change (wait_object);
-         if (tmp_data) xfree (tmp_data);
+         /* Use free, not XFree, because x_get_window_property
+            calls xmalloc itself.  */
+         if (tmp_data) free (tmp_data);
          break;
        }
 
@@ -1309,7 +1332,9 @@ receive_incremental_selection (display, window, property, target_type,
        }
       bcopy (tmp_data, (*data_ret) + offset, tmp_size_bytes);
       offset += tmp_size_bytes;
-      xfree (tmp_data);
+      /* Use free, not XFree, because x_get_window_property
+        calls xmalloc itself.  */
+      free (tmp_data);
     }
 }
 \f
@@ -1365,7 +1390,9 @@ x_get_window_property_as_lisp_data (display, window, property, target_type,
 
       unsigned int min_size_bytes = * ((unsigned int *) data);
       BLOCK_INPUT;
-      XFree ((char *) data);
+      /* Use free, not XFree, because x_get_window_property
+        calls xmalloc itself.  */
+      free ((char *) data);
       UNBLOCK_INPUT;
       receive_incremental_selection (display, window, property, target_type,
                                     min_size_bytes, &data, &bytes,
@@ -1383,7 +1410,9 @@ x_get_window_property_as_lisp_data (display, window, property, target_type,
   val = selection_data_to_lisp_data (display, data, bytes,
                                     actual_type, actual_format);
   
-  xfree ((char *) data);
+  /* Use free, not XFree, because x_get_window_property
+     calls xmalloc itself.  */
+  free ((char *) data);
   return val;
 }
 \f
@@ -1485,6 +1514,8 @@ selection_data_to_lisp_data (display, data, size, type, format)
 }
 
 
+/* Use free, not XFree, to free the data obtained with this function.  */
+
 static void
 lisp_data_to_selection_data (display, obj,
                             data_ret, type_ret, size_ret,
@@ -1687,7 +1718,9 @@ clean_local_selection_data (obj)
 }
 \f
 /* Called from XTread_socket to handle SelectionNotify events.
-   If it's the selection we are waiting for, stop waiting.  */
+   If it's the selection we are waiting for, stop waiting
+   by setting the car of reading_selection_reply to non-nil.
+   We store t there if the reply is successful, lambda if not.  */
 
 void
 x_handle_selection_notify (event)
@@ -1698,7 +1731,8 @@ x_handle_selection_notify (event)
   if (event->selection != reading_which_selection)
     return;
 
-  XCONS (reading_selection_reply)->car = Qt;
+  XCONS (reading_selection_reply)->car
+    = (event->property != 0 ? Qt : Qlambda);
 }
 
 \f
@@ -1715,7 +1749,7 @@ anything that the functions on `selection-converter-alist' know about.")
 {
   check_x ();
   CHECK_SYMBOL (selection_name, 0);
-  if (NILP (selection_value)) error ("selection-value may not be nil.");
+  if (NILP (selection_value)) error ("selection-value may not be nil");
   x_own_selection (selection_name, selection_value);
   return selection_value;
 }
@@ -1967,7 +2001,9 @@ DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
                           Fcons (make_number (format), Qnil))));
 
   ret = (bytes ? make_string ((char *) data, bytes) : Qnil);
-  xfree (data);
+  /* Use free, not XFree, because x_get_window_property
+     calls xmalloc itself.  */
+  free (data);
   return ret;
 }
 
@@ -2119,7 +2155,7 @@ and there is no meaningful selection value.");
 \(This happens when some other X client makes its own selection\n\
 or when a Lisp program explicitly clears the selection.)\n\
 The functions are called with one argument, the selection type\n\
-\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.)");
+\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD').");
   Vx_lost_selection_hooks = Qnil;
 
   DEFVAR_LISP ("x-sent-selection-hooks", &Vx_sent_selection_hooks,
@@ -2138,7 +2174,7 @@ it merely informs you that they have happened.");
 
   DEFVAR_INT ("x-selection-timeout", &x_selection_timeout,
    "Number of milliseconds to wait for a selection reply.\n\
-If the selection owner doens't reply in this time, we give up.\n\
+If the selection owner doesn't reply in this time, we give up.\n\
 A value of 0 means wait as long as necessary.  This is initialized from the\n\
 \"*selectionTimeout\" resource.");
   x_selection_timeout = 0;