summaryrefslogtreecommitdiff
path: root/src/xselect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xselect.c')
-rw-r--r--src/xselect.c2209
1 files changed, 0 insertions, 2209 deletions
diff --git a/src/xselect.c b/src/xselect.c
deleted file mode 100644
index 009e206ebdf..00000000000
--- a/src/xselect.c
+++ /dev/null
@@ -1,2209 +0,0 @@
-/* X Selection processing for Emacs.
- Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-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, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Rewritten by jwz */
-
-#include <config.h>
-#include "lisp.h"
-#include "xterm.h" /* for all of the X includes */
-#include "dispextern.h" /* frame.h seems to want this */
-#include "frame.h" /* Need this to get the X window of selected_frame */
-#include "blockinput.h"
-
-#define CUT_BUFFER_SUPPORT
-
-Lisp_Object QPRIMARY, QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
- QTEXT, QDELETE, QMULTIPLE, QINCR, QEMACS_TMP, QTARGETS, QATOM, QNULL,
- QATOM_PAIR;
-
-#ifdef CUT_BUFFER_SUPPORT
-Lisp_Object QCUT_BUFFER0, QCUT_BUFFER1, QCUT_BUFFER2, QCUT_BUFFER3,
- QCUT_BUFFER4, QCUT_BUFFER5, QCUT_BUFFER6, QCUT_BUFFER7;
-#endif
-
-static Lisp_Object Vx_lost_selection_hooks;
-static Lisp_Object Vx_sent_selection_hooks;
-
-/* If this is a smaller number than the max-request-size of the display,
- emacs will use INCR selection transfer when the selection is larger
- than this. The max-request-size is usually around 64k, so if you want
- emacs to use incremental selection transfers when the selection is
- smaller than that, set this. I added this mostly for debugging the
- incremental transfer stuff, but it might improve server performance. */
-#define MAX_SELECTION_QUANTUM 0xFFFFFF
-
-#ifdef HAVE_X11R4
-#define SELECTION_QUANTUM(dpy) ((XMaxRequestSize(dpy) << 2) - 100)
-#else
-#define SELECTION_QUANTUM(dpy) (((dpy)->max_request_size << 2) - 100)
-#endif
-
-/* The timestamp of the last input event Emacs received from the X server. */
-/* 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)
- 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.)
- FRAME is the frame for which we made the selection.
- 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 Lisp are the
- selection-values. */
-static Lisp_Object Vselection_alist;
-
-/* This is an alist whose CARs are selection-types (whose names are the same
- as the names of X Atoms) and whose CDRs are the names of Lisp functions to
- call to convert the given Emacs selection value to a string representing
- the given selection type. This is for Lisp-level extension of the emacs
- selection handling. */
-static Lisp_Object Vselection_converter_alist;
-
-/* If the selection owner takes too long to reply to a selection request,
- we give up on it. This is in milliseconds (0 = no timeout.) */
-static int x_selection_timeout;
-
-/* Utility functions */
-
-static void lisp_data_to_selection_data ();
-static Lisp_Object selection_data_to_lisp_data ();
-static Lisp_Object x_get_window_property_as_lisp_data ();
-
-/* This converts a Lisp symbol to a server Atom, avoiding a server
- roundtrip whenever possible. */
-
-static Atom
-symbol_to_x_atom (dpyinfo, display, sym)
- struct x_display_info *dpyinfo;
- Display *display;
- Lisp_Object sym;
-{
- Atom val;
- if (NILP (sym)) return 0;
- if (EQ (sym, QPRIMARY)) return XA_PRIMARY;
- if (EQ (sym, QSECONDARY)) return XA_SECONDARY;
- if (EQ (sym, QSTRING)) return XA_STRING;
- if (EQ (sym, QINTEGER)) return XA_INTEGER;
- if (EQ (sym, QATOM)) return XA_ATOM;
- if (EQ (sym, QCLIPBOARD)) return dpyinfo->Xatom_CLIPBOARD;
- if (EQ (sym, QTIMESTAMP)) return dpyinfo->Xatom_TIMESTAMP;
- if (EQ (sym, QTEXT)) return dpyinfo->Xatom_TEXT;
- if (EQ (sym, QDELETE)) return dpyinfo->Xatom_DELETE;
- if (EQ (sym, QMULTIPLE)) return dpyinfo->Xatom_MULTIPLE;
- if (EQ (sym, QINCR)) return dpyinfo->Xatom_INCR;
- if (EQ (sym, QEMACS_TMP)) return dpyinfo->Xatom_EMACS_TMP;
- if (EQ (sym, QTARGETS)) return dpyinfo->Xatom_TARGETS;
- if (EQ (sym, QNULL)) return dpyinfo->Xatom_NULL;
-#ifdef CUT_BUFFER_SUPPORT
- if (EQ (sym, QCUT_BUFFER0)) return XA_CUT_BUFFER0;
- if (EQ (sym, QCUT_BUFFER1)) return XA_CUT_BUFFER1;
- if (EQ (sym, QCUT_BUFFER2)) return XA_CUT_BUFFER2;
- if (EQ (sym, QCUT_BUFFER3)) return XA_CUT_BUFFER3;
- if (EQ (sym, QCUT_BUFFER4)) return XA_CUT_BUFFER4;
- if (EQ (sym, QCUT_BUFFER5)) return XA_CUT_BUFFER5;
- if (EQ (sym, QCUT_BUFFER6)) return XA_CUT_BUFFER6;
- if (EQ (sym, QCUT_BUFFER7)) return XA_CUT_BUFFER7;
-#endif
- if (!SYMBOLP (sym)) abort ();
-
-#if 0
- fprintf (stderr, " XInternAtom %s\n", (char *) XSYMBOL (sym)->name->data);
-#endif
- BLOCK_INPUT;
- val = XInternAtom (display, (char *) XSYMBOL (sym)->name->data, False);
- UNBLOCK_INPUT;
- return val;
-}
-
-
-/* This converts a server Atom to a Lisp symbol, avoiding server roundtrips
- and calls to intern whenever possible. */
-
-static Lisp_Object
-x_atom_to_symbol (dpyinfo, display, atom)
- struct x_display_info *dpyinfo;
- Display *display;
- Atom atom;
-{
- char *str;
- Lisp_Object val;
- if (! atom) return Qnil;
- switch (atom)
- {
- case XA_PRIMARY:
- return QPRIMARY;
- case XA_SECONDARY:
- return QSECONDARY;
- case XA_STRING:
- return QSTRING;
- case XA_INTEGER:
- return QINTEGER;
- case XA_ATOM:
- return QATOM;
-#ifdef CUT_BUFFER_SUPPORT
- case XA_CUT_BUFFER0:
- return QCUT_BUFFER0;
- case XA_CUT_BUFFER1:
- return QCUT_BUFFER1;
- case XA_CUT_BUFFER2:
- return QCUT_BUFFER2;
- case XA_CUT_BUFFER3:
- return QCUT_BUFFER3;
- case XA_CUT_BUFFER4:
- return QCUT_BUFFER4;
- case XA_CUT_BUFFER5:
- return QCUT_BUFFER5;
- case XA_CUT_BUFFER6:
- return QCUT_BUFFER6;
- case XA_CUT_BUFFER7:
- return QCUT_BUFFER7;
-#endif
- }
-
- if (atom == dpyinfo->Xatom_CLIPBOARD)
- return QCLIPBOARD;
- if (atom == dpyinfo->Xatom_TIMESTAMP)
- return QTIMESTAMP;
- if (atom == dpyinfo->Xatom_TEXT)
- return QTEXT;
- if (atom == dpyinfo->Xatom_DELETE)
- return QDELETE;
- if (atom == dpyinfo->Xatom_MULTIPLE)
- return QMULTIPLE;
- if (atom == dpyinfo->Xatom_INCR)
- return QINCR;
- if (atom == dpyinfo->Xatom_EMACS_TMP)
- return QEMACS_TMP;
- if (atom == dpyinfo->Xatom_TARGETS)
- return QTARGETS;
- if (atom == dpyinfo->Xatom_NULL)
- return QNULL;
-
- BLOCK_INPUT;
- str = XGetAtomName (display, atom);
- UNBLOCK_INPUT;
-#if 0
- fprintf (stderr, " XGetAtomName --> %s\n", str);
-#endif
- if (! str) return Qnil;
- val = intern (str);
- BLOCK_INPUT;
- /* This was allocated by Xlib, so use XFree. */
- XFree (str);
- UNBLOCK_INPUT;
- return val;
-}
-
-/* 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 void
-x_own_selection (selection_name, selection_value)
- Lisp_Object selection_name, selection_value;
-{
- Window selecting_window = FRAME_X_WINDOW (selected_frame);
- Display *display = FRAME_X_DISPLAY (selected_frame);
- Time time = last_event_timestamp;
- Atom selection_atom;
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
-
- CHECK_SYMBOL (selection_name, 0);
- selection_atom = symbol_to_x_atom (dpyinfo, display, selection_name);
-
- BLOCK_INPUT;
- x_catch_errors (display);
- XSetSelectionOwner (display, selection_atom, selecting_window, time);
- x_check_errors (display, "Can't set selection: %s");
- x_uncatch_errors (display);
- UNBLOCK_INPUT;
-
- /* Now update the local cache */
- {
- Lisp_Object selection_time;
- Lisp_Object selection_data;
- Lisp_Object prev_value;
-
- selection_time = long_to_cons ((unsigned long) time);
- selection_data = Fcons (selection_name,
- Fcons (selection_value,
- Fcons (selection_time,
- Fcons (Fselected_frame (), Qnil))));
- prev_value = assq_no_quit (selection_name, Vselection_alist);
-
- Vselection_alist = Fcons (selection_data, Vselection_alist);
-
- /* If we already owned the selection, remove the old selection data.
- Perhaps we should destructively modify it instead.
- Don't use Fdelq as that may QUIT. */
- if (!NILP (prev_value))
- {
- Lisp_Object rest; /* we know it's not the CAR, so it's easy. */
- for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
- if (EQ (prev_value, Fcar (XCONS (rest)->cdr)))
- {
- XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
- break;
- }
- }
- }
-}
-
-/* Given a selection-name and desired type, look up our local copy of
- the selection value and convert it to the type.
- The value is nil or a string.
- This function is used both for remote requests
- and for local x-get-selection-internal.
-
- This calls random Lisp code, and may signal or gc. */
-
-static Lisp_Object
-x_get_local_selection (selection_symbol, target_type)
- Lisp_Object selection_symbol, target_type;
-{
- Lisp_Object local_value;
- Lisp_Object handler_fn, value, type, check;
- int count;
-
- local_value = assq_no_quit (selection_symbol, Vselection_alist);
-
- if (NILP (local_value)) return Qnil;
-
- /* TIMESTAMP and MULTIPLE are special cases 'cause that's easiest. */
- if (EQ (target_type, QTIMESTAMP))
- {
- handler_fn = Qnil;
- value = XCONS (XCONS (XCONS (local_value)->cdr)->cdr)->car;
- }
-#if 0
- else if (EQ (target_type, QDELETE))
- {
- handler_fn = Qnil;
- Fx_disown_selection_internal
- (selection_symbol,
- XCONS (XCONS (XCONS (local_value)->cdr)->cdr)->car);
- value = QNULL;
- }
-#endif
-
-#if 0 /* #### MULTIPLE doesn't work yet */
- else if (CONSP (target_type)
- && XCONS (target_type)->car == QMULTIPLE)
- {
- Lisp_Object pairs;
- int size;
- int i;
- pairs = XCONS (target_type)->cdr;
- size = XVECTOR (pairs)->size;
- /* If the target is MULTIPLE, then target_type looks like
- (MULTIPLE . [[SELECTION1 TARGET1] [SELECTION2 TARGET2] ... ])
- We modify the second element of each pair in the vector and
- return it as [[SELECTION1 <value1>] [SELECTION2 <value2>] ... ]
- */
- for (i = 0; i < size; i++)
- {
- Lisp_Object pair;
- pair = XVECTOR (pairs)->contents [i];
- XVECTOR (pair)->contents [1]
- = x_get_local_selection (XVECTOR (pair)->contents [0],
- XVECTOR (pair)->contents [1]);
- }
- return pairs;
- }
-#endif
- else
- {
- /* Don't allow a quit within the converter.
- When the user types C-g, he would be surprised
- if by luck it came during a converter. */
- count = specpdl_ptr - specpdl;
- specbind (Qinhibit_quit, Qt);
-
- CHECK_SYMBOL (target_type, 0);
- handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist));
- if (!NILP (handler_fn))
- value = call3 (handler_fn,
- selection_symbol, target_type,
- XCONS (XCONS (local_value)->cdr)->car);
- else
- value = Qnil;
- unbind_to (count, Qnil);
- }
-
- /* Make sure this value is of a type that we could transmit
- to another X client. */
-
- check = value;
- if (CONSP (value)
- && SYMBOLP (XCONS (value)->car))
- type = XCONS (value)->car,
- check = XCONS (value)->cdr;
-
- if (STRINGP (check)
- || VECTORP (check)
- || SYMBOLP (check)
- || INTEGERP (check)
- || NILP (value))
- return value;
- /* Check for a value that cons_to_long could handle. */
- else if (CONSP (check)
- && INTEGERP (XCONS (check)->car)
- && (INTEGERP (XCONS (check)->cdr)
- ||
- (CONSP (XCONS (check)->cdr)
- && INTEGERP (XCONS (XCONS (check)->cdr)->car)
- && NILP (XCONS (XCONS (check)->cdr)->cdr))))
- return value;
- else
- return
- Fsignal (Qerror,
- Fcons (build_string ("invalid data returned by selection-conversion function"),
- Fcons (handler_fn, Fcons (value, Qnil))));
-}
-
-/* Subroutines of x_reply_selection_request. */
-
-/* Send a SelectionNotify event to the requestor with property=None,
- meaning we were unable to do what they wanted. */
-
-static void
-x_decline_selection_request (event)
- struct input_event *event;
-{
- XSelectionEvent reply;
- reply.type = SelectionNotify;
- reply.display = SELECTION_EVENT_DISPLAY (event);
- reply.requestor = SELECTION_EVENT_REQUESTOR (event);
- reply.selection = SELECTION_EVENT_SELECTION (event);
- reply.time = SELECTION_EVENT_TIME (event);
- reply.target = SELECTION_EVENT_TARGET (event);
- reply.property = None;
-
- BLOCK_INPUT;
- XSendEvent (reply.display, reply.requestor, False, 0L,
- (XEvent *) &reply);
- XFlush (reply.display);
- UNBLOCK_INPUT;
-}
-
-/* This is the selection request currently being processed.
- It is set to zero when the request is fully processed. */
-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 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
-x_selection_request_lisp_error (ignore)
- Lisp_Object ignore;
-{
- if (x_selection_current_request != 0)
- x_decline_selection_request (x_selection_current_request);
- return Qnil;
-}
-
-
-/* This stuff is so that INCR selections are reentrant (that is, so we can
- be servicing multiple INCR selection requests simultaneously.) I haven't
- actually tested that yet. */
-
-/* Keep a list of the property changes that are awaited. */
-
-struct prop_location
-{
- int identifier;
- Display *display;
- Window window;
- Atom property;
- int desired_state;
- int arrived;
- struct prop_location *next;
-};
-
-static struct prop_location *expect_property_change ();
-static void wait_for_property_change ();
-static void unexpect_property_change ();
-static int waiting_for_other_props_on_window ();
-
-static int prop_location_identifier;
-
-static Lisp_Object property_change_reply;
-
-static struct prop_location *property_change_reply_object;
-
-static struct prop_location *property_change_wait_list;
-
-static Lisp_Object
-queue_selection_requests_unwind (frame)
- Lisp_Object frame;
-{
- FRAME_PTR f = XFRAME (frame);
-
- if (! NILP (frame))
- x_stop_queuing_selection_requests (FRAME_X_DISPLAY (f));
- return Qnil;
-}
-
-/* Return some frame whose display info is DPYINFO.
- Return nil if there is none. */
-
-static Lisp_Object
-some_frame_on_display (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- Lisp_Object list, frame;
-
- FOR_EACH_FRAME (list, frame)
- {
- if (FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
- return frame;
- }
-
- return Qnil;
-}
-
-/* Send the reply to a selection request event EVENT.
- TYPE is the type of selection data requested.
- DATA and SIZE describe the data to send, already converted.
- FORMAT is the unit-size (in bits) of the data to be transmitted. */
-
-static void
-x_reply_selection_request (event, format, data, size, type)
- struct input_event *event;
- int format, size;
- unsigned char *data;
- Atom type;
-{
- XSelectionEvent reply;
- Display *display = SELECTION_EVENT_DISPLAY (event);
- Window window = SELECTION_EVENT_REQUESTOR (event);
- int bytes_remaining;
- int format_bytes = format/8;
- int max_bytes = SELECTION_QUANTUM (display);
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
- if (max_bytes > MAX_SELECTION_QUANTUM)
- max_bytes = MAX_SELECTION_QUANTUM;
-
- reply.type = SelectionNotify;
- reply.display = display;
- reply.requestor = window;
- reply.selection = SELECTION_EVENT_SELECTION (event);
- reply.time = SELECTION_EVENT_TIME (event);
- reply.target = SELECTION_EVENT_TARGET (event);
- reply.property = SELECTION_EVENT_PROPERTY (event);
- if (reply.property == None)
- reply.property = reply.target;
-
- /* #### XChangeProperty can generate BadAlloc, and we must handle it! */
- BLOCK_INPUT;
- x_catch_errors (display);
-
- /* Store the data on the requested property.
- If the selection is large, only store the first N bytes of it.
- */
- bytes_remaining = size * format_bytes;
- if (bytes_remaining <= max_bytes)
- {
- /* Send all the data at once, with minimal handshaking. */
-#if 0
- fprintf (stderr,"\nStoring all %d\n", bytes_remaining);
-#endif
- XChangeProperty (display, window, reply.property, type, format,
- PropModeReplace, data, size);
- /* At this point, the selection was successfully stored; ack it. */
- XSendEvent (display, window, False, 0L, (XEvent *) &reply);
- }
- else
- {
- /* Send an INCR selection. */
- struct prop_location *wait_object;
- int had_errors;
- int count = specpdl_ptr - specpdl;
- Lisp_Object frame;
-
- frame = some_frame_on_display (dpyinfo);
-
- /* If the display no longer has frames, we can't expect
- to get many more selection requests from it, so don't
- bother trying to queue them. */
- if (!NILP (frame))
- {
- x_start_queuing_selection_requests (display);
-
- record_unwind_protect (queue_selection_requests_unwind,
- frame);
- }
-
- if (x_window_to_frame (dpyinfo, window)) /* #### debug */
- error ("Attempt to transfer an INCR to ourself!");
-#if 0
- fprintf (stderr, "\nINCR %d\n", bytes_remaining);
-#endif
- wait_object = expect_property_change (display, window, reply.property,
- PropertyDelete);
-
- XChangeProperty (display, window, reply.property, dpyinfo->Xatom_INCR,
- 32, PropModeReplace,
- (unsigned char *) &bytes_remaining, 1);
- XSelectInput (display, window, PropertyChangeMask);
- /* Tell 'em the INCR data is there... */
- XSendEvent (display, window, False, 0L, (XEvent *) &reply);
- XFlush (display);
-
- had_errors = x_had_errors_p (display);
- UNBLOCK_INPUT;
-
- /* 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);
-
- while (bytes_remaining)
- {
- int i = ((bytes_remaining < max_bytes)
- ? bytes_remaining
- : max_bytes);
-
- BLOCK_INPUT;
-
- wait_object
- = expect_property_change (display, window, reply.property,
- PropertyDelete);
-#if 0
- fprintf (stderr," INCR adding %d\n", i);
-#endif
- /* Append the next chunk of data to the property. */
- XChangeProperty (display, window, reply.property, type, format,
- PropModeAppend, data, i / format_bytes);
- bytes_remaining -= i;
- data += i;
- XFlush (display);
- had_errors = x_had_errors_p (display);
- UNBLOCK_INPUT;
-
- if (had_errors)
- break;
-
- /* 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 requester
- that we're done. */
-#if 0
- fprintf (stderr," INCR done\n");
-#endif
- BLOCK_INPUT;
- if (! waiting_for_other_props_on_window (display, window))
- XSelectInput (display, window, 0L);
-
- XChangeProperty (display, window, reply.property, type, format,
- PropModeReplace, data, 0);
-
- unbind_to (count, Qnil);
- }
-
- XFlush (display);
- x_uncatch_errors (display);
- UNBLOCK_INPUT;
-}
-
-/* Handle a SelectionRequest event EVENT.
- This is called from keyboard.c when such an event is found in the queue. */
-
-void
-x_handle_selection_request (event)
- struct input_event *event;
-{
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object local_selection_data;
- Lisp_Object selection_symbol;
- Lisp_Object target_symbol;
- Lisp_Object converted_selection;
- Time local_selection_time;
- Lisp_Object successful_p;
- int count;
- struct x_display_info *dpyinfo
- = x_display_info_for_display (SELECTION_EVENT_DISPLAY (event));
-
- local_selection_data = Qnil;
- target_symbol = Qnil;
- converted_selection = Qnil;
- successful_p = Qnil;
-
- GCPRO3 (local_selection_data, converted_selection, target_symbol);
-
- selection_symbol = x_atom_to_symbol (dpyinfo,
- SELECTION_EVENT_DISPLAY (event),
- SELECTION_EVENT_SELECTION (event));
-
- local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
-
- if (NILP (local_selection_data))
- {
- /* Someone asked for the selection, but we don't have it any more.
- */
- x_decline_selection_request (event);
- goto DONE;
- }
-
- local_selection_time = (Time)
- cons_to_long (XCONS (XCONS (XCONS (local_selection_data)->cdr)->cdr)->car);
-
- if (SELECTION_EVENT_TIME (event) != CurrentTime
- && local_selection_time > SELECTION_EVENT_TIME (event))
- {
- /* Someone asked for the selection, and we have one, but not the one
- they're looking for.
- */
- x_decline_selection_request (event);
- goto DONE;
- }
-
- count = specpdl_ptr - specpdl;
- x_selection_current_request = event;
- record_unwind_protect (x_selection_request_lisp_error, Qnil);
-
- target_symbol = x_atom_to_symbol (dpyinfo, SELECTION_EVENT_DISPLAY (event),
- SELECTION_EVENT_TARGET (event));
-
-#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
- = x_get_local_selection (selection_symbol, target_symbol);
-
- if (! NILP (converted_selection))
- {
- unsigned char *data;
- unsigned int size;
- int format;
- Atom type;
- int nofree;
-
- lisp_data_to_selection_data (SELECTION_EVENT_DISPLAY (event),
- converted_selection,
- &data, &type, &size, &format, &nofree);
-
- x_reply_selection_request (event, format, data, size, type);
- successful_p = Qt;
-
- /* 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)
- free (data);
- }
- unbind_to (count, Qnil);
-
- DONE:
-
- UNGCPRO;
-
- /* Let random lisp code notice that the selection has been asked for. */
- {
- Lisp_Object rest;
- rest = Vx_sent_selection_hooks;
- if (!EQ (rest, Qunbound))
- for (; CONSP (rest); rest = Fcdr (rest))
- call3 (Fcar (rest), selection_symbol, target_symbol, successful_p);
- }
-}
-
-/* Handle a SelectionClear event EVENT, which indicates that some other
- client cleared out our previously asserted selection.
- This is called from keyboard.c when such an event is found in the queue. */
-
-void
-x_handle_selection_clear (event)
- struct input_event *event;
-{
- Display *display = SELECTION_EVENT_DISPLAY (event);
- Atom selection = SELECTION_EVENT_SELECTION (event);
- Time changed_owner_time = SELECTION_EVENT_TIME (event);
-
- Lisp_Object selection_symbol, local_selection_data;
- Time local_selection_time;
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
- selection_symbol = x_atom_to_symbol (dpyinfo, display, 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 = (Time)
- cons_to_long (XCONS (XCONS (XCONS (local_selection_data)->cdr)->cdr)->car);
-
- /* 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
- request was generated.) */
-
- if (changed_owner_time != CurrentTime
- && local_selection_time > changed_owner_time)
- return;
-
- /* Otherwise, we're really honest and truly being told to drop it.
- Don't use Fdelq as that may QUIT;. */
-
- if (EQ (local_selection_data, Fcar (Vselection_alist)))
- Vselection_alist = Fcdr (Vselection_alist);
- else
- {
- Lisp_Object rest;
- for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
- if (EQ (local_selection_data, Fcar (XCONS (rest)->cdr)))
- {
- XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
- break;
- }
- }
-
- /* Let random lisp code notice that the selection has been stolen. */
-
- {
- Lisp_Object rest;
- rest = Vx_lost_selection_hooks;
- if (!EQ (rest, Qunbound))
- {
- for (; CONSP (rest); rest = Fcdr (rest))
- call1 (Fcar (rest), selection_symbol);
- prepare_menu_bars ();
- redisplay_preserve_echo_area ();
- }
- }
-}
-
-/* Clear all selections that were made from frame F.
- We do this when about to delete a frame. */
-
-void
-x_clear_frame_selections (f)
- FRAME_PTR f;
-{
- Lisp_Object frame;
- Lisp_Object rest;
-
- XSETFRAME (frame, 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)))))))
- {
- /* Let random Lisp code notice that the selection has been stolen. */
- Lisp_Object hooks, selection_symbol;
-
- hooks = Vx_lost_selection_hooks;
- 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)))))))
- {
- /* Let random Lisp code notice that the selection has been stolen. */
- Lisp_Object hooks, selection_symbol;
-
- hooks = Vx_lost_selection_hooks;
- 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;
- }
-}
-
-/* Nonzero if any properties for DISPLAY and WINDOW
- are on the list of what we are waiting for. */
-
-static int
-waiting_for_other_props_on_window (display, window)
- Display *display;
- Window window;
-{
- struct prop_location *rest = property_change_wait_list;
- while (rest)
- if (rest->display == display && rest->window == window)
- return 1;
- else
- rest = rest->next;
- return 0;
-}
-
-/* Add an entry to the list of property changes we are waiting for.
- DISPLAY, WINDOW, PROPERTY, STATE describe what we will wait for.
- The return value is a number that uniquely identifies
- this awaited property change. */
-
-static struct prop_location *
-expect_property_change (display, window, property, state)
- Display *display;
- Window window;
- Lisp_Object property;
- int state;
-{
- struct prop_location *pl
- = (struct prop_location *) xmalloc (sizeof (struct prop_location));
- pl->identifier = ++prop_location_identifier;
- pl->display = display;
- pl->window = window;
- pl->property = property;
- pl->desired_state = state;
- pl->next = property_change_wait_list;
- pl->arrived = 0;
- property_change_wait_list = pl;
- return pl;
-}
-
-/* Delete an entry from the list of property changes we are waiting for.
- IDENTIFIER is the number that uniquely identifies the entry. */
-
-static void
-unexpect_property_change (location)
- struct prop_location *location;
-{
- struct prop_location *prev = 0, *rest = property_change_wait_list;
- while (rest)
- {
- if (rest == location)
- {
- if (prev)
- prev->next = rest->next;
- else
- property_change_wait_list = rest->next;
- free (rest);
- return;
- }
- prev = rest;
- rest = rest->next;
- }
-}
-
-/* Remove the property change expectation element for IDENTIFIER. */
-
-static Lisp_Object
-wait_for_property_change_unwind (identifierval)
- Lisp_Object identifierval;
-{
- unexpect_property_change ((struct prop_location *)
- (XFASTINT (XCONS (identifierval)->car) << 16
- | XFASTINT (XCONS (identifierval)->cdr)));
- return Qnil;
-}
-
-/* Actually wait for a property change.
- IDENTIFIER should be the value that expect_property_change returned. */
-
-static void
-wait_for_property_change (location)
- struct prop_location *location;
-{
- int secs, usecs;
- int count = specpdl_ptr - specpdl;
- Lisp_Object tem;
-
- tem = Fcons (Qnil, Qnil);
- XSETFASTINT (XCONS (tem)->car, (EMACS_UINT)location >> 16);
- XSETFASTINT (XCONS (tem)->cdr, (EMACS_UINT)location & 0xffff);
-
- /* Make sure to do unexpect_property_change if we quit or err. */
- record_unwind_protect (wait_for_property_change_unwind, tem);
-
- XCONS (property_change_reply)->car = Qnil;
-
- property_change_reply_object = location;
- /* If the event we are waiting for arrives beyond here, it will set
- property_change_reply, because property_change_reply_object says so. */
- if (! location->arrived)
- {
- secs = x_selection_timeout / 1000;
- usecs = (x_selection_timeout % 1000) * 1000;
- 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");
- }
-
- unbind_to (count, Qnil);
-}
-
-/* Called from XTread_socket in response to a PropertyNotify event. */
-
-void
-x_handle_property_notify (event)
- XPropertyEvent *event;
-{
- struct prop_location *prev = 0, *rest = property_change_wait_list;
- while (rest)
- {
- if (rest->property == event->atom
- && rest->window == event->window
- && rest->display == event->display
- && rest->desired_state == event->state)
- {
-#if 0
- fprintf (stderr, "Saw expected prop-%s on %s\n",
- (event->state == PropertyDelete ? "delete" : "change"),
- (char *) XSYMBOL (x_atom_to_symbol (dpyinfo, event->display,
- event->atom))
- ->name->data);
-#endif
-
- rest->arrived = 1;
-
- /* If this is the one wait_for_property_change is waiting for,
- tell it to wake up. */
- if (rest == property_change_reply_object)
- XCONS (property_change_reply)->car = Qt;
-
- if (prev)
- prev->next = rest->next;
- else
- property_change_wait_list = rest->next;
- free (rest);
- return;
- }
- prev = rest;
- rest = rest->next;
- }
-#if 0
- fprintf (stderr, "Saw UNexpected prop-%s on %s\n",
- (event->state == PropertyDelete ? "delete" : "change"),
- (char *) XSYMBOL (x_atom_to_symbol (dpyinfo,
- event->display, event->atom))
- ->name->data);
-#endif
-}
-
-
-
-#if 0 /* #### MULTIPLE doesn't work yet */
-
-static Lisp_Object
-fetch_multiple_target (event)
- XSelectionRequestEvent *event;
-{
- Display *display = event->display;
- Window window = event->requestor;
- Atom target = event->target;
- Atom selection_atom = event->selection;
- int result;
-
- return
- Fcons (QMULTIPLE,
- x_get_window_property_as_lisp_data (display, window, target,
- QMULTIPLE, selection_atom));
-}
-
-static Lisp_Object
-copy_multiple_data (obj)
- Lisp_Object obj;
-{
- Lisp_Object vec;
- int i;
- int size;
- if (CONSP (obj))
- return Fcons (XCONS (obj)->car, copy_multiple_data (XCONS (obj)->cdr));
-
- CHECK_VECTOR (obj, 0);
- vec = Fmake_vector (size = XVECTOR (obj)->size, Qnil);
- for (i = 0; i < size; i++)
- {
- Lisp_Object vec2 = XVECTOR (obj)->contents [i];
- CHECK_VECTOR (vec2, 0);
- if (XVECTOR (vec2)->size != 2)
- /* ??? Confusing error message */
- Fsignal (Qerror, Fcons (build_string ("vectors must be of length 2"),
- Fcons (vec2, Qnil)));
- XVECTOR (vec)->contents [i] = Fmake_vector (2, Qnil);
- XVECTOR (XVECTOR (vec)->contents [i])->contents [0]
- = XVECTOR (vec2)->contents [0];
- XVECTOR (XVECTOR (vec)->contents [i])->contents [1]
- = XVECTOR (vec2)->contents [1];
- }
- return vec;
-}
-
-#endif
-
-
-/* Variables for communication with x_handle_selection_notify. */
-static Atom reading_which_selection;
-static Lisp_Object reading_selection_reply;
-static Window reading_selection_window;
-
-/* Do protocol to read selection-data from the server.
- Converts this to Lisp data and returns it. */
-
-static Lisp_Object
-x_get_foreign_selection (selection_symbol, target_type)
- Lisp_Object selection_symbol, target_type;
-{
- Window requestor_window = FRAME_X_WINDOW (selected_frame);
- Display *display = FRAME_X_DISPLAY (selected_frame);
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
- Time requestor_time = last_event_timestamp;
- Atom target_property = dpyinfo->Xatom_EMACS_TMP;
- Atom selection_atom = symbol_to_x_atom (dpyinfo, display, selection_symbol);
- Atom type_atom;
- int secs, usecs;
- int count = specpdl_ptr - specpdl;
- Lisp_Object frame;
-
- if (CONSP (target_type))
- type_atom = symbol_to_x_atom (dpyinfo, display, XCONS (target_type)->car);
- else
- type_atom = symbol_to_x_atom (dpyinfo, display, target_type);
-
- BLOCK_INPUT;
- x_catch_errors (display);
- XConvertSelection (display, selection_atom, type_atom, target_property,
- requestor_window, requestor_time);
- XFlush (display);
-
- /* Prepare to block until the reply has been read. */
- reading_selection_window = requestor_window;
- reading_which_selection = selection_atom;
- XCONS (reading_selection_reply)->car = Qnil;
-
- frame = some_frame_on_display (dpyinfo);
-
- /* If the display no longer has frames, we can't expect
- to get many more selection requests from it, so don't
- bother trying to queue them. */
- if (!NILP (frame))
- {
- x_start_queuing_selection_requests (display);
-
- record_unwind_protect (queue_selection_requests_unwind,
- frame);
- }
- UNBLOCK_INPUT;
-
- /* This allows quits. Also, don't wait forever. */
- secs = x_selection_timeout / 1000;
- usecs = (x_selection_timeout % 1000) * 1000;
- wait_reading_process_input (secs, usecs, reading_selection_reply, 0);
-
- BLOCK_INPUT;
- x_check_errors (display, "Cannot get selection: %s");
- x_uncatch_errors (display);
- unbind_to (count, Qnil);
- UNBLOCK_INPUT;
-
- if (NILP (XCONS (reading_selection_reply)->car))
- 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
- x_get_window_property_as_lisp_data (display, requestor_window,
- target_property, target_type,
- selection_atom);
-}
-
-/* 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,
- delete_p)
- Display *display;
- Window window;
- Atom property;
- unsigned char **data_ret;
- int *bytes_ret;
- Atom *actual_type_ret;
- int *actual_format_ret;
- unsigned long *actual_size_ret;
- int delete_p;
-{
- int total_size;
- unsigned long bytes_remaining;
- int offset = 0;
- unsigned char *tmp_data = 0;
- int result;
- int buffer_size = SELECTION_QUANTUM (display);
- if (buffer_size > MAX_SELECTION_QUANTUM) buffer_size = MAX_SELECTION_QUANTUM;
-
- BLOCK_INPUT;
- /* First probe the thing to find out how big it is. */
- result = XGetWindowProperty (display, window, property,
- 0L, 0L, False, AnyPropertyType,
- actual_type_ret, actual_format_ret,
- actual_size_ret,
- &bytes_remaining, &tmp_data);
- if (result != Success)
- {
- UNBLOCK_INPUT;
- *data_ret = 0;
- *bytes_ret = 0;
- return;
- }
- /* This was allocated by Xlib, so use XFree. */
- XFree ((char *) tmp_data);
-
- if (*actual_type_ret == None || *actual_format_ret == 0)
- {
- UNBLOCK_INPUT;
- return;
- }
-
- total_size = bytes_remaining + 1;
- *data_ret = (unsigned char *) xmalloc (total_size);
-
- /* Now read, until we've gotten it all. */
- while (bytes_remaining)
- {
-#if 0
- int last = bytes_remaining;
-#endif
- result
- = XGetWindowProperty (display, window, property,
- (long)offset/4, (long)buffer_size/4,
- False,
- AnyPropertyType,
- actual_type_ret, actual_format_ret,
- actual_size_ret, &bytes_remaining, &tmp_data);
-#if 0
- fprintf (stderr, "<< read %d\n", last-bytes_remaining);
-#endif
- /* If this doesn't return Success at this point, it means that
- some clod deleted the selection while we were in the midst of
- reading it. Deal with that, I guess....
- */
- if (result != Success) break;
- *actual_size_ret *= *actual_format_ret / 8;
- bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret);
- offset += *actual_size_ret;
- /* This was allocated by Xlib, so use XFree. */
- XFree ((char *) tmp_data);
- }
-
- XFlush (display);
- UNBLOCK_INPUT;
- *bytes_ret = offset;
-}
-
-/* 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,
- type_ret, format_ret, size_ret)
- Display *display;
- Window window;
- Atom property;
- Lisp_Object target_type; /* for error messages only */
- unsigned int min_size_bytes;
- unsigned char **data_ret;
- int *size_bytes_ret;
- Atom *type_ret;
- unsigned long *size_ret;
- int *format_ret;
-{
- int offset = 0;
- struct prop_location *wait_object;
- *size_bytes_ret = min_size_bytes;
- *data_ret = (unsigned char *) xmalloc (*size_bytes_ret);
-#if 0
- fprintf (stderr, "\nread INCR %d\n", min_size_bytes);
-#endif
-
- /* At this point, we have read an INCR property.
- Delete the property to ack it.
- (But first, prepare to receive the next event in this handshake.)
-
- Now, we must loop, waiting for the sending window to put a value on
- that property, then reading the property, then deleting it to ack.
- We are done when the sender places a property of length 0.
- */
- BLOCK_INPUT;
- XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask);
- XDeleteProperty (display, window, property);
- wait_object = expect_property_change (display, window, property,
- PropertyNewValue);
- XFlush (display);
- UNBLOCK_INPUT;
-
- while (1)
- {
- unsigned char *tmp_data;
- int tmp_size_bytes;
- wait_for_property_change (wait_object);
- /* expect it again immediately, because x_get_window_property may
- .. 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,
- &tmp_data, &tmp_size_bytes,
- type_ret, format_ret, size_ret, 1);
-
- if (tmp_size_bytes == 0) /* we're done */
- {
-#if 0
- fprintf (stderr, " read INCR done\n");
-#endif
- if (! waiting_for_other_props_on_window (display, window))
- XSelectInput (display, window, STANDARD_EVENT_SET);
- unexpect_property_change (wait_object);
- /* Use free, not XFree, because x_get_window_property
- calls xmalloc itself. */
- if (tmp_data) free (tmp_data);
- break;
- }
-
- BLOCK_INPUT;
- XDeleteProperty (display, window, property);
- wait_object = expect_property_change (display, window, property,
- PropertyNewValue);
- XFlush (display);
- UNBLOCK_INPUT;
-
-#if 0
- fprintf (stderr, " read INCR %d\n", tmp_size_bytes);
-#endif
- if (*size_bytes_ret < offset + tmp_size_bytes)
- {
-#if 0
- fprintf (stderr, " read INCR realloc %d -> %d\n",
- *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);
- }
- bcopy (tmp_data, (*data_ret) + offset, tmp_size_bytes);
- offset += tmp_size_bytes;
- /* Use free, not XFree, because x_get_window_property
- calls xmalloc itself. */
- free (tmp_data);
- }
-}
-
-/* Once a requested selection is "ready" (we got a SelectionNotify event),
- fetch value from property PROPERTY of X window WINDOW on display DISPLAY.
- TARGET_TYPE and SELECTION_ATOM are used in error message if this fails. */
-
-static Lisp_Object
-x_get_window_property_as_lisp_data (display, window, property, target_type,
- selection_atom)
- Display *display;
- Window window;
- Atom property;
- Lisp_Object target_type; /* for error messages only */
- Atom selection_atom; /* for error messages only */
-{
- Atom actual_type;
- int actual_format;
- unsigned long actual_size;
- unsigned char *data = 0;
- int bytes = 0;
- Lisp_Object val;
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
- x_get_window_property (display, window, property, &data, &bytes,
- &actual_type, &actual_format, &actual_size, 1);
- if (! data)
- {
- int there_is_a_selection_owner;
- BLOCK_INPUT;
- there_is_a_selection_owner
- = XGetSelectionOwner (display, selection_atom);
- UNBLOCK_INPUT;
- while (1) /* Note debugger can no longer return, so this is obsolete */
- Fsignal (Qerror,
- there_is_a_selection_owner ?
- Fcons (build_string ("selection owner couldn't convert"),
- actual_type
- ? Fcons (target_type,
- Fcons (x_atom_to_symbol (dpyinfo, display,
- actual_type),
- Qnil))
- : Fcons (target_type, Qnil))
- : Fcons (build_string ("no selection"),
- Fcons (x_atom_to_symbol (dpyinfo, display,
- selection_atom),
- Qnil)));
- }
-
- if (actual_type == dpyinfo->Xatom_INCR)
- {
- /* That wasn't really the data, just the beginning. */
-
- unsigned int min_size_bytes = * ((unsigned int *) data);
- BLOCK_INPUT;
- /* 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,
- &actual_type, &actual_format,
- &actual_size);
- }
-
- BLOCK_INPUT;
- XDeleteProperty (display, window, property);
- XFlush (display);
- UNBLOCK_INPUT;
-
- /* It's been read. Now convert it to a lisp object in some semi-rational
- manner. */
- val = selection_data_to_lisp_data (display, data, bytes,
- actual_type, actual_format);
-
- /* Use free, not XFree, because x_get_window_property
- calls xmalloc itself. */
- free ((char *) data);
- return val;
-}
-
-/* These functions convert from the selection data read from the server into
- something that we can use from Lisp, and vice versa.
-
- Type: Format: Size: Lisp Type:
- ----- ------- ----- -----------
- * 8 * String
- ATOM 32 1 Symbol
- ATOM 32 > 1 Vector of Symbols
- * 16 1 Integer
- * 16 > 1 Vector of Integers
- * 32 1 if <=16 bits: Integer
- if > 16 bits: Cons of top16, bot16
- * 32 > 1 Vector of the above
-
- When converting a Lisp number to C, it is assumed to be of format 16 if
- it is an integer, and of format 32 if it is a cons of two integers.
-
- When converting a vector of numbers from Lisp to C, it is assumed to be
- of format 16 if every element in the vector is an integer, and is assumed
- to be of format 32 if any element is a cons of two integers.
-
- When converting an object to C, it may be of the form (SYMBOL . <data>)
- where SYMBOL is what we should claim that the type is. Format and
- representation are as above. */
-
-
-
-static Lisp_Object
-selection_data_to_lisp_data (display, data, size, type, format)
- Display *display;
- unsigned char *data;
- Atom type;
- int size, format;
-{
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
- if (type == dpyinfo->Xatom_NULL)
- return QNULL;
-
- /* Convert any 8-bit data to a string, for compactness. */
- else if (format == 8)
- return make_string ((char *) data, size);
-
- /* Convert a single atom to a Lisp_Symbol. Convert a set of atoms to
- a vector of symbols.
- */
- else if (type == XA_ATOM)
- {
- int i;
- if (size == sizeof (Atom))
- return x_atom_to_symbol (dpyinfo, display, *((Atom *) data));
- else
- {
- Lisp_Object v = Fmake_vector (size / sizeof (Atom), 0);
- for (i = 0; i < size / sizeof (Atom); i++)
- Faset (v, i, x_atom_to_symbol (dpyinfo, display,
- ((Atom *) data) [i]));
- return v;
- }
- }
-
- /* Convert a single 16 or small 32 bit number to a Lisp_Int.
- If the number is > 16 bits, convert it to a cons of integers,
- 16 bits in each half.
- */
- else if (format == 32 && size == sizeof (long))
- return long_to_cons (((unsigned long *) data) [0]);
- else if (format == 16 && size == sizeof (short))
- return make_number ((int) (((unsigned short *) data) [0]));
-
- /* Convert any other kind of data to a vector of numbers, represented
- as above (as an integer, or a cons of two 16 bit integers.)
- */
- else if (format == 16)
- {
- int i;
- Lisp_Object v = Fmake_vector (size / 4, 0);
- for (i = 0; i < size / 4; i++)
- {
- int j = (int) ((unsigned short *) data) [i];
- Faset (v, i, make_number (j));
- }
- return v;
- }
- else
- {
- int i;
- Lisp_Object v = Fmake_vector (size / 4, 0);
- for (i = 0; i < size / 4; i++)
- {
- unsigned long j = ((unsigned long *) data) [i];
- Faset (v, i, long_to_cons (j));
- }
- return v;
- }
-}
-
-
-/* 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,
- format_ret, nofree_ret)
- Display *display;
- Lisp_Object obj;
- unsigned char **data_ret;
- Atom *type_ret;
- unsigned int *size_ret;
- int *format_ret;
- int *nofree_ret;
-{
- Lisp_Object type = Qnil;
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
-
- *nofree_ret = 0;
-
- if (CONSP (obj) && SYMBOLP (XCONS (obj)->car))
- {
- type = XCONS (obj)->car;
- obj = XCONS (obj)->cdr;
- if (CONSP (obj) && NILP (XCONS (obj)->cdr))
- obj = XCONS (obj)->car;
- }
-
- if (EQ (obj, QNULL) || (EQ (type, QNULL)))
- { /* This is not the same as declining */
- *format_ret = 32;
- *size_ret = 0;
- *data_ret = 0;
- type = QNULL;
- }
- else if (STRINGP (obj))
- {
- *format_ret = 8;
- *size_ret = XSTRING (obj)->size;
- *data_ret = XSTRING (obj)->data;
- *nofree_ret = 1;
- if (NILP (type)) type = QSTRING;
- }
- else if (SYMBOLP (obj))
- {
- *format_ret = 32;
- *size_ret = 1;
- *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1);
- (*data_ret) [sizeof (Atom)] = 0;
- (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, display, obj);
- if (NILP (type)) type = QATOM;
- }
- else if (INTEGERP (obj)
- && XINT (obj) < 0xFFFF
- && XINT (obj) > -0xFFFF)
- {
- *format_ret = 16;
- *size_ret = 1;
- *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
- (*data_ret) [sizeof (short)] = 0;
- (*(short **) data_ret) [0] = (short) XINT (obj);
- if (NILP (type)) type = QINTEGER;
- }
- else if (INTEGERP (obj)
- || (CONSP (obj) && INTEGERP (XCONS (obj)->car)
- && (INTEGERP (XCONS (obj)->cdr)
- || (CONSP (XCONS (obj)->cdr)
- && INTEGERP (XCONS (XCONS (obj)->cdr)->car)))))
- {
- *format_ret = 32;
- *size_ret = 1;
- *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
- (*data_ret) [sizeof (long)] = 0;
- (*(unsigned long **) data_ret) [0] = cons_to_long (obj);
- if (NILP (type)) type = QINTEGER;
- }
- else if (VECTORP (obj))
- {
- /* Lisp_Vectors may represent a set of ATOMs;
- a set of 16 or 32 bit INTEGERs;
- or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...]
- */
- int i;
-
- if (SYMBOLP (XVECTOR (obj)->contents [0]))
- /* This vector is an ATOM set */
- {
- if (NILP (type)) type = QATOM;
- *size_ret = XVECTOR (obj)->size;
- *format_ret = 32;
- *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom));
- for (i = 0; i < *size_ret; i++)
- if (SYMBOLP (XVECTOR (obj)->contents [i]))
- (*(Atom **) data_ret) [i]
- = symbol_to_x_atom (dpyinfo, display, XVECTOR (obj)->contents [i]);
- else
- Fsignal (Qerror, /* Qselection_error */
- Fcons (build_string
- ("all elements of selection vector must have same type"),
- Fcons (obj, Qnil)));
- }
-#if 0 /* #### MULTIPLE doesn't work yet */
- else if (VECTORP (XVECTOR (obj)->contents [0]))
- /* This vector is an ATOM_PAIR set */
- {
- if (NILP (type)) type = QATOM_PAIR;
- *size_ret = XVECTOR (obj)->size;
- *format_ret = 32;
- *data_ret = (unsigned char *)
- xmalloc ((*size_ret) * sizeof (Atom) * 2);
- for (i = 0; i < *size_ret; i++)
- if (VECTORP (XVECTOR (obj)->contents [i]))
- {
- Lisp_Object pair = XVECTOR (obj)->contents [i];
- if (XVECTOR (pair)->size != 2)
- Fsignal (Qerror,
- Fcons (build_string
- ("elements of the vector must be vectors of exactly two elements"),
- Fcons (pair, Qnil)));
-
- (*(Atom **) data_ret) [i * 2]
- = symbol_to_x_atom (dpyinfo, display,
- XVECTOR (pair)->contents [0]);
- (*(Atom **) data_ret) [(i * 2) + 1]
- = symbol_to_x_atom (dpyinfo, display,
- XVECTOR (pair)->contents [1]);
- }
- else
- Fsignal (Qerror,
- Fcons (build_string
- ("all elements of the vector must be of the same type"),
- Fcons (obj, Qnil)));
-
- }
-#endif
- else
- /* This vector is an INTEGER set, or something like it */
- {
- *size_ret = XVECTOR (obj)->size;
- if (NILP (type)) type = QINTEGER;
- *format_ret = 16;
- for (i = 0; i < *size_ret; i++)
- if (CONSP (XVECTOR (obj)->contents [i]))
- *format_ret = 32;
- else if (!INTEGERP (XVECTOR (obj)->contents [i]))
- Fsignal (Qerror, /* Qselection_error */
- Fcons (build_string
- ("elements of selection vector must be integers or conses of integers"),
- Fcons (obj, Qnil)));
-
- *data_ret = (unsigned char *) xmalloc (*size_ret * (*format_ret/8));
- for (i = 0; i < *size_ret; i++)
- if (*format_ret == 32)
- (*((unsigned long **) data_ret)) [i]
- = cons_to_long (XVECTOR (obj)->contents [i]);
- else
- (*((unsigned short **) data_ret)) [i]
- = (unsigned short) cons_to_long (XVECTOR (obj)->contents [i]);
- }
- }
- else
- Fsignal (Qerror, /* Qselection_error */
- Fcons (build_string ("unrecognised selection data"),
- Fcons (obj, Qnil)));
-
- *type_ret = symbol_to_x_atom (dpyinfo, display, type);
-}
-
-static Lisp_Object
-clean_local_selection_data (obj)
- Lisp_Object obj;
-{
- if (CONSP (obj)
- && INTEGERP (XCONS (obj)->car)
- && CONSP (XCONS (obj)->cdr)
- && INTEGERP (XCONS (XCONS (obj)->cdr)->car)
- && NILP (XCONS (XCONS (obj)->cdr)->cdr))
- obj = Fcons (XCONS (obj)->car, XCONS (obj)->cdr);
-
- if (CONSP (obj)
- && INTEGERP (XCONS (obj)->car)
- && INTEGERP (XCONS (obj)->cdr))
- {
- if (XINT (XCONS (obj)->car) == 0)
- return XCONS (obj)->cdr;
- if (XINT (XCONS (obj)->car) == -1)
- return make_number (- XINT (XCONS (obj)->cdr));
- }
- if (VECTORP (obj))
- {
- int i;
- int size = XVECTOR (obj)->size;
- Lisp_Object copy;
- if (size == 1)
- return clean_local_selection_data (XVECTOR (obj)->contents [0]);
- copy = Fmake_vector (size, Qnil);
- for (i = 0; i < size; i++)
- XVECTOR (copy)->contents [i]
- = clean_local_selection_data (XVECTOR (obj)->contents [i]);
- return copy;
- }
- return obj;
-}
-
-/* Called from XTread_socket to handle SelectionNotify events.
- 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)
- XSelectionEvent *event;
-{
- if (event->requestor != reading_selection_window)
- return;
- if (event->selection != reading_which_selection)
- return;
-
- XCONS (reading_selection_reply)->car
- = (event->property != 0 ? Qt : Qlambda);
-}
-
-
-DEFUN ("x-own-selection-internal", Fx_own_selection_internal,
- Sx_own_selection_internal, 2, 2, 0,
- "Assert an X selection of the given TYPE with the given VALUE.\n\
-TYPE is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
-\(Those are literal upper-case symbol names, since that's what X expects.)\n\
-VALUE is typically a string, or a cons of two markers, but may be\n\
-anything that the functions on `selection-converter-alist' know about.")
- (selection_name, selection_value)
- Lisp_Object selection_name, selection_value;
-{
- check_x ();
- CHECK_SYMBOL (selection_name, 0);
- if (NILP (selection_value)) error ("selection-value may not be nil");
- x_own_selection (selection_name, selection_value);
- return selection_value;
-}
-
-
-/* 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. */
-
-DEFUN ("x-get-selection-internal", Fx_get_selection_internal,
- Sx_get_selection_internal, 2, 2, 0,
- "Return text selected from some X window.\n\
-SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
-\(Those are literal upper-case symbol names, since that's what X expects.)\n\
-TYPE is the type of data desired, typically `STRING'.")
- (selection_symbol, target_type)
- Lisp_Object selection_symbol, target_type;
-{
- Lisp_Object val = Qnil;
- struct gcpro gcpro1, gcpro2;
- GCPRO2 (target_type, val); /* we store newly consed data into these */
- check_x ();
- CHECK_SYMBOL (selection_symbol, 0);
-
-#if 0 /* #### MULTIPLE doesn't work yet */
- if (CONSP (target_type)
- && XCONS (target_type)->car == QMULTIPLE)
- {
- CHECK_VECTOR (XCONS (target_type)->cdr, 0);
- /* So we don't destructively modify this... */
- target_type = copy_multiple_data (target_type);
- }
- else
-#endif
- CHECK_SYMBOL (target_type, 0);
-
- val = x_get_local_selection (selection_symbol, target_type);
-
- if (NILP (val))
- {
- val = x_get_foreign_selection (selection_symbol, target_type);
- goto DONE;
- }
-
- if (CONSP (val)
- && SYMBOLP (XCONS (val)->car))
- {
- val = XCONS (val)->cdr;
- if (CONSP (val) && NILP (XCONS (val)->cdr))
- val = XCONS (val)->car;
- }
- val = clean_local_selection_data (val);
- DONE:
- UNGCPRO;
- return val;
-}
-
-DEFUN ("x-disown-selection-internal", Fx_disown_selection_internal,
- Sx_disown_selection_internal, 1, 2, 0,
- "If we own the selection SELECTION, disown it.\n\
-Disowning it means there is no such selection.")
- (selection, time)
- Lisp_Object selection;
- Lisp_Object time;
-{
- Time timestamp;
- Atom selection_atom;
- XSelectionClearEvent event;
- Display *display;
- struct x_display_info *dpyinfo;
-
- check_x ();
- display = FRAME_X_DISPLAY (selected_frame);
- dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
- CHECK_SYMBOL (selection, 0);
- if (NILP (time))
- timestamp = last_event_timestamp;
- else
- timestamp = cons_to_long (time);
-
- if (NILP (assq_no_quit (selection, Vselection_alist)))
- return Qnil; /* Don't disown the selection when we're not the owner. */
-
- selection_atom = symbol_to_x_atom (dpyinfo, display, selection);
-
- BLOCK_INPUT;
- XSetSelectionOwner (display, selection_atom, None, timestamp);
- UNBLOCK_INPUT;
-
- /* It doesn't seem to be guaranteed that a SelectionClear event will be
- generated for a window which owns the selection when that window sets
- the selection owner to None. The NCD server does, the MIT Sun4 server
- doesn't. So we synthesize one; this means we might get two, but
- that's ok, because the second one won't have any effect. */
- SELECTION_EVENT_DISPLAY (&event) = display;
- SELECTION_EVENT_SELECTION (&event) = selection_atom;
- SELECTION_EVENT_TIME (&event) = timestamp;
- x_handle_selection_clear (&event);
-
- return Qt;
-}
-
-/* Get rid of all the selections in buffer BUFFER.
- This is used when we kill a buffer. */
-
-void
-x_disown_buffer_selections (buffer)
- Lisp_Object buffer;
-{
- Lisp_Object tail;
- struct buffer *buf = XBUFFER (buffer);
-
- for (tail = Vselection_alist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object elt, value;
- elt = XCONS (tail)->car;
- value = XCONS (elt)->cdr;
- if (CONSP (value) && MARKERP (XCONS (value)->car)
- && XMARKER (XCONS (value)->car)->buffer == buf)
- Fx_disown_selection_internal (XCONS (elt)->car, Qnil);
- }
-}
-
-DEFUN ("x-selection-owner-p", Fx_selection_owner_p, Sx_selection_owner_p,
- 0, 1, 0,
- "Whether the current Emacs process owns the given X Selection.\n\
-The arg should be the name of the selection in question, typically one of\n\
-the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
-\(Those are literal upper-case symbol names, since that's what X expects.)\n\
-For convenience, the symbol nil is the same as `PRIMARY',\n\
-and t is the same as `SECONDARY'.)")
- (selection)
- Lisp_Object selection;
-{
- check_x ();
- CHECK_SYMBOL (selection, 0);
- if (EQ (selection, Qnil)) selection = QPRIMARY;
- if (EQ (selection, Qt)) selection = QSECONDARY;
-
- if (NILP (Fassq (selection, Vselection_alist)))
- return Qnil;
- return Qt;
-}
-
-DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
- 0, 1, 0,
- "Whether there is an owner for the given X Selection.\n\
-The arg should be the name of the selection in question, typically one of\n\
-the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
-\(Those are literal upper-case symbol names, since that's what X expects.)\n\
-For convenience, the symbol nil is the same as `PRIMARY',\n\
-and t is the same as `SECONDARY'.)")
- (selection)
- Lisp_Object selection;
-{
- Window owner;
- Atom atom;
- Display *dpy;
-
- /* It should be safe to call this before we have an X frame. */
- if (! FRAME_X_P (selected_frame))
- return Qnil;
-
- dpy = FRAME_X_DISPLAY (selected_frame);
- CHECK_SYMBOL (selection, 0);
- if (!NILP (Fx_selection_owner_p (selection)))
- return Qt;
- if (EQ (selection, Qnil)) selection = QPRIMARY;
- if (EQ (selection, Qt)) selection = QSECONDARY;
- atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (selected_frame),
- dpy, selection);
- if (atom == 0)
- return Qnil;
- BLOCK_INPUT;
- owner = XGetSelectionOwner (dpy, atom);
- UNBLOCK_INPUT;
- return (owner ? Qt : Qnil);
-}
-
-
-#ifdef CUT_BUFFER_SUPPORT
-
-/* Ensure that all 8 cut buffers exist. ICCCM says we gotta... */
-static void
-initialize_cut_buffers (display, window)
- Display *display;
- Window window;
-{
- unsigned char *data = (unsigned char *) "";
- BLOCK_INPUT;
-#define FROB(atom) XChangeProperty (display, window, atom, XA_STRING, 8, \
- PropModeAppend, data, 0)
- FROB (XA_CUT_BUFFER0);
- FROB (XA_CUT_BUFFER1);
- FROB (XA_CUT_BUFFER2);
- FROB (XA_CUT_BUFFER3);
- FROB (XA_CUT_BUFFER4);
- FROB (XA_CUT_BUFFER5);
- FROB (XA_CUT_BUFFER6);
- FROB (XA_CUT_BUFFER7);
-#undef FROB
- UNBLOCK_INPUT;
-}
-
-
-#define CHECK_CUT_BUFFER(symbol,n) \
- { CHECK_SYMBOL ((symbol), (n)); \
- if (!EQ((symbol), QCUT_BUFFER0) && !EQ((symbol), QCUT_BUFFER1) \
- && !EQ((symbol), QCUT_BUFFER2) && !EQ((symbol), QCUT_BUFFER3) \
- && !EQ((symbol), QCUT_BUFFER4) && !EQ((symbol), QCUT_BUFFER5) \
- && !EQ((symbol), QCUT_BUFFER6) && !EQ((symbol), QCUT_BUFFER7)) \
- Fsignal (Qerror, \
- Fcons (build_string ("doesn't name a cut buffer"), \
- Fcons ((symbol), Qnil))); \
- }
-
-DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
- Sx_get_cut_buffer_internal, 1, 1, 0,
- "Returns the value of the named cut buffer (typically CUT_BUFFER0).")
- (buffer)
- Lisp_Object buffer;
-{
- Window window;
- Atom buffer_atom;
- unsigned char *data;
- int bytes;
- Atom type;
- int format;
- unsigned long size;
- Lisp_Object ret;
- Display *display;
- struct x_display_info *dpyinfo;
-
- check_x ();
- display = FRAME_X_DISPLAY (selected_frame);
- dpyinfo = FRAME_X_DISPLAY_INFO (selected_frame);
- window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
- CHECK_CUT_BUFFER (buffer, 0);
- buffer_atom = symbol_to_x_atom (dpyinfo, display, buffer);
-
- x_get_window_property (display, window, buffer_atom, &data, &bytes,
- &type, &format, &size, 0);
- if (!data) return Qnil;
-
- if (format != 8 || type != XA_STRING)
- Fsignal (Qerror,
- Fcons (build_string ("cut buffer doesn't contain 8-bit data"),
- Fcons (x_atom_to_symbol (dpyinfo, display, type),
- Fcons (make_number (format), Qnil))));
-
- ret = (bytes ? make_string ((char *) data, bytes) : Qnil);
- /* Use free, not XFree, because x_get_window_property
- calls xmalloc itself. */
- free (data);
- return ret;
-}
-
-
-DEFUN ("x-store-cut-buffer-internal", Fx_store_cut_buffer_internal,
- Sx_store_cut_buffer_internal, 2, 2, 0,
- "Sets the value of the named cut buffer (typically CUT_BUFFER0).")
- (buffer, string)
- Lisp_Object buffer, string;
-{
- Window window;
- Atom buffer_atom;
- unsigned char *data;
- int bytes;
- int bytes_remaining;
- int max_bytes;
- Display *display;
-
- check_x ();
- display = FRAME_X_DISPLAY (selected_frame);
- window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
-
- max_bytes = SELECTION_QUANTUM (display);
- if (max_bytes > MAX_SELECTION_QUANTUM)
- max_bytes = MAX_SELECTION_QUANTUM;
-
- CHECK_CUT_BUFFER (buffer, 0);
- CHECK_STRING (string, 0);
- buffer_atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (selected_frame),
- display, buffer);
- data = (unsigned char *) XSTRING (string)->data;
- bytes = XSTRING (string)->size;
- bytes_remaining = bytes;
-
- if (! FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized)
- {
- initialize_cut_buffers (display, window);
- FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized = 1;
- }
-
- BLOCK_INPUT;
-
- /* Don't mess up with an empty value. */
- if (!bytes_remaining)
- XChangeProperty (display, window, buffer_atom, XA_STRING, 8,
- PropModeReplace, data, 0);
-
- while (bytes_remaining)
- {
- int chunk = (bytes_remaining < max_bytes
- ? bytes_remaining : max_bytes);
- XChangeProperty (display, window, buffer_atom, XA_STRING, 8,
- (bytes_remaining == bytes
- ? PropModeReplace
- : PropModeAppend),
- data, chunk);
- data += chunk;
- bytes_remaining -= chunk;
- }
- UNBLOCK_INPUT;
- return string;
-}
-
-
-DEFUN ("x-rotate-cut-buffers-internal", Fx_rotate_cut_buffers_internal,
- Sx_rotate_cut_buffers_internal, 1, 1, 0,
- "Rotate the values of the cut buffers by the given number of steps;\n\
-positive means move values forward, negative means backward.")
- (n)
- Lisp_Object n;
-{
- Window window;
- Atom props[8];
- Display *display;
-
- check_x ();
- display = FRAME_X_DISPLAY (selected_frame);
- window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
- CHECK_NUMBER (n, 0);
- if (XINT (n) == 0)
- return n;
- if (! FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized)
- {
- initialize_cut_buffers (display, window);
- FRAME_X_DISPLAY_INFO (selected_frame)->cut_buffers_initialized = 1;
- }
-
- props[0] = XA_CUT_BUFFER0;
- props[1] = XA_CUT_BUFFER1;
- props[2] = XA_CUT_BUFFER2;
- props[3] = XA_CUT_BUFFER3;
- props[4] = XA_CUT_BUFFER4;
- props[5] = XA_CUT_BUFFER5;
- props[6] = XA_CUT_BUFFER6;
- props[7] = XA_CUT_BUFFER7;
- BLOCK_INPUT;
- XRotateWindowProperties (display, window, props, 8, XINT (n));
- UNBLOCK_INPUT;
- return n;
-}
-
-#endif
-
-void
-syms_of_xselect ()
-{
- defsubr (&Sx_get_selection_internal);
- defsubr (&Sx_own_selection_internal);
- defsubr (&Sx_disown_selection_internal);
- defsubr (&Sx_selection_owner_p);
- defsubr (&Sx_selection_exists_p);
-
-#ifdef CUT_BUFFER_SUPPORT
- defsubr (&Sx_get_cut_buffer_internal);
- defsubr (&Sx_store_cut_buffer_internal);
- defsubr (&Sx_rotate_cut_buffers_internal);
-#endif
-
- reading_selection_reply = Fcons (Qnil, Qnil);
- staticpro (&reading_selection_reply);
- reading_selection_window = 0;
- reading_which_selection = 0;
-
- property_change_wait_list = 0;
- prop_location_identifier = 0;
- property_change_reply = Fcons (Qnil, Qnil);
- staticpro (&property_change_reply);
-
- Vselection_alist = Qnil;
- staticpro (&Vselection_alist);
-
- DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist,
- "An alist associating X Windows selection-types with functions.\n\
-These functions are called to convert the selection, with three args:\n\
-the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
-a desired type to which the selection should be converted;\n\
-and the local selection value (whatever was given to `x-own-selection').\n\
-\n\
-The function should return the value to send to the X server\n\
-\(typically a string). A return value of nil\n\
-means that the conversion could not be done.\n\
-A return value which is the symbol `NULL'\n\
-means that a side-effect was executed,\n\
-and there is no meaningful selection value.");
- Vselection_converter_alist = Qnil;
-
- DEFVAR_LISP ("x-lost-selection-hooks", &Vx_lost_selection_hooks,
- "A list of functions to be called when Emacs loses an X selection.\n\
-\(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').");
- Vx_lost_selection_hooks = Qnil;
-
- DEFVAR_LISP ("x-sent-selection-hooks", &Vx_sent_selection_hooks,
- "A list of functions to be called when Emacs answers a selection request.\n\
-The functions are called with four arguments:\n\
- - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
- - the selection-type which Emacs was asked to convert the\n\
- selection into before sending (for example, `STRING' or `LENGTH');\n\
- - a flag indicating success or failure for responding to the request.\n\
-We might have failed (and declined the request) for any number of reasons,\n\
-including being asked for a selection that we no longer own, or being asked\n\
-to convert into a type that we don't know about or that is inappropriate.\n\
-This hook doesn't let you change the behavior of Emacs's selection replies,\n\
-it merely informs you that they have happened.");
- Vx_sent_selection_hooks = Qnil;
-
- DEFVAR_INT ("x-selection-timeout", &x_selection_timeout,
- "Number of milliseconds to wait for a selection reply.\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;
-
- QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY);
- QSECONDARY = intern ("SECONDARY"); staticpro (&QSECONDARY);
- QSTRING = intern ("STRING"); staticpro (&QSTRING);
- QINTEGER = intern ("INTEGER"); staticpro (&QINTEGER);
- QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
- QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP);
- QTEXT = intern ("TEXT"); staticpro (&QTEXT);
- QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP);
- QDELETE = intern ("DELETE"); staticpro (&QDELETE);
- QMULTIPLE = intern ("MULTIPLE"); staticpro (&QMULTIPLE);
- QINCR = intern ("INCR"); staticpro (&QINCR);
- QEMACS_TMP = intern ("_EMACS_TMP_"); staticpro (&QEMACS_TMP);
- QTARGETS = intern ("TARGETS"); staticpro (&QTARGETS);
- QATOM = intern ("ATOM"); staticpro (&QATOM);
- QATOM_PAIR = intern ("ATOM_PAIR"); staticpro (&QATOM_PAIR);
- QNULL = intern ("NULL"); staticpro (&QNULL);
-
-#ifdef CUT_BUFFER_SUPPORT
- QCUT_BUFFER0 = intern ("CUT_BUFFER0"); staticpro (&QCUT_BUFFER0);
- QCUT_BUFFER1 = intern ("CUT_BUFFER1"); staticpro (&QCUT_BUFFER1);
- QCUT_BUFFER2 = intern ("CUT_BUFFER2"); staticpro (&QCUT_BUFFER2);
- QCUT_BUFFER3 = intern ("CUT_BUFFER3"); staticpro (&QCUT_BUFFER3);
- QCUT_BUFFER4 = intern ("CUT_BUFFER4"); staticpro (&QCUT_BUFFER4);
- QCUT_BUFFER5 = intern ("CUT_BUFFER5"); staticpro (&QCUT_BUFFER5);
- QCUT_BUFFER6 = intern ("CUT_BUFFER6"); staticpro (&QCUT_BUFFER6);
- QCUT_BUFFER7 = intern ("CUT_BUFFER7"); staticpro (&QCUT_BUFFER7);
-#endif
-
-}