* data.c (Fbyteorder): New function.
[bpt/emacs.git] / src / xselect.c
CommitLineData
2408b3a1 1/* X Selection processing for Emacs.
2f51feb8 2 Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2003
d9c0d4a3 3 Free Software Foundation.
ede4db72
RS
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
ede4db72 21
c6c5df7f 22
ede4db72
RS
23/* Rewritten by jwz */
24
18160b98 25#include <config.h>
5b698285 26#include <stdio.h> /* termhooks.h needs this */
ede4db72
RS
27#include "lisp.h"
28#include "xterm.h" /* for all of the X includes */
7da64e5c
RS
29#include "dispextern.h" /* frame.h seems to want this */
30#include "frame.h" /* Need this to get the X window of selected_frame */
9ac0d9e0 31#include "blockinput.h"
5faa9b45 32#include "buffer.h"
dfcf069d 33#include "process.h"
1fb3821b
JD
34#include "termhooks.h"
35
36#include <X11/Xproto.h>
7da64e5c 37
d9c0d4a3
GM
38struct prop_location;
39
40static Lisp_Object x_atom_to_symbol P_ ((Display *dpy, Atom atom));
41static Atom symbol_to_x_atom P_ ((struct x_display_info *, Display *,
42 Lisp_Object));
43static void x_own_selection P_ ((Lisp_Object, Lisp_Object));
5109c8dd 44static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object, int));
d9c0d4a3
GM
45static void x_decline_selection_request P_ ((struct input_event *));
46static Lisp_Object x_selection_request_lisp_error P_ ((Lisp_Object));
47static Lisp_Object queue_selection_requests_unwind P_ ((Lisp_Object));
48static Lisp_Object some_frame_on_display P_ ((struct x_display_info *));
49static void x_reply_selection_request P_ ((struct input_event *, int,
50 unsigned char *, int, Atom));
51static int waiting_for_other_props_on_window P_ ((Display *, Window));
52static struct prop_location *expect_property_change P_ ((Display *, Window,
53 Atom, int));
54static void unexpect_property_change P_ ((struct prop_location *));
55static Lisp_Object wait_for_property_change_unwind P_ ((Lisp_Object));
56static void wait_for_property_change P_ ((struct prop_location *));
57static Lisp_Object x_get_foreign_selection P_ ((Lisp_Object, Lisp_Object));
58static void x_get_window_property P_ ((Display *, Window, Atom,
59 unsigned char **, int *,
60 Atom *, int *, unsigned long *, int));
61static void receive_incremental_selection P_ ((Display *, Window, Atom,
62 Lisp_Object, unsigned,
63 unsigned char **, int *,
64 Atom *, int *, unsigned long *));
65static Lisp_Object x_get_window_property_as_lisp_data P_ ((Display *,
66 Window, Atom,
67 Lisp_Object, Atom));
68static Lisp_Object selection_data_to_lisp_data P_ ((Display *, unsigned char *,
69 int, Atom, int));
70static void lisp_data_to_selection_data P_ ((Display *, Lisp_Object,
71 unsigned char **, Atom *,
72 unsigned *, int *, int *));
73static Lisp_Object clean_local_selection_data P_ ((Lisp_Object));
74static void initialize_cut_buffers P_ ((Display *, Window));
75
76
77/* Printing traces to stderr. */
78
79#ifdef TRACE_SELECTION
80#define TRACE0(fmt) \
81 fprintf (stderr, "%d: " fmt "\n", getpid ())
82#define TRACE1(fmt, a0) \
83 fprintf (stderr, "%d: " fmt "\n", getpid (), a0)
84#define TRACE2(fmt, a0, a1) \
85 fprintf (stderr, "%d: " fmt "\n", getpid (), a0, a1)
86#else
87#define TRACE0(fmt) (void) 0
88#define TRACE1(fmt, a0) (void) 0
89#define TRACE2(fmt, a0, a1) (void) 0
90#endif
91
92
ede4db72
RS
93#define CUT_BUFFER_SUPPORT
94
ede4db72
RS
95Lisp_Object QPRIMARY, QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
96 QTEXT, QDELETE, QMULTIPLE, QINCR, QEMACS_TMP, QTARGETS, QATOM, QNULL,
97 QATOM_PAIR;
98
e6c7c988 99Lisp_Object QCOMPOUND_TEXT; /* This is a type of selection. */
5109c8dd 100Lisp_Object QUTF8_STRING; /* This is a type of selection. */
e6c7c988 101
5a79ea57 102Lisp_Object Qcompound_text_with_extensions;
fbbe0ace 103
ede4db72
RS
104#ifdef CUT_BUFFER_SUPPORT
105Lisp_Object QCUT_BUFFER0, QCUT_BUFFER1, QCUT_BUFFER2, QCUT_BUFFER3,
106 QCUT_BUFFER4, QCUT_BUFFER5, QCUT_BUFFER6, QCUT_BUFFER7;
107#endif
108
8f4f023f
RS
109static Lisp_Object Vx_lost_selection_hooks;
110static Lisp_Object Vx_sent_selection_hooks;
2584c9ec
KH
111/* Coding system for communicating with other X clients via cutbuffer,
112 selection, and clipboard. */
93e4ce1b 113static Lisp_Object Vselection_coding_system;
ede4db72 114
16cd5029
KH
115/* Coding system for the next communicating with other X clients. */
116static Lisp_Object Vnext_selection_coding_system;
117
e57ad4d8
KH
118static Lisp_Object Qforeign_selection;
119
ede4db72
RS
120/* If this is a smaller number than the max-request-size of the display,
121 emacs will use INCR selection transfer when the selection is larger
122 than this. The max-request-size is usually around 64k, so if you want
1b65481e 123 emacs to use incremental selection transfers when the selection is
ede4db72 124 smaller than that, set this. I added this mostly for debugging the
8f4f023f 125 incremental transfer stuff, but it might improve server performance. */
ede4db72
RS
126#define MAX_SELECTION_QUANTUM 0xFFFFFF
127
c3498e64
JB
128#ifdef HAVE_X11R4
129#define SELECTION_QUANTUM(dpy) ((XMaxRequestSize(dpy) << 2) - 100)
130#else
131#define SELECTION_QUANTUM(dpy) (((dpy)->max_request_size << 2) - 100)
132#endif
ede4db72 133
7da64e5c 134/* The timestamp of the last input event Emacs received from the X server. */
29674445
KH
135/* Defined in keyboard.c. */
136extern unsigned long last_event_timestamp;
ede4db72
RS
137
138/* This is an association list whose elements are of the form
118bd841
RS
139 ( SELECTION-NAME SELECTION-VALUE SELECTION-TIMESTAMP FRAME)
140 SELECTION-NAME is a lisp symbol, whose name is the name of an X Atom.
141 SELECTION-VALUE is the value that emacs owns for that selection.
ede4db72 142 It may be any kind of Lisp object.
118bd841 143 SELECTION-TIMESTAMP is the time at which emacs began owning this selection,
ede4db72 144 as a cons of two 16-bit numbers (making a 32 bit time.)
118bd841
RS
145 FRAME is the frame for which we made the selection.
146 If there is an entry in this alist, then it can be assumed that Emacs owns
ede4db72
RS
147 that selection.
148 The only (eq) parts of this list that are visible from Lisp are the
8f4f023f
RS
149 selection-values. */
150static Lisp_Object Vselection_alist;
ede4db72
RS
151
152/* This is an alist whose CARs are selection-types (whose names are the same
153 as the names of X Atoms) and whose CDRs are the names of Lisp functions to
1b65481e 154 call to convert the given Emacs selection value to a string representing
ede4db72 155 the given selection type. This is for Lisp-level extension of the emacs
8f4f023f
RS
156 selection handling. */
157static Lisp_Object Vselection_converter_alist;
ede4db72
RS
158
159/* If the selection owner takes too long to reply to a selection request,
8f4f023f 160 we give up on it. This is in milliseconds (0 = no timeout.) */
31ade731 161static EMACS_INT x_selection_timeout;
ede4db72
RS
162\f
163/* Utility functions */
164
165static void lisp_data_to_selection_data ();
166static Lisp_Object selection_data_to_lisp_data ();
167static Lisp_Object x_get_window_property_as_lisp_data ();
168
1b65481e 169/* This converts a Lisp symbol to a server Atom, avoiding a server
ede4db72
RS
170 roundtrip whenever possible. */
171
172static Atom
5c3a351a
RS
173symbol_to_x_atom (dpyinfo, display, sym)
174 struct x_display_info *dpyinfo;
ede4db72
RS
175 Display *display;
176 Lisp_Object sym;
177{
178 Atom val;
179 if (NILP (sym)) return 0;
180 if (EQ (sym, QPRIMARY)) return XA_PRIMARY;
181 if (EQ (sym, QSECONDARY)) return XA_SECONDARY;
182 if (EQ (sym, QSTRING)) return XA_STRING;
183 if (EQ (sym, QINTEGER)) return XA_INTEGER;
184 if (EQ (sym, QATOM)) return XA_ATOM;
5c3a351a
RS
185 if (EQ (sym, QCLIPBOARD)) return dpyinfo->Xatom_CLIPBOARD;
186 if (EQ (sym, QTIMESTAMP)) return dpyinfo->Xatom_TIMESTAMP;
187 if (EQ (sym, QTEXT)) return dpyinfo->Xatom_TEXT;
e6c7c988 188 if (EQ (sym, QCOMPOUND_TEXT)) return dpyinfo->Xatom_COMPOUND_TEXT;
5109c8dd 189 if (EQ (sym, QUTF8_STRING)) return dpyinfo->Xatom_UTF8_STRING;
5c3a351a
RS
190 if (EQ (sym, QDELETE)) return dpyinfo->Xatom_DELETE;
191 if (EQ (sym, QMULTIPLE)) return dpyinfo->Xatom_MULTIPLE;
192 if (EQ (sym, QINCR)) return dpyinfo->Xatom_INCR;
193 if (EQ (sym, QEMACS_TMP)) return dpyinfo->Xatom_EMACS_TMP;
194 if (EQ (sym, QTARGETS)) return dpyinfo->Xatom_TARGETS;
195 if (EQ (sym, QNULL)) return dpyinfo->Xatom_NULL;
ede4db72
RS
196#ifdef CUT_BUFFER_SUPPORT
197 if (EQ (sym, QCUT_BUFFER0)) return XA_CUT_BUFFER0;
198 if (EQ (sym, QCUT_BUFFER1)) return XA_CUT_BUFFER1;
199 if (EQ (sym, QCUT_BUFFER2)) return XA_CUT_BUFFER2;
200 if (EQ (sym, QCUT_BUFFER3)) return XA_CUT_BUFFER3;
201 if (EQ (sym, QCUT_BUFFER4)) return XA_CUT_BUFFER4;
202 if (EQ (sym, QCUT_BUFFER5)) return XA_CUT_BUFFER5;
203 if (EQ (sym, QCUT_BUFFER6)) return XA_CUT_BUFFER6;
204 if (EQ (sym, QCUT_BUFFER7)) return XA_CUT_BUFFER7;
205#endif
206 if (!SYMBOLP (sym)) abort ();
207
d5db4077 208 TRACE1 (" XInternAtom %s", (char *) SDATA (SYMBOL_NAME (sym)));
ede4db72 209 BLOCK_INPUT;
d5db4077 210 val = XInternAtom (display, (char *) SDATA (SYMBOL_NAME (sym)), False);
ede4db72
RS
211 UNBLOCK_INPUT;
212 return val;
213}
214
215
216/* This converts a server Atom to a Lisp symbol, avoiding server roundtrips
217 and calls to intern whenever possible. */
218
219static Lisp_Object
d9c0d4a3
GM
220x_atom_to_symbol (dpy, atom)
221 Display *dpy;
ede4db72
RS
222 Atom atom;
223{
d9c0d4a3 224 struct x_display_info *dpyinfo;
ede4db72
RS
225 char *str;
226 Lisp_Object val;
1b65481e 227
d9c0d4a3
GM
228 if (! atom)
229 return Qnil;
1b65481e 230
7da64e5c
RS
231 switch (atom)
232 {
233 case XA_PRIMARY:
234 return QPRIMARY;
235 case XA_SECONDARY:
236 return QSECONDARY;
237 case XA_STRING:
238 return QSTRING;
239 case XA_INTEGER:
240 return QINTEGER;
241 case XA_ATOM:
242 return QATOM;
ede4db72 243#ifdef CUT_BUFFER_SUPPORT
7da64e5c
RS
244 case XA_CUT_BUFFER0:
245 return QCUT_BUFFER0;
246 case XA_CUT_BUFFER1:
247 return QCUT_BUFFER1;
248 case XA_CUT_BUFFER2:
249 return QCUT_BUFFER2;
250 case XA_CUT_BUFFER3:
251 return QCUT_BUFFER3;
252 case XA_CUT_BUFFER4:
253 return QCUT_BUFFER4;
254 case XA_CUT_BUFFER5:
255 return QCUT_BUFFER5;
256 case XA_CUT_BUFFER6:
257 return QCUT_BUFFER6;
258 case XA_CUT_BUFFER7:
259 return QCUT_BUFFER7;
ede4db72 260#endif
7da64e5c
RS
261 }
262
d9c0d4a3 263 dpyinfo = x_display_info_for_display (dpy);
5c3a351a 264 if (atom == dpyinfo->Xatom_CLIPBOARD)
7da64e5c 265 return QCLIPBOARD;
5c3a351a 266 if (atom == dpyinfo->Xatom_TIMESTAMP)
7da64e5c 267 return QTIMESTAMP;
5c3a351a 268 if (atom == dpyinfo->Xatom_TEXT)
7da64e5c 269 return QTEXT;
e6c7c988
KH
270 if (atom == dpyinfo->Xatom_COMPOUND_TEXT)
271 return QCOMPOUND_TEXT;
5109c8dd
KH
272 if (atom == dpyinfo->Xatom_UTF8_STRING)
273 return QUTF8_STRING;
5c3a351a 274 if (atom == dpyinfo->Xatom_DELETE)
7da64e5c 275 return QDELETE;
5c3a351a 276 if (atom == dpyinfo->Xatom_MULTIPLE)
7da64e5c 277 return QMULTIPLE;
5c3a351a 278 if (atom == dpyinfo->Xatom_INCR)
7da64e5c 279 return QINCR;
5c3a351a 280 if (atom == dpyinfo->Xatom_EMACS_TMP)
7da64e5c 281 return QEMACS_TMP;
5c3a351a 282 if (atom == dpyinfo->Xatom_TARGETS)
7da64e5c 283 return QTARGETS;
5c3a351a 284 if (atom == dpyinfo->Xatom_NULL)
7da64e5c 285 return QNULL;
ede4db72
RS
286
287 BLOCK_INPUT;
d9c0d4a3 288 str = XGetAtomName (dpy, atom);
ede4db72 289 UNBLOCK_INPUT;
d9c0d4a3 290 TRACE1 ("XGetAtomName --> %s", str);
ede4db72
RS
291 if (! str) return Qnil;
292 val = intern (str);
293 BLOCK_INPUT;
0158abbc 294 /* This was allocated by Xlib, so use XFree. */
ede4db72
RS
295 XFree (str);
296 UNBLOCK_INPUT;
297 return val;
298}
8a89415e 299\f
ede4db72 300/* Do protocol to assert ourself as a selection owner.
1b65481e 301 Update the Vselection_alist so that we can reply to later requests for
ede4db72
RS
302 our selection. */
303
304static void
305x_own_selection (selection_name, selection_value)
306 Lisp_Object selection_name, selection_value;
307{
378c33ca
GM
308 struct frame *sf = SELECTED_FRAME ();
309 Window selecting_window = FRAME_X_WINDOW (sf);
310 Display *display = FRAME_X_DISPLAY (sf);
7da64e5c 311 Time time = last_event_timestamp;
ede4db72 312 Atom selection_atom;
378c33ca 313 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (sf);
5a499696 314 int count;
ede4db72 315
b7826503 316 CHECK_SYMBOL (selection_name);
5c3a351a 317 selection_atom = symbol_to_x_atom (dpyinfo, display, selection_name);
ede4db72
RS
318
319 BLOCK_INPUT;
5a499696 320 count = x_catch_errors (display);
ede4db72 321 XSetSelectionOwner (display, selection_atom, selecting_window, time);
a7b24d46 322 x_check_errors (display, "Can't set selection: %s");
5a499696 323 x_uncatch_errors (display, count);
ede4db72
RS
324 UNBLOCK_INPUT;
325
326 /* Now update the local cache */
327 {
328 Lisp_Object selection_time;
329 Lisp_Object selection_data;
330 Lisp_Object prev_value;
331
332 selection_time = long_to_cons ((unsigned long) time);
333 selection_data = Fcons (selection_name,
334 Fcons (selection_value,
118bd841 335 Fcons (selection_time,
378c33ca 336 Fcons (selected_frame, Qnil))));
ede4db72
RS
337 prev_value = assq_no_quit (selection_name, Vselection_alist);
338
339 Vselection_alist = Fcons (selection_data, Vselection_alist);
340
341 /* If we already owned the selection, remove the old selection data.
342 Perhaps we should destructively modify it instead.
343 Don't use Fdelq as that may QUIT. */
344 if (!NILP (prev_value))
345 {
346 Lisp_Object rest; /* we know it's not the CAR, so it's easy. */
347 for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
8e713be6 348 if (EQ (prev_value, Fcar (XCDR (rest))))
ede4db72 349 {
f3fbd155 350 XSETCDR (rest, Fcdr (XCDR (rest)));
ede4db72
RS
351 break;
352 }
353 }
354 }
355}
356\f
357/* Given a selection-name and desired type, look up our local copy of
358 the selection value and convert it to the type.
359 The value is nil or a string.
5109c8dd
KH
360 This function is used both for remote requests (LOCAL_REQUEST is zero)
361 and for local x-get-selection-internal (LOCAL_REQUEST is nonzero).
ede4db72
RS
362
363 This calls random Lisp code, and may signal or gc. */
364
365static Lisp_Object
5109c8dd 366x_get_local_selection (selection_symbol, target_type, local_request)
ede4db72 367 Lisp_Object selection_symbol, target_type;
5109c8dd 368 int local_request;
ede4db72
RS
369{
370 Lisp_Object local_value;
371 Lisp_Object handler_fn, value, type, check;
372 int count;
373
374 local_value = assq_no_quit (selection_symbol, Vselection_alist);
375
376 if (NILP (local_value)) return Qnil;
377
378 /* TIMESTAMP and MULTIPLE are special cases 'cause that's easiest. */
379 if (EQ (target_type, QTIMESTAMP))
380 {
381 handler_fn = Qnil;
8e713be6 382 value = XCAR (XCDR (XCDR (local_value)));
ede4db72
RS
383 }
384#if 0
385 else if (EQ (target_type, QDELETE))
386 {
387 handler_fn = Qnil;
388 Fx_disown_selection_internal
389 (selection_symbol,
8e713be6 390 XCAR (XCDR (XCDR (local_value))));
ede4db72
RS
391 value = QNULL;
392 }
393#endif
394
395#if 0 /* #### MULTIPLE doesn't work yet */
396 else if (CONSP (target_type)
8e713be6 397 && XCAR (target_type) == QMULTIPLE)
ede4db72 398 {
9d2d1dd8
KH
399 Lisp_Object pairs;
400 int size;
ede4db72 401 int i;
8e713be6 402 pairs = XCDR (target_type);
9d2d1dd8 403 size = XVECTOR (pairs)->size;
ede4db72
RS
404 /* If the target is MULTIPLE, then target_type looks like
405 (MULTIPLE . [[SELECTION1 TARGET1] [SELECTION2 TARGET2] ... ])
406 We modify the second element of each pair in the vector and
407 return it as [[SELECTION1 <value1>] [SELECTION2 <value2>] ... ]
408 */
409 for (i = 0; i < size; i++)
410 {
9d2d1dd8
KH
411 Lisp_Object pair;
412 pair = XVECTOR (pairs)->contents [i];
ede4db72
RS
413 XVECTOR (pair)->contents [1]
414 = x_get_local_selection (XVECTOR (pair)->contents [0],
5109c8dd
KH
415 XVECTOR (pair)->contents [1],
416 local_request);
ede4db72
RS
417 }
418 return pairs;
419 }
420#endif
421 else
422 {
423 /* Don't allow a quit within the converter.
424 When the user types C-g, he would be surprised
425 if by luck it came during a converter. */
aed13378 426 count = SPECPDL_INDEX ();
ede4db72
RS
427 specbind (Qinhibit_quit, Qt);
428
b7826503 429 CHECK_SYMBOL (target_type);
ede4db72 430 handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist));
4f06187f
RS
431 /* gcpro is not needed here since nothing but HANDLER_FN
432 is live, and that ought to be a symbol. */
433
1eb4d468
RS
434 if (!NILP (handler_fn))
435 value = call3 (handler_fn,
5109c8dd 436 selection_symbol, (local_request ? Qnil : target_type),
8e713be6 437 XCAR (XCDR (local_value)));
1eb4d468
RS
438 else
439 value = Qnil;
ede4db72
RS
440 unbind_to (count, Qnil);
441 }
442
443 /* Make sure this value is of a type that we could transmit
444 to another X client. */
a87ed99c 445
ede4db72
RS
446 check = value;
447 if (CONSP (value)
8e713be6
KR
448 && SYMBOLP (XCAR (value)))
449 type = XCAR (value),
450 check = XCDR (value);
1b65481e 451
ede4db72
RS
452 if (STRINGP (check)
453 || VECTORP (check)
454 || SYMBOLP (check)
7da64e5c 455 || INTEGERP (check)
ede4db72
RS
456 || NILP (value))
457 return value;
a87ed99c 458 /* Check for a value that cons_to_long could handle. */
ede4db72 459 else if (CONSP (check)
8e713be6
KR
460 && INTEGERP (XCAR (check))
461 && (INTEGERP (XCDR (check))
ede4db72 462 ||
8e713be6
KR
463 (CONSP (XCDR (check))
464 && INTEGERP (XCAR (XCDR (check)))
465 && NILP (XCDR (XCDR (check))))))
ede4db72
RS
466 return value;
467 else
468 return
469 Fsignal (Qerror,
a87ed99c 470 Fcons (build_string ("invalid data returned by selection-conversion function"),
ede4db72
RS
471 Fcons (handler_fn, Fcons (value, Qnil))));
472}
473\f
474/* Subroutines of x_reply_selection_request. */
475
5d0ba25b 476/* Send a SelectionNotify event to the requestor with property=None,
ede4db72
RS
477 meaning we were unable to do what they wanted. */
478
479static void
480x_decline_selection_request (event)
481 struct input_event *event;
482{
483 XSelectionEvent reply;
d9c0d4a3 484 int count;
1b65481e 485
ede4db72
RS
486 reply.type = SelectionNotify;
487 reply.display = SELECTION_EVENT_DISPLAY (event);
5d0ba25b 488 reply.requestor = SELECTION_EVENT_REQUESTOR (event);
ede4db72
RS
489 reply.selection = SELECTION_EVENT_SELECTION (event);
490 reply.time = SELECTION_EVENT_TIME (event);
491 reply.target = SELECTION_EVENT_TARGET (event);
492 reply.property = None;
493
d9c0d4a3
GM
494 /* The reason for the error may be that the receiver has
495 died in the meantime. Handle that case. */
ede4db72 496 BLOCK_INPUT;
d9c0d4a3
GM
497 count = x_catch_errors (reply.display);
498 XSendEvent (reply.display, reply.requestor, False, 0L, (XEvent *) &reply);
5c3a351a 499 XFlush (reply.display);
d9c0d4a3 500 x_uncatch_errors (reply.display, count);
ede4db72
RS
501 UNBLOCK_INPUT;
502}
503
504/* This is the selection request currently being processed.
505 It is set to zero when the request is fully processed. */
506static struct input_event *x_selection_current_request;
507
ca29f2b8
GM
508/* Display info in x_selection_request. */
509
510static struct x_display_info *selection_request_dpyinfo;
511
ede4db72 512/* Used as an unwind-protect clause so that, if a selection-converter signals
2a1a4c9d 513 an error, we tell the requester that we were unable to do what they wanted
ede4db72
RS
514 before we throw to top-level or go into the debugger or whatever. */
515
516static Lisp_Object
517x_selection_request_lisp_error (ignore)
518 Lisp_Object ignore;
519{
ca29f2b8
GM
520 if (x_selection_current_request != 0
521 && selection_request_dpyinfo->display)
ede4db72
RS
522 x_decline_selection_request (x_selection_current_request);
523 return Qnil;
524}
525\f
d1f21a66
RS
526
527/* This stuff is so that INCR selections are reentrant (that is, so we can
528 be servicing multiple INCR selection requests simultaneously.) I haven't
529 actually tested that yet. */
530
531/* Keep a list of the property changes that are awaited. */
532
533struct prop_location
534{
535 int identifier;
536 Display *display;
537 Window window;
538 Atom property;
539 int desired_state;
540 int arrived;
541 struct prop_location *next;
542};
543
544static struct prop_location *expect_property_change ();
545static void wait_for_property_change ();
546static void unexpect_property_change ();
547static int waiting_for_other_props_on_window ();
548
549static int prop_location_identifier;
550
551static Lisp_Object property_change_reply;
552
553static struct prop_location *property_change_reply_object;
554
555static struct prop_location *property_change_wait_list;
55b2d45d
RS
556
557static Lisp_Object
558queue_selection_requests_unwind (frame)
559 Lisp_Object frame;
560{
561 FRAME_PTR f = XFRAME (frame);
562
563 if (! NILP (frame))
564 x_stop_queuing_selection_requests (FRAME_X_DISPLAY (f));
ab552306 565 return Qnil;
55b2d45d
RS
566}
567
568/* Return some frame whose display info is DPYINFO.
569 Return nil if there is none. */
570
571static Lisp_Object
572some_frame_on_display (dpyinfo)
573 struct x_display_info *dpyinfo;
574{
575 Lisp_Object list, frame;
576
577 FOR_EACH_FRAME (list, frame)
578 {
579 if (FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
580 return frame;
581 }
582
583 return Qnil;
584}
d1f21a66 585\f
ede4db72
RS
586/* Send the reply to a selection request event EVENT.
587 TYPE is the type of selection data requested.
588 DATA and SIZE describe the data to send, already converted.
589 FORMAT is the unit-size (in bits) of the data to be transmitted. */
590
591static void
592x_reply_selection_request (event, format, data, size, type)
593 struct input_event *event;
594 int format, size;
595 unsigned char *data;
596 Atom type;
597{
598 XSelectionEvent reply;
599 Display *display = SELECTION_EVENT_DISPLAY (event);
5d0ba25b 600 Window window = SELECTION_EVENT_REQUESTOR (event);
ede4db72
RS
601 int bytes_remaining;
602 int format_bytes = format/8;
603 int max_bytes = SELECTION_QUANTUM (display);
5c3a351a 604 struct x_display_info *dpyinfo = x_display_info_for_display (display);
5a499696 605 int count;
ede4db72
RS
606
607 if (max_bytes > MAX_SELECTION_QUANTUM)
608 max_bytes = MAX_SELECTION_QUANTUM;
609
610 reply.type = SelectionNotify;
611 reply.display = display;
5d0ba25b 612 reply.requestor = window;
ede4db72
RS
613 reply.selection = SELECTION_EVENT_SELECTION (event);
614 reply.time = SELECTION_EVENT_TIME (event);
615 reply.target = SELECTION_EVENT_TARGET (event);
616 reply.property = SELECTION_EVENT_PROPERTY (event);
617 if (reply.property == None)
618 reply.property = reply.target;
619
620 /* #### XChangeProperty can generate BadAlloc, and we must handle it! */
afe1529d 621 BLOCK_INPUT;
ad7f9d12 622 count = x_catch_errors (display);
ede4db72 623
ede4db72
RS
624 /* Store the data on the requested property.
625 If the selection is large, only store the first N bytes of it.
626 */
627 bytes_remaining = size * format_bytes;
628 if (bytes_remaining <= max_bytes)
629 {
630 /* Send all the data at once, with minimal handshaking. */
d9c0d4a3 631 TRACE1 ("Sending all %d bytes", bytes_remaining);
ede4db72
RS
632 XChangeProperty (display, window, reply.property, type, format,
633 PropModeReplace, data, size);
634 /* At this point, the selection was successfully stored; ack it. */
2f65feb6 635 XSendEvent (display, window, False, 0L, (XEvent *) &reply);
ede4db72
RS
636 }
637 else
638 {
639 /* Send an INCR selection. */
d1f21a66 640 struct prop_location *wait_object;
afe1529d 641 int had_errors;
55b2d45d 642 Lisp_Object frame;
ede4db72 643
55b2d45d
RS
644 frame = some_frame_on_display (dpyinfo);
645
646 /* If the display no longer has frames, we can't expect
647 to get many more selection requests from it, so don't
648 bother trying to queue them. */
649 if (!NILP (frame))
650 {
651 x_start_queuing_selection_requests (display);
652
653 record_unwind_protect (queue_selection_requests_unwind,
654 frame);
655 }
2f65feb6 656
19126e11 657 if (x_window_to_frame (dpyinfo, window)) /* #### debug */
606140dd 658 error ("Attempt to transfer an INCR to ourself!");
1b65481e 659
d9c0d4a3
GM
660 TRACE2 ("Start sending %d bytes incrementally (%s)",
661 bytes_remaining, XGetAtomName (display, reply.property));
d1f21a66
RS
662 wait_object = expect_property_change (display, window, reply.property,
663 PropertyDelete);
ede4db72 664
d9c0d4a3
GM
665 TRACE1 ("Set %s to number of bytes to send",
666 XGetAtomName (display, reply.property));
5c3a351a 667 XChangeProperty (display, window, reply.property, dpyinfo->Xatom_INCR,
55b2d45d
RS
668 32, PropModeReplace,
669 (unsigned char *) &bytes_remaining, 1);
ede4db72 670 XSelectInput (display, window, PropertyChangeMask);
1b65481e 671
ede4db72 672 /* Tell 'em the INCR data is there... */
d9c0d4a3 673 TRACE0 ("Send SelectionNotify event");
55b2d45d 674 XSendEvent (display, window, False, 0L, (XEvent *) &reply);
5c3a351a 675 XFlush (display);
afe1529d
RS
676
677 had_errors = x_had_errors_p (display);
2f65feb6 678 UNBLOCK_INPUT;
ede4db72 679
2a1a4c9d 680 /* First, wait for the requester to ack by deleting the property.
ede4db72 681 This can run random lisp code (process handlers) or signal. */
afe1529d 682 if (! had_errors)
d9c0d4a3
GM
683 {
684 TRACE1 ("Waiting for ACK (deletion of %s)",
685 XGetAtomName (display, reply.property));
686 wait_for_property_change (wait_object);
687 }
ede4db72 688
d9c0d4a3 689 TRACE0 ("Got ACK");
ede4db72
RS
690 while (bytes_remaining)
691 {
692 int i = ((bytes_remaining < max_bytes)
693 ? bytes_remaining
694 : max_bytes);
2f65feb6
RS
695
696 BLOCK_INPUT;
697
d1f21a66
RS
698 wait_object
699 = expect_property_change (display, window, reply.property,
700 PropertyDelete);
d9c0d4a3
GM
701
702 TRACE1 ("Sending increment of %d bytes", i);
703 TRACE1 ("Set %s to increment data",
704 XGetAtomName (display, reply.property));
1b65481e 705
ede4db72
RS
706 /* Append the next chunk of data to the property. */
707 XChangeProperty (display, window, reply.property, type, format,
708 PropModeAppend, data, i / format_bytes);
709 bytes_remaining -= i;
710 data += i;
5c3a351a 711 XFlush (display);
afe1529d 712 had_errors = x_had_errors_p (display);
2f65feb6 713 UNBLOCK_INPUT;
ede4db72 714
afe1529d
RS
715 if (had_errors)
716 break;
717
2a1a4c9d 718 /* Now wait for the requester to ack this chunk by deleting the
d9c0d4a3
GM
719 property. This can run random lisp code or signal. */
720 TRACE1 ("Waiting for increment ACK (deletion of %s)",
721 XGetAtomName (display, reply.property));
d1f21a66 722 wait_for_property_change (wait_object);
ede4db72 723 }
1b65481e 724
d9c0d4a3
GM
725 /* Now write a zero-length chunk to the property to tell the
726 requester that we're done. */
2f65feb6 727 BLOCK_INPUT;
ede4db72
RS
728 if (! waiting_for_other_props_on_window (display, window))
729 XSelectInput (display, window, 0L);
730
d9c0d4a3
GM
731 TRACE1 ("Set %s to a 0-length chunk to indicate EOF",
732 XGetAtomName (display, reply.property));
ede4db72
RS
733 XChangeProperty (display, window, reply.property, type, format,
734 PropModeReplace, data, 0);
d9c0d4a3 735 TRACE0 ("Done sending incrementally");
ede4db72 736 }
afe1529d 737
ceabd272 738 /* rms, 2003-01-03: I think I have fixed this bug. */
47a6ac17
GM
739 /* The window we're communicating with may have been deleted
740 in the meantime (that's a real situation from a bug report).
741 In this case, there may be events in the event queue still
742 refering to the deleted window, and we'll get a BadWindow error
743 in XTread_socket when processing the events. I don't have
744 an idea how to fix that. gerd, 2001-01-98. */
afe1529d 745 XFlush (display);
5a499696 746 x_uncatch_errors (display, count);
afe1529d 747 UNBLOCK_INPUT;
ede4db72
RS
748}
749\f
750/* Handle a SelectionRequest event EVENT.
751 This is called from keyboard.c when such an event is found in the queue. */
752
753void
754x_handle_selection_request (event)
755 struct input_event *event;
756{
757 struct gcpro gcpro1, gcpro2, gcpro3;
9d2d1dd8 758 Lisp_Object local_selection_data;
ede4db72 759 Lisp_Object selection_symbol;
9d2d1dd8
KH
760 Lisp_Object target_symbol;
761 Lisp_Object converted_selection;
ede4db72 762 Time local_selection_time;
9d2d1dd8 763 Lisp_Object successful_p;
ede4db72 764 int count;
5c3a351a
RS
765 struct x_display_info *dpyinfo
766 = x_display_info_for_display (SELECTION_EVENT_DISPLAY (event));
ede4db72 767
9d2d1dd8
KH
768 local_selection_data = Qnil;
769 target_symbol = Qnil;
770 converted_selection = Qnil;
771 successful_p = Qnil;
772
ede4db72
RS
773 GCPRO3 (local_selection_data, converted_selection, target_symbol);
774
d9c0d4a3 775 selection_symbol = x_atom_to_symbol (SELECTION_EVENT_DISPLAY (event),
ede4db72
RS
776 SELECTION_EVENT_SELECTION (event));
777
778 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
ede4db72
RS
779
780 if (NILP (local_selection_data))
781 {
782 /* Someone asked for the selection, but we don't have it any more.
783 */
784 x_decline_selection_request (event);
785 goto DONE;
786 }
787
788 local_selection_time = (Time)
8e713be6 789 cons_to_long (XCAR (XCDR (XCDR (local_selection_data))));
ede4db72
RS
790
791 if (SELECTION_EVENT_TIME (event) != CurrentTime
7da64e5c 792 && local_selection_time > SELECTION_EVENT_TIME (event))
ede4db72
RS
793 {
794 /* Someone asked for the selection, and we have one, but not the one
795 they're looking for.
796 */
797 x_decline_selection_request (event);
798 goto DONE;
799 }
800
ede4db72 801 x_selection_current_request = event;
331379bf 802 count = SPECPDL_INDEX ();
ca29f2b8 803 selection_request_dpyinfo = dpyinfo;
ede4db72
RS
804 record_unwind_protect (x_selection_request_lisp_error, Qnil);
805
d9c0d4a3 806 target_symbol = x_atom_to_symbol (SELECTION_EVENT_DISPLAY (event),
ede4db72
RS
807 SELECTION_EVENT_TARGET (event));
808
809#if 0 /* #### MULTIPLE doesn't work yet */
810 if (EQ (target_symbol, QMULTIPLE))
811 target_symbol = fetch_multiple_target (event);
812#endif
1b65481e 813
ede4db72 814 /* Convert lisp objects back into binary data */
1b65481e 815
ede4db72 816 converted_selection
5109c8dd 817 = x_get_local_selection (selection_symbol, target_symbol, 0);
1b65481e 818
ede4db72
RS
819 if (! NILP (converted_selection))
820 {
821 unsigned char *data;
822 unsigned int size;
823 int format;
824 Atom type;
aca39f42
RS
825 int nofree;
826
2f65feb6
RS
827 lisp_data_to_selection_data (SELECTION_EVENT_DISPLAY (event),
828 converted_selection,
aca39f42 829 &data, &type, &size, &format, &nofree);
1b65481e 830
ede4db72
RS
831 x_reply_selection_request (event, format, data, size, type);
832 successful_p = Qt;
833
834 /* Indicate we have successfully processed this event. */
7da64e5c 835 x_selection_current_request = 0;
ede4db72 836
4feb31b2 837 /* Use xfree, not XFree, because lisp_data_to_selection_data
0158abbc 838 calls xmalloc itself. */
aca39f42 839 if (!nofree)
4feb31b2 840 xfree (data);
ede4db72
RS
841 }
842 unbind_to (count, Qnil);
843
844 DONE:
845
ede4db72
RS
846 /* Let random lisp code notice that the selection has been asked for. */
847 {
9d2d1dd8
KH
848 Lisp_Object rest;
849 rest = Vx_sent_selection_hooks;
ede4db72
RS
850 if (!EQ (rest, Qunbound))
851 for (; CONSP (rest); rest = Fcdr (rest))
852 call3 (Fcar (rest), selection_symbol, target_symbol, successful_p);
853 }
4f06187f
RS
854
855 UNGCPRO;
ede4db72
RS
856}
857\f
e18e6130 858/* Handle a SelectionClear event EVENT, which indicates that some
ede4db72
RS
859 client cleared out our previously asserted selection.
860 This is called from keyboard.c when such an event is found in the queue. */
861
862void
863x_handle_selection_clear (event)
864 struct input_event *event;
865{
866 Display *display = SELECTION_EVENT_DISPLAY (event);
867 Atom selection = SELECTION_EVENT_SELECTION (event);
868 Time changed_owner_time = SELECTION_EVENT_TIME (event);
1b65481e 869
ede4db72
RS
870 Lisp_Object selection_symbol, local_selection_data;
871 Time local_selection_time;
5c3a351a 872 struct x_display_info *dpyinfo = x_display_info_for_display (display);
e18e6130
RS
873 struct x_display_info *t_dpyinfo;
874
875 /* If the new selection owner is also Emacs,
876 don't clear the new selection. */
877 BLOCK_INPUT;
878 /* Check each display on the same terminal,
879 to see if this Emacs job now owns the selection
880 through that display. */
881 for (t_dpyinfo = x_display_list; t_dpyinfo; t_dpyinfo = t_dpyinfo->next)
882 if (t_dpyinfo->kboard == dpyinfo->kboard)
883 {
884 Window owner_window
885 = XGetSelectionOwner (t_dpyinfo->display, selection);
886 if (x_window_to_frame (t_dpyinfo, owner_window) != 0)
887 {
888 UNBLOCK_INPUT;
889 return;
890 }
891 }
892 UNBLOCK_INPUT;
ede4db72 893
d9c0d4a3 894 selection_symbol = x_atom_to_symbol (display, selection);
ede4db72
RS
895
896 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
897
898 /* Well, we already believe that we don't own it, so that's just fine. */
899 if (NILP (local_selection_data)) return;
900
901 local_selection_time = (Time)
8e713be6 902 cons_to_long (XCAR (XCDR (XCDR (local_selection_data))));
ede4db72
RS
903
904 /* This SelectionClear is for a selection that we no longer own, so we can
905 disregard it. (That is, we have reasserted the selection since this
906 request was generated.) */
907
908 if (changed_owner_time != CurrentTime
909 && local_selection_time > changed_owner_time)
910 return;
911
912 /* Otherwise, we're really honest and truly being told to drop it.
913 Don't use Fdelq as that may QUIT;. */
914
915 if (EQ (local_selection_data, Fcar (Vselection_alist)))
916 Vselection_alist = Fcdr (Vselection_alist);
917 else
918 {
919 Lisp_Object rest;
920 for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
8e713be6 921 if (EQ (local_selection_data, Fcar (XCDR (rest))))
ede4db72 922 {
f3fbd155 923 XSETCDR (rest, Fcdr (XCDR (rest)));
ede4db72
RS
924 break;
925 }
926 }
927
928 /* Let random lisp code notice that the selection has been stolen. */
929
930 {
d1f21a66
RS
931 Lisp_Object rest;
932 rest = Vx_lost_selection_hooks;
ede4db72 933 if (!EQ (rest, Qunbound))
d1f21a66
RS
934 {
935 for (; CONSP (rest); rest = Fcdr (rest))
936 call1 (Fcar (rest), selection_symbol);
7c6b2ea4 937 prepare_menu_bars ();
3007ebfb 938 redisplay_preserve_echo_area (20);
d1f21a66 939 }
ede4db72
RS
940 }
941}
942
118bd841
RS
943/* Clear all selections that were made from frame F.
944 We do this when about to delete a frame. */
945
946void
947x_clear_frame_selections (f)
948 FRAME_PTR f;
949{
950 Lisp_Object frame;
951 Lisp_Object rest;
952
90851bbe 953 XSETFRAME (frame, f);
118bd841
RS
954
955 /* Otherwise, we're really honest and truly being told to drop it.
956 Don't use Fdelq as that may QUIT;. */
957
0d199f9c
RS
958 /* Delete elements from the beginning of Vselection_alist. */
959 while (!NILP (Vselection_alist)
960 && EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (Vselection_alist)))))))
961 {
962 /* Let random Lisp code notice that the selection has been stolen. */
963 Lisp_Object hooks, selection_symbol;
964
965 hooks = Vx_lost_selection_hooks;
966 selection_symbol = Fcar (Fcar (Vselection_alist));
967
968 if (!EQ (hooks, Qunbound))
969 {
970 for (; CONSP (hooks); hooks = Fcdr (hooks))
971 call1 (Fcar (hooks), selection_symbol);
996b804d
MB
972#if 0 /* This can crash when deleting a frame
973 from x_connection_closed. Anyway, it seems unnecessary;
974 something else should cause a redisplay. */
3007ebfb 975 redisplay_preserve_echo_area (21);
996b804d 976#endif
0d199f9c
RS
977 }
978
979 Vselection_alist = Fcdr (Vselection_alist);
980 }
981
982 /* Delete elements after the beginning of Vselection_alist. */
118bd841 983 for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
8e713be6 984 if (EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (XCDR (rest))))))))
118bd841
RS
985 {
986 /* Let random Lisp code notice that the selection has been stolen. */
987 Lisp_Object hooks, selection_symbol;
988
989 hooks = Vx_lost_selection_hooks;
8e713be6 990 selection_symbol = Fcar (Fcar (XCDR (rest)));
118bd841
RS
991
992 if (!EQ (hooks, Qunbound))
993 {
994 for (; CONSP (hooks); hooks = Fcdr (hooks))
995 call1 (Fcar (hooks), selection_symbol);
996b804d 996#if 0 /* See above */
3007ebfb 997 redisplay_preserve_echo_area (22);
996b804d 998#endif
118bd841 999 }
f3fbd155 1000 XSETCDR (rest, Fcdr (XCDR (rest)));
118bd841
RS
1001 break;
1002 }
1003}
ede4db72 1004\f
ede4db72
RS
1005/* Nonzero if any properties for DISPLAY and WINDOW
1006 are on the list of what we are waiting for. */
1007
1008static int
1009waiting_for_other_props_on_window (display, window)
1010 Display *display;
1011 Window window;
1012{
1013 struct prop_location *rest = property_change_wait_list;
1014 while (rest)
1015 if (rest->display == display && rest->window == window)
1016 return 1;
1017 else
1018 rest = rest->next;
1019 return 0;
1020}
1021
1022/* Add an entry to the list of property changes we are waiting for.
1023 DISPLAY, WINDOW, PROPERTY, STATE describe what we will wait for.
1024 The return value is a number that uniquely identifies
1025 this awaited property change. */
1026
d1f21a66 1027static struct prop_location *
ede4db72
RS
1028expect_property_change (display, window, property, state)
1029 Display *display;
1030 Window window;
6c070502 1031 Atom property;
ede4db72
RS
1032 int state;
1033{
d9c0d4a3 1034 struct prop_location *pl = (struct prop_location *) xmalloc (sizeof *pl);
2f65feb6 1035 pl->identifier = ++prop_location_identifier;
ede4db72
RS
1036 pl->display = display;
1037 pl->window = window;
1038 pl->property = property;
1039 pl->desired_state = state;
1040 pl->next = property_change_wait_list;
d1f21a66 1041 pl->arrived = 0;
ede4db72 1042 property_change_wait_list = pl;
d1f21a66 1043 return pl;
ede4db72
RS
1044}
1045
1046/* Delete an entry from the list of property changes we are waiting for.
2f65feb6 1047 IDENTIFIER is the number that uniquely identifies the entry. */
ede4db72
RS
1048
1049static void
d1f21a66
RS
1050unexpect_property_change (location)
1051 struct prop_location *location;
ede4db72
RS
1052{
1053 struct prop_location *prev = 0, *rest = property_change_wait_list;
1054 while (rest)
1055 {
d1f21a66 1056 if (rest == location)
ede4db72
RS
1057 {
1058 if (prev)
1059 prev->next = rest->next;
1060 else
1061 property_change_wait_list = rest->next;
4feb31b2 1062 xfree (rest);
ede4db72
RS
1063 return;
1064 }
1065 prev = rest;
1066 rest = rest->next;
1067 }
1068}
1069
2f65feb6
RS
1070/* Remove the property change expectation element for IDENTIFIER. */
1071
1072static Lisp_Object
1073wait_for_property_change_unwind (identifierval)
1074 Lisp_Object identifierval;
1075{
c4898489 1076 unexpect_property_change ((struct prop_location *)
8e713be6
KR
1077 (XFASTINT (XCAR (identifierval)) << 16
1078 | XFASTINT (XCDR (identifierval))));
ab552306 1079 return Qnil;
2f65feb6
RS
1080}
1081
ede4db72 1082/* Actually wait for a property change.
2f65feb6 1083 IDENTIFIER should be the value that expect_property_change returned. */
ede4db72
RS
1084
1085static void
d1f21a66
RS
1086wait_for_property_change (location)
1087 struct prop_location *location;
ede4db72 1088{
2f65feb6 1089 int secs, usecs;
aed13378 1090 int count = SPECPDL_INDEX ();
d1f21a66
RS
1091 Lisp_Object tem;
1092
c4898489 1093 tem = Fcons (Qnil, Qnil);
f3fbd155
KR
1094 XSETCARFASTINT (tem, (EMACS_UINT)location >> 16);
1095 XSETCDRFASTINT (tem, (EMACS_UINT)location & 0xffff);
2f65feb6
RS
1096
1097 /* Make sure to do unexpect_property_change if we quit or err. */
d1f21a66 1098 record_unwind_protect (wait_for_property_change_unwind, tem);
2f65feb6 1099
f3fbd155 1100 XSETCAR (property_change_reply, Qnil);
2f65feb6 1101
afe1529d
RS
1102 property_change_reply_object = location;
1103 /* If the event we are waiting for arrives beyond here, it will set
1104 property_change_reply, because property_change_reply_object says so. */
d1f21a66
RS
1105 if (! location->arrived)
1106 {
d1f21a66
RS
1107 secs = x_selection_timeout / 1000;
1108 usecs = (x_selection_timeout % 1000) * 1000;
d9c0d4a3 1109 TRACE2 (" Waiting %d secs, %d usecs", secs, usecs);
d1f21a66
RS
1110 wait_reading_process_input (secs, usecs, property_change_reply, 0);
1111
8e713be6 1112 if (NILP (XCAR (property_change_reply)))
d9c0d4a3
GM
1113 {
1114 TRACE0 (" Timed out");
1115 error ("Timed out waiting for property-notify event");
1116 }
d1f21a66 1117 }
2f65feb6
RS
1118
1119 unbind_to (count, Qnil);
ede4db72
RS
1120}
1121
1122/* Called from XTread_socket in response to a PropertyNotify event. */
1123
1124void
1125x_handle_property_notify (event)
1126 XPropertyEvent *event;
1127{
1128 struct prop_location *prev = 0, *rest = property_change_wait_list;
d9c0d4a3 1129
ede4db72
RS
1130 while (rest)
1131 {
1132 if (rest->property == event->atom
1133 && rest->window == event->window
1134 && rest->display == event->display
1135 && rest->desired_state == event->state)
1136 {
d9c0d4a3
GM
1137 TRACE2 ("Expected %s of property %s",
1138 (event->state == PropertyDelete ? "deletion" : "change"),
1139 XGetAtomName (event->display, event->atom));
ede4db72 1140
d1f21a66
RS
1141 rest->arrived = 1;
1142
ede4db72
RS
1143 /* If this is the one wait_for_property_change is waiting for,
1144 tell it to wake up. */
d1f21a66 1145 if (rest == property_change_reply_object)
f3fbd155 1146 XSETCAR (property_change_reply, Qt);
ede4db72
RS
1147
1148 if (prev)
1149 prev->next = rest->next;
1150 else
1151 property_change_wait_list = rest->next;
4feb31b2 1152 xfree (rest);
ede4db72
RS
1153 return;
1154 }
1b65481e 1155
ede4db72
RS
1156 prev = rest;
1157 rest = rest->next;
1158 }
ede4db72
RS
1159}
1160
1161
1162\f
1163#if 0 /* #### MULTIPLE doesn't work yet */
1164
1165static Lisp_Object
1166fetch_multiple_target (event)
1167 XSelectionRequestEvent *event;
1168{
1169 Display *display = event->display;
5d0ba25b 1170 Window window = event->requestor;
ede4db72
RS
1171 Atom target = event->target;
1172 Atom selection_atom = event->selection;
1173 int result;
1174
1175 return
1176 Fcons (QMULTIPLE,
1177 x_get_window_property_as_lisp_data (display, window, target,
1178 QMULTIPLE, selection_atom));
1179}
1180
1181static Lisp_Object
1182copy_multiple_data (obj)
1183 Lisp_Object obj;
1184{
1185 Lisp_Object vec;
1186 int i;
1187 int size;
1188 if (CONSP (obj))
8e713be6 1189 return Fcons (XCAR (obj), copy_multiple_data (XCDR (obj)));
1b65481e 1190
b7826503 1191 CHECK_VECTOR (obj);
ede4db72
RS
1192 vec = Fmake_vector (size = XVECTOR (obj)->size, Qnil);
1193 for (i = 0; i < size; i++)
1194 {
1195 Lisp_Object vec2 = XVECTOR (obj)->contents [i];
b7826503 1196 CHECK_VECTOR (vec2);
ede4db72
RS
1197 if (XVECTOR (vec2)->size != 2)
1198 /* ??? Confusing error message */
1199 Fsignal (Qerror, Fcons (build_string ("vectors must be of length 2"),
1200 Fcons (vec2, Qnil)));
1201 XVECTOR (vec)->contents [i] = Fmake_vector (2, Qnil);
1202 XVECTOR (XVECTOR (vec)->contents [i])->contents [0]
1203 = XVECTOR (vec2)->contents [0];
1204 XVECTOR (XVECTOR (vec)->contents [i])->contents [1]
1205 = XVECTOR (vec2)->contents [1];
1206 }
1207 return vec;
1208}
1209
1210#endif
1211
1212\f
1213/* Variables for communication with x_handle_selection_notify. */
1214static Atom reading_which_selection;
1215static Lisp_Object reading_selection_reply;
1216static Window reading_selection_window;
1217
1218/* Do protocol to read selection-data from the server.
1219 Converts this to Lisp data and returns it. */
1220
1221static Lisp_Object
1222x_get_foreign_selection (selection_symbol, target_type)
1223 Lisp_Object selection_symbol, target_type;
1224{
378c33ca
GM
1225 struct frame *sf = SELECTED_FRAME ();
1226 Window requestor_window = FRAME_X_WINDOW (sf);
1227 Display *display = FRAME_X_DISPLAY (sf);
1228 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (sf);
5d0ba25b 1229 Time requestor_time = last_event_timestamp;
5c3a351a
RS
1230 Atom target_property = dpyinfo->Xatom_EMACS_TMP;
1231 Atom selection_atom = symbol_to_x_atom (dpyinfo, display, selection_symbol);
ede4db72 1232 Atom type_atom;
80da0190 1233 int secs, usecs;
5a499696 1234 int count;
55b2d45d 1235 Lisp_Object frame;
ede4db72
RS
1236
1237 if (CONSP (target_type))
8e713be6 1238 type_atom = symbol_to_x_atom (dpyinfo, display, XCAR (target_type));
ede4db72 1239 else
5c3a351a 1240 type_atom = symbol_to_x_atom (dpyinfo, display, target_type);
ede4db72
RS
1241
1242 BLOCK_INPUT;
1b65481e 1243
5a499696 1244 count = x_catch_errors (display);
1b65481e 1245
d9c0d4a3
GM
1246 TRACE2 ("Get selection %s, type %s",
1247 XGetAtomName (display, type_atom),
1248 XGetAtomName (display, target_property));
1249
ede4db72 1250 XConvertSelection (display, selection_atom, type_atom, target_property,
5d0ba25b 1251 requestor_window, requestor_time);
5c3a351a 1252 XFlush (display);
ede4db72
RS
1253
1254 /* Prepare to block until the reply has been read. */
5d0ba25b 1255 reading_selection_window = requestor_window;
ede4db72 1256 reading_which_selection = selection_atom;
f3fbd155 1257 XSETCAR (reading_selection_reply, Qnil);
55b2d45d
RS
1258
1259 frame = some_frame_on_display (dpyinfo);
1260
1261 /* If the display no longer has frames, we can't expect
1262 to get many more selection requests from it, so don't
1263 bother trying to queue them. */
1264 if (!NILP (frame))
1265 {
1266 x_start_queuing_selection_requests (display);
1267
1268 record_unwind_protect (queue_selection_requests_unwind,
1269 frame);
1270 }
ede4db72
RS
1271 UNBLOCK_INPUT;
1272
80da0190
RS
1273 /* This allows quits. Also, don't wait forever. */
1274 secs = x_selection_timeout / 1000;
1275 usecs = (x_selection_timeout % 1000) * 1000;
d9c0d4a3 1276 TRACE1 (" Start waiting %d secs for SelectionNotify", secs);
80da0190 1277 wait_reading_process_input (secs, usecs, reading_selection_reply, 0);
d9c0d4a3 1278 TRACE1 (" Got event = %d", !NILP (XCAR (reading_selection_reply)));
ede4db72 1279
7c6b2ea4 1280 BLOCK_INPUT;
a7b24d46 1281 x_check_errors (display, "Cannot get selection: %s");
5a499696 1282 x_uncatch_errors (display, count);
7c6b2ea4
RS
1283 UNBLOCK_INPUT;
1284
8e713be6 1285 if (NILP (XCAR (reading_selection_reply)))
606140dd 1286 error ("Timed out waiting for reply from selection owner");
8e713be6 1287 if (EQ (XCAR (reading_selection_reply), Qlambda))
d5db4077 1288 error ("No `%s' selection", SDATA (SYMBOL_NAME (selection_symbol)));
ede4db72
RS
1289
1290 /* Otherwise, the selection is waiting for us on the requested property. */
1291 return
5d0ba25b 1292 x_get_window_property_as_lisp_data (display, requestor_window,
ede4db72
RS
1293 target_property, target_type,
1294 selection_atom);
1295}
1296\f
1297/* Subroutines of x_get_window_property_as_lisp_data */
1298
4feb31b2 1299/* Use xfree, not XFree, to free the data obtained with this function. */
0158abbc 1300
ede4db72
RS
1301static void
1302x_get_window_property (display, window, property, data_ret, bytes_ret,
1303 actual_type_ret, actual_format_ret, actual_size_ret,
1304 delete_p)
1305 Display *display;
1306 Window window;
1307 Atom property;
1308 unsigned char **data_ret;
1309 int *bytes_ret;
1310 Atom *actual_type_ret;
1311 int *actual_format_ret;
1312 unsigned long *actual_size_ret;
1313 int delete_p;
1314{
1315 int total_size;
1316 unsigned long bytes_remaining;
1317 int offset = 0;
1318 unsigned char *tmp_data = 0;
1319 int result;
1320 int buffer_size = SELECTION_QUANTUM (display);
1b65481e 1321
d9c0d4a3
GM
1322 if (buffer_size > MAX_SELECTION_QUANTUM)
1323 buffer_size = MAX_SELECTION_QUANTUM;
1b65481e 1324
ede4db72 1325 BLOCK_INPUT;
1b65481e 1326
ede4db72
RS
1327 /* First probe the thing to find out how big it is. */
1328 result = XGetWindowProperty (display, window, property,
137edb72 1329 0L, 0L, False, AnyPropertyType,
ede4db72
RS
1330 actual_type_ret, actual_format_ret,
1331 actual_size_ret,
1332 &bytes_remaining, &tmp_data);
ede4db72
RS
1333 if (result != Success)
1334 {
2f65feb6 1335 UNBLOCK_INPUT;
ede4db72
RS
1336 *data_ret = 0;
1337 *bytes_ret = 0;
1338 return;
1339 }
1b65481e 1340
0158abbc
RS
1341 /* This was allocated by Xlib, so use XFree. */
1342 XFree ((char *) tmp_data);
1b65481e 1343
ede4db72
RS
1344 if (*actual_type_ret == None || *actual_format_ret == 0)
1345 {
2f65feb6 1346 UNBLOCK_INPUT;
ede4db72
RS
1347 return;
1348 }
1349
1350 total_size = bytes_remaining + 1;
1351 *data_ret = (unsigned char *) xmalloc (total_size);
1b65481e 1352
2a1a4c9d 1353 /* Now read, until we've gotten it all. */
ede4db72
RS
1354 while (bytes_remaining)
1355 {
d9c0d4a3 1356#ifdef TRACE_SELECTION
ede4db72
RS
1357 int last = bytes_remaining;
1358#endif
1359 result
1360 = XGetWindowProperty (display, window, property,
137edb72 1361 (long)offset/4, (long)buffer_size/4,
2f65feb6 1362 False,
ede4db72
RS
1363 AnyPropertyType,
1364 actual_type_ret, actual_format_ret,
1365 actual_size_ret, &bytes_remaining, &tmp_data);
d9c0d4a3
GM
1366
1367 TRACE2 ("Read %ld bytes from property %s",
1368 last - bytes_remaining,
1369 XGetAtomName (display, property));
1370
ede4db72
RS
1371 /* If this doesn't return Success at this point, it means that
1372 some clod deleted the selection while we were in the midst of
d9c0d4a3
GM
1373 reading it. Deal with that, I guess.... */
1374 if (result != Success)
1375 break;
ede4db72
RS
1376 *actual_size_ret *= *actual_format_ret / 8;
1377 bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret);
1378 offset += *actual_size_ret;
1b65481e 1379
0158abbc
RS
1380 /* This was allocated by Xlib, so use XFree. */
1381 XFree ((char *) tmp_data);
ede4db72 1382 }
2f65feb6 1383
5c3a351a 1384 XFlush (display);
ede4db72
RS
1385 UNBLOCK_INPUT;
1386 *bytes_ret = offset;
1387}
1388\f
4feb31b2 1389/* Use xfree, not XFree, to free the data obtained with this function. */
0158abbc 1390
ede4db72
RS
1391static void
1392receive_incremental_selection (display, window, property, target_type,
1393 min_size_bytes, data_ret, size_bytes_ret,
1394 type_ret, format_ret, size_ret)
1395 Display *display;
1396 Window window;
1397 Atom property;
1398 Lisp_Object target_type; /* for error messages only */
1399 unsigned int min_size_bytes;
1400 unsigned char **data_ret;
1401 int *size_bytes_ret;
1402 Atom *type_ret;
1403 unsigned long *size_ret;
1404 int *format_ret;
1405{
1406 int offset = 0;
d1f21a66 1407 struct prop_location *wait_object;
ede4db72
RS
1408 *size_bytes_ret = min_size_bytes;
1409 *data_ret = (unsigned char *) xmalloc (*size_bytes_ret);
d9c0d4a3
GM
1410
1411 TRACE1 ("Read %d bytes incrementally", min_size_bytes);
2f65feb6
RS
1412
1413 /* At this point, we have read an INCR property.
1414 Delete the property to ack it.
1415 (But first, prepare to receive the next event in this handshake.)
ede4db72
RS
1416
1417 Now, we must loop, waiting for the sending window to put a value on
1418 that property, then reading the property, then deleting it to ack.
1419 We are done when the sender places a property of length 0.
1420 */
2f65feb6
RS
1421 BLOCK_INPUT;
1422 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask);
d9c0d4a3
GM
1423 TRACE1 (" Delete property %s",
1424 XSYMBOL (x_atom_to_symbol (display, property))->name->data);
2f65feb6 1425 XDeleteProperty (display, window, property);
d9c0d4a3
GM
1426 TRACE1 (" Expect new value of property %s",
1427 XSYMBOL (x_atom_to_symbol (display, property))->name->data);
d1f21a66
RS
1428 wait_object = expect_property_change (display, window, property,
1429 PropertyNewValue);
5c3a351a 1430 XFlush (display);
2f65feb6
RS
1431 UNBLOCK_INPUT;
1432
ede4db72
RS
1433 while (1)
1434 {
1435 unsigned char *tmp_data;
1436 int tmp_size_bytes;
d9c0d4a3
GM
1437
1438 TRACE0 (" Wait for property change");
d1f21a66 1439 wait_for_property_change (wait_object);
1b65481e 1440
ede4db72 1441 /* expect it again immediately, because x_get_window_property may
2a1a4c9d 1442 .. no it won't, I don't get it.
d9c0d4a3
GM
1443 .. Ok, I get it now, the Xt code that implements INCR is broken. */
1444 TRACE0 (" Get property value");
ede4db72
RS
1445 x_get_window_property (display, window, property,
1446 &tmp_data, &tmp_size_bytes,
1447 type_ret, format_ret, size_ret, 1);
1448
d9c0d4a3
GM
1449 TRACE1 (" Read increment of %d bytes", tmp_size_bytes);
1450
ede4db72
RS
1451 if (tmp_size_bytes == 0) /* we're done */
1452 {
d9c0d4a3
GM
1453 TRACE0 ("Done reading incrementally");
1454
2f65feb6
RS
1455 if (! waiting_for_other_props_on_window (display, window))
1456 XSelectInput (display, window, STANDARD_EVENT_SET);
d1f21a66 1457 unexpect_property_change (wait_object);
4feb31b2 1458 /* Use xfree, not XFree, because x_get_window_property
0158abbc 1459 calls xmalloc itself. */
4feb31b2 1460 if (tmp_data) xfree (tmp_data);
ede4db72
RS
1461 break;
1462 }
2f65feb6
RS
1463
1464 BLOCK_INPUT;
d9c0d4a3
GM
1465 TRACE1 (" ACK by deleting property %s",
1466 XGetAtomName (display, property));
2f65feb6 1467 XDeleteProperty (display, window, property);
d1f21a66
RS
1468 wait_object = expect_property_change (display, window, property,
1469 PropertyNewValue);
5c3a351a 1470 XFlush (display);
2f65feb6
RS
1471 UNBLOCK_INPUT;
1472
ede4db72
RS
1473 if (*size_bytes_ret < offset + tmp_size_bytes)
1474 {
ede4db72
RS
1475 *size_bytes_ret = offset + tmp_size_bytes;
1476 *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret);
1477 }
1b65481e 1478
018cfa07 1479 bcopy (tmp_data, (*data_ret) + offset, tmp_size_bytes);
ede4db72 1480 offset += tmp_size_bytes;
1b65481e 1481
4feb31b2 1482 /* Use xfree, not XFree, because x_get_window_property
0158abbc 1483 calls xmalloc itself. */
4feb31b2 1484 xfree (tmp_data);
ede4db72
RS
1485 }
1486}
d9c0d4a3 1487
ede4db72
RS
1488\f
1489/* Once a requested selection is "ready" (we got a SelectionNotify event),
1490 fetch value from property PROPERTY of X window WINDOW on display DISPLAY.
1491 TARGET_TYPE and SELECTION_ATOM are used in error message if this fails. */
1492
1493static Lisp_Object
1494x_get_window_property_as_lisp_data (display, window, property, target_type,
1495 selection_atom)
1496 Display *display;
1497 Window window;
1498 Atom property;
1499 Lisp_Object target_type; /* for error messages only */
1500 Atom selection_atom; /* for error messages only */
1501{
1502 Atom actual_type;
1503 int actual_format;
1504 unsigned long actual_size;
1505 unsigned char *data = 0;
1506 int bytes = 0;
1507 Lisp_Object val;
5c3a351a 1508 struct x_display_info *dpyinfo = x_display_info_for_display (display);
ede4db72 1509
d9c0d4a3
GM
1510 TRACE0 ("Reading selection data");
1511
ede4db72
RS
1512 x_get_window_property (display, window, property, &data, &bytes,
1513 &actual_type, &actual_format, &actual_size, 1);
1514 if (! data)
1515 {
1516 int there_is_a_selection_owner;
1517 BLOCK_INPUT;
1518 there_is_a_selection_owner
1519 = XGetSelectionOwner (display, selection_atom);
1520 UNBLOCK_INPUT;
5a499696
RS
1521 Fsignal (Qerror,
1522 there_is_a_selection_owner
1523 ? Fcons (build_string ("selection owner couldn't convert"),
ede4db72
RS
1524 actual_type
1525 ? Fcons (target_type,
d9c0d4a3 1526 Fcons (x_atom_to_symbol (display,
5c3a351a 1527 actual_type),
ede4db72
RS
1528 Qnil))
1529 : Fcons (target_type, Qnil))
5a499696 1530 : Fcons (build_string ("no selection"),
d9c0d4a3 1531 Fcons (x_atom_to_symbol (display,
5a499696
RS
1532 selection_atom),
1533 Qnil)));
ede4db72 1534 }
1b65481e 1535
5c3a351a 1536 if (actual_type == dpyinfo->Xatom_INCR)
ede4db72
RS
1537 {
1538 /* That wasn't really the data, just the beginning. */
1539
1540 unsigned int min_size_bytes = * ((unsigned int *) data);
1541 BLOCK_INPUT;
4feb31b2 1542 /* Use xfree, not XFree, because x_get_window_property
0158abbc 1543 calls xmalloc itself. */
4feb31b2 1544 xfree ((char *) data);
ede4db72
RS
1545 UNBLOCK_INPUT;
1546 receive_incremental_selection (display, window, property, target_type,
1547 min_size_bytes, &data, &bytes,
1548 &actual_type, &actual_format,
1549 &actual_size);
1550 }
1551
2f65feb6 1552 BLOCK_INPUT;
d9c0d4a3 1553 TRACE1 (" Delete property %s", XGetAtomName (display, property));
2f65feb6 1554 XDeleteProperty (display, window, property);
5c3a351a 1555 XFlush (display);
2f65feb6
RS
1556 UNBLOCK_INPUT;
1557
ede4db72
RS
1558 /* It's been read. Now convert it to a lisp object in some semi-rational
1559 manner. */
1560 val = selection_data_to_lisp_data (display, data, bytes,
1561 actual_type, actual_format);
1b65481e 1562
4feb31b2 1563 /* Use xfree, not XFree, because x_get_window_property
0158abbc 1564 calls xmalloc itself. */
4feb31b2 1565 xfree ((char *) data);
ede4db72
RS
1566 return val;
1567}
1568\f
1569/* These functions convert from the selection data read from the server into
1570 something that we can use from Lisp, and vice versa.
1571
1572 Type: Format: Size: Lisp Type:
1573 ----- ------- ----- -----------
1574 * 8 * String
1575 ATOM 32 1 Symbol
1576 ATOM 32 > 1 Vector of Symbols
1577 * 16 1 Integer
1578 * 16 > 1 Vector of Integers
1579 * 32 1 if <=16 bits: Integer
1580 if > 16 bits: Cons of top16, bot16
1581 * 32 > 1 Vector of the above
1582
1583 When converting a Lisp number to C, it is assumed to be of format 16 if
1584 it is an integer, and of format 32 if it is a cons of two integers.
1585
1586 When converting a vector of numbers from Lisp to C, it is assumed to be
1587 of format 16 if every element in the vector is an integer, and is assumed
1588 to be of format 32 if any element is a cons of two integers.
1589
1590 When converting an object to C, it may be of the form (SYMBOL . <data>)
1591 where SYMBOL is what we should claim that the type is. Format and
1592 representation are as above. */
1593
1594
1595
1596static Lisp_Object
1597selection_data_to_lisp_data (display, data, size, type, format)
1598 Display *display;
1599 unsigned char *data;
1600 Atom type;
1601 int size, format;
1602{
5c3a351a 1603 struct x_display_info *dpyinfo = x_display_info_for_display (display);
ede4db72 1604
5c3a351a 1605 if (type == dpyinfo->Xatom_NULL)
ede4db72
RS
1606 return QNULL;
1607
1608 /* Convert any 8-bit data to a string, for compactness. */
1609 else if (format == 8)
e6c7c988 1610 {
e57ad4d8
KH
1611 Lisp_Object str, lispy_type;
1612
1613 str = make_unibyte_string ((char *) data, size);
1614 /* Indicate that this string is from foreign selection by a text
1615 property `foreign-selection' so that the caller of
1616 x-get-selection-internal (usually x-get-selection) can know
1617 that the string must be decode. */
1618 if (type == dpyinfo->Xatom_COMPOUND_TEXT)
1619 lispy_type = QCOMPOUND_TEXT;
1620 else if (type == dpyinfo->Xatom_UTF8_STRING)
1621 lispy_type = QUTF8_STRING;
e6c7c988 1622 else
e57ad4d8
KH
1623 lispy_type = QSTRING;
1624 Fput_text_property (make_number (0), make_number (size),
1625 Qforeign_selection, lispy_type, str);
e6c7c988
KH
1626 return str;
1627 }
ede4db72
RS
1628 /* Convert a single atom to a Lisp_Symbol. Convert a set of atoms to
1629 a vector of symbols.
1630 */
1631 else if (type == XA_ATOM)
1632 {
1633 int i;
1634 if (size == sizeof (Atom))
d9c0d4a3 1635 return x_atom_to_symbol (display, *((Atom *) data));
ede4db72
RS
1636 else
1637 {
e607a484
RS
1638 Lisp_Object v = Fmake_vector (make_number (size / sizeof (Atom)),
1639 make_number (0));
ede4db72 1640 for (i = 0; i < size / sizeof (Atom); i++)
e607a484 1641 Faset (v, make_number (i),
d9c0d4a3 1642 x_atom_to_symbol (display, ((Atom *) data) [i]));
ede4db72
RS
1643 return v;
1644 }
1645 }
1646
1647 /* Convert a single 16 or small 32 bit number to a Lisp_Int.
1648 If the number is > 16 bits, convert it to a cons of integers,
1649 16 bits in each half.
1650 */
2f51feb8
AS
1651 else if (format == 32 && size == sizeof (int))
1652 return long_to_cons (((unsigned int *) data) [0]);
ede4db72
RS
1653 else if (format == 16 && size == sizeof (short))
1654 return make_number ((int) (((unsigned short *) data) [0]));
1655
1656 /* Convert any other kind of data to a vector of numbers, represented
1657 as above (as an integer, or a cons of two 16 bit integers.)
1658 */
1659 else if (format == 16)
1660 {
1661 int i;
937a3875
RS
1662 Lisp_Object v;
1663 v = Fmake_vector (make_number (size / 2), make_number (0));
1664 for (i = 0; i < size / 2; i++)
ede4db72
RS
1665 {
1666 int j = (int) ((unsigned short *) data) [i];
e607a484 1667 Faset (v, make_number (i), make_number (j));
ede4db72
RS
1668 }
1669 return v;
1670 }
1671 else
1672 {
1673 int i;
e607a484 1674 Lisp_Object v = Fmake_vector (make_number (size / 4), make_number (0));
ede4db72
RS
1675 for (i = 0; i < size / 4; i++)
1676 {
2f51feb8 1677 unsigned int j = ((unsigned int *) data) [i];
e607a484 1678 Faset (v, make_number (i), long_to_cons (j));
ede4db72
RS
1679 }
1680 return v;
1681 }
1682}
1683
1684
4feb31b2 1685/* Use xfree, not XFree, to free the data obtained with this function. */
0158abbc 1686
ede4db72
RS
1687static void
1688lisp_data_to_selection_data (display, obj,
aca39f42
RS
1689 data_ret, type_ret, size_ret,
1690 format_ret, nofree_ret)
ede4db72
RS
1691 Display *display;
1692 Lisp_Object obj;
1693 unsigned char **data_ret;
1694 Atom *type_ret;
1695 unsigned int *size_ret;
1696 int *format_ret;
aca39f42 1697 int *nofree_ret;
ede4db72
RS
1698{
1699 Lisp_Object type = Qnil;
5c3a351a 1700 struct x_display_info *dpyinfo = x_display_info_for_display (display);
aca39f42
RS
1701
1702 *nofree_ret = 0;
1703
8e713be6 1704 if (CONSP (obj) && SYMBOLP (XCAR (obj)))
ede4db72 1705 {
8e713be6
KR
1706 type = XCAR (obj);
1707 obj = XCDR (obj);
1708 if (CONSP (obj) && NILP (XCDR (obj)))
1709 obj = XCAR (obj);
ede4db72
RS
1710 }
1711
1712 if (EQ (obj, QNULL) || (EQ (type, QNULL)))
1713 { /* This is not the same as declining */
1714 *format_ret = 32;
1715 *size_ret = 0;
1716 *data_ret = 0;
1717 type = QNULL;
1718 }
1719 else if (STRINGP (obj))
1720 {
5109c8dd 1721 xassert (! STRING_MULTIBYTE (obj));
7b9ae523 1722 if (NILP (type))
5109c8dd
KH
1723 type = QSTRING;
1724 *format_ret = 8;
1725 *size_ret = SBYTES (obj);
1726 *data_ret = SDATA (obj);
1727 *nofree_ret = 1;
ede4db72
RS
1728 }
1729 else if (SYMBOLP (obj))
1730 {
1731 *format_ret = 32;
1732 *size_ret = 1;
1733 *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1);
1734 (*data_ret) [sizeof (Atom)] = 0;
5c3a351a 1735 (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, display, obj);
ede4db72
RS
1736 if (NILP (type)) type = QATOM;
1737 }
7da64e5c 1738 else if (INTEGERP (obj)
ede4db72
RS
1739 && XINT (obj) < 0xFFFF
1740 && XINT (obj) > -0xFFFF)
1741 {
1742 *format_ret = 16;
1743 *size_ret = 1;
1744 *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
1745 (*data_ret) [sizeof (short)] = 0;
1746 (*(short **) data_ret) [0] = (short) XINT (obj);
1747 if (NILP (type)) type = QINTEGER;
1748 }
a87ed99c 1749 else if (INTEGERP (obj)
8e713be6
KR
1750 || (CONSP (obj) && INTEGERP (XCAR (obj))
1751 && (INTEGERP (XCDR (obj))
1752 || (CONSP (XCDR (obj))
1753 && INTEGERP (XCAR (XCDR (obj)))))))
ede4db72
RS
1754 {
1755 *format_ret = 32;
1756 *size_ret = 1;
1757 *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
1758 (*data_ret) [sizeof (long)] = 0;
1759 (*(unsigned long **) data_ret) [0] = cons_to_long (obj);
1760 if (NILP (type)) type = QINTEGER;
1761 }
1762 else if (VECTORP (obj))
1763 {
1764 /* Lisp_Vectors may represent a set of ATOMs;
1765 a set of 16 or 32 bit INTEGERs;
1766 or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...]
1767 */
1768 int i;
1769
1770 if (SYMBOLP (XVECTOR (obj)->contents [0]))
1771 /* This vector is an ATOM set */
1772 {
1773 if (NILP (type)) type = QATOM;
1774 *size_ret = XVECTOR (obj)->size;
1775 *format_ret = 32;
1776 *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom));
1777 for (i = 0; i < *size_ret; i++)
1778 if (SYMBOLP (XVECTOR (obj)->contents [i]))
1779 (*(Atom **) data_ret) [i]
5c3a351a 1780 = symbol_to_x_atom (dpyinfo, display, XVECTOR (obj)->contents [i]);
ede4db72
RS
1781 else
1782 Fsignal (Qerror, /* Qselection_error */
1783 Fcons (build_string
1784 ("all elements of selection vector must have same type"),
1785 Fcons (obj, Qnil)));
1786 }
1787#if 0 /* #### MULTIPLE doesn't work yet */
1788 else if (VECTORP (XVECTOR (obj)->contents [0]))
1789 /* This vector is an ATOM_PAIR set */
1790 {
1791 if (NILP (type)) type = QATOM_PAIR;
1792 *size_ret = XVECTOR (obj)->size;
1793 *format_ret = 32;
1794 *data_ret = (unsigned char *)
1795 xmalloc ((*size_ret) * sizeof (Atom) * 2);
1796 for (i = 0; i < *size_ret; i++)
1797 if (VECTORP (XVECTOR (obj)->contents [i]))
1798 {
1799 Lisp_Object pair = XVECTOR (obj)->contents [i];
1800 if (XVECTOR (pair)->size != 2)
1801 Fsignal (Qerror,
1b65481e 1802 Fcons (build_string
ede4db72
RS
1803 ("elements of the vector must be vectors of exactly two elements"),
1804 Fcons (pair, Qnil)));
1b65481e 1805
ede4db72 1806 (*(Atom **) data_ret) [i * 2]
5c3a351a
RS
1807 = symbol_to_x_atom (dpyinfo, display,
1808 XVECTOR (pair)->contents [0]);
ede4db72 1809 (*(Atom **) data_ret) [(i * 2) + 1]
5c3a351a
RS
1810 = symbol_to_x_atom (dpyinfo, display,
1811 XVECTOR (pair)->contents [1]);
ede4db72
RS
1812 }
1813 else
1814 Fsignal (Qerror,
1815 Fcons (build_string
1816 ("all elements of the vector must be of the same type"),
1817 Fcons (obj, Qnil)));
1b65481e 1818
ede4db72
RS
1819 }
1820#endif
1821 else
1822 /* This vector is an INTEGER set, or something like it */
1823 {
1824 *size_ret = XVECTOR (obj)->size;
1825 if (NILP (type)) type = QINTEGER;
1826 *format_ret = 16;
1827 for (i = 0; i < *size_ret; i++)
1828 if (CONSP (XVECTOR (obj)->contents [i]))
1829 *format_ret = 32;
7da64e5c 1830 else if (!INTEGERP (XVECTOR (obj)->contents [i]))
ede4db72
RS
1831 Fsignal (Qerror, /* Qselection_error */
1832 Fcons (build_string
1833 ("elements of selection vector must be integers or conses of integers"),
1834 Fcons (obj, Qnil)));
1835
1836 *data_ret = (unsigned char *) xmalloc (*size_ret * (*format_ret/8));
1837 for (i = 0; i < *size_ret; i++)
1838 if (*format_ret == 32)
1839 (*((unsigned long **) data_ret)) [i]
1840 = cons_to_long (XVECTOR (obj)->contents [i]);
1841 else
1842 (*((unsigned short **) data_ret)) [i]
1843 = (unsigned short) cons_to_long (XVECTOR (obj)->contents [i]);
1844 }
1845 }
1846 else
1847 Fsignal (Qerror, /* Qselection_error */
1848 Fcons (build_string ("unrecognised selection data"),
1849 Fcons (obj, Qnil)));
1850
5c3a351a 1851 *type_ret = symbol_to_x_atom (dpyinfo, display, type);
ede4db72
RS
1852}
1853
1854static Lisp_Object
1855clean_local_selection_data (obj)
1856 Lisp_Object obj;
1857{
1858 if (CONSP (obj)
8e713be6
KR
1859 && INTEGERP (XCAR (obj))
1860 && CONSP (XCDR (obj))
1861 && INTEGERP (XCAR (XCDR (obj)))
1862 && NILP (XCDR (XCDR (obj))))
1863 obj = Fcons (XCAR (obj), XCDR (obj));
ede4db72
RS
1864
1865 if (CONSP (obj)
8e713be6
KR
1866 && INTEGERP (XCAR (obj))
1867 && INTEGERP (XCDR (obj)))
ede4db72 1868 {
8e713be6
KR
1869 if (XINT (XCAR (obj)) == 0)
1870 return XCDR (obj);
1871 if (XINT (XCAR (obj)) == -1)
1872 return make_number (- XINT (XCDR (obj)));
ede4db72
RS
1873 }
1874 if (VECTORP (obj))
1875 {
1876 int i;
1877 int size = XVECTOR (obj)->size;
1878 Lisp_Object copy;
1879 if (size == 1)
1880 return clean_local_selection_data (XVECTOR (obj)->contents [0]);
e607a484 1881 copy = Fmake_vector (make_number (size), Qnil);
ede4db72
RS
1882 for (i = 0; i < size; i++)
1883 XVECTOR (copy)->contents [i]
1884 = clean_local_selection_data (XVECTOR (obj)->contents [i]);
1885 return copy;
1886 }
1887 return obj;
1888}
1889\f
1890/* Called from XTread_socket to handle SelectionNotify events.
606140dd
KH
1891 If it's the selection we are waiting for, stop waiting
1892 by setting the car of reading_selection_reply to non-nil.
1893 We store t there if the reply is successful, lambda if not. */
ede4db72
RS
1894
1895void
1896x_handle_selection_notify (event)
1897 XSelectionEvent *event;
1898{
5d0ba25b 1899 if (event->requestor != reading_selection_window)
ede4db72
RS
1900 return;
1901 if (event->selection != reading_which_selection)
1902 return;
1903
d9c0d4a3 1904 TRACE0 ("Received SelectionNotify");
f3fbd155
KR
1905 XSETCAR (reading_selection_reply,
1906 (event->property != 0 ? Qt : Qlambda));
ede4db72
RS
1907}
1908
1909\f
a0d76c27 1910DEFUN ("x-own-selection-internal", Fx_own_selection_internal,
8c1a1077
PJ
1911 Sx_own_selection_internal, 2, 2, 0,
1912 doc: /* Assert an X selection of the given TYPE with the given VALUE.
1913TYPE is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
1914\(Those are literal upper-case symbol names, since that's what X expects.)
1915VALUE is typically a string, or a cons of two markers, but may be
1916anything that the functions on `selection-converter-alist' know about. */)
1917 (selection_name, selection_value)
ede4db72
RS
1918 Lisp_Object selection_name, selection_value;
1919{
703e0710 1920 check_x ();
b7826503 1921 CHECK_SYMBOL (selection_name);
606140dd 1922 if (NILP (selection_value)) error ("selection-value may not be nil");
ede4db72
RS
1923 x_own_selection (selection_name, selection_value);
1924 return selection_value;
1925}
1926
1927
1928/* Request the selection value from the owner. If we are the owner,
1929 simply return our selection value. If we are not the owner, this
1930 will block until all of the data has arrived. */
1931
a0d76c27 1932DEFUN ("x-get-selection-internal", Fx_get_selection_internal,
8c1a1077
PJ
1933 Sx_get_selection_internal, 2, 2, 0,
1934 doc: /* Return text selected from some X window.
1935SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
1936\(Those are literal upper-case symbol names, since that's what X expects.)
1937TYPE is the type of data desired, typically `STRING'. */)
1938 (selection_symbol, target_type)
ede4db72
RS
1939 Lisp_Object selection_symbol, target_type;
1940{
1941 Lisp_Object val = Qnil;
1942 struct gcpro gcpro1, gcpro2;
1943 GCPRO2 (target_type, val); /* we store newly consed data into these */
703e0710 1944 check_x ();
b7826503 1945 CHECK_SYMBOL (selection_symbol);
ede4db72
RS
1946
1947#if 0 /* #### MULTIPLE doesn't work yet */
1948 if (CONSP (target_type)
8e713be6 1949 && XCAR (target_type) == QMULTIPLE)
ede4db72 1950 {
b7826503 1951 CHECK_VECTOR (XCDR (target_type));
ede4db72
RS
1952 /* So we don't destructively modify this... */
1953 target_type = copy_multiple_data (target_type);
1954 }
1955 else
1956#endif
b7826503 1957 CHECK_SYMBOL (target_type);
ede4db72 1958
5109c8dd 1959 val = x_get_local_selection (selection_symbol, target_type, 1);
ede4db72
RS
1960
1961 if (NILP (val))
1962 {
1963 val = x_get_foreign_selection (selection_symbol, target_type);
1964 goto DONE;
1965 }
1966
1967 if (CONSP (val)
8e713be6 1968 && SYMBOLP (XCAR (val)))
ede4db72 1969 {
8e713be6
KR
1970 val = XCDR (val);
1971 if (CONSP (val) && NILP (XCDR (val)))
1972 val = XCAR (val);
ede4db72
RS
1973 }
1974 val = clean_local_selection_data (val);
1975 DONE:
1976 UNGCPRO;
1977 return val;
1978}
1979
a0d76c27 1980DEFUN ("x-disown-selection-internal", Fx_disown_selection_internal,
8c1a1077
PJ
1981 Sx_disown_selection_internal, 1, 2, 0,
1982 doc: /* If we own the selection SELECTION, disown it.
1983Disowning it means there is no such selection. */)
1984 (selection, time)
ede4db72
RS
1985 Lisp_Object selection;
1986 Lisp_Object time;
1987{
ede4db72
RS
1988 Time timestamp;
1989 Atom selection_atom;
44d46531 1990 struct selection_input_event event;
3834c318 1991 Display *display;
5c3a351a 1992 struct x_display_info *dpyinfo;
378c33ca 1993 struct frame *sf = SELECTED_FRAME ();
ede4db72 1994
703e0710 1995 check_x ();
378c33ca
GM
1996 display = FRAME_X_DISPLAY (sf);
1997 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
b7826503 1998 CHECK_SYMBOL (selection);
ede4db72 1999 if (NILP (time))
7da64e5c 2000 timestamp = last_event_timestamp;
ede4db72
RS
2001 else
2002 timestamp = cons_to_long (time);
2003
2004 if (NILP (assq_no_quit (selection, Vselection_alist)))
2005 return Qnil; /* Don't disown the selection when we're not the owner. */
2006
5c3a351a 2007 selection_atom = symbol_to_x_atom (dpyinfo, display, selection);
ede4db72
RS
2008
2009 BLOCK_INPUT;
2010 XSetSelectionOwner (display, selection_atom, None, timestamp);
2011 UNBLOCK_INPUT;
2012
eb8c3be9 2013 /* It doesn't seem to be guaranteed that a SelectionClear event will be
ede4db72
RS
2014 generated for a window which owns the selection when that window sets
2015 the selection owner to None. The NCD server does, the MIT Sun4 server
2016 doesn't. So we synthesize one; this means we might get two, but
2017 that's ok, because the second one won't have any effect. */
8d47f8c4
RS
2018 SELECTION_EVENT_DISPLAY (&event) = display;
2019 SELECTION_EVENT_SELECTION (&event) = selection_atom;
2020 SELECTION_EVENT_TIME (&event) = timestamp;
44d46531 2021 x_handle_selection_clear ((struct input_event *) &event);
ede4db72
RS
2022
2023 return Qt;
2024}
2025
a87ed99c
RS
2026/* Get rid of all the selections in buffer BUFFER.
2027 This is used when we kill a buffer. */
2028
2029void
2030x_disown_buffer_selections (buffer)
2031 Lisp_Object buffer;
2032{
2033 Lisp_Object tail;
2034 struct buffer *buf = XBUFFER (buffer);
2035
8e713be6 2036 for (tail = Vselection_alist; CONSP (tail); tail = XCDR (tail))
a87ed99c
RS
2037 {
2038 Lisp_Object elt, value;
8e713be6
KR
2039 elt = XCAR (tail);
2040 value = XCDR (elt);
2041 if (CONSP (value) && MARKERP (XCAR (value))
2042 && XMARKER (XCAR (value))->buffer == buf)
2043 Fx_disown_selection_internal (XCAR (elt), Qnil);
a87ed99c
RS
2044 }
2045}
ede4db72
RS
2046
2047DEFUN ("x-selection-owner-p", Fx_selection_owner_p, Sx_selection_owner_p,
8c1a1077
PJ
2048 0, 1, 0,
2049 doc: /* Whether the current Emacs process owns the given X Selection.
2050The arg should be the name of the selection in question, typically one of
2051the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.
2052\(Those are literal upper-case symbol names, since that's what X expects.)
2053For convenience, the symbol nil is the same as `PRIMARY',
2054and t is the same as `SECONDARY'. */)
2055 (selection)
ede4db72
RS
2056 Lisp_Object selection;
2057{
703e0710 2058 check_x ();
b7826503 2059 CHECK_SYMBOL (selection);
ede4db72
RS
2060 if (EQ (selection, Qnil)) selection = QPRIMARY;
2061 if (EQ (selection, Qt)) selection = QSECONDARY;
1b65481e 2062
ede4db72
RS
2063 if (NILP (Fassq (selection, Vselection_alist)))
2064 return Qnil;
2065 return Qt;
2066}
2067
2068DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
8c1a1077
PJ
2069 0, 1, 0,
2070 doc: /* Whether there is an owner for the given X Selection.
2071The arg should be the name of the selection in question, typically one of
2072the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.
2073\(Those are literal upper-case symbol names, since that's what X expects.)
2074For convenience, the symbol nil is the same as `PRIMARY',
2075and t is the same as `SECONDARY'. */)
2076 (selection)
ede4db72
RS
2077 Lisp_Object selection;
2078{
2079 Window owner;
356ba514 2080 Atom atom;
3834c318 2081 Display *dpy;
378c33ca 2082 struct frame *sf = SELECTED_FRAME ();
3834c318 2083
b8c70430 2084 /* It should be safe to call this before we have an X frame. */
378c33ca 2085 if (! FRAME_X_P (sf))
b8c70430
RS
2086 return Qnil;
2087
378c33ca 2088 dpy = FRAME_X_DISPLAY (sf);
b7826503 2089 CHECK_SYMBOL (selection);
ede4db72
RS
2090 if (!NILP (Fx_selection_owner_p (selection)))
2091 return Qt;
356ba514
RS
2092 if (EQ (selection, Qnil)) selection = QPRIMARY;
2093 if (EQ (selection, Qt)) selection = QSECONDARY;
378c33ca 2094 atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (sf), dpy, selection);
356ba514
RS
2095 if (atom == 0)
2096 return Qnil;
ede4db72 2097 BLOCK_INPUT;
356ba514 2098 owner = XGetSelectionOwner (dpy, atom);
ede4db72
RS
2099 UNBLOCK_INPUT;
2100 return (owner ? Qt : Qnil);
2101}
2102
2103\f
2104#ifdef CUT_BUFFER_SUPPORT
2105
ede4db72
RS
2106/* Ensure that all 8 cut buffers exist. ICCCM says we gotta... */
2107static void
2108initialize_cut_buffers (display, window)
2109 Display *display;
2110 Window window;
2111{
2112 unsigned char *data = (unsigned char *) "";
2113 BLOCK_INPUT;
2114#define FROB(atom) XChangeProperty (display, window, atom, XA_STRING, 8, \
2115 PropModeAppend, data, 0)
2116 FROB (XA_CUT_BUFFER0);
2117 FROB (XA_CUT_BUFFER1);
2118 FROB (XA_CUT_BUFFER2);
2119 FROB (XA_CUT_BUFFER3);
2120 FROB (XA_CUT_BUFFER4);
2121 FROB (XA_CUT_BUFFER5);
2122 FROB (XA_CUT_BUFFER6);
2123 FROB (XA_CUT_BUFFER7);
2124#undef FROB
2125 UNBLOCK_INPUT;
ede4db72
RS
2126}
2127
2128
b7826503
PJ
2129#define CHECK_CUT_BUFFER(symbol) \
2130 { CHECK_SYMBOL ((symbol)); \
ede4db72
RS
2131 if (!EQ((symbol), QCUT_BUFFER0) && !EQ((symbol), QCUT_BUFFER1) \
2132 && !EQ((symbol), QCUT_BUFFER2) && !EQ((symbol), QCUT_BUFFER3) \
2133 && !EQ((symbol), QCUT_BUFFER4) && !EQ((symbol), QCUT_BUFFER5) \
2134 && !EQ((symbol), QCUT_BUFFER6) && !EQ((symbol), QCUT_BUFFER7)) \
2135 Fsignal (Qerror, \
a87ed99c 2136 Fcons (build_string ("doesn't name a cut buffer"), \
ede4db72
RS
2137 Fcons ((symbol), Qnil))); \
2138 }
2139
a87ed99c 2140DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
8c1a1077
PJ
2141 Sx_get_cut_buffer_internal, 1, 1, 0,
2142 doc: /* Returns the value of the named cut buffer (typically CUT_BUFFER0). */)
2143 (buffer)
ede4db72
RS
2144 Lisp_Object buffer;
2145{
3834c318 2146 Window window;
ede4db72
RS
2147 Atom buffer_atom;
2148 unsigned char *data;
2149 int bytes;
2150 Atom type;
2151 int format;
2152 unsigned long size;
2153 Lisp_Object ret;
3834c318 2154 Display *display;
5c3a351a 2155 struct x_display_info *dpyinfo;
378c33ca 2156 struct frame *sf = SELECTED_FRAME ();
ede4db72 2157
703e0710 2158 check_x ();
378c33ca
GM
2159 display = FRAME_X_DISPLAY (sf);
2160 dpyinfo = FRAME_X_DISPLAY_INFO (sf);
3834c318 2161 window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
b7826503 2162 CHECK_CUT_BUFFER (buffer);
5c3a351a 2163 buffer_atom = symbol_to_x_atom (dpyinfo, display, buffer);
ede4db72
RS
2164
2165 x_get_window_property (display, window, buffer_atom, &data, &bytes,
2166 &type, &format, &size, 0);
22e00739
RS
2167 if (!data || !format)
2168 return Qnil;
1b65481e 2169
ede4db72
RS
2170 if (format != 8 || type != XA_STRING)
2171 Fsignal (Qerror,
2172 Fcons (build_string ("cut buffer doesn't contain 8-bit data"),
d9c0d4a3 2173 Fcons (x_atom_to_symbol (display, type),
ede4db72
RS
2174 Fcons (make_number (format), Qnil))));
2175
2176 ret = (bytes ? make_string ((char *) data, bytes) : Qnil);
4feb31b2 2177 /* Use xfree, not XFree, because x_get_window_property
0158abbc 2178 calls xmalloc itself. */
4feb31b2 2179 xfree (data);
ede4db72
RS
2180 return ret;
2181}
2182
2183
a87ed99c 2184DEFUN ("x-store-cut-buffer-internal", Fx_store_cut_buffer_internal,
8c1a1077
PJ
2185 Sx_store_cut_buffer_internal, 2, 2, 0,
2186 doc: /* Sets the value of the named cut buffer (typically CUT_BUFFER0). */)
2187 (buffer, string)
ede4db72
RS
2188 Lisp_Object buffer, string;
2189{
3834c318 2190 Window window;
ede4db72
RS
2191 Atom buffer_atom;
2192 unsigned char *data;
2193 int bytes;
2194 int bytes_remaining;
3834c318
RS
2195 int max_bytes;
2196 Display *display;
378c33ca 2197 struct frame *sf = SELECTED_FRAME ();
ede4db72 2198
703e0710 2199 check_x ();
378c33ca 2200 display = FRAME_X_DISPLAY (sf);
3834c318
RS
2201 window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
2202
2203 max_bytes = SELECTION_QUANTUM (display);
2204 if (max_bytes > MAX_SELECTION_QUANTUM)
2205 max_bytes = MAX_SELECTION_QUANTUM;
2206
b7826503
PJ
2207 CHECK_CUT_BUFFER (buffer);
2208 CHECK_STRING (string);
378c33ca 2209 buffer_atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (sf),
5c3a351a 2210 display, buffer);
d5db4077
KR
2211 data = (unsigned char *) SDATA (string);
2212 bytes = SBYTES (string);
ede4db72
RS
2213 bytes_remaining = bytes;
2214
378c33ca 2215 if (! FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized)
04649dbc
KH
2216 {
2217 initialize_cut_buffers (display, window);
378c33ca 2218 FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized = 1;
04649dbc 2219 }
ede4db72
RS
2220
2221 BLOCK_INPUT;
10608c8c
RS
2222
2223 /* Don't mess up with an empty value. */
2224 if (!bytes_remaining)
2225 XChangeProperty (display, window, buffer_atom, XA_STRING, 8,
2226 PropModeReplace, data, 0);
2227
ede4db72
RS
2228 while (bytes_remaining)
2229 {
2230 int chunk = (bytes_remaining < max_bytes
2231 ? bytes_remaining : max_bytes);
2232 XChangeProperty (display, window, buffer_atom, XA_STRING, 8,
2233 (bytes_remaining == bytes
2234 ? PropModeReplace
2235 : PropModeAppend),
2236 data, chunk);
2237 data += chunk;
2238 bytes_remaining -= chunk;
2239 }
2240 UNBLOCK_INPUT;
2241 return string;
2242}
2243
2244
a87ed99c 2245DEFUN ("x-rotate-cut-buffers-internal", Fx_rotate_cut_buffers_internal,
8c1a1077
PJ
2246 Sx_rotate_cut_buffers_internal, 1, 1, 0,
2247 doc: /* Rotate the values of the cut buffers by the given number of step.
2248Positive means shift the values forward, negative means backward. */)
2249 (n)
ede4db72
RS
2250 Lisp_Object n;
2251{
3834c318
RS
2252 Window window;
2253 Atom props[8];
2254 Display *display;
378c33ca 2255 struct frame *sf = SELECTED_FRAME ();
ede4db72 2256
703e0710 2257 check_x ();
378c33ca 2258 display = FRAME_X_DISPLAY (sf);
3834c318 2259 window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
b7826503 2260 CHECK_NUMBER (n);
3834c318
RS
2261 if (XINT (n) == 0)
2262 return n;
378c33ca 2263 if (! FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized)
04649dbc
KH
2264 {
2265 initialize_cut_buffers (display, window);
378c33ca 2266 FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized = 1;
04649dbc 2267 }
3834c318 2268
ede4db72
RS
2269 props[0] = XA_CUT_BUFFER0;
2270 props[1] = XA_CUT_BUFFER1;
2271 props[2] = XA_CUT_BUFFER2;
2272 props[3] = XA_CUT_BUFFER3;
2273 props[4] = XA_CUT_BUFFER4;
2274 props[5] = XA_CUT_BUFFER5;
2275 props[6] = XA_CUT_BUFFER6;
2276 props[7] = XA_CUT_BUFFER7;
2277 BLOCK_INPUT;
2278 XRotateWindowProperties (display, window, props, 8, XINT (n));
2279 UNBLOCK_INPUT;
2280 return n;
2281}
2282
2283#endif
2284\f
1fb3821b
JD
2285/***********************************************************************
2286 Drag and drop support
2287***********************************************************************/
2288/* Check that lisp values are of correct type for x_fill_property_data.
2289 That is, number, string or a cons with two numbers (low and high 16
2290 bit parts of a 32 bit number). */
2291
2292int
2293x_check_property_data (data)
2294 Lisp_Object data;
2295{
2296 Lisp_Object iter;
2297 int size = 0;
2298
2299 for (iter = data; CONSP (iter) && size != -1; iter = XCDR (iter), ++size)
2300 {
2301 Lisp_Object o = XCAR (iter);
2302
2303 if (! NUMBERP (o) && ! STRINGP (o) && ! CONSP (o))
2304 size = -1;
2305 else if (CONSP (o) &&
2306 (! NUMBERP (XCAR (o)) || ! NUMBERP (XCDR (o))))
2307 size = -1;
2308 }
2309
2310 return size;
2311}
2312
2313/* Convert lisp values to a C array. Values may be a number, a string
2314 which is taken as an X atom name and converted to the atom value, or
2315 a cons containing the two 16 bit parts of a 32 bit number.
2316
2317 DPY is the display use to look up X atoms.
2318 DATA is a Lisp list of values to be converted.
2319 RET is the C array that contains the converted values. It is assumed
2320 it is big enough to hol all values.
2321 FORMAT is 8, 16 or 32 and gives the size in bits for each C value to
2322 be stored in RET. */
2323
2324void
2325x_fill_property_data (dpy, data, ret, format)
2326 Display *dpy;
2327 Lisp_Object data;
2328 void *ret;
2329 int format;
2330{
2331 CARD32 val;
2332 CARD32 *d32 = (CARD32 *) ret;
2333 CARD16 *d16 = (CARD16 *) ret;
2334 CARD8 *d08 = (CARD8 *) ret;
2335 Lisp_Object iter;
2336
2337 for (iter = data; CONSP (iter); iter = XCDR (iter))
2338 {
2339 Lisp_Object o = XCAR (iter);
2340
2341 if (INTEGERP (o))
2342 val = (CARD32) XFASTINT (o);
2343 else if (FLOATP (o))
2344 val = (CARD32) XFLOAT (o);
2345 else if (CONSP (o))
2346 val = (CARD32) cons_to_long (o);
2347 else if (STRINGP (o))
2348 {
2349 BLOCK_INPUT;
2350 val = XInternAtom (dpy, (char *) SDATA (o), False);
2351 UNBLOCK_INPUT;
2352 }
2353 else
2354 error ("Wrong type, must be string, number or cons");
2355
2356 if (format == 8)
2357 *d08++ = (CARD8) val;
2358 else if (format == 16)
2359 *d16++ = (CARD16) val;
2360 else
2361 *d32++ = val;
2362 }
2363}
2364
2365/* Convert an array of C values to a Lisp list.
2366 F is the frame to be used to look up X atoms if the TYPE is XA_ATOM.
2367 DATA is a C array of values to be converted.
2368 TYPE is the type of the data. Only XA_ATOM is special, it converts
2369 each number in DATA to its corresponfing X atom as a symbol.
2370 FORMAT is 8, 16 or 32 and gives the size in bits for each C value to
2371 be stored in RET.
2372 SIZE is the number of elements in DATA.
2373
2374 Also see comment for selection_data_to_lisp_data above. */
2375
2376Lisp_Object
2377x_property_data_to_lisp (f, data, type, format, size)
2378 struct frame *f;
2379 unsigned char *data;
2380 Atom type;
2381 int format;
2382 unsigned long size;
2383{
2384 return selection_data_to_lisp_data (FRAME_X_DISPLAY (f),
2385 data, size*format/8, type, format);
2386}
2387
2388/* Get the mouse position frame relative coordinates. */
2389
2390static void
2391mouse_position_for_drop (f, x, y)
2392 FRAME_PTR f;
2393 int *x;
2394 int *y;
2395{
2396 Window root, dummy_window;
2397 int dummy;
2398
2399 BLOCK_INPUT;
2400
2401 XQueryPointer (FRAME_X_DISPLAY (f),
2402 DefaultRootWindow (FRAME_X_DISPLAY (f)),
2403
2404 /* The root window which contains the pointer. */
2405 &root,
2406
2407 /* Window pointer is on, not used */
2408 &dummy_window,
2409
2410 /* The position on that root window. */
2411 x, y,
2412
2413 /* x/y in dummy_window coordinates, not used. */
2414 &dummy, &dummy,
2415
2416 /* Modifier keys and pointer buttons, about which
2417 we don't care. */
2418 (unsigned int *) &dummy);
2419
2420
2421 /* Absolute to relative. */
2422 *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
2423 *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
2424
2425 UNBLOCK_INPUT;
2426}
2427
2428DEFUN ("x-get-atom-name", Fx_get_atom_name,
2429 Sx_get_atom_name, 1, 2, 0,
2430 doc: /* Return the X atom name for VALUE as a string.
2431VALUE may be a number or a cons where the car is the upper 16 bits and
2432the cdr is the lower 16 bits of a 32 bit value.
2433Use the display for FRAME or the current frame if FRAME is not given or nil.
2434
2435If the value is 0 or the atom is not known, return the empty string. */)
2436 (value, frame)
2437 Lisp_Object value, frame;
2438{
2439 struct frame *f = check_x_frame (frame);
2440 char *name = 0;
2441 Lisp_Object ret = Qnil;
2442 int count;
2443 Display *dpy = FRAME_X_DISPLAY (f);
2444 Atom atom;
2445
2446 if (INTEGERP (value))
2447 atom = (Atom) XUINT (value);
2448 else if (FLOATP (value))
2449 atom = (Atom) XFLOAT (value);
2450 else if (CONSP (value))
2451 atom = (Atom) cons_to_long (value);
2452 else
2453 error ("Wrong type, value must be number or cons");
2454
2455 BLOCK_INPUT;
2456 count = x_catch_errors (dpy);
2457
2458 name = atom ? XGetAtomName (dpy, atom) : "";
2459
2460 if (! x_had_errors_p (dpy))
2461 ret = make_string (name, strlen (name));
2462
2463 x_uncatch_errors (dpy, count);
2464
2465 if (atom && name) XFree (name);
2466 if (NILP (ret)) ret = make_string ("", 0);
2467
2468 UNBLOCK_INPUT;
2469
2470 return ret;
2471}
2472
2473/* Convert an XClientMessageEvent to a Lisp event of type DRAG_N_DROP_EVENT.
2474 TODO: Check if this client event really is a DND event? */
2475
2476int
2477x_handle_dnd_message (f, event, dpyinfo, bufp)
2478 struct frame *f;
2479 XClientMessageEvent *event;
2480 struct x_display_info *dpyinfo;
2481 struct input_event *bufp;
2482{
2483 Lisp_Object vec;
2484 Lisp_Object frame;
2485 unsigned long size = (8*sizeof (event->data))/event->format;
2486 int x, y;
2487
2488 XSETFRAME (frame, f);
2489
2490 vec = Fmake_vector (4, Qnil);
2491 AREF (vec, 0) = SYMBOL_NAME (x_atom_to_symbol (FRAME_X_DISPLAY (f),
2492 event->message_type));
2493 AREF (vec, 1) = frame;
2494 AREF (vec, 2) = XFASTINT (event->format);
2495 AREF (vec, 3) = x_property_data_to_lisp (f,
2496 event->data.b,
2497 event->message_type,
2498 event->format,
2499 size);
2500
2501 mouse_position_for_drop (f, &x, &y);
2502 bufp->kind = DRAG_N_DROP_EVENT;
2503 bufp->frame_or_window = Fcons (frame, vec);
2504 bufp->timestamp = CurrentTime;
2505 bufp->x = make_number (x);
2506 bufp->y = make_number (y);
2507 bufp->arg = Qnil;
2508 bufp->modifiers = 0;
2509
2510 return 1;
2511}
2512
2513DEFUN ("x-send-client-message", Fx_send_client_event,
2514 Sx_send_client_message, 6, 6, 0,
2515 doc: /* Send a client message of MESSAGE-TYPE to window DEST on DISPLAY.
2516
2517For DISPLAY, specify either a frame or a display name (a string).
2518If DISPLAY is nil, that stands for the selected frame's display.
2519DEST may be a number, in which case it is a Window id. The value 0 may
2520be used to send to the root window of the DISPLAY.
2521If DEST is a cons, it is converted to a 32 bit number
2522with the high 16 bits from the car and the lower 16 bit from the cdr. That
2523number is then used as a window id.
2524If DEST is a frame the event is sent to the outer window of that frame.
2525Nil means the currently selected frame.
2526If DEST is the string "PointerWindow" the event is sent to the window that
2527contains the pointer. If DEST is the string "InputFocus" the event is
2528sent to the window that has the input focus.
2529FROM is the frame sending the event. Use nil for currently selected frame.
2530MESSAGE-TYPE is the name of an Atom as a string.
2531FORMAT must be one of 8, 16 or 32 and determines the size of the values in
2532bits. VALUES is a list of numbers, cons and/or strings containing the values
2533to send. If a value is a string, it is converted to an Atom and the value of
2534the Atom is sent. If a value is a cons, it is converted to a 32 bit number
2535with the high 16 bits from the car and the lower 16 bit from the cdr.
2536If more values than fits into the event is given, the excessive values
2537are ignored. */)
2538 (display, dest, from, message_type, format, values)
2539 Lisp_Object display, dest, from, message_type, format, values;
2540{
2541 struct x_display_info *dpyinfo = check_x_display_info (display);
2542 Window wdest;
2543 XEvent event;
2544 Lisp_Object cons;
2545 int size;
2546 struct frame *f = check_x_frame (from);
2547 int count;
2548 int to_root;
2549
2550 CHECK_STRING (message_type);
2551 CHECK_NUMBER (format);
2552 CHECK_CONS (values);
2553
2554 if (x_check_property_data (values) == -1)
2555 error ("Bad data in VALUES, must be number, cons or string");
2556
2557 event.xclient.type = ClientMessage;
2558 event.xclient.format = XFASTINT (format);
2559
2560 if (event.xclient.format != 8 && event.xclient.format != 16
2561 && event.xclient.format != 32)
2562 error ("FORMAT must be one of 8, 16 or 32");
2563
2564 if (FRAMEP (dest) || NILP (dest))
2565 {
2566 struct frame *fdest = check_x_frame (dest);
2567 wdest = FRAME_OUTER_WINDOW (fdest);
2568 }
2569 else if (STRINGP (dest))
2570 {
2571 if (strcmp (SDATA (dest), "PointerWindow") == 0)
2572 wdest = PointerWindow;
2573 else if (strcmp (SDATA (dest), "InputFocus") == 0)
2574 wdest = InputFocus;
2575 else
2576 error ("DEST as a string must be one of PointerWindow or InputFocus");
2577 }
2578 else if (INTEGERP (dest))
2579 wdest = (Window) XFASTINT (dest);
2580 else if (FLOATP (dest))
2581 wdest = (Window) XFLOAT (dest);
2582 else if (CONSP (dest))
2583 {
2584 if (! NUMBERP (XCAR (dest)) || ! NUMBERP (XCDR (dest)))
2585 error ("Both car and cdr for DEST must be numbers");
2586 else
2587 wdest = (Window) cons_to_long (dest);
2588 }
2589 else
2590 error ("DEST must be a frame, nil, string, number or cons");
2591
2592 if (wdest == 0) wdest = dpyinfo->root_window;
2593 to_root = wdest == dpyinfo->root_window;
2594
2595 for (cons = values, size = 0; CONSP (cons); cons = XCDR (cons), ++size)
2596 ;
2597
2598 BLOCK_INPUT;
2599
2600 event.xclient.message_type
2601 = XInternAtom (dpyinfo->display, SDATA (message_type), False);
2602 event.xclient.display = dpyinfo->display;
2603
2604 /* Some clients (metacity for example) expects sending window to be here
2605 when sending to the root window. */
2606 event.xclient.window = to_root ? FRAME_OUTER_WINDOW (f) : wdest;
2607
2608 memset (event.xclient.data.b, 0, sizeof (event.xclient.data.b));
2609 x_fill_property_data (dpyinfo->display, values, event.xclient.data.b,
2610 event.xclient.format);
2611
2612 /* If event mask is 0 the event is sent to the client that created
2613 the destination window. But if we are sending to the root window,
2614 there is no such client. Then we set the event mask to 0xffff. The
2615 event then goes to clients selecting for events on the root window. */
2616 count = x_catch_errors (dpyinfo->display);
2617 {
2618 int propagate = to_root ? False : True;
2619 unsigned mask = to_root ? 0xffff : 0;
2620 XSendEvent (dpyinfo->display, wdest, propagate, mask, &event);
2621 XFlush (dpyinfo->display);
2622 }
2623 x_uncatch_errors (dpyinfo->display, count);
2624 UNBLOCK_INPUT;
2625
2626 return Qnil;
2627}
2628
2629\f
ede4db72
RS
2630void
2631syms_of_xselect ()
2632{
ede4db72
RS
2633 defsubr (&Sx_get_selection_internal);
2634 defsubr (&Sx_own_selection_internal);
2635 defsubr (&Sx_disown_selection_internal);
2636 defsubr (&Sx_selection_owner_p);
2637 defsubr (&Sx_selection_exists_p);
2638
2639#ifdef CUT_BUFFER_SUPPORT
a87ed99c
RS
2640 defsubr (&Sx_get_cut_buffer_internal);
2641 defsubr (&Sx_store_cut_buffer_internal);
2642 defsubr (&Sx_rotate_cut_buffers_internal);
ede4db72
RS
2643#endif
2644
1fb3821b
JD
2645 defsubr (&Sx_get_atom_name);
2646 defsubr (&Sx_send_client_message);
2647
ede4db72
RS
2648 reading_selection_reply = Fcons (Qnil, Qnil);
2649 staticpro (&reading_selection_reply);
2650 reading_selection_window = 0;
2651 reading_which_selection = 0;
2652
2653 property_change_wait_list = 0;
2f65feb6 2654 prop_location_identifier = 0;
ede4db72
RS
2655 property_change_reply = Fcons (Qnil, Qnil);
2656 staticpro (&property_change_reply);
2657
2658 Vselection_alist = Qnil;
2659 staticpro (&Vselection_alist);
2660
2661 DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist,
8c1a1077
PJ
2662 doc: /* An alist associating X Windows selection-types with functions.
2663These functions are called to convert the selection, with three args:
2664the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');
2665a desired type to which the selection should be converted;
2666and the local selection value (whatever was given to `x-own-selection').
2667
2668The function should return the value to send to the X server
2669\(typically a string). A return value of nil
2670means that the conversion could not be done.
2671A return value which is the symbol `NULL'
2672means that a side-effect was executed,
2673and there is no meaningful selection value. */);
ede4db72
RS
2674 Vselection_converter_alist = Qnil;
2675
2676 DEFVAR_LISP ("x-lost-selection-hooks", &Vx_lost_selection_hooks,
8c1a1077
PJ
2677 doc: /* A list of functions to be called when Emacs loses an X selection.
2678\(This happens when some other X client makes its own selection
2679or when a Lisp program explicitly clears the selection.)
2680The functions are called with one argument, the selection type
2681\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'). */);
ede4db72
RS
2682 Vx_lost_selection_hooks = Qnil;
2683
2684 DEFVAR_LISP ("x-sent-selection-hooks", &Vx_sent_selection_hooks,
8c1a1077
PJ
2685 doc: /* A list of functions to be called when Emacs answers a selection request.
2686The functions are called with four arguments:
2687 - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');
2688 - the selection-type which Emacs was asked to convert the
2689 selection into before sending (for example, `STRING' or `LENGTH');
2690 - a flag indicating success or failure for responding to the request.
2691We might have failed (and declined the request) for any number of reasons,
2692including being asked for a selection that we no longer own, or being asked
2693to convert into a type that we don't know about or that is inappropriate.
2694This hook doesn't let you change the behavior of Emacs's selection replies,
2695it merely informs you that they have happened. */);
ede4db72
RS
2696 Vx_sent_selection_hooks = Qnil;
2697
93e4ce1b 2698 DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system,
8c1a1077
PJ
2699 doc: /* Coding system for communicating with other X clients.
2700When sending or receiving text via cut_buffer, selection, and clipboard,
2701the text is encoded or decoded by this coding system.
5a79ea57
EZ
2702The default value is `compound-text-with-extensions'. */);
2703 Vselection_coding_system = intern ("compound-text-with-extensions");
2584c9ec 2704
16cd5029 2705 DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system,
8c1a1077
PJ
2706 doc: /* Coding system for the next communication with other X clients.
2707Usually, `selection-coding-system' is used for communicating with
f8f8d464
JB
2708other X clients. But, if this variable is set, it is used for the
2709next communication only. After the communication, this variable is
8c1a1077 2710set to nil. */);
16cd5029
KH
2711 Vnext_selection_coding_system = Qnil;
2712
ede4db72 2713 DEFVAR_INT ("x-selection-timeout", &x_selection_timeout,
8c1a1077
PJ
2714 doc: /* Number of milliseconds to wait for a selection reply.
2715If the selection owner doesn't reply in this time, we give up.
2716A value of 0 means wait as long as necessary. This is initialized from the
2717\"*selectionTimeout\" resource. */);
ede4db72
RS
2718 x_selection_timeout = 0;
2719
2720 QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY);
2721 QSECONDARY = intern ("SECONDARY"); staticpro (&QSECONDARY);
2722 QSTRING = intern ("STRING"); staticpro (&QSTRING);
2723 QINTEGER = intern ("INTEGER"); staticpro (&QINTEGER);
2724 QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
2725 QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP);
2726 QTEXT = intern ("TEXT"); staticpro (&QTEXT);
e6c7c988 2727 QCOMPOUND_TEXT = intern ("COMPOUND_TEXT"); staticpro (&QCOMPOUND_TEXT);
5109c8dd 2728 QUTF8_STRING = intern ("UTF8_STRING"); staticpro (&QUTF8_STRING);
ede4db72
RS
2729 QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP);
2730 QDELETE = intern ("DELETE"); staticpro (&QDELETE);
2731 QMULTIPLE = intern ("MULTIPLE"); staticpro (&QMULTIPLE);
2732 QINCR = intern ("INCR"); staticpro (&QINCR);
2733 QEMACS_TMP = intern ("_EMACS_TMP_"); staticpro (&QEMACS_TMP);
2734 QTARGETS = intern ("TARGETS"); staticpro (&QTARGETS);
2735 QATOM = intern ("ATOM"); staticpro (&QATOM);
2736 QATOM_PAIR = intern ("ATOM_PAIR"); staticpro (&QATOM_PAIR);
2737 QNULL = intern ("NULL"); staticpro (&QNULL);
5a79ea57
EZ
2738 Qcompound_text_with_extensions = intern ("compound-text-with-extensions");
2739 staticpro (&Qcompound_text_with_extensions);
ede4db72
RS
2740
2741#ifdef CUT_BUFFER_SUPPORT
2742 QCUT_BUFFER0 = intern ("CUT_BUFFER0"); staticpro (&QCUT_BUFFER0);
2743 QCUT_BUFFER1 = intern ("CUT_BUFFER1"); staticpro (&QCUT_BUFFER1);
2744 QCUT_BUFFER2 = intern ("CUT_BUFFER2"); staticpro (&QCUT_BUFFER2);
2745 QCUT_BUFFER3 = intern ("CUT_BUFFER3"); staticpro (&QCUT_BUFFER3);
2746 QCUT_BUFFER4 = intern ("CUT_BUFFER4"); staticpro (&QCUT_BUFFER4);
2747 QCUT_BUFFER5 = intern ("CUT_BUFFER5"); staticpro (&QCUT_BUFFER5);
2748 QCUT_BUFFER6 = intern ("CUT_BUFFER6"); staticpro (&QCUT_BUFFER6);
2749 QCUT_BUFFER7 = intern ("CUT_BUFFER7"); staticpro (&QCUT_BUFFER7);
2750#endif
2751
e57ad4d8
KH
2752 Qforeign_selection = intern ("foreign-selection");
2753 staticpro (&Qforeign_selection);
ede4db72 2754}
ab5796a9
MB
2755
2756/* arch-tag: 7c293b0f-9918-4f69-8ac7-03e142307236
2757 (do not change this comment) */