aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Moellmann2001-07-12 14:38:51 +0000
committerGerd Moellmann2001-07-12 14:38:51 +0000
commitd9c0d4a31a12b6c2944ebba1ae5552ef249c28d2 (patch)
tree990760c462616a72cf08edd26bbc103b68950398 /src
parent158f4aea95b259d8f1129ede0c322e065971710e (diff)
downloademacs-d9c0d4a31a12b6c2944ebba1ae5552ef249c28d2.tar.gz
emacs-d9c0d4a31a12b6c2944ebba1ae5552ef249c28d2.zip
(x_decline_selection_request): Handle errors
caused by receivers that have vanished. (TRACE0, TRACE1, TRACE2): New macros, defined depending on TRACE_SELECTION. Replace fprintfs in #if 0 with TRACE macros to facilitate debugging. Add additional trace statements. (toplevel): Add prototypes for file-local functions. (x_atom_to_symbol): Remove DPYINFO parameter.
Diffstat (limited to 'src')
-rw-r--r--src/xselect.c249
1 files changed, 169 insertions, 80 deletions
diff --git a/src/xselect.c b/src/xselect.c
index eae1b0cdb13..91011589bc4 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -1,5 +1,6 @@
1/* X Selection processing for Emacs. 1/* X Selection processing for Emacs.
2 Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000 Free Software Foundation. 2 Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2001
3 Free Software Foundation.
3 4
4This file is part of GNU Emacs. 5This file is part of GNU Emacs.
5 6
@@ -33,6 +34,61 @@ Boston, MA 02111-1307, USA. */
33#include "process.h" 34#include "process.h"
34#include "composite.h" 35#include "composite.h"
35 36
37struct prop_location;
38
39static Lisp_Object x_atom_to_symbol P_ ((Display *dpy, Atom atom));
40static Atom symbol_to_x_atom P_ ((struct x_display_info *, Display *,
41 Lisp_Object));
42static void x_own_selection P_ ((Lisp_Object, Lisp_Object));
43static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object));
44static void x_decline_selection_request P_ ((struct input_event *));
45static Lisp_Object x_selection_request_lisp_error P_ ((Lisp_Object));
46static Lisp_Object queue_selection_requests_unwind P_ ((Lisp_Object));
47static Lisp_Object some_frame_on_display P_ ((struct x_display_info *));
48static void x_reply_selection_request P_ ((struct input_event *, int,
49 unsigned char *, int, Atom));
50static int waiting_for_other_props_on_window P_ ((Display *, Window));
51static struct prop_location *expect_property_change P_ ((Display *, Window,
52 Atom, int));
53static void unexpect_property_change P_ ((struct prop_location *));
54static Lisp_Object wait_for_property_change_unwind P_ ((Lisp_Object));
55static void wait_for_property_change P_ ((struct prop_location *));
56static Lisp_Object x_get_foreign_selection P_ ((Lisp_Object, Lisp_Object));
57static void x_get_window_property P_ ((Display *, Window, Atom,
58 unsigned char **, int *,
59 Atom *, int *, unsigned long *, int));
60static void receive_incremental_selection P_ ((Display *, Window, Atom,
61 Lisp_Object, unsigned,
62 unsigned char **, int *,
63 Atom *, int *, unsigned long *));
64static Lisp_Object x_get_window_property_as_lisp_data P_ ((Display *,
65 Window, Atom,
66 Lisp_Object, Atom));
67static Lisp_Object selection_data_to_lisp_data P_ ((Display *, unsigned char *,
68 int, Atom, int));
69static void lisp_data_to_selection_data P_ ((Display *, Lisp_Object,
70 unsigned char **, Atom *,
71 unsigned *, int *, int *));
72static Lisp_Object clean_local_selection_data P_ ((Lisp_Object));
73static void initialize_cut_buffers P_ ((Display *, Window));
74
75
76/* Printing traces to stderr. */
77
78#ifdef TRACE_SELECTION
79#define TRACE0(fmt) \
80 fprintf (stderr, "%d: " fmt "\n", getpid ())
81#define TRACE1(fmt, a0) \
82 fprintf (stderr, "%d: " fmt "\n", getpid (), a0)
83#define TRACE2(fmt, a0, a1) \
84 fprintf (stderr, "%d: " fmt "\n", getpid (), a0, a1)
85#else
86#define TRACE0(fmt) (void) 0
87#define TRACE1(fmt, a0) (void) 0
88#define TRACE2(fmt, a0, a1) (void) 0
89#endif
90
91
36#define CUT_BUFFER_SUPPORT 92#define CUT_BUFFER_SUPPORT
37 93
38Lisp_Object QPRIMARY, QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP, 94Lisp_Object QPRIMARY, QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
@@ -142,9 +198,7 @@ symbol_to_x_atom (dpyinfo, display, sym)
142#endif 198#endif
143 if (!SYMBOLP (sym)) abort (); 199 if (!SYMBOLP (sym)) abort ();
144 200
145#if 0 201 TRACE1 (" XInternAtom %s", (char *) XSYMBOL (sym)->name->data);
146 fprintf (stderr, " XInternAtom %s\n", (char *) XSYMBOL (sym)->name->data);
147#endif
148 BLOCK_INPUT; 202 BLOCK_INPUT;
149 val = XInternAtom (display, (char *) XSYMBOL (sym)->name->data, False); 203 val = XInternAtom (display, (char *) XSYMBOL (sym)->name->data, False);
150 UNBLOCK_INPUT; 204 UNBLOCK_INPUT;
@@ -156,14 +210,17 @@ symbol_to_x_atom (dpyinfo, display, sym)
156 and calls to intern whenever possible. */ 210 and calls to intern whenever possible. */
157 211
158static Lisp_Object 212static Lisp_Object
159x_atom_to_symbol (dpyinfo, display, atom) 213x_atom_to_symbol (dpy, atom)
160 struct x_display_info *dpyinfo; 214 Display *dpy;
161 Display *display;
162 Atom atom; 215 Atom atom;
163{ 216{
217 struct x_display_info *dpyinfo;
164 char *str; 218 char *str;
165 Lisp_Object val; 219 Lisp_Object val;
166 if (! atom) return Qnil; 220
221 if (! atom)
222 return Qnil;
223
167 switch (atom) 224 switch (atom)
168 { 225 {
169 case XA_PRIMARY: 226 case XA_PRIMARY:
@@ -196,6 +253,7 @@ x_atom_to_symbol (dpyinfo, display, atom)
196#endif 253#endif
197 } 254 }
198 255
256 dpyinfo = x_display_info_for_display (dpy);
199 if (atom == dpyinfo->Xatom_CLIPBOARD) 257 if (atom == dpyinfo->Xatom_CLIPBOARD)
200 return QCLIPBOARD; 258 return QCLIPBOARD;
201 if (atom == dpyinfo->Xatom_TIMESTAMP) 259 if (atom == dpyinfo->Xatom_TIMESTAMP)
@@ -218,11 +276,9 @@ x_atom_to_symbol (dpyinfo, display, atom)
218 return QNULL; 276 return QNULL;
219 277
220 BLOCK_INPUT; 278 BLOCK_INPUT;
221 str = XGetAtomName (display, atom); 279 str = XGetAtomName (dpy, atom);
222 UNBLOCK_INPUT; 280 UNBLOCK_INPUT;
223#if 0 281 TRACE1 ("XGetAtomName --> %s", str);
224 fprintf (stderr, " XGetAtomName --> %s\n", str);
225#endif
226 if (! str) return Qnil; 282 if (! str) return Qnil;
227 val = intern (str); 283 val = intern (str);
228 BLOCK_INPUT; 284 BLOCK_INPUT;
@@ -411,6 +467,8 @@ x_decline_selection_request (event)
411 struct input_event *event; 467 struct input_event *event;
412{ 468{
413 XSelectionEvent reply; 469 XSelectionEvent reply;
470 int count;
471
414 reply.type = SelectionNotify; 472 reply.type = SelectionNotify;
415 reply.display = SELECTION_EVENT_DISPLAY (event); 473 reply.display = SELECTION_EVENT_DISPLAY (event);
416 reply.requestor = SELECTION_EVENT_REQUESTOR (event); 474 reply.requestor = SELECTION_EVENT_REQUESTOR (event);
@@ -419,10 +477,13 @@ x_decline_selection_request (event)
419 reply.target = SELECTION_EVENT_TARGET (event); 477 reply.target = SELECTION_EVENT_TARGET (event);
420 reply.property = None; 478 reply.property = None;
421 479
480 /* The reason for the error may be that the receiver has
481 died in the meantime. Handle that case. */
422 BLOCK_INPUT; 482 BLOCK_INPUT;
423 XSendEvent (reply.display, reply.requestor, False, 0L, 483 count = x_catch_errors (reply.display);
424 (XEvent *) &reply); 484 XSendEvent (reply.display, reply.requestor, False, 0L, (XEvent *) &reply);
425 XFlush (reply.display); 485 XFlush (reply.display);
486 x_uncatch_errors (reply.display, count);
426 UNBLOCK_INPUT; 487 UNBLOCK_INPUT;
427} 488}
428 489
@@ -553,9 +614,7 @@ x_reply_selection_request (event, format, data, size, type)
553 if (bytes_remaining <= max_bytes) 614 if (bytes_remaining <= max_bytes)
554 { 615 {
555 /* Send all the data at once, with minimal handshaking. */ 616 /* Send all the data at once, with minimal handshaking. */
556#if 0 617 TRACE1 ("Sending all %d bytes", bytes_remaining);
557 fprintf (stderr,"\nStoring all %d\n", bytes_remaining);
558#endif
559 XChangeProperty (display, window, reply.property, type, format, 618 XChangeProperty (display, window, reply.property, type, format,
560 PropModeReplace, data, size); 619 PropModeReplace, data, size);
561 /* At this point, the selection was successfully stored; ack it. */ 620 /* At this point, the selection was successfully stored; ack it. */
@@ -583,17 +642,21 @@ x_reply_selection_request (event, format, data, size, type)
583 642
584 if (x_window_to_frame (dpyinfo, window)) /* #### debug */ 643 if (x_window_to_frame (dpyinfo, window)) /* #### debug */
585 error ("Attempt to transfer an INCR to ourself!"); 644 error ("Attempt to transfer an INCR to ourself!");
586#if 0 645
587 fprintf (stderr, "\nINCR %d\n", bytes_remaining); 646 TRACE2 ("Start sending %d bytes incrementally (%s)",
588#endif 647 bytes_remaining, XGetAtomName (display, reply.property));
589 wait_object = expect_property_change (display, window, reply.property, 648 wait_object = expect_property_change (display, window, reply.property,
590 PropertyDelete); 649 PropertyDelete);
591 650
651 TRACE1 ("Set %s to number of bytes to send",
652 XGetAtomName (display, reply.property));
592 XChangeProperty (display, window, reply.property, dpyinfo->Xatom_INCR, 653 XChangeProperty (display, window, reply.property, dpyinfo->Xatom_INCR,
593 32, PropModeReplace, 654 32, PropModeReplace,
594 (unsigned char *) &bytes_remaining, 1); 655 (unsigned char *) &bytes_remaining, 1);
595 XSelectInput (display, window, PropertyChangeMask); 656 XSelectInput (display, window, PropertyChangeMask);
657
596 /* Tell 'em the INCR data is there... */ 658 /* Tell 'em the INCR data is there... */
659 TRACE0 ("Send SelectionNotify event");
597 XSendEvent (display, window, False, 0L, (XEvent *) &reply); 660 XSendEvent (display, window, False, 0L, (XEvent *) &reply);
598 XFlush (display); 661 XFlush (display);
599 662
@@ -603,8 +666,13 @@ x_reply_selection_request (event, format, data, size, type)
603 /* First, wait for the requester to ack by deleting the property. 666 /* First, wait for the requester to ack by deleting the property.
604 This can run random lisp code (process handlers) or signal. */ 667 This can run random lisp code (process handlers) or signal. */
605 if (! had_errors) 668 if (! had_errors)
606 wait_for_property_change (wait_object); 669 {
670 TRACE1 ("Waiting for ACK (deletion of %s)",
671 XGetAtomName (display, reply.property));
672 wait_for_property_change (wait_object);
673 }
607 674
675 TRACE0 ("Got ACK");
608 while (bytes_remaining) 676 while (bytes_remaining)
609 { 677 {
610 int i = ((bytes_remaining < max_bytes) 678 int i = ((bytes_remaining < max_bytes)
@@ -616,9 +684,11 @@ x_reply_selection_request (event, format, data, size, type)
616 wait_object 684 wait_object
617 = expect_property_change (display, window, reply.property, 685 = expect_property_change (display, window, reply.property,
618 PropertyDelete); 686 PropertyDelete);
619#if 0 687
620 fprintf (stderr," INCR adding %d\n", i); 688 TRACE1 ("Sending increment of %d bytes", i);
621#endif 689 TRACE1 ("Set %s to increment data",
690 XGetAtomName (display, reply.property));
691
622 /* Append the next chunk of data to the property. */ 692 /* Append the next chunk of data to the property. */
623 XChangeProperty (display, window, reply.property, type, format, 693 XChangeProperty (display, window, reply.property, type, format,
624 PropModeAppend, data, i / format_bytes); 694 PropModeAppend, data, i / format_bytes);
@@ -632,21 +702,23 @@ x_reply_selection_request (event, format, data, size, type)
632 break; 702 break;
633 703
634 /* Now wait for the requester to ack this chunk by deleting the 704 /* Now wait for the requester to ack this chunk by deleting the
635 property. This can run random lisp code or signal. 705 property. This can run random lisp code or signal. */
636 */ 706 TRACE1 ("Waiting for increment ACK (deletion of %s)",
707 XGetAtomName (display, reply.property));
637 wait_for_property_change (wait_object); 708 wait_for_property_change (wait_object);
638 } 709 }
639 /* Now write a zero-length chunk to the property to tell the requester 710
640 that we're done. */ 711 /* Now write a zero-length chunk to the property to tell the
641#if 0 712 requester that we're done. */
642 fprintf (stderr," INCR done\n");
643#endif
644 BLOCK_INPUT; 713 BLOCK_INPUT;
645 if (! waiting_for_other_props_on_window (display, window)) 714 if (! waiting_for_other_props_on_window (display, window))
646 XSelectInput (display, window, 0L); 715 XSelectInput (display, window, 0L);
647 716
717 TRACE1 ("Set %s to a 0-length chunk to indicate EOF",
718 XGetAtomName (display, reply.property));
648 XChangeProperty (display, window, reply.property, type, format, 719 XChangeProperty (display, window, reply.property, type, format,
649 PropModeReplace, data, 0); 720 PropModeReplace, data, 0);
721 TRACE0 ("Done sending incrementally");
650 } 722 }
651 723
652 /* The window we're communicating with may have been deleted 724 /* The window we're communicating with may have been deleted
@@ -685,8 +757,7 @@ x_handle_selection_request (event)
685 757
686 GCPRO3 (local_selection_data, converted_selection, target_symbol); 758 GCPRO3 (local_selection_data, converted_selection, target_symbol);
687 759
688 selection_symbol = x_atom_to_symbol (dpyinfo, 760 selection_symbol = x_atom_to_symbol (SELECTION_EVENT_DISPLAY (event),
689 SELECTION_EVENT_DISPLAY (event),
690 SELECTION_EVENT_SELECTION (event)); 761 SELECTION_EVENT_SELECTION (event));
691 762
692 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist); 763 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
@@ -717,7 +788,7 @@ x_handle_selection_request (event)
717 selection_request_dpyinfo = dpyinfo; 788 selection_request_dpyinfo = dpyinfo;
718 record_unwind_protect (x_selection_request_lisp_error, Qnil); 789 record_unwind_protect (x_selection_request_lisp_error, Qnil);
719 790
720 target_symbol = x_atom_to_symbol (dpyinfo, SELECTION_EVENT_DISPLAY (event), 791 target_symbol = x_atom_to_symbol (SELECTION_EVENT_DISPLAY (event),
721 SELECTION_EVENT_TARGET (event)); 792 SELECTION_EVENT_TARGET (event));
722 793
723#if 0 /* #### MULTIPLE doesn't work yet */ 794#if 0 /* #### MULTIPLE doesn't work yet */
@@ -805,7 +876,7 @@ x_handle_selection_clear (event)
805 } 876 }
806 UNBLOCK_INPUT; 877 UNBLOCK_INPUT;
807 878
808 selection_symbol = x_atom_to_symbol (dpyinfo, display, selection); 879 selection_symbol = x_atom_to_symbol (display, selection);
809 880
810 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist); 881 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
811 882
@@ -945,8 +1016,7 @@ expect_property_change (display, window, property, state)
945 Atom property; 1016 Atom property;
946 int state; 1017 int state;
947{ 1018{
948 struct prop_location *pl 1019 struct prop_location *pl = (struct prop_location *) xmalloc (sizeof *pl);
949 = (struct prop_location *) xmalloc (sizeof (struct prop_location));
950 pl->identifier = ++prop_location_identifier; 1020 pl->identifier = ++prop_location_identifier;
951 pl->display = display; 1021 pl->display = display;
952 pl->window = window; 1022 pl->window = window;
@@ -1021,10 +1091,14 @@ wait_for_property_change (location)
1021 { 1091 {
1022 secs = x_selection_timeout / 1000; 1092 secs = x_selection_timeout / 1000;
1023 usecs = (x_selection_timeout % 1000) * 1000; 1093 usecs = (x_selection_timeout % 1000) * 1000;
1094 TRACE2 (" Waiting %d secs, %d usecs", secs, usecs);
1024 wait_reading_process_input (secs, usecs, property_change_reply, 0); 1095 wait_reading_process_input (secs, usecs, property_change_reply, 0);
1025 1096
1026 if (NILP (XCAR (property_change_reply))) 1097 if (NILP (XCAR (property_change_reply)))
1027 error ("Timed out waiting for property-notify event"); 1098 {
1099 TRACE0 (" Timed out");
1100 error ("Timed out waiting for property-notify event");
1101 }
1028 } 1102 }
1029 1103
1030 unbind_to (count, Qnil); 1104 unbind_to (count, Qnil);
@@ -1037,6 +1111,7 @@ x_handle_property_notify (event)
1037 XPropertyEvent *event; 1111 XPropertyEvent *event;
1038{ 1112{
1039 struct prop_location *prev = 0, *rest = property_change_wait_list; 1113 struct prop_location *prev = 0, *rest = property_change_wait_list;
1114
1040 while (rest) 1115 while (rest)
1041 { 1116 {
1042 if (rest->property == event->atom 1117 if (rest->property == event->atom
@@ -1044,13 +1119,9 @@ x_handle_property_notify (event)
1044 && rest->display == event->display 1119 && rest->display == event->display
1045 && rest->desired_state == event->state) 1120 && rest->desired_state == event->state)
1046 { 1121 {
1047#if 0 1122 TRACE2 ("Expected %s of property %s",
1048 fprintf (stderr, "Saw expected prop-%s on %s\n", 1123 (event->state == PropertyDelete ? "deletion" : "change"),
1049 (event->state == PropertyDelete ? "delete" : "change"), 1124 XGetAtomName (event->display, event->atom));
1050 (char *) XSYMBOL (x_atom_to_symbol (dpyinfo, event->display,
1051 event->atom))
1052 ->name->data);
1053#endif
1054 1125
1055 rest->arrived = 1; 1126 rest->arrived = 1;
1056 1127
@@ -1066,16 +1137,10 @@ x_handle_property_notify (event)
1066 xfree (rest); 1137 xfree (rest);
1067 return; 1138 return;
1068 } 1139 }
1140
1069 prev = rest; 1141 prev = rest;
1070 rest = rest->next; 1142 rest = rest->next;
1071 } 1143 }
1072#if 0
1073 fprintf (stderr, "Saw UNexpected prop-%s on %s\n",
1074 (event->state == PropertyDelete ? "delete" : "change"),
1075 (char *) XSYMBOL (x_atom_to_symbol (dpyinfo,
1076 event->display, event->atom))
1077 ->name->data);
1078#endif
1079} 1144}
1080 1145
1081 1146
@@ -1160,7 +1225,13 @@ x_get_foreign_selection (selection_symbol, target_type)
1160 type_atom = symbol_to_x_atom (dpyinfo, display, target_type); 1225 type_atom = symbol_to_x_atom (dpyinfo, display, target_type);
1161 1226
1162 BLOCK_INPUT; 1227 BLOCK_INPUT;
1228
1163 count = x_catch_errors (display); 1229 count = x_catch_errors (display);
1230
1231 TRACE2 ("Get selection %s, type %s",
1232 XGetAtomName (display, type_atom),
1233 XGetAtomName (display, target_property));
1234
1164 XConvertSelection (display, selection_atom, type_atom, target_property, 1235 XConvertSelection (display, selection_atom, type_atom, target_property,
1165 requestor_window, requestor_time); 1236 requestor_window, requestor_time);
1166 XFlush (display); 1237 XFlush (display);
@@ -1187,7 +1258,9 @@ x_get_foreign_selection (selection_symbol, target_type)
1187 /* This allows quits. Also, don't wait forever. */ 1258 /* This allows quits. Also, don't wait forever. */
1188 secs = x_selection_timeout / 1000; 1259 secs = x_selection_timeout / 1000;
1189 usecs = (x_selection_timeout % 1000) * 1000; 1260 usecs = (x_selection_timeout % 1000) * 1000;
1261 TRACE1 (" Start waiting %d secs for SelectionNotify", secs);
1190 wait_reading_process_input (secs, usecs, reading_selection_reply, 0); 1262 wait_reading_process_input (secs, usecs, reading_selection_reply, 0);
1263 TRACE1 (" Got event = %d", !NILP (XCAR (reading_selection_reply)));
1191 1264
1192 BLOCK_INPUT; 1265 BLOCK_INPUT;
1193 x_check_errors (display, "Cannot get selection: %s"); 1266 x_check_errors (display, "Cannot get selection: %s");
@@ -1230,9 +1303,12 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
1230 unsigned char *tmp_data = 0; 1303 unsigned char *tmp_data = 0;
1231 int result; 1304 int result;
1232 int buffer_size = SELECTION_QUANTUM (display); 1305 int buffer_size = SELECTION_QUANTUM (display);
1233 if (buffer_size > MAX_SELECTION_QUANTUM) buffer_size = MAX_SELECTION_QUANTUM; 1306
1307 if (buffer_size > MAX_SELECTION_QUANTUM)
1308 buffer_size = MAX_SELECTION_QUANTUM;
1234 1309
1235 BLOCK_INPUT; 1310 BLOCK_INPUT;
1311
1236 /* First probe the thing to find out how big it is. */ 1312 /* First probe the thing to find out how big it is. */
1237 result = XGetWindowProperty (display, window, property, 1313 result = XGetWindowProperty (display, window, property,
1238 0L, 0L, False, AnyPropertyType, 1314 0L, 0L, False, AnyPropertyType,
@@ -1246,6 +1322,7 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
1246 *bytes_ret = 0; 1322 *bytes_ret = 0;
1247 return; 1323 return;
1248 } 1324 }
1325
1249 /* This was allocated by Xlib, so use XFree. */ 1326 /* This was allocated by Xlib, so use XFree. */
1250 XFree ((char *) tmp_data); 1327 XFree ((char *) tmp_data);
1251 1328
@@ -1261,7 +1338,7 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
1261 /* Now read, until we've gotten it all. */ 1338 /* Now read, until we've gotten it all. */
1262 while (bytes_remaining) 1339 while (bytes_remaining)
1263 { 1340 {
1264#if 0 1341#ifdef TRACE_SELECTION
1265 int last = bytes_remaining; 1342 int last = bytes_remaining;
1266#endif 1343#endif
1267 result 1344 result
@@ -1271,17 +1348,20 @@ x_get_window_property (display, window, property, data_ret, bytes_ret,
1271 AnyPropertyType, 1348 AnyPropertyType,
1272 actual_type_ret, actual_format_ret, 1349 actual_type_ret, actual_format_ret,
1273 actual_size_ret, &bytes_remaining, &tmp_data); 1350 actual_size_ret, &bytes_remaining, &tmp_data);
1274#if 0 1351
1275 fprintf (stderr, "<< read %d\n", last-bytes_remaining); 1352 TRACE2 ("Read %ld bytes from property %s",
1276#endif 1353 last - bytes_remaining,
1354 XGetAtomName (display, property));
1355
1277 /* If this doesn't return Success at this point, it means that 1356 /* If this doesn't return Success at this point, it means that
1278 some clod deleted the selection while we were in the midst of 1357 some clod deleted the selection while we were in the midst of
1279 reading it. Deal with that, I guess.... 1358 reading it. Deal with that, I guess.... */
1280 */ 1359 if (result != Success)
1281 if (result != Success) break; 1360 break;
1282 *actual_size_ret *= *actual_format_ret / 8; 1361 *actual_size_ret *= *actual_format_ret / 8;
1283 bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret); 1362 bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret);
1284 offset += *actual_size_ret; 1363 offset += *actual_size_ret;
1364
1285 /* This was allocated by Xlib, so use XFree. */ 1365 /* This was allocated by Xlib, so use XFree. */
1286 XFree ((char *) tmp_data); 1366 XFree ((char *) tmp_data);
1287 } 1367 }
@@ -1312,9 +1392,8 @@ receive_incremental_selection (display, window, property, target_type,
1312 struct prop_location *wait_object; 1392 struct prop_location *wait_object;
1313 *size_bytes_ret = min_size_bytes; 1393 *size_bytes_ret = min_size_bytes;
1314 *data_ret = (unsigned char *) xmalloc (*size_bytes_ret); 1394 *data_ret = (unsigned char *) xmalloc (*size_bytes_ret);
1315#if 0 1395
1316 fprintf (stderr, "\nread INCR %d\n", min_size_bytes); 1396 TRACE1 ("Read %d bytes incrementally", min_size_bytes);
1317#endif
1318 1397
1319 /* At this point, we have read an INCR property. 1398 /* At this point, we have read an INCR property.
1320 Delete the property to ack it. 1399 Delete the property to ack it.
@@ -1326,7 +1405,11 @@ receive_incremental_selection (display, window, property, target_type,
1326 */ 1405 */
1327 BLOCK_INPUT; 1406 BLOCK_INPUT;
1328 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask); 1407 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask);
1408 TRACE1 (" Delete property %s",
1409 XSYMBOL (x_atom_to_symbol (display, property))->name->data);
1329 XDeleteProperty (display, window, property); 1410 XDeleteProperty (display, window, property);
1411 TRACE1 (" Expect new value of property %s",
1412 XSYMBOL (x_atom_to_symbol (display, property))->name->data);
1330 wait_object = expect_property_change (display, window, property, 1413 wait_object = expect_property_change (display, window, property,
1331 PropertyNewValue); 1414 PropertyNewValue);
1332 XFlush (display); 1415 XFlush (display);
@@ -1336,20 +1419,24 @@ receive_incremental_selection (display, window, property, target_type,
1336 { 1419 {
1337 unsigned char *tmp_data; 1420 unsigned char *tmp_data;
1338 int tmp_size_bytes; 1421 int tmp_size_bytes;
1422
1423 TRACE0 (" Wait for property change");
1339 wait_for_property_change (wait_object); 1424 wait_for_property_change (wait_object);
1425
1340 /* expect it again immediately, because x_get_window_property may 1426 /* expect it again immediately, because x_get_window_property may
1341 .. no it won't, I don't get it. 1427 .. no it won't, I don't get it.
1342 .. Ok, I get it now, the Xt code that implements INCR is broken. 1428 .. Ok, I get it now, the Xt code that implements INCR is broken. */
1343 */ 1429 TRACE0 (" Get property value");
1344 x_get_window_property (display, window, property, 1430 x_get_window_property (display, window, property,
1345 &tmp_data, &tmp_size_bytes, 1431 &tmp_data, &tmp_size_bytes,
1346 type_ret, format_ret, size_ret, 1); 1432 type_ret, format_ret, size_ret, 1);
1347 1433
1434 TRACE1 (" Read increment of %d bytes", tmp_size_bytes);
1435
1348 if (tmp_size_bytes == 0) /* we're done */ 1436 if (tmp_size_bytes == 0) /* we're done */
1349 { 1437 {
1350#if 0 1438 TRACE0 ("Done reading incrementally");
1351 fprintf (stderr, " read INCR done\n"); 1439
1352#endif
1353 if (! waiting_for_other_props_on_window (display, window)) 1440 if (! waiting_for_other_props_on_window (display, window))
1354 XSelectInput (display, window, STANDARD_EVENT_SET); 1441 XSelectInput (display, window, STANDARD_EVENT_SET);
1355 unexpect_property_change (wait_object); 1442 unexpect_property_change (wait_object);
@@ -1360,31 +1447,29 @@ receive_incremental_selection (display, window, property, target_type,
1360 } 1447 }
1361 1448
1362 BLOCK_INPUT; 1449 BLOCK_INPUT;
1450 TRACE1 (" ACK by deleting property %s",
1451 XGetAtomName (display, property));
1363 XDeleteProperty (display, window, property); 1452 XDeleteProperty (display, window, property);
1364 wait_object = expect_property_change (display, window, property, 1453 wait_object = expect_property_change (display, window, property,
1365 PropertyNewValue); 1454 PropertyNewValue);
1366 XFlush (display); 1455 XFlush (display);
1367 UNBLOCK_INPUT; 1456 UNBLOCK_INPUT;
1368 1457
1369#if 0
1370 fprintf (stderr, " read INCR %d\n", tmp_size_bytes);
1371#endif
1372 if (*size_bytes_ret < offset + tmp_size_bytes) 1458 if (*size_bytes_ret < offset + tmp_size_bytes)
1373 { 1459 {
1374#if 0
1375 fprintf (stderr, " read INCR realloc %d -> %d\n",
1376 *size_bytes_ret, offset + tmp_size_bytes);
1377#endif
1378 *size_bytes_ret = offset + tmp_size_bytes; 1460 *size_bytes_ret = offset + tmp_size_bytes;
1379 *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret); 1461 *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret);
1380 } 1462 }
1463
1381 bcopy (tmp_data, (*data_ret) + offset, tmp_size_bytes); 1464 bcopy (tmp_data, (*data_ret) + offset, tmp_size_bytes);
1382 offset += tmp_size_bytes; 1465 offset += tmp_size_bytes;
1466
1383 /* Use xfree, not XFree, because x_get_window_property 1467 /* Use xfree, not XFree, because x_get_window_property
1384 calls xmalloc itself. */ 1468 calls xmalloc itself. */
1385 xfree (tmp_data); 1469 xfree (tmp_data);
1386 } 1470 }
1387} 1471}
1472
1388 1473
1389/* Once a requested selection is "ready" (we got a SelectionNotify event), 1474/* Once a requested selection is "ready" (we got a SelectionNotify event),
1390 fetch value from property PROPERTY of X window WINDOW on display DISPLAY. 1475 fetch value from property PROPERTY of X window WINDOW on display DISPLAY.
@@ -1407,6 +1492,8 @@ x_get_window_property_as_lisp_data (display, window, property, target_type,
1407 Lisp_Object val; 1492 Lisp_Object val;
1408 struct x_display_info *dpyinfo = x_display_info_for_display (display); 1493 struct x_display_info *dpyinfo = x_display_info_for_display (display);
1409 1494
1495 TRACE0 ("Reading selection data");
1496
1410 x_get_window_property (display, window, property, &data, &bytes, 1497 x_get_window_property (display, window, property, &data, &bytes,
1411 &actual_type, &actual_format, &actual_size, 1); 1498 &actual_type, &actual_format, &actual_size, 1);
1412 if (! data) 1499 if (! data)
@@ -1421,12 +1508,12 @@ x_get_window_property_as_lisp_data (display, window, property, target_type,
1421 ? Fcons (build_string ("selection owner couldn't convert"), 1508 ? Fcons (build_string ("selection owner couldn't convert"),
1422 actual_type 1509 actual_type
1423 ? Fcons (target_type, 1510 ? Fcons (target_type,
1424 Fcons (x_atom_to_symbol (dpyinfo, display, 1511 Fcons (x_atom_to_symbol (display,
1425 actual_type), 1512 actual_type),
1426 Qnil)) 1513 Qnil))
1427 : Fcons (target_type, Qnil)) 1514 : Fcons (target_type, Qnil))
1428 : Fcons (build_string ("no selection"), 1515 : Fcons (build_string ("no selection"),
1429 Fcons (x_atom_to_symbol (dpyinfo, display, 1516 Fcons (x_atom_to_symbol (display,
1430 selection_atom), 1517 selection_atom),
1431 Qnil))); 1518 Qnil)));
1432 } 1519 }
@@ -1448,6 +1535,7 @@ x_get_window_property_as_lisp_data (display, window, property, target_type,
1448 } 1535 }
1449 1536
1450 BLOCK_INPUT; 1537 BLOCK_INPUT;
1538 TRACE1 (" Delete property %s", XGetAtomName (display, property));
1451 XDeleteProperty (display, window, property); 1539 XDeleteProperty (display, window, property);
1452 XFlush (display); 1540 XFlush (display);
1453 UNBLOCK_INPUT; 1541 UNBLOCK_INPUT;
@@ -1574,14 +1662,14 @@ selection_data_to_lisp_data (display, data, size, type, format)
1574 { 1662 {
1575 int i; 1663 int i;
1576 if (size == sizeof (Atom)) 1664 if (size == sizeof (Atom))
1577 return x_atom_to_symbol (dpyinfo, display, *((Atom *) data)); 1665 return x_atom_to_symbol (display, *((Atom *) data));
1578 else 1666 else
1579 { 1667 {
1580 Lisp_Object v = Fmake_vector (make_number (size / sizeof (Atom)), 1668 Lisp_Object v = Fmake_vector (make_number (size / sizeof (Atom)),
1581 make_number (0)); 1669 make_number (0));
1582 for (i = 0; i < size / sizeof (Atom); i++) 1670 for (i = 0; i < size / sizeof (Atom); i++)
1583 Faset (v, make_number (i), 1671 Faset (v, make_number (i),
1584 x_atom_to_symbol (dpyinfo, display, ((Atom *) data) [i])); 1672 x_atom_to_symbol (display, ((Atom *) data) [i]));
1585 return v; 1673 return v;
1586 } 1674 }
1587 } 1675 }
@@ -1853,6 +1941,7 @@ x_handle_selection_notify (event)
1853 if (event->selection != reading_which_selection) 1941 if (event->selection != reading_which_selection)
1854 return; 1942 return;
1855 1943
1944 TRACE0 ("Received SelectionNotify");
1856 XCAR (reading_selection_reply) 1945 XCAR (reading_selection_reply)
1857 = (event->property != 0 ? Qt : Qlambda); 1946 = (event->property != 0 ? Qt : Qlambda);
1858} 1947}
@@ -2121,7 +2210,7 @@ DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
2121 if (format != 8 || type != XA_STRING) 2210 if (format != 8 || type != XA_STRING)
2122 Fsignal (Qerror, 2211 Fsignal (Qerror,
2123 Fcons (build_string ("cut buffer doesn't contain 8-bit data"), 2212 Fcons (build_string ("cut buffer doesn't contain 8-bit data"),
2124 Fcons (x_atom_to_symbol (dpyinfo, display, type), 2213 Fcons (x_atom_to_symbol (display, type),
2125 Fcons (make_number (format), Qnil)))); 2214 Fcons (make_number (format), Qnil))));
2126 2215
2127 ret = (bytes ? make_string ((char *) data, bytes) : Qnil); 2216 ret = (bytes ? make_string ((char *) data, bytes) : Qnil);