+/* These 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 (Qselect_convert_in, selection, type, value);
+}
+
+Lisp_Object
+select_coerce (Lisp_Object selection,
+ Lisp_Object type,
+ Lisp_Object value)
+{
+ return call3 (Qselect_coerce, 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))
+ {
+ /* Try looking in selection-coercible-types to see if any of
+ them are present for this selection. We try them *in order*;
+ the first for which a conversion succeeds gets returned. */
+ EXTERNAL_LIST_LOOP_2 (element, Vselection_coercible_types)
+ {
+ Lisp_Object ret;
+
+ value = get_local_selection (selection, element);
+
+ if (NILP (value))
+ continue;
+
+ ret = call3 (Qselect_convert_out, selection, type, value);
+
+ if (!NILP (ret))
+ return ret;
+ }
+
+ return Qnil;
+ }
+
+ return call3 (Qselect_convert_out, selection, type, value);
+}
+
+\f
+/* 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);)
+ {
+ Lisp_Object selection, values, prev = Qnil;
+
+ selection = XCAR (rest);
+
+ for (values = XCAR (XCDR (selection));
+ !NILP (values);
+ values = XCDR (values))
+ {
+ 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;
+ }
+
+ /* 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);
+ }
+}
+
+\f