summaryrefslogtreecommitdiff
path: root/src/=xselect.c.old
diff options
context:
space:
mode:
authorJim Blandy <jimb@redhat.com>1991-01-05 19:03:03 +0000
committerJim Blandy <jimb@redhat.com>1991-01-05 19:03:03 +0000
commitef2d40100a0fd262819a13ce549e2a3941dc2325 (patch)
tree701706279c4c3bddacff2aadb5a69d4400ceede8 /src/=xselect.c.old
parentf307a3f0e99d8034c5a118f06f85e1c75b1c0300 (diff)
downloademacs-ef2d40100a0fd262819a13ce549e2a3941dc2325.tar.gz
Initial revision
Diffstat (limited to 'src/=xselect.c.old')
-rw-r--r--src/=xselect.c.old666
1 files changed, 666 insertions, 0 deletions
diff --git a/src/=xselect.c.old b/src/=xselect.c.old
new file mode 100644
index 00000000000..8d3e3d12fc4
--- /dev/null
+++ b/src/=xselect.c.old
@@ -0,0 +1,666 @@
+/* X Selection processing for emacs
+ Copyright (C) 1990 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "config.h"
+#include "lisp.h"
+#include "xterm.h"
+#include "screen.h"
+
+#ifdef HAVE_X11
+
+/* Macros for X Selections */
+#define MAX_SELECTION(dpy) (((dpy)->max_request_size << 3) - 100)
+#define SELECTION_LENGTH(len,format) ((len) * ((format) >> 3))
+
+/* The last 23 bits of the timestamp of the last mouse button event. */
+extern Time mouse_timestamp;
+
+/* t if a mouse button is depressed. */
+
+extern Lisp_Object Vmouse_grabbed;
+
+/* When emacs became the PRIMARY selection owner. */
+Time x_begin_selection_own;
+
+/* When emacs became the CLIPBOARD selection owner. */
+Time x_begin_clipboard_own;
+
+/* The value of the current CLIPBOARD selection. */
+Lisp_Object Vx_clipboard_value;
+
+/* The value of the current PRIMARY selection. */
+Lisp_Object Vx_selection_value;
+
+/* Emacs' selection property identifier. */
+Atom Xatom_emacs_selection;
+
+/* Clipboard selection atom. */
+Atom Xatom_clipboard_selection;
+
+/* Clipboard atom. */
+Atom Xatom_clipboard;
+
+/* Atom for indicating incremental selection transfer. */
+Atom Xatom_incremental;
+
+/* Atom for indicating multiple selection request list */
+Atom Xatom_multiple;
+
+/* Atom for what targets emacs handles. */
+Atom Xatom_targets;
+
+/* Atom for indicating timstamp selection request */
+Atom Xatom_timestamp;
+
+/* Atom requesting we delete our selection. */
+Atom Xatom_delete;
+
+/* Selection magic. */
+Atom Xatom_insert_selection;
+
+/* Type of property for INSERT_SELECTION. */
+Atom Xatom_pair;
+
+/* More selection magic. */
+Atom Xatom_insert_property;
+
+/* Atom for indicating property type TEXT */
+Atom Xatom_text;
+
+/* These are to handle incremental selection transfer. */
+Window incr_requestor;
+Atom incr_property;
+int incr_nbytes;
+unsigned char *incr_value;
+unsigned char *incr_ptr;
+
+/* SELECTION OWNER CODE */
+
+/* Become the selection owner and make our data the selection value.
+ If we are already the owner, merely change data and timestamp values.
+ This avoids generating SelectionClear events for ourselves. */
+
+DEFUN ("x-own-selection", Fx_own_selection, Sx_own_selection,
+ 1, 1, "sStore text for pasting: ",
+ "Stores string STRING for pasting in another X window.\n\
+This is done with the X11 selection mechanism.")
+ (string)
+ register Lisp_Object string;
+{
+ Window owner_window, selecting_window;
+ Time event_time;
+
+ CHECK_STRING (string, 0);
+
+ BLOCK_INPUT;
+ selecting_window = selected_screen->display.x->window_desc;
+
+ if (EQ (Qnil, Vx_selection_value)) /* We are not the owner. */
+ {
+ event_time = mouse_timestamp;
+ XSetSelectionOwner (x_current_display, XA_PRIMARY,
+ selecting_window, event_time);
+ owner_window = XGetSelectionOwner (x_current_display, XA_PRIMARY);
+
+ if (owner_window != selecting_window)
+ {
+ UNBLOCK_INPUT;
+ error ("X error: could not acquire selection ownership");
+ }
+ }
+
+ x_begin_selection_own = event_time;
+ Vx_selection_value = string;
+ UNBLOCK_INPUT;
+
+ return Qnil;
+}
+
+/* CLIPBOARD OWNERSHIP */
+
+DEFUN ("x-own-clipboard", Fx_own_clipboard, Sx_own_clipboard,
+ 1, 1, "sCLIPBOARD string: ",
+ "Assert X clipboard ownership with value STRING.")
+ (string)
+ register Lisp_Object string;
+{
+ Window owner_window, selecting_window;
+ Time event_time;
+
+ CHECK_STRING (string, 0);
+
+ BLOCK_INPUT;
+ selecting_window = selected_screen->display.x->window_desc;
+
+ if (EQ (Qnil, Vx_clipboard_value))
+ {
+ event_time = mouse_timestamp;
+ XSetSelectionOwner (x_current_display, Xatom_clipboard,
+ selecting_window, event_time);
+ owner_window = XGetSelectionOwner (x_current_display, Xatom_clipboard);
+
+ if (owner_window != selecting_window)
+ {
+ UNBLOCK_INPUT;
+ error ("X error: could not acquire selection ownership");
+ }
+ }
+
+ x_begin_clipboard_own = event_time;
+ Vx_clipboard_value = string;
+ UNBLOCK_INPUT;
+
+ return Qnil;
+}
+
+/* Clear our selection ownership data, as some other client has
+ become the owner. */
+
+void
+x_disown_selection (old_owner, selection, changed_owner_time)
+ Window *old_owner;
+ Atom selection;
+ Time changed_owner_time;
+{
+ struct screen *s = x_window_to_screen (old_owner);
+
+ if (s) /* We are the owner */
+ {
+ if (selection == XA_PRIMARY)
+ {
+ x_begin_selection_own = 0;
+ Vx_selection_value = Qnil;
+ }
+ else if (selection == Xatom_clipboard)
+ {
+ x_begin_clipboard_own = 0;
+ Vx_clipboard_value = Qnil;
+ }
+ else
+ abort ();
+ }
+ else
+ abort (); /* Inconsistent state. */
+}
+
+int x_selection_alloc_error;
+int x_converting_selection;
+
+/* Reply to some client's request for our selection data. Data is
+ placed in a propery supplied by the requesting window.
+
+ If the data exceeds the maximum amount the server can send,
+ then prepare to send it incrementally, and reply to the client with
+ the total size of the data.
+
+ But first, check for all the other crufty stuff we could get. */
+
+void
+x_answer_selection_request (event)
+ XSelectionRequestEvent event;
+{
+ Time emacs_own_time;
+ Lisp_Object selection_value;
+ XSelectionEvent evt;
+ int format = 8; /* We have only byte sized (text) data. */
+
+ evt.type = SelectionNotify; /* Construct reply event */
+ evt.display = event.display;
+ evt.requestor = event.requestor;
+ evt.selection = event.selection;
+ evt.time = event.time;
+ evt.target = event.target;
+
+ if (event.selection == XA_PRIMARY)
+ {
+ emacs_own_time = x_begin_selection_own;
+ selection_value = Vx_selection_value;
+ }
+ else if (event.selection == Xatom_clipboard)
+ {
+ emacs_own_time = x_begin_clipboard_own;
+ selection_value = Vx_clipboard_value;
+ }
+ else
+ abort ();
+
+ if (event.time != CurrentTime
+ && event.time < emacs_own_time)
+ evt.property = None;
+ else
+ {
+ if (event.property == None) /* obsolete client */
+ evt.property = event.target;
+ else
+ evt.property = event.property;
+ }
+
+ if (event.target == Xatom_targets) /* Send List of target atoms */
+ {
+ }
+ else if (event.target == Xatom_multiple) /* Recvd list: <target, prop> */
+ {
+ Atom type;
+ int return_format;
+ unsigned long items, bytes_left;
+ unsigned char *data;
+ int result, i;
+
+ if (event.property == 0 /* 0 == NULL */
+ || event.property == None)
+ return;
+
+ result = XGetWindowProperty (event.display, event.requestor,
+ event.property, 0L, 10000000L,
+ True, Xatom_pair, &type, &return_format,
+ &items, &bytes_left, &data);
+
+ if (result == Success && type == Xatom_pair)
+ for (i = items; i > 0; i--)
+ {
+ /* Convert each element of the list. */
+ }
+
+ (void) XSendEvent (x_current_display, evt.requestor, False,
+ 0L, (XEvent *) &evt);
+ return;
+ }
+ else if (event.target == Xatom_timestamp) /* Send ownership timestamp */
+ {
+ if (! emacs_own_time)
+ abort ();
+
+ format = 32;
+ XChangeProperty (evt.display, evt.requestor, evt.property,
+ evt.target, format, PropModeReplace,
+ (unsigned char *) &emacs_own_time, format);
+ return;
+ }
+ else if (event.target == Xatom_delete) /* Delete our selection. */
+ {
+ if (EQ (Qnil, selection_value))
+ abort ();
+
+ x_disown_selection (event.owner, event.selection, event.time);
+
+ /* Now return property of type NULL, length 0. */
+ XChangeProperty (event.display, event.requestor, event.property,
+ 0, format, PropModeReplace, (unsigned char *) 0, 0);
+ return;
+ }
+ else if (event.target == Xatom_insert_selection)
+ {
+ Atom type;
+ int return_format;
+ unsigned long items, bytes_left;
+ unsigned char *data;
+ int result = XGetWindowProperty (event.display, event.requestor,
+ event.property, 0L, 10000000L,
+ True, Xatom_pair, &type, &return_format,
+ &items, &bytes_left, &data);
+ if (result == Success && type == Xatom_pair)
+ {
+ /* Convert the first atom to (a selection) to the target
+ indicated by the second atom. */
+ }
+ }
+ else if (event.target == Xatom_insert_property)
+ {
+ Atom type;
+ int return_format;
+ unsigned long items, bytes_left;
+ unsigned char *data;
+ int result = XGetWindowProperty (event.display, event.requestor,
+ event.property, 0L, 10000000L,
+ True, XA_STRING, &type, &return_format,
+ &items, &bytes_left, &data);
+
+ if (result == Success && type == XA_STRING && return_format == 8)
+ {
+ if (event.selection == Xatom_emacs_selection)
+ Vx_selection_value = make_string (data);
+ else if (event.selection == Xatom_clipboard_selection)
+ Vx_clipboard_value = make_string (data);
+ else
+ abort ();
+ }
+
+ return;
+ }
+ else if ((event.target == Xatom_text
+ || event.target == XA_STRING))
+ {
+ int size = XSTRING (selection_value)->size;
+ unsigned char *data = XSTRING (selection_value)->data;
+
+ if (EQ (Qnil, selection_value))
+ abort ();
+
+ /* Place data on requestor window's property. */
+ if (SELECTION_LENGTH (size, format)
+ <= MAX_SELECTION (x_current_display))
+ {
+ x_converting_selection = 1;
+ XChangeProperty (evt.display, evt.requestor, evt.property,
+ evt.target, format, PropModeReplace,
+ data, size);
+ if (x_selection_alloc_error)
+ {
+ x_selection_alloc_error = 0;
+ abort ();
+ }
+ x_converting_selection = 0;
+ }
+ else /* Send incrementally */
+ {
+ evt.target = Xatom_incremental;
+ incr_requestor = evt.requestor;
+ incr_property = evt.property;
+ x_converting_selection = 1;
+
+ /* Need to handle Alloc errors on these requests. */
+ XChangeProperty (evt.display, incr_requestor, incr_property,
+ Xatom_incremental, 32,
+ PropModeReplace,
+ (unsigned char *) &size, 1);
+ if (x_selection_alloc_error)
+ {
+ x_selection_alloc_error = 0;
+ x_converting_selection = 0;
+ abort ();
+ /* Now abort the send. */
+ }
+
+ incr_nbytes = size;
+ incr_value = data;
+ incr_ptr = data;
+
+ /* Ask for notification when requestor deletes property. */
+ XSelectInput (x_current_display, incr_requestor, PropertyChangeMask);
+
+ /* If we're sending incrementally, perhaps block here
+ until all sent? */
+ }
+ }
+ else
+ evt.property = None;
+
+ /* Don't do this if there was an Alloc error: abort the transfer
+ by sending None. */
+ (void) XSendEvent (x_current_display, evt.requestor, False,
+ 0L, (XEvent *) &evt);
+}
+
+/* Send an increment of selection data in response to a PropertyNotify event.
+ The increment is placed in a property on the requestor's window.
+ When the requestor has processed the increment, it deletes the property,
+ which sends us another PropertyNotify event.
+
+ When there is no more data to send, we send a zero-length increment. */
+
+void
+x_send_incremental (event)
+ XPropertyEvent event;
+{
+ if (incr_requestor
+ && incr_requestor == event.window
+ && incr_property == event.atom
+ && event.state == PropertyDelete)
+ {
+ int format = 8;
+ int length = MAX_SELECTION (x_current_display);
+ int bytes_left = (incr_nbytes - (incr_ptr - incr_value));
+
+ if (length > bytes_left) /* Also sends 0 len when finished. */
+ length = bytes_left;
+ XChangeProperty (x_current_display, incr_requestor,
+ incr_property, XA_STRING, format,
+ PropModeAppend, incr_ptr, length);
+ if (x_selection_alloc_error)
+ {
+ x_selection_alloc_error = 0;
+ x_converting_selection = 0;
+ /* Abandon the transmission. */
+ abort ();
+ }
+ if (length > 0)
+ incr_ptr += length;
+ else
+ { /* Everything's sent */
+ XSelectInput (x_current_display, incr_requestor, 0L);
+ incr_requestor = (Window) 0;
+ incr_property = (Atom) 0;
+ incr_nbytes = 0;
+ incr_value = (unsigned char *) 0;
+ incr_ptr = (unsigned char *) 0;
+ x_converting_selection = 0;
+ }
+ }
+}
+
+/* SELECTION REQUESTOR CODE */
+
+/* Predicate function used to match a requested event. */
+
+Bool
+XCheckSelectionEvent (dpy, event, window)
+ Display *dpy;
+ XEvent *event;
+ char *window;
+{
+ if (event->type == SelectionNotify)
+ if (event->xselection.requestor == (Window) window)
+ return True;
+
+ return False;
+}
+
+/* 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", Fx_get_selection, Sx_get_selection, 0, 0, 0,
+ "Return text selected from some X window.\n\
+This is done with the X11 selection mechanism.")
+ ()
+{
+ XEvent event;
+ Lisp_Object val;
+ Time requestor_time; /* Timestamp of selection request. */
+ Window requestor_window;
+
+ if (!EQ (Qnil, Vx_selection_value)) /* We are the owner */
+ return Vx_selection_value;
+
+ BLOCK_INPUT;
+ requestor_time = mouse_timestamp;
+ requestor_window = selected_screen->display.x->window_desc;
+ XConvertSelection (x_current_display, XA_PRIMARY, XA_STRING,
+ Xatom_emacs_selection, requestor_window, requestor_time);
+ XIfEvent (x_current_display,
+ &event,
+ XCheckSelectionEvent,
+ (char *) requestor_window);
+ val = x_selection_arrival (&event, requestor_window, requestor_time);
+ UNBLOCK_INPUT;
+
+ return val;
+}
+
+/* Request the clipboard contents from its owner. If we are the owner,
+ simply return the clipboard string. */
+
+DEFUN ("x-get-clipboard", Fx_get_clipboard, Sx_get_clipboard, 0, 0, 0,
+ "Return text pasted to the clipboard.\n\
+This is done with the X11 selection mechanism.")
+ ()
+{
+ XEvent event;
+ Lisp_Object val;
+ Time requestor_time; /* Timestamp of selection request. */
+ Window requestor_window;
+
+ if (!EQ (Qnil, Vx_clipboard_value)) /* We are the owner */
+ return Vx_selection_value;
+
+ BLOCK_INPUT;
+ requestor_time = mouse_timestamp;
+ requestor_window = selected_screen->display.x->window_desc;
+ XConvertSelection (x_current_display, Xatom_clipboard, XA_STRING,
+ Xatom_clipboard_selection,
+ requestor_window, requestor_time);
+ XIfEvent (x_current_display,
+ &event,
+ XCheckSelectionEvent,
+ (char *) requestor_window);
+ val = x_selection_arrival (&event, requestor_window, requestor_time);
+ UNBLOCK_INPUT;
+
+ return val;
+}
+
+Lisp_Object
+x_selection_arrival (event, requestor_window, requestor_time)
+ register XSelectionEvent *event;
+ Window requestor_window;
+ Time requestor_time;
+{
+ int result;
+ Atom type, selection;
+ int format;
+ unsigned long items;
+ unsigned long bytes_left;
+ unsigned char *data = 0;
+ int offset = 0;
+
+ if (event->selection == XA_PRIMARY)
+ selection = Xatom_emacs_selection;
+ else if (event->selection == Xatom_clipboard)
+ selection = Xatom_clipboard_selection;
+ else
+ abort ();
+
+ if (event->requestor == requestor_window
+ && event->time == requestor_time
+ && event->property != None)
+ if (event->target != Xatom_incremental)
+ {
+ unsigned char *return_string =
+ (unsigned char *) alloca (MAX_SELECTION (x_current_display));
+
+ do
+ {
+ result = XGetWindowProperty (x_current_display,
+ requestor_window,
+ event->property, 0L,
+ 10000000L, True, XA_STRING,
+ &type, &format, &items,
+ &bytes_left, &data);
+ if (result == Success && type == XA_STRING && format == 8
+ && offset < MAX_SELECTION (x_current_display))
+ {
+ bcopy (data, return_string + offset, items);
+ offset += items;
+ }
+ XFree ((char *) data);
+ }
+ while (bytes_left);
+
+ return make_string (return_string, offset);
+ }
+ else /* Prepare incremental transfer. */
+ {
+ unsigned char *increment_value;
+ unsigned char *increment_ptr;
+ int total_size;
+ int *increment_nbytes = 0;
+
+ result = XGetWindowProperty (x_current_display, requestor_window,
+ selection, 0L, 10000000L, False,
+ event->property, &type, &format,
+ &items, &bytes_left,
+ (unsigned char **) &increment_nbytes);
+ if (result == Success)
+ {
+ XPropertyEvent property_event;
+
+ total_size = *increment_nbytes;
+ increment_value = (unsigned char *) alloca (total_size);
+ increment_ptr = increment_value;
+
+ XDeleteProperty (x_current_display, event->requestor,
+ event->property);
+ XFlush (x_current_display);
+ XFree ((char *) increment_nbytes);
+
+ do
+ { /* NOTE: this blocks. */
+ XWindowEvent (x_current_display, requestor_window,
+ PropertyChangeMask,
+ (XEvent *) &property_event);
+
+ if (property_event.atom == selection
+ && property_event.state == PropertyNewValue)
+ do
+ {
+ result = XGetWindowProperty (x_current_display,
+ requestor_window,
+ selection, 0L,
+ 10000000L, True,
+ AnyPropertyType,
+ &type, &format,
+ &items, &bytes_left,
+ &data);
+ if (result == Success && type == XA_STRING
+ && format == 8)
+ {
+ bcopy (data, increment_ptr, items);
+ increment_ptr += items;
+ }
+ }
+ while (bytes_left);
+
+ }
+ while (increment_ptr < (increment_value + total_size));
+
+ return make_string (increment_value,
+ (increment_ptr - increment_value));
+ }
+ }
+
+ return Qnil;
+}
+
+void
+syms_of_xselect ()
+{
+ DEFVAR_LISP ("x-selection-value", &Vx_selection_value,
+ "The value of emacs' last cut-string.");
+ Vx_selection_value = Qnil;
+
+ DEFVAR_LISP ("x-clipboard-value", &Vx_clipboard_value,
+ "The string emacs last sent to the clipboard.");
+ Vx_clipboard_value = Qnil;
+
+ defsubr (&Sx_own_selection);
+ defsubr (&Sx_get_selection);
+ defsubr (&Sx_own_clipboard);
+ defsubr (&Sx_get_clipboard);
+}
+#endif /* X11 */