X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/929bb973dd3faf1655f03ac758942d5b009354ad..6d12ff8b3344d4284f78e0be56cda076f9a3d6e7:/src/xselect.c diff --git a/src/xselect.c b/src/xselect.c index 9eee4ee959..5a3b7452c6 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -1,5 +1,5 @@ /* X Selection processing for Emacs. - Copyright (C) 1993-1997, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1993-1997, 2000-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -35,11 +35,11 @@ along with GNU Emacs. If not, see . */ #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" +#include "character.h" #include "buffer.h" #include "process.h" #include "termhooks.h" #include "keyboard.h" -#include "character.h" #include @@ -180,16 +180,11 @@ x_queue_event (struct input_event *event) } } - queue_tmp - = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue)); - - if (queue_tmp != NULL) - { - TRACE1 ("QUEUE SELECTION EVENT %p", queue_tmp); - queue_tmp->event = *event; - queue_tmp->next = selection_queue; - selection_queue = queue_tmp; - } + queue_tmp = xmalloc (sizeof *queue_tmp); + TRACE1 ("QUEUE SELECTION EVENT %p", queue_tmp); + queue_tmp->event = *event; + queue_tmp->next = selection_queue; + selection_queue = queue_tmp; } /* Start queuing SELECTION_REQUEST_EVENT events. */ @@ -198,7 +193,7 @@ static void x_start_queuing_selection_requests (void) { if (x_queue_selection_requests) - abort (); + emacs_abort (); x_queue_selection_requests++; TRACE1 ("x_start_queuing_selection_requests %d", x_queue_selection_requests); @@ -221,7 +216,7 @@ x_stop_queuing_selection_requests (void) TRACE1 ("RESTORE SELECTION EVENT %p", queue_tmp); kbd_buffer_unget_event (&queue_tmp->event); selection_queue = queue_tmp->next; - xfree ((char *)queue_tmp); + xfree (queue_tmp); } } @@ -250,7 +245,7 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym) 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; - if (!SYMBOLP (sym)) abort (); + if (!SYMBOLP (sym)) emacs_abort (); TRACE1 (" XInternAtom %s", SSDATA (SYMBOL_NAME (sym))); BLOCK_INPUT; @@ -358,8 +353,9 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, INTEGER_TO_CONS (timestamp), frame); prev_value = LOCAL_SELECTION (selection_name, dpyinfo); - dpyinfo->terminal->Vselection_alist - = Fcons (selection_data, dpyinfo->terminal->Vselection_alist); + tset_selection_alist + (dpyinfo->terminal, + Fcons (selection_data, dpyinfo->terminal->Vselection_alist)); /* If we already owned the selection, remove the old selection data. Don't use Fdelq as that may QUIT. */ @@ -515,7 +511,7 @@ static struct selection_data *converted_selections; static Atom conversion_fail_tag; /* 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 + an error, we tell the requestor 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 @@ -692,7 +688,7 @@ x_reply_selection_request (struct input_event *event, bytes_remaining = cs->size; bytes_remaining *= format_bytes; - /* Wait for the requester to ack by deleting the property. + /* Wait for the requestor to ack by deleting the property. This can run Lisp code (process handlers) or signal. */ if (! had_errors) { @@ -731,7 +727,7 @@ x_reply_selection_request (struct input_event *event, if (had_errors) break; - /* Wait for the requester to ack this chunk by deleting + /* Wait for the requestor to ack this chunk by deleting the property. This can run Lisp code or signal. */ TRACE1 ("Waiting for increment ACK (deletion of %s)", XGetAtomName (display, cs->property)); @@ -739,7 +735,7 @@ x_reply_selection_request (struct input_event *event, } /* Now write a zero-length chunk to the property to tell the - requester that we're done. */ + requestor that we're done. */ BLOCK_INPUT; if (! waiting_for_other_props_on_window (display, window)) XSelectInput (display, window, 0L); @@ -756,7 +752,7 @@ x_reply_selection_request (struct input_event *event, /* The window we're communicating with may have been deleted in the meantime (that's a real situation from a bug report). In this case, there may be events in the event queue still - refering to the deleted window, and we'll get a BadWindow error + referring to the deleted window, and we'll get a BadWindow error in XTread_socket when processing the events. I don't have an idea how to fix that. gerd, 2001-01-98. */ /* 2004-09-10: XSync and UNBLOCK so that possible protocol errors are @@ -912,7 +908,7 @@ x_convert_selection (struct input_event *event, Lisp_Object selection_symbol, { if (for_multiple) { - cs = xmalloc (sizeof (struct selection_data)); + cs = xmalloc (sizeof *cs); cs->data = (unsigned char *) &conversion_fail_tag; cs->size = 1; cs->format = 32; @@ -929,7 +925,8 @@ x_convert_selection (struct input_event *event, Lisp_Object selection_symbol, } /* Otherwise, record the converted selection to binary. */ - cs = xmalloc (sizeof (struct selection_data)); + cs = xmalloc (sizeof *cs); + cs->data = NULL; cs->nofree = 1; cs->property = property; cs->wait_object = NULL; @@ -993,7 +990,7 @@ x_handle_selection_clear (struct input_event *event) break; } } - dpyinfo->terminal->Vselection_alist = Vselection_alist; + tset_selection_alist (dpyinfo->terminal, Vselection_alist); /* Run the `x-lost-selection-functions' abnormal hook. */ { @@ -1043,7 +1040,7 @@ x_clear_frame_selections (FRAME_PTR f) args[1] = Fcar (Fcar (t->Vselection_alist)); Frun_hook_with_args (2, args); - t->Vselection_alist = XCDR (t->Vselection_alist); + tset_selection_alist (t, XCDR (t->Vselection_alist)); } /* Delete elements after the beginning of Vselection_alist. */ @@ -1084,7 +1081,7 @@ static struct prop_location * expect_property_change (Display *display, Window window, Atom property, int state) { - struct prop_location *pl = (struct prop_location *) xmalloc (sizeof *pl); + struct prop_location *pl = xmalloc (sizeof *pl); pl->identifier = ++prop_location_identifier; pl->display = display; pl->window = window; @@ -1138,11 +1135,10 @@ wait_for_property_change_unwind (Lisp_Object loc) static void wait_for_property_change (struct prop_location *location) { - int secs, usecs; ptrdiff_t count = SPECPDL_INDEX (); if (property_change_reply_object) - abort (); + emacs_abort (); /* Make sure to do unexpect_property_change if we quit or err. */ record_unwind_protect (wait_for_property_change_unwind, @@ -1155,10 +1151,11 @@ wait_for_property_change (struct prop_location *location) property_change_reply, because property_change_reply_object says so. */ if (! location->arrived) { - secs = x_selection_timeout / 1000; - usecs = (x_selection_timeout % 1000) * 1000; - TRACE2 (" Waiting %d secs, %d usecs", secs, usecs); - wait_reading_process_output (secs, usecs, 0, 0, + EMACS_INT timeout = max (0, x_selection_timeout); + EMACS_INT secs = timeout / 1000; + int nsecs = (timeout % 1000) * 1000000; + TRACE2 (" Waiting %"pI"d secs, %d nsecs", secs, nsecs); + wait_reading_process_output (secs, nsecs, 0, 0, property_change_reply, NULL, 0); if (NILP (XCAR (property_change_reply))) @@ -1227,7 +1224,8 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, Atom type_atom = (CONSP (target_type) ? symbol_to_x_atom (dpyinfo, XCAR (target_type)) : symbol_to_x_atom (dpyinfo, target_type)); - int secs, usecs; + EMACS_INT timeout, secs; + int nsecs; if (!FRAME_LIVE_P (f)) return Qnil; @@ -1263,10 +1261,11 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, UNBLOCK_INPUT; /* This allows quits. Also, don't wait forever. */ - secs = x_selection_timeout / 1000; - usecs = (x_selection_timeout % 1000) * 1000; - TRACE1 (" Start waiting %d secs for SelectionNotify", secs); - wait_reading_process_output (secs, usecs, 0, 0, + timeout = max (0, x_selection_timeout); + secs = timeout / 1000; + nsecs = (timeout % 1000) * 1000000; + TRACE1 (" Start waiting %"pI"d secs for SelectionNotify", secs); + wait_reading_process_output (secs, nsecs, 0, 0, reading_selection_reply, NULL, 0); TRACE1 (" Got event = %d", !NILP (XCAR (reading_selection_reply))); @@ -1323,7 +1322,7 @@ x_get_window_property (Display *display, Window window, Atom property, goto done; /* This was allocated by Xlib, so use XFree. */ - XFree ((char *) tmp_data); + XFree (tmp_data); if (*actual_type_ret == None || *actual_format_ret == 0) goto done; @@ -1356,7 +1355,7 @@ x_get_window_property (Display *display, Window window, Atom property, break; bytes_per_item = *actual_format_ret >> 3; - xassert (*actual_size_ret <= buffer_size / bytes_per_item); + eassert (*actual_size_ret <= buffer_size / bytes_per_item); /* The man page for XGetWindowProperty says: "If the returned format is 32, the returned data is represented @@ -1405,7 +1404,7 @@ x_get_window_property (Display *display, Window window, Atom property, offset += bytes_gotten; /* This was allocated by Xlib, so use XFree. */ - XFree ((char *) tmp_data); + XFree (tmp_data); } XFlush (display); @@ -1443,7 +1442,7 @@ receive_incremental_selection (Display *display, Window window, Atom property, struct prop_location *wait_object; if (min (PTRDIFF_MAX, SIZE_MAX) < min_size_bytes) memory_full (SIZE_MAX); - *data_ret = (unsigned char *) xmalloc (min_size_bytes); + *data_ret = xmalloc (min_size_bytes); *size_bytes_ret = min_size_bytes; TRACE1 ("Read %u bytes incrementally", min_size_bytes); @@ -1570,7 +1569,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window, BLOCK_INPUT; /* Use xfree, not XFree, because x_get_window_property calls xmalloc itself. */ - xfree ((char *) data); + xfree (data); UNBLOCK_INPUT; receive_incremental_selection (display, window, property, target_type, min_size_bytes, &data, &bytes, @@ -1591,7 +1590,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window, /* Use xfree, not XFree, because x_get_window_property calls xmalloc itself. */ - xfree ((char *) data); + xfree (data); return val; } @@ -1777,20 +1776,24 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, } else if (SYMBOLP (obj)) { - *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1); + void *data = xmalloc (sizeof (Atom) + 1); + Atom *x_atom_ptr = data; + *data_ret = data; *format_ret = 32; *size_ret = 1; (*data_ret) [sizeof (Atom)] = 0; - (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, obj); + *x_atom_ptr = symbol_to_x_atom (dpyinfo, obj); if (NILP (type)) type = QATOM; } else if (RANGED_INTEGERP (X_SHRT_MIN, obj, X_SHRT_MAX)) { - *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1); + void *data = xmalloc (sizeof (short) + 1); + short *short_ptr = data; + *data_ret = data; *format_ret = 16; *size_ret = 1; (*data_ret) [sizeof (short)] = 0; - (*(short **) data_ret) [0] = XINT (obj); + *short_ptr = XINT (obj); if (NILP (type)) type = QINTEGER; } else if (INTEGERP (obj) @@ -1799,11 +1802,13 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, || (CONSP (XCDR (obj)) && INTEGERP (XCAR (XCDR (obj))))))) { - *data_ret = (unsigned char *) xmalloc (sizeof (unsigned long) + 1); + void *data = xmalloc (sizeof (unsigned long) + 1); + unsigned long *x_long_ptr = data; + *data_ret = data; *format_ret = 32; *size_ret = 1; (*data_ret) [sizeof (unsigned long)] = 0; - (*(unsigned long **) data_ret) [0] = cons_to_x_long (obj); + *x_long_ptr = cons_to_x_long (obj); if (NILP (type)) type = QINTEGER; } else if (VECTORP (obj)) @@ -1815,30 +1820,35 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, ptrdiff_t i; ptrdiff_t size = ASIZE (obj); - if (SYMBOLP (XVECTOR (obj)->contents [0])) + if (SYMBOLP (AREF (obj, 0))) /* This vector is an ATOM set */ { + void *data; + Atom *x_atoms; if (NILP (type)) type = QATOM; for (i = 0; i < size; i++) - if (!SYMBOLP (XVECTOR (obj)->contents [i])) + if (!SYMBOLP (AREF (obj, i))) signal_error ("All elements of selection vector must have same type", obj); - *data_ret = xnmalloc (size, sizeof (Atom)); + *data_ret = data = xnmalloc (size, sizeof *x_atoms); + x_atoms = data; *format_ret = 32; *size_ret = size; for (i = 0; i < size; i++) - (*(Atom **) data_ret) [i] - = symbol_to_x_atom (dpyinfo, XVECTOR (obj)->contents [i]); + x_atoms[i] = symbol_to_x_atom (dpyinfo, AREF (obj, i)); } else /* This vector is an INTEGER set, or something like it */ { int format = 16; int data_size = sizeof (short); + void *data; + unsigned long *x_atoms; + short *shorts; if (NILP (type)) type = QINTEGER; for (i = 0; i < size; i++) { - if (! RANGED_INTEGERP (X_SHRT_MIN, XVECTOR (obj)->contents[i], + if (! RANGED_INTEGERP (X_SHRT_MIN, AREF (obj, i), X_SHRT_MAX)) { /* Use sizeof (long) even if it is more than 32 bits. @@ -1849,17 +1859,17 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, break; } } - *data_ret = xnmalloc (size, data_size); + *data_ret = data = xnmalloc (size, data_size); + x_atoms = data; + shorts = data; *format_ret = format; *size_ret = size; for (i = 0; i < size; i++) { if (format == 32) - (*((unsigned long **) data_ret)) [i] = - cons_to_x_long (XVECTOR (obj)->contents[i]); + x_atoms[i] = cons_to_x_long (AREF (obj, i)); else - (*((short **) data_ret)) [i] = - XINT (XVECTOR (obj)->contents[i]); + shorts[i] = XINT (AREF (obj, i)); } } } @@ -1894,11 +1904,10 @@ clean_local_selection_data (Lisp_Object obj) ptrdiff_t size = ASIZE (obj); Lisp_Object copy; if (size == 1) - return clean_local_selection_data (XVECTOR (obj)->contents [0]); + return clean_local_selection_data (AREF (obj, 0)); copy = Fmake_vector (make_number (size), Qnil); for (i = 0; i < size; i++) - XVECTOR (copy)->contents [i] - = clean_local_selection_data (XVECTOR (obj)->contents [i]); + ASET (copy, i, clean_local_selection_data (AREF (obj, i))); return copy; } return obj; @@ -1981,7 +1990,9 @@ VALUE is typically a string, or a cons of two markers, but may be anything that the functions on `selection-converter-alist' know about. FRAME should be a frame that should own the selection. If omitted or -nil, it defaults to the selected frame. */) +nil, it defaults to the selected frame. + +On Nextstep, FRAME is unused. */) (Lisp_Object selection, Lisp_Object value, Lisp_Object frame) { if (NILP (frame)) frame = selected_frame; @@ -2002,15 +2013,18 @@ nil, it defaults to the selected frame. */) DEFUN ("x-get-selection-internal", Fx_get_selection_internal, Sx_get_selection_internal, 2, 4, 0, doc: /* Return text selected from some X window. -SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. +SELECTION-SYMBOL is typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. \(Those are literal upper-case symbol names, since that's what X expects.) -TYPE is the type of data desired, typically `STRING'. -TIME_STAMP is the time to use in the XConvertSelection call for foreign +TARGET-TYPE is the type of data desired, typically `STRING'. + +TIME-STAMP is the time to use in the XConvertSelection call for foreign selections. If omitted, defaults to the time for the last event. TERMINAL should be a terminal object or a frame specifying the X server to query. If omitted or nil, that stands for the selected -frame's display, or the first available X display. */) +frame's display, or the first available X display. + +On Nextstep, TIME-STAMP and TERMINAL are unused. */) (Lisp_Object selection_symbol, Lisp_Object target_type, Lisp_Object time_stamp, Lisp_Object terminal) { @@ -2051,9 +2065,15 @@ DEFUN ("x-disown-selection-internal", Fx_disown_selection_internal, doc: /* If we own the selection SELECTION, disown it. Disowning it means there is no such selection. +Sets the last-change time for the selection to TIME-OBJECT (by default +the time of the last event). + TERMINAL should be a terminal object or a frame specifying the X server to query. If omitted or nil, that stands for the selected -frame's display, or the first available X display. */) +frame's display, or the first available X display. + +On Nextstep, the TIME-OBJECT and TERMINAL arguments are unused. +On MS-DOS, all this does is return non-nil if we own the selection. */) (Lisp_Object selection, Lisp_Object time_object, Lisp_Object terminal) { Time timestamp; @@ -2109,7 +2129,9 @@ and t is the same as `SECONDARY'. TERMINAL should be a terminal object or a frame specifying the X server to query. If omitted or nil, that stands for the selected -frame's display, or the first available X display. */) +frame's display, or the first available X display. + +On Nextstep, TERMINAL is unused. */) (Lisp_Object selection, Lisp_Object terminal) { struct frame *f = frame_for_x_selection (terminal); @@ -2128,13 +2150,15 @@ DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p, 0, 2, 0, doc: /* Whether there is an owner for the given X selection. SELECTION should be the name of the selection in question, typically -one of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. (X expects -these literal upper-case names.) The symbol nil is the same as -`PRIMARY', and t is the same as `SECONDARY'. +one of the symbols `PRIMARY', `SECONDARY', `CLIPBOARD', or +`CLIPBOARD_MANAGER' (X expects these literal upper-case names.) The +symbol nil is the same as `PRIMARY', and t is the same as `SECONDARY'. TERMINAL should be a terminal object or a frame specifying the X server to query. If omitted or nil, that stands for the selected -frame's display, or the first available X display. */) +frame's display, or the first available X display. + +On Nextstep, TERMINAL is unused. */) (Lisp_Object selection, Lisp_Object terminal) { Window owner; @@ -2257,8 +2281,14 @@ x_clipboard_manager_save_all (void) local_frame = XCAR (XCDR (XCDR (XCDR (local_selection)))); if (FRAME_LIVE_P (XFRAME (local_frame))) - internal_condition_case_1 (x_clipboard_manager_save, local_frame, - Qt, x_clipboard_manager_error_2); + { + Lisp_Object args[1]; + args[0] = build_string ("Saving clipboard to X clipboard manager..."); + Fmessage (1, args); + + internal_condition_case_1 (x_clipboard_manager_save, local_frame, + Qt, x_clipboard_manager_error_2); + } } } @@ -2354,7 +2384,7 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format) F is the frame to be used to look up X atoms if the TYPE is XA_ATOM. DATA is a C array of values to be converted. TYPE is the type of the data. Only XA_ATOM is special, it converts - each number in DATA to its corresponfing X atom as a symbol. + each number in DATA to its corresponding X atom as a symbol. FORMAT is 8, 16 or 32 and gives the size in bits for each C value to be stored in RET. SIZE is the number of elements in DATA.