--- ../orig/xemacs-21.2/src/select.h	Fri Jul 14 16:04:00 2000
+++ xemacs-21.2/src/select.h	Sat Jul 15 19:14:28 2000
@@ -38,29 +38,28 @@
 /* Selection strategies */
 extern Lisp_Object Qreplace_all, Qreplace_existing, Qappend;
 
-/* This is an association list whose elements are of the form
-     ( selection-name selection-value selection-timestamp )
-   selection-name is a lisp symbol, whose name is the name of an X Atom.
-   selection-value is the value that emacs owns for that selection.
-     It may be any kind of Lisp object.
-   selection-timestamp is the time at which emacs began owning this selection,
-     as a cons of two 16-bit numbers (making a 32 bit time).
-   If there is an entry in this alist, then it can be assumed that emacs owns
-    that selection.
-   The only (eq) parts of this list that are visible from elisp are the
-    selection-values.
- */
-extern Lisp_Object Vselection_alist;
-
 /* "Selection owner couldn't convert selection" */
 extern Lisp_Object Qselection_conversion_error;
 
-Lisp_Object get_local_selection (Lisp_Object selection_symbol,
-				 Lisp_Object target_type);
-Lisp_Object convert_selection (Lisp_Object selection_symbol,
-			       Lisp_Object selection_value,
-			       Lisp_Object target_type,
-			       int output);
+/* Selection input & output */
+Lisp_Object select_convert_in (Lisp_Object selection,
+			       Lisp_Object type,
+			       Lisp_Object value);
+Lisp_Object select_convert_out (Lisp_Object selection,
+				Lisp_Object type,
+				Lisp_Object value);
+
+/* Notifications */
 void handle_selection_clear (Lisp_Object selection_symbol);
+
+void select_notify_buffer_kill (Lisp_Object buffer);
+
+/* Lisp functions we export for other files' use */
+EXFUN (Fregister_selection_data_type, 2);
+EXFUN (Fselection_data_type_name, 2);
+EXFUN (Favailable_selection_types, 2);
+EXFUN (Fselection_owner_p, 1);
+EXFUN (Fselection_exists_p, 3);
+EXFUN (Fget_selection_timestamp, 1);
 
 #endif /* INCLUDED_select_h_ */
--- ../orig/xemacs-21.2/src/select.c	Fri Jul 14 16:03:45 2000
+++ xemacs-21.2/src/select.c	Sat Jul 15 21:29:47 2000
@@ -26,6 +26,7 @@
 
 #include "buffer.h"
 #include "device.h"
+#include "extents.h"
 #include "console.h"
 #include "objects.h"
 
@@ -60,6 +61,7 @@
 Lisp_Object Vselection_converter_out_alist;
 Lisp_Object Vselection_converter_in_alist;
 Lisp_Object Vselection_appender_alist;
+Lisp_Object Vselection_buffer_killed_alist;
 
 Lisp_Object Vlost_selection_hooks;
 
@@ -78,47 +80,11 @@
  */
 Lisp_Object Vselection_alist;
 
-static Lisp_Object
-clean_local_selection_data (Lisp_Object obj)
-{
-  if (CONSP (obj) &&
-      INTP (XCAR (obj)) &&
-      CONSP (XCDR (obj)) &&
-      INTP (XCAR (XCDR (obj))) &&
-      NILP (XCDR (XCDR (obj))))
-    obj = Fcons (XCAR (obj), XCDR (obj));
-
-  if (CONSP (obj) &&
-      INTP (XCAR (obj)) &&
-      INTP (XCDR (obj)))
-    {
-      if (XINT (XCAR (obj)) == 0)
-	return XCDR (obj);
-      if (XINT (XCAR (obj)) == -1)
-	return make_int (- XINT (XCDR (obj)));
-    }
-  if (VECTORP (obj))
-    {
-      int i;
-      int len = XVECTOR_LENGTH (obj);
-      Lisp_Object copy;
-      if (len == 1)
-	return clean_local_selection_data (XVECTOR_DATA (obj) [0]);
-      copy = make_vector (len, Qnil);
-      for (i = 0; i < len; i++)
-	XVECTOR_DATA (copy) [i] =
-	  clean_local_selection_data (XVECTOR_DATA (obj) [i]);
-      return copy;
-    }
-  return obj;
-}
-
 /* Given a selection-name and desired type, this looks up our local copy of
    the selection value and converts it to the type. */
-Lisp_Object
+static Lisp_Object
 get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type)
 {
-  /* This function can GC */
   Lisp_Object local_value = assq_no_quit (selection_symbol, Vselection_alist);
 
   if (!NILP (local_value))
@@ -128,13 +94,9 @@
 
       /* First try to find an entry of the appropriate type */
       value = assq_no_quit (target_type, value_list);
+
       if (!NILP (value))
-	return value;
-      
-      /* We couldn't. Try for a generic type instead. */
-      value = assq_no_quit (target_type, Qnil);
-  
-      return convert_selection (selection_symbol, value, target_type, 0);    
+	return XCDR (value);
     }
 
   return Qnil;
@@ -166,90 +128,6 @@
 	}
 #endif
 
-/* Given a selection-value and desired type, this converts the value to the
-   requested type. This calls random elisp code, and may signal or gc. */
-Lisp_Object
-convert_selection (Lisp_Object selection_symbol,
-		   Lisp_Object selection_value,
-		   Lisp_Object target_type,
-		   int output)
-{
-  /* This function can GC */
-  Lisp_Object handler_fn, value /*, check */;
-  
-  if (NILP (selection_value)) return Qnil;
-
-  /* TIMESTAMP and MULTIPLE are special cases 'cause that's easiest. */
-  if (EQ (target_type, QTIMESTAMP))
-    {
-      handler_fn = Qnil;
-      value = XCAR (XCDR (XCDR (selection_value)));
-    }
-  else
-    {
-      /* target_type can be any kind of thing... we used to
-	 CHECK_SYMBOL it here - ajh */
-      
-      handler_fn = Fcdr (Fassq (target_type,
-				output ? Vselection_converter_out_alist
-				: Vselection_converter_in_alist));
-      if (NILP (handler_fn)) return Qnil;
-      value = call3 (handler_fn,
-		     selection_symbol, target_type,
-		     selection_value);
-    }
-
-  return value;
-
-#if 0 /* #### We used to do all this type checking, and it's so *boring*.
-	      The new extensions to the clipboard mechanism make it more
-	      likely that other types will turn up that we don't know about,
-	      so I've disabled it - ajh */
-  
-  /* This lets the selection function to return (TYPE . VALUE).  For example,
-     when the selected type is LINE_NUMBER, the returned type is SPAN, not
-     INTEGER.
-   */
-  check = value;
-  if (CONSP (value) && SYMBOLP (XCAR (value)))
-    check = XCDR (value);
-
-  /* Strings, vectors, and symbols are converted to selection data format in
-     the obvious way.  Integers are converted to 16 bit quantities if they're
-     small enough, otherwise 32 bits are used.
-   */
-  if (STRINGP (check) ||
-      VECTORP (check) ||
-      SYMBOLP (check) ||
-      INTP    (check) ||
-      CHARP   (check) ||
-      NILP (value))
-    return value;
-
-  /* (N . M) or (N M) get turned into a 32 bit quantity.  So if you want to
-     always return a small quantity as 32 bits, your converter routine needs
-     to return a cons.
-   */
-  else if (CONSP (check) &&
-	   INTP (XCAR (check)) &&
-	   (INTP (XCDR (check)) ||
-	    (CONSP (XCDR (check)) &&
-	     INTP (XCAR (XCDR (check))) &&
-	     NILP (XCDR (XCDR (check))))))
-    return value;
-  /* Otherwise the lisp converter function returned something unrecognized.
-   */
-  else
-    signal_error (Qerror,
-                  list3 (build_string
-			 ("unrecognized selection-conversion type"),
-                         handler_fn,
-                         value));
-
-  return Qnil;	/* suppress compiler warning */
-#endif
-}
-
 DEFUN ("own-selection-internal", Fown_selection_internal, 2, 5, 0, /*
 Assert a selection of the given NAME with the given VALUE, and
 optional window-system DATA-TYPE. HOW-TO-ADD specifies how the
@@ -472,12 +350,13 @@
 
       types = Fcons (type, types);
 
-      if (STRINGP (value) && (NILP (type) || EQ (type, QSTRING)
-			      || EQ (type, QTEXT) || EQ (type, QCOMPOUND_TEXT)))
+      if ((STRINGP (value) || EXTENTP (value))
+	  && (NILP (type) || EQ (type, QSTRING)
+	      || EQ (type, QTEXT) || EQ (type, QCOMPOUND_TEXT)))
 	types = Fcons (QTEXT, Fcons (QCOMPOUND_TEXT, Fcons (QSTRING, types)));
-      else if (INTP (value) && (NILP (type) || EQ (type, QINTEGER)))
+      else if (INTP (value) && NILP (type))
 	types = Fcons (QINTEGER, types);
-      else if (SYMBOLP (value) && (NILP (type) || EQ (type, QATOM)))
+      else if (SYMBOLP (value) && NILP (type))
 	types = Fcons (QATOM, types);
     }
   
@@ -585,6 +464,22 @@
     : Qnil;
 }
 
+/* Get the timestamp of the given selection */
+DEFUN ("get-selection-timestamp", Fget_selection_timestamp, 1, 1, 0, /*
+Return the timestamp associated with the specified SELECTION, if it exists.
+Note that the timestamp is a device-specific object, and may not actually be
+visible from Lisp.
+*/
+       (selection))
+{
+  Lisp_Object local_value = assq_no_quit (selection, Vselection_alist);
+
+  if (!NILP (local_value))
+    return XCAR (XCDR (XCDR (local_value)));
+
+  return Qnil;
+}
+
 /* Request the selection value from the owner.  If we are the owner,
    simply return our selection value.  If we are not the owner, this
    will block until all of the data has arrived.
@@ -629,20 +524,128 @@
       val = DEVMETH (XDEVICE (device), get_foreign_selection,
 		     (selection_symbol, target_type));
     }
-  else
+
+  /* Used to call clean_local_selection here... but that really belonged
+     in Lisp (so the equivalent is now built-in to the INTEGER conversion
+     function select-convert-from-integer) - ajh */
+  
+  UNGCPRO;
+  return val;
+}
+
+/* These two are convenient interfaces to the lisp code in select.el;
+   this way we can rename them easily rather than having to hunt everywhere.
+   Also, this gives us access to get_local_selection so that convert_out
+   can retrieve the internal selection value automatically if passed a
+   value of Qnil. */
+Lisp_Object
+select_convert_in (Lisp_Object selection,
+		   Lisp_Object type,
+		   Lisp_Object value)
+{
+  return call3 (intern ("select-convert-in"),
+		selection, type, value);
+}
+
+Lisp_Object
+select_convert_out (Lisp_Object selection,
+		    Lisp_Object type,
+		    Lisp_Object value)
+{
+  if (NILP (value))
+    value = get_local_selection (selection, type);
+
+  if (NILP (value))
+    return Qnil;
+
+  return call3 (intern ("select-convert-out"),
+		selection, type, value);
+}
+		     
+
+/* Gets called from kill-buffer; this lets us dispose of buffer-dependent
+   selections (or alternatively make them independent of the buffer) when
+   it gets vaped. */
+void
+select_notify_buffer_kill (Lisp_Object buffer)
+{
+  Lisp_Object rest;
+  struct gcpro gcpro1, gcpro2, gcpro3;
+  
+  /* For each element of Vselection_alist */
+  for (rest = Vselection_alist;
+       !NILP (rest);)
     {
-      if (CONSP (val) && SYMBOLP (XCAR (val)))
+      Lisp_Object selection, values, prev = Qnil;
+
+      selection = XCAR (rest);
+      
+      for (values = XCAR (XCDR (selection));
+	   !NILP (values);
+	   values = XCDR (values))
 	{
-	  val = XCDR (val);
-	  if (CONSP (val) && NILP (XCDR (val)))
-	    val = XCAR (val);
+	  Lisp_Object value, handler_fn;
+
+	  /* Extract the (type . value) pair. */
+	  value = XCAR (values);
+
+	  /* Find the handler function (if any). */
+	  handler_fn = Fcdr (Fassq (XCAR (value),
+				    Vselection_buffer_killed_alist));
+
+	  if (!NILP (handler_fn))
+	    {
+	      Lisp_Object newval;
+
+	      /* Protect ourselves, just in case some tomfool calls
+		 own-selection from with the buffer-killed handler, then
+		 causes a GC. Just as a note, *don't do this*. */
+	      GCPRO3 (rest, values, value);
+	      
+	      newval = call4 (handler_fn, XCAR (selection), XCAR (value),
+			      XCDR (value), buffer);
+
+	      UNGCPRO;
+	      
+	      /* Set or delete the value (by destructively modifying
+		 the list). */
+	      if (!NILP (newval))
+		{
+		  Fsetcdr (value, newval);
+		  
+		  prev = values;
+		}
+	      else
+		{
+		  if (NILP (prev))
+		    Fsetcar (XCDR (selection), XCDR (values));
+		  else
+		    Fsetcdr (prev, XCDR (values));
+		}
+	    }
+	  else
+	    prev = values;
 	}
-      val = clean_local_selection_data (val);
+
+      /* If we have no values for this selection */
+      if (NILP (XCAR (XCDR (selection))))
+	{
+	  /* Move on to the next element *first* */
+	  rest = XCDR (rest);
+
+	  /* Protect it and disown this selection */
+	  GCPRO1 (rest);
+
+	  Fdisown_selection_internal (XCAR (selection), Qnil, Qnil);
+
+	  UNGCPRO;
+	}
+      else
+	rest = XCDR (rest);
     }
-  UNGCPRO;
-  return val;
 }
 
+
 void
 syms_of_select (void)
 {
@@ -714,7 +717,7 @@
   DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_out_alist /*
 An alist associating selection-types (such as STRING and TIMESTAMP) with
 functions.  This is an alias for `selection-converter-alist-out', and should
-be considered obsolete. Use the new name instead. */ );
+be considered obsolete.  Use the new name instead. */ );
 									      
   DEFVAR_LISP ("selection-converter-out-alist",
 	       &Vselection_converter_out_alist /*
@@ -726,7 +729,7 @@
 
 The return type of these functions depends upon the device in question;
 for mswindows, a string should be returned containing data in the requested
-format, or nil to indicate that the conversion could not be done. Additionally,
+format, or nil to indicate that the conversion could not be done.  Additionally,
 it is permissible to return a cons of the form (DATA-TYPE . STRING) suggesting
 a new data type to use instead.
 
@@ -777,7 +780,7 @@
 value.  These functions should return a suitable representation of the
 value, or nil to indicate that the conversion was not possible.
 
-See also `selection-converter-alist-out'. */ );
+See also `selection-converter-out-alist'. */ );
   Vselection_converter_in_alist = Qnil;
 
   DEFVAR_LISP ("selection-appender-alist",
@@ -789,6 +792,17 @@
 return a value representing the catenation of the two values, or nil to
 indicate that this was not possible. */ );
   Vselection_appender_alist = Qnil;
+  
+  DEFVAR_LISP ("selection-buffer-killed-alist",
+	       &Vselection_buffer_killed_alist /*
+An alist associating selection-types (such as STRING and TIMESTAMP) with
+functions.  These functions will be called whenever a buffer is killed,
+with four args: the name of the selection (typically PRIMARY, SECONDARY
+or CLIPBOARD); the type of the selection; the value of the selection; and
+the buffer that has just been killed.  These functions should return a new
+selection value, or nil to indicate that the selection value should be
+deleted. */ );
+  Vselection_buffer_killed_alist = Qnil;
   
   DEFVAR_LISP ("lost-selection-hooks", &Vlost_selection_hooks /*
 A function or functions to be called after we have been notified
--- ../orig/xemacs-21.2/src/select-msw.c	Fri Jul 14 16:03:40 2000
+++ xemacs-21.2/src/select-msw.c	Sat Jul 15 20:42:25 2000
@@ -33,6 +33,7 @@
 #include "select.h"
 #include "opaque.h"
 #include "file-coding.h"
+#include "buffer.h"
 
 #include "console-msw.h"
 
@@ -212,10 +213,9 @@
     }
 
   /* Convert things appropriately */
-  data = convert_selection (selection_name,
-			    selection_value,
-			    cfObject,
-			    TRUE);
+  data = select_convert_out (selection_name,
+			     cfObject,
+			     selection_value);
 
   if (NILP (data))
     return Qnil;
@@ -484,8 +484,9 @@
     }
 
   /* Place it in a Lisp string */
-  ret = make_uninit_string (size);
-  memcpy (XSTRING_DATA (ret), data, size);
+  TO_INTERNAL_FORMAT (DATA, (data, size),
+		      LISP_STRING, ret,
+		      Qbinary);
 
   GlobalUnlock (data);
   CloseClipboard ();
@@ -495,10 +496,9 @@
   /* Convert this to the appropriate type. If we can't find anything,
      then we return a cons of the form (DATA-TYPE . STRING), where the
      string contains the raw binary data. */
-  value = convert_selection (selection_symbol,
-			     ret,
+  value = select_convert_in (selection_symbol,
 			     cfObject,
-			     FALSE);
+			     ret);
 
   UNGCPRO;
   
--- ../orig/xemacs-21.2/src/select-x.c	Fri Jul 14 16:03:43 2000
+++ xemacs-21.2/src/select-x.c	Sat Jul 15 20:43:28 2000
@@ -200,8 +200,6 @@
 
 
 /* Do protocol to assert ourself as a selection owner.
-   Update the Vselection_alist so that we can reply to later requests for
-   our selection.
  */
 static Lisp_Object
 x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
@@ -376,11 +374,34 @@
       {
 	Display *dpy = XtDisplay (widget);
 	Window window = (Window) *private_id;
-	Lisp_Object selection = assq_no_quit (QCLIPBOARD, Vselection_alist);
-	if (NILP (selection)) abort ();
-	/* #### This should probably be using get_local_selection - ajh */
-	selection = assq_no_quit (Qnil, XCDR (selection));
-	if (!STRINGP (selection)) abort ();
+	Lisp_Object selection = select_convert_out (QCLIPBOARD, Qnil, Qnil);
+
+	/* 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);
+	if (NILP (selection))
+	  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)
+		|| EQ (XCAR (selection), QCOMPOUND_TEXT)))
+	  selection = XCDR (selection);
+
+	if (NILP (selection))
+	  signal_error (Qselection_conversion_error,
+			build_string ("no selection"));
+
+	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,
@@ -549,7 +570,8 @@
 {
   /* This function can GC */
   struct gcpro gcpro1, gcpro2, gcpro3;
-  Lisp_Object local_selection_data = Qnil;
+  Lisp_Object temp_obj;
+  Lisp_Object selection_data = Qnil;
   Lisp_Object selection_symbol;
   Lisp_Object target_symbol = Qnil;
   Lisp_Object converted_selection = Qnil;
@@ -558,33 +580,28 @@
   int count;
   struct device *d = get_device_from_display (event->display);
 
-  GCPRO3 (local_selection_data, converted_selection, target_symbol);
+  GCPRO3 (selection_data, converted_selection, target_symbol);
 
   selection_symbol = x_atom_to_symbol (d, event->selection);
+  target_symbol = x_atom_to_symbol (d, event->target);
 
-  local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
-
-#if 0
-  /* This list isn't user-visible, so it can't "go bad." */
-  assert (CONSP (local_selection_data));
-  assert (CONSP (XCDR (local_selection_data)));
-  assert (CONSP (XCDR (XCDR (local_selection_data))));
-  assert (NILP  (XCDR (XCDR (XCDR (local_selection_data)))));
-  assert (CONSP (XCAR (XCDR (XCDR (local_selection_data)))));
-  assert (INTP  (XCAR (XCAR (XCDR (XCDR (local_selection_data))))));
-  assert (INTP  (XCDR (XCAR (XCDR (XCDR (local_selection_data))))));
+#if 0 /* #### MULTIPLE doesn't work yet */
+  if (EQ (target_symbol, QMULTIPLE))
+    target_symbol = fetch_multiple_target (event);
 #endif
 
-  if (NILP (local_selection_data))
+  temp_obj = Fget_selection_timestamp (selection_symbol);
+
+  if (NILP (temp_obj))
     {
-      /* Someone asked for the selection, but we don't have it any more. */
+      /* We don't appear to have the selection. */
       x_decline_selection_request (event);
+
       goto DONE_LABEL;
     }
 
-  local_selection_time =
-    * (Time *) XOPAQUE_DATA (XCAR (XCDR (XCDR (local_selection_data))));
-
+  local_selection_time = * (Time *) XOPAQUE_DATA (temp_obj);
+  
   if (event->time != CurrentTime &&
       local_selection_time > event->time)
     {
@@ -594,35 +611,37 @@
       goto DONE_LABEL;
     }
 
+  selection_data = select_convert_out (selection_symbol,
+				       target_symbol,
+				       Qnil);
+
+  /* #### Is this the right thing to do? I'm no X expert. -- ajh */
+  if (NILP (selection_data))
+    {
+      /* We don't appear to have a selection in that data type. */
+      x_decline_selection_request (event);
+      goto DONE_LABEL;
+    }
+
   count = specpdl_depth ();
   record_unwind_protect (x_selection_request_lisp_error,
 			 make_opaque_ptr (event));
-  target_symbol = x_atom_to_symbol (d, event->target);
 
-#if 0 /* #### MULTIPLE doesn't work yet */
-  if (EQ (target_symbol, QMULTIPLE))
-    target_symbol = fetch_multiple_target (event);
-#endif
-
-  /* Convert lisp objects back into binary data */
-
-  converted_selection =
-    get_local_selection (selection_symbol, target_symbol);
-
-  if (! NILP (converted_selection))
-    {
-      unsigned char *data;
-      unsigned int size;
-      int format;
-      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);
-    }
+  {
+    unsigned char *data;
+    unsigned int size;
+    int format;
+    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:
@@ -657,18 +676,18 @@
   Atom selection = event->selection;
   Time changed_owner_time = event->time;
 
-  Lisp_Object selection_symbol, local_selection_data;
+  Lisp_Object selection_symbol, local_selection_time_lisp;
   Time local_selection_time;
 
   selection_symbol = x_atom_to_symbol (d, selection);
 
-  local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
-
-  /* Well, we already believe that we don't own it, so that's just fine. */
-  if (NILP (local_selection_data)) return;
+  local_selection_time_lisp = Fget_selection_timestamp (selection_symbol);
 
-  local_selection_time =
-    * (Time *) XOPAQUE_DATA (XCAR (XCDR (XCDR (local_selection_data))));
+  /* 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
      disregard it.  (That is, we have reasserted the selection since this
@@ -923,10 +942,13 @@
 
   /* otherwise, the selection is waiting for us on the requested property. */
 
-  /* #### Should probably call convert_selection here? - ajh */
-  return x_get_window_property_as_lisp_data (display, requestor_window,
-					     target_property, target_type,
-					     selection_atom);
+  return select_convert_in (selection_symbol,
+			    target_type,
+			    x_get_window_property_as_lisp_data(display,
+							       requestor_window,
+							       target_property,
+							       target_type,
+							       selection_atom));
 }
 
 
@@ -1126,6 +1148,9 @@
   return val;
 }
 
+/* #### These are going to move into Lisp code(!) with the aid of
+        some new functions I'm working on - ajh */
+
 /* These functions convert from the selection data read from the server into
    something that we can use from elisp, and vice versa.
 
@@ -1771,5 +1796,7 @@
   DEVICE_XATOM_NULL          (d) = XInternAtom (D, "NULL",          False);
   DEVICE_XATOM_ATOM_PAIR     (d) = XInternAtom (D, "ATOM_PAIR",     False);
   DEVICE_XATOM_COMPOUND_TEXT (d) = XInternAtom (D, "COMPOUND_TEXT", False);
+
+  /* #### I don't like the looks of this... what is it for? - ajh */
   DEVICE_XATOM_EMACS_TMP     (d) = XInternAtom (D, "_EMACS_TMP_",   False);
 }
--- ../orig/xemacs-21.2/src/buffer.c	Mon Jun 12 05:18:06 2000
+++ xemacs-21.2/src/buffer.c	Sat Jul 15 16:24:59 2000
@@ -84,6 +84,7 @@
 #ifdef REGION_CACHE_NEEDS_WORK
 #include "region-cache.h"
 #endif
+#include "select.h"     /* for select_notify_buffer_kill */
 #include "specifier.h"
 #include "syntax.h"
 #include "sysdep.h"	/* for getwd */
@@ -1220,15 +1221,13 @@
 
       /* Then run the hooks.  */
       run_hook (Qkill_buffer_hook);
-#ifdef HAVE_X_WINDOWS
-      /* If an X selection was in this buffer, disown it.
-	 We could have done this by simply adding this function to the
-	 kill-buffer-hook, but the user might mess that up.
-	 */
-      if (EQ (Vwindow_system, Qx))
-	call0 (intern ("xselect-kill-buffer-hook"));
-      /* #### generalize me! */
-#endif /* HAVE_X_WINDOWS */
+
+      /* Inform the selection code that a buffer just got killed.
+	 We do this in C because (a) it's faster, and (b) it needs
+         to access data internal to select.c that can't be seen from
+         Lisp (so the Lisp code would just call into C anyway. */
+      select_notify_buffer_kill (buf);
+      
       unbind_to (speccount, Qnil);
       UNGCPRO;
       b = XBUFFER (buf);        /* Hypothetical relocating GC. */
--- ../orig/xemacs-21.2/lisp/select.el	Fri Jul 14 15:57:36 2000
+++ xemacs-21.2/lisp/select.el	Sat Jul 15 21:26:47 2000
@@ -105,11 +105,6 @@
 		    (get-selection type (cdr data-type))
 		  (signal (car err) (cdr err)))))
 	   (get-selection-internal type data-type))))
-;;    (when (and (consp text) (symbolp (car text)))
-;;      (setq text (cdr text)))
-;; This is no longer an error (selections can be of types other than text)
-;;    (when (not (stringp text))
-;;      (error "Selection is not a string: %S" text))
     text))
 
 ;; FSFmacs calls this `x-set-selection', and reverses the
@@ -153,21 +148,12 @@
 					;(if (stringp type)
 					;    (setq type (intern type)))
     (or type (setq type 'PRIMARY))
-    (flet ((own-selection-1
-	    (type data how-to-add data-type)
-	    (when (or (eq how-to-add 'append) (eq how-to-add t))
-	      (unless (stringp data)
-		;; kludge!
-		(setq data (select-convert-to-text type 'STRING data))
-		(if (stringp data)
-		    (setq data (concat (get-selection type) data)))))
-	    (own-selection-internal type data how-to-add data-type)))
-      (if (null data)
-	  (disown-selection-internal type)
-	(own-selection-1 type data how-to-add data-type)
-	(when (and (eq type 'PRIMARY)
-		   selection-sets-clipboard)
-	  (own-selection-internal 'CLIPBOARD data how-to-add data-type))))
+    (if (null data)
+	(disown-selection-internal type)
+      (own-selection-internal type data how-to-add data-type)
+      (when (and (eq type 'PRIMARY)
+		 selection-sets-clipboard)
+	 (own-selection-internal 'CLIPBOARD data how-to-add data-type)))
     (cond ((eq type 'PRIMARY)
 	   (setq primary-selection-extent
 		 (select-make-extent-for-selection
@@ -180,7 +166,7 @@
   ;; when behaving as the latter, we better not set it, or we will
   ;; cause unwanted sticky-region behavior in kill-region and friends.
   (if (interactive-p)
-      (setq zmacs-region-stays t))
+  (setq zmacs-region-stays t))
   data)
 
 (defun dehilight-selection (selection)
@@ -378,11 +364,31 @@
       (disown-selection nil)
       )))
 
+
 ;;; Functions to convert the selection into various other selection
-;;; types.  Every selection type that emacs handles is implemented
-;;; this way, except for TIMESTAMP, which is a special case. These are
-;;; all moved from x-select.el
+;;; types.
 
+;; These two functions get called by C code...
+(defun select-convert-in (selection type value)
+  "Attempt to convert the specified external VALUE to the specified DATA-TYPE,
+for the specified SELECTION. Return nil if this is impossible, or a
+suitable internal representation otherwise."
+  (when value
+    (let ((handler-fn (cdr (assq type selection-converter-in-alist))))
+      (when handler-fn
+	(apply handler-fn (list selection type value))))))
+
+(defun select-convert-out (selection type value)
+  "Attempt to convert the specified internal VALUE for the specified DATA-TYPE
+and SELECTION. Return nil if this is impossible, or a suitable external
+representation otherwise."
+  (when value
+    (let ((handler-fn (cdr (assq type selection-converter-out-alist))))
+      (when handler-fn
+	(apply handler-fn (list selection type value))))))
+
+;; The rest of the functions on this "page" are conversion handlers,
+;; append handlers and buffer-kill handlers.
 (defun select-convert-to-text (selection type value)
   (cond ((stringp value)
 	 value)
@@ -408,6 +414,10 @@
 	     (buffer-substring (car value) (cdr value)))))
 	(t nil)))
 
+(defun select-convert-from-text (selection type value)
+  (when (stringp value)
+    value))
+
 (defun select-convert-to-string (selection type value)
   (let ((outval (select-convert-to-text selection type value)))
     ;; force the string to be not in Compound Text format.
@@ -438,6 +448,9 @@
 	(cons (ash value -16) (logand value 65535))
       nil)))
 
+(defun select-convert-from-length (selection type value)
+  (select-convert-to-length selection type value))
+
 (defun select-convert-to-targets (selection type value)
   ;; return a vector of atoms, but remove duplicates first.
   (let* ((all (cons 'TIMESTAMP (mapcar 'car selection-converter-alist)))
@@ -445,8 +458,6 @@
     (while rest
       (cond ((memq (car rest) (cdr rest))
 	     (setcdr rest (delq (car rest) (cdr rest))))
-	    ((eq (car (cdr rest)) '_EMACS_INTERNAL)  ; shh, it's a secret
-	     (setcdr rest (cdr (cdr rest))))
 	    (t
 	     (setq rest (cdr rest)))))
     (apply 'vector all)))
@@ -469,6 +480,10 @@
 			       (error "selection is in a killed buffer"))))
 	(t nil)))
 
+(defun select-convert-from-filename (selection type value)
+  (when (stringp value)
+    value))
+
 (defun select-convert-to-charpos (selection type value)
   (let (a b tmp)
     (cond ((cond ((extentp value)
@@ -586,12 +601,61 @@
   (and (integerp value)
        (cons (ash value -16) (logand value 65535))))
 
+;; Can convert from the following integer representations
+;;
+;;    integer
+;;    (integer . integer)
+;;    (integer integer)
+;;    (list [integer|(integer . integer)]*)
+;;    (vector [integer|(integer . integer)]*)
+;;
+;; Cons'd integers get cleaned up a little.
+
+(defun select-convert-from-integer (selection type value)
+  (cond ((integerp value)		; Integer
+	 value)
+	
+	((and (consp value)		; (integer . integer)
+	      (integerp (car value))
+	      (integerp (cdr value)))
+	 (if (eq (car value) 0)
+	     (cdr value)
+	   (if (and (eq (car value) -1)
+		    (< (cdr value) 0))
+	       (cdr value)
+	     value)))
+	
+	((and (listp value)		; (integer integer)
+	      (eq (length value) 2)
+	      (integerp (car value))
+	      (integerp (cadr value)))
+	 (if (eq (car value) 0)
+	     (cadr value)
+	   (if (and (eq (car value) -1)
+		    (< (cdr value) 0))
+	       (- (cadr value))
+	     (cons (car value) (cadr value)))))
+	
+	((listp value)			; list
+	 (if (cdr value)
+	     (mapcar '(lambda (x)
+			(select-convert-from-integer selection type x))
+		     value)
+	   (select-convert-from-integer selection type (car value))))
+	
+	((vectorp value)		; vector
+	 (if (eq (length value) 1)
+	     (select-convert-from-integer selection type (aref value 0))
+	   (mapvector '(lambda (x)
+			(select-convert-from-integer selection type x))
+		     value)))
+	
+	(t nil)
+	))
+
 (defun select-convert-to-atom (selection type value)
   (and (symbolp value) value))
 
-(defun select-convert-to-identity (selection type value) ; used internally
-  (vector value))
-
 ;;; CF_xxx conversions
 (defun select-convert-from-cf-text (selection type value)
   (replace-in-string (if (string-match "\0" value)
@@ -630,9 +694,32 @@
 ;; appending numbers to strings, etc...
   (cond ((and (stringp value1) (stringp value2))
 	 (select-append-to-string selection 'STRING value1 value2))
-	(t
-	 nil)))
+	(t nil)))
 
+;;; Buffer kill handlers
+
+;; #### Should this function take the text *out* of the buffer that's
+;; being killed? Or should it do what the original code did and just
+;; destroy the selection?
+(defun select-buffer-killed-default (selection type value buffer)
+;; This handler gets used if the type is "nil".
+  (cond ((extentp value)
+	 (unless (eq (extent-object value) buffer)
+	   value))
+	((markerp value)
+	 (unless (eq (marker-buffer value) buffer)
+	   value))
+	((and (consp value)
+	      (markerp (car value))
+	      (markerp (cdr value)))
+	 (unless (or (eq (marker-buffer (car value)) buffer)
+		     (eq (marker-buffer (cdr value)) buffer))
+	   value))
+	(t value)))
+
+(defun select-buffer-killed-text (selection type value buffer)
+  (select-buffer-killed-default selection type value buffer))
+	
 ;; Types listed in here can be selections of XEmacs
 (setq selection-converter-out-alist
       '((TEXT . select-convert-to-text)
@@ -653,13 +740,26 @@
 	(NAME . select-convert-to-name)
 	(ATOM . select-convert-to-atom)
 	(INTEGER . select-convert-to-integer)
-	(_EMACS_INTERNAL . select-convert-to-identity)
 	(CF_TEXT . select-convert-to-cf-text)
 	))
 
 ;; Types listed here can be selections foreign to XEmacs
 (setq selection-converter-in-alist
-      '((CF_TEXT . select-convert-from-cf-text)
+      '(; Specific types that get handled by generic converters
+	(COMPOUND_TEXT . select-convert-from-text)
+	(SOURCE_LOC . select-convert-from-text)
+	(OWNER_OS . select-convert-from-text)
+	(HOST_NAME . select-convert-from-text)
+	(USER . select-convert-from-text)
+	(CLASS . select-convert-from-text)
+	(NAME . select-convert-from-text)
+	; Generic types
+	(INTEGER . select-convert-from-integer)
+	(TEXT . select-convert-from-text)
+	(STRING . select-convert-from-text)
+	(LENGTH . select-convert-from-length)
+	(FILE_NAME . select-convert-from-filename)
+	(CF_TEXT . select-convert-from-cf-text)
 	))
 
 ;; Types listed here can be appended by own-selection
@@ -670,5 +770,13 @@
 	(COMPOUND_TEXT . select-append-to-compound-text)
 	(CF_TEXT . select-append-to-cf-text)
 	))
+
+;; Types listed here have buffer-kill handlers
+(setq selection-buffer-killed-alist
+      '((nil . select-buffer-killed-default)
+	(TEXT . select-buffer-killed-text)
+	(STRING . select-buffer-killed-text)
+	(COMPOUND_TEXT . select-buffer-killed-text)
+	(CF_TEXT . select-buffer-killed-text)))
 
 ;;; select.el ends here
--- ../orig/xemacs-21.2/lisp/x-select.el	Thu Sep  2 09:47:56 1999
+++ xemacs-21.2/lisp/x-select.el	Sat Jul 15 17:23:42 2000
@@ -88,36 +88,6 @@
 ;(setq x-sent-selection-hooks 'x-notice-selection-failures)
 
 
-;;; Selections in killed buffers
-;;; this function is called by kill-buffer as if it were on the
-;;; kill-buffer-hook (though it isn't really).
-
-(defun xselect-kill-buffer-hook ()
-  ;; Probably the right thing is to write a C function to return a list
-  ;; of the selections which emacs owns, since it could conceivably own
-  ;; a user-defined selection type that we've never heard of.
-  (xselect-kill-buffer-hook-1 'PRIMARY)
-  (xselect-kill-buffer-hook-1 'SECONDARY)
-  (xselect-kill-buffer-hook-1 'CLIPBOARD))
-
-(defun xselect-kill-buffer-hook-1 (selection)
-  (let (value)
-    (if (and (selection-owner-p selection)
-	     (setq value (get-selection-internal selection '_EMACS_INTERNAL))
-	     ;; The _EMACS_INTERNAL selection type has a converter registered
-	     ;; for it that does no translation.  This only works if emacs is
-	     ;; requesting the selection from itself.  We could have done this
-	     ;; by writing a C function to return the raw selection data, and
-	     ;; that might be the right way to do this, but this was easy.
-	     (or (and (consp value)
-		      (markerp (car value))
-		      (eq (current-buffer) (marker-buffer (car value))))
-		 (and (extent-live-p value)
-		      (eq (current-buffer) (extent-object value)))
-                 (and (extentp value) (not (extent-live-p value)))))
-	(disown-selection-internal selection))))
-
-
 ;;; Cut Buffer support
 
 ;;; FSF name x-get-cut-buffer
