Mercurial > emacs
comparison src/xselect.c @ 4373:02a515f35abc
(prop_location_identifier): Was named prop_location_tick.
(property_change_reply_identifier): Renamed from ...-tick.
(struct prop_location): Field `identifier' renamed from `tick'.
Various functions changed accordingly.
(x_handle_selection_request): Delete local struct var `reply'.
(wait_for_property_change_unwind): New function.
(wait_for_property_change): Add unwind protect.
(wait_for_property_change): Eventually time out with error.
(x_reply_selection_request): XFlushQueue and UNBLOCK_INPUT
before calling wait_for_property_change.
(x_get_window_property): Simplify input blocking/unblocking.
Don't delete the property here.
(receive_incremental_selection): Delete property here.
Call XSelectInput to enable and disable PropertyChangeMask.
(x_get_window_property_as_lisp_data): And here.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Sat, 31 Jul 1993 05:55:52 +0000 |
parents | 889d81e3f507 |
children | 3bd8248cc191 |
comparison
equal
deleted
inserted
replaced
4372:189b84c7dbc5 | 4373:02a515f35abc |
---|---|
469 if (reply.property == None) | 469 if (reply.property == None) |
470 reply.property = reply.target; | 470 reply.property = reply.target; |
471 | 471 |
472 /* #### XChangeProperty can generate BadAlloc, and we must handle it! */ | 472 /* #### XChangeProperty can generate BadAlloc, and we must handle it! */ |
473 | 473 |
474 BLOCK_INPUT; | |
475 /* Store the data on the requested property. | 474 /* Store the data on the requested property. |
476 If the selection is large, only store the first N bytes of it. | 475 If the selection is large, only store the first N bytes of it. |
477 */ | 476 */ |
478 bytes_remaining = size * format_bytes; | 477 bytes_remaining = size * format_bytes; |
479 if (bytes_remaining <= max_bytes) | 478 if (bytes_remaining <= max_bytes) |
480 { | 479 { |
481 /* Send all the data at once, with minimal handshaking. */ | 480 /* Send all the data at once, with minimal handshaking. */ |
482 #if 0 | 481 #if 0 |
483 fprintf (stderr,"\nStoring all %d\n", bytes_remaining); | 482 fprintf (stderr,"\nStoring all %d\n", bytes_remaining); |
484 #endif | 483 #endif |
484 BLOCK_INPUT; | |
485 XChangeProperty (display, window, reply.property, type, format, | 485 XChangeProperty (display, window, reply.property, type, format, |
486 PropModeReplace, data, size); | 486 PropModeReplace, data, size); |
487 /* At this point, the selection was successfully stored; ack it. */ | 487 /* At this point, the selection was successfully stored; ack it. */ |
488 (void) XSendEvent (display, window, False, 0L, (XEvent *) &reply); | 488 XSendEvent (display, window, False, 0L, (XEvent *) &reply); |
489 XFlushQueue (); | |
490 UNBLOCK_INPUT; | |
489 } | 491 } |
490 else | 492 else |
491 { | 493 { |
492 /* Send an INCR selection. */ | 494 /* Send an INCR selection. */ |
493 int prop_id; | 495 int prop_id; |
496 | |
497 BLOCK_INPUT; | |
494 | 498 |
495 if (x_window_to_frame (window)) /* #### debug */ | 499 if (x_window_to_frame (window)) /* #### debug */ |
496 error ("attempt to transfer an INCR to ourself!"); | 500 error ("attempt to transfer an INCR to ourself!"); |
497 #if 0 | 501 #if 0 |
498 fprintf (stderr, "\nINCR %d\n", bytes_remaining); | 502 fprintf (stderr, "\nINCR %d\n", bytes_remaining); |
504 32, PropModeReplace, (unsigned char *) | 508 32, PropModeReplace, (unsigned char *) |
505 &bytes_remaining, 1); | 509 &bytes_remaining, 1); |
506 XSelectInput (display, window, PropertyChangeMask); | 510 XSelectInput (display, window, PropertyChangeMask); |
507 /* Tell 'em the INCR data is there... */ | 511 /* Tell 'em the INCR data is there... */ |
508 (void) XSendEvent (display, window, False, 0L, (XEvent *) &reply); | 512 (void) XSendEvent (display, window, False, 0L, (XEvent *) &reply); |
513 XFlushQueue (); | |
514 UNBLOCK_INPUT; | |
509 | 515 |
510 /* First, wait for the requestor to ack by deleting the property. | 516 /* First, wait for the requestor to ack by deleting the property. |
511 This can run random lisp code (process handlers) or signal. */ | 517 This can run random lisp code (process handlers) or signal. */ |
512 wait_for_property_change (prop_id); | 518 wait_for_property_change (prop_id); |
513 | 519 |
514 while (bytes_remaining) | 520 while (bytes_remaining) |
515 { | 521 { |
516 int i = ((bytes_remaining < max_bytes) | 522 int i = ((bytes_remaining < max_bytes) |
517 ? bytes_remaining | 523 ? bytes_remaining |
518 : max_bytes); | 524 : max_bytes); |
525 | |
526 BLOCK_INPUT; | |
527 | |
519 prop_id = expect_property_change (display, window, reply.property, | 528 prop_id = expect_property_change (display, window, reply.property, |
520 PropertyDelete); | 529 PropertyDelete); |
521 #if 0 | 530 #if 0 |
522 fprintf (stderr," INCR adding %d\n", i); | 531 fprintf (stderr," INCR adding %d\n", i); |
523 #endif | 532 #endif |
524 /* Append the next chunk of data to the property. */ | 533 /* Append the next chunk of data to the property. */ |
525 XChangeProperty (display, window, reply.property, type, format, | 534 XChangeProperty (display, window, reply.property, type, format, |
526 PropModeAppend, data, i / format_bytes); | 535 PropModeAppend, data, i / format_bytes); |
527 bytes_remaining -= i; | 536 bytes_remaining -= i; |
528 data += i; | 537 data += i; |
538 XFlushQueue (); | |
539 UNBLOCK_INPUT; | |
529 | 540 |
530 /* Now wait for the requestor to ack this chunk by deleting the | 541 /* Now wait for the requestor to ack this chunk by deleting the |
531 property. This can run random lisp code or signal. | 542 property. This can run random lisp code or signal. |
532 */ | 543 */ |
533 wait_for_property_change (prop_id); | 544 wait_for_property_change (prop_id); |
535 /* Now write a zero-length chunk to the property to tell the requestor | 546 /* Now write a zero-length chunk to the property to tell the requestor |
536 that we're done. */ | 547 that we're done. */ |
537 #if 0 | 548 #if 0 |
538 fprintf (stderr," INCR done\n"); | 549 fprintf (stderr," INCR done\n"); |
539 #endif | 550 #endif |
551 BLOCK_INPUT; | |
540 if (! waiting_for_other_props_on_window (display, window)) | 552 if (! waiting_for_other_props_on_window (display, window)) |
541 XSelectInput (display, window, 0L); | 553 XSelectInput (display, window, 0L); |
542 | 554 |
543 XChangeProperty (display, window, reply.property, type, format, | 555 XChangeProperty (display, window, reply.property, type, format, |
544 PropModeReplace, data, 0); | 556 PropModeReplace, data, 0); |
545 } | 557 XFlushQueue (); |
546 XFlushQueue (); | 558 UNBLOCK_INPUT; |
547 UNBLOCK_INPUT; | 559 } |
548 } | 560 } |
549 | 561 |
550 /* Handle a SelectionRequest event EVENT. | 562 /* Handle a SelectionRequest event EVENT. |
551 This is called from keyboard.c when such an event is found in the queue. */ | 563 This is called from keyboard.c when such an event is found in the queue. */ |
552 | 564 |
553 void | 565 void |
554 x_handle_selection_request (event) | 566 x_handle_selection_request (event) |
555 struct input_event *event; | 567 struct input_event *event; |
556 { | 568 { |
557 struct gcpro gcpro1, gcpro2, gcpro3; | 569 struct gcpro gcpro1, gcpro2, gcpro3; |
558 XSelectionEvent reply; | |
559 Lisp_Object local_selection_data = Qnil; | 570 Lisp_Object local_selection_data = Qnil; |
560 Lisp_Object selection_symbol; | 571 Lisp_Object selection_symbol; |
561 Lisp_Object target_symbol = Qnil; | 572 Lisp_Object target_symbol = Qnil; |
562 Lisp_Object converted_selection = Qnil; | 573 Lisp_Object converted_selection = Qnil; |
563 Time local_selection_time; | 574 Time local_selection_time; |
564 Lisp_Object successful_p = Qnil; | 575 Lisp_Object successful_p = Qnil; |
565 int count; | 576 int count; |
566 | 577 |
567 GCPRO3 (local_selection_data, converted_selection, target_symbol); | 578 GCPRO3 (local_selection_data, converted_selection, target_symbol); |
568 | 579 |
569 reply.type = SelectionNotify; /* Construct the reply event */ | 580 selection_symbol = x_atom_to_symbol (SELECTION_EVENT_DISPLAY (event), |
570 reply.display = SELECTION_EVENT_DISPLAY (event); | |
571 reply.requestor = SELECTION_EVENT_REQUESTOR (event); | |
572 reply.selection = SELECTION_EVENT_SELECTION (event); | |
573 reply.time = SELECTION_EVENT_TIME (event); | |
574 reply.target = SELECTION_EVENT_TARGET (event); | |
575 reply.property = SELECTION_EVENT_PROPERTY (event); | |
576 if (reply.property == None) | |
577 reply.property = reply.target; | |
578 | |
579 selection_symbol = x_atom_to_symbol (reply.display, | |
580 SELECTION_EVENT_SELECTION (event)); | 581 SELECTION_EVENT_SELECTION (event)); |
581 | 582 |
582 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist); | 583 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist); |
583 | |
584 #if 0 | |
585 # define CDR(x) (XCONS (x)->cdr) | |
586 # define CAR(x) (XCONS (x)->car) | |
587 /* This list isn't user-visible, so it can't "go bad." */ | |
588 if (!CONSP (local_selection_data)) abort (); | |
589 if (!CONSP (CDR (local_selection_data))) abort (); | |
590 if (!CONSP (CDR (CDR (local_selection_data)))) abort (); | |
591 if (!NILP (CDR (CDR (CDR (local_selection_data))))) abort (); | |
592 if (!CONSP (CAR (CDR (CDR (local_selection_data))))) abort (); | |
593 if (!INTEGERP (CAR (CAR (CDR (CDR (local_selection_data)))))) abort (); | |
594 if (!INTEGERP (CDR (CAR (CDR (CDR (local_selection_data)))))) abort (); | |
595 # undef CAR | |
596 # undef CDR | |
597 #endif | |
598 | 584 |
599 if (NILP (local_selection_data)) | 585 if (NILP (local_selection_data)) |
600 { | 586 { |
601 /* Someone asked for the selection, but we don't have it any more. | 587 /* Someone asked for the selection, but we don't have it any more. |
602 */ | 588 */ |
619 | 605 |
620 count = specpdl_ptr - specpdl; | 606 count = specpdl_ptr - specpdl; |
621 x_selection_current_request = event; | 607 x_selection_current_request = event; |
622 record_unwind_protect (x_selection_request_lisp_error, Qnil); | 608 record_unwind_protect (x_selection_request_lisp_error, Qnil); |
623 | 609 |
624 target_symbol = x_atom_to_symbol (reply.display, | 610 target_symbol = x_atom_to_symbol (SELECTION_EVENT_DISPLAY (event), |
625 SELECTION_EVENT_TARGET (event)); | 611 SELECTION_EVENT_TARGET (event)); |
626 | 612 |
627 #if 0 /* #### MULTIPLE doesn't work yet */ | 613 #if 0 /* #### MULTIPLE doesn't work yet */ |
628 if (EQ (target_symbol, QMULTIPLE)) | 614 if (EQ (target_symbol, QMULTIPLE)) |
629 target_symbol = fetch_multiple_target (event); | 615 target_symbol = fetch_multiple_target (event); |
640 unsigned int size; | 626 unsigned int size; |
641 int format; | 627 int format; |
642 Atom type; | 628 Atom type; |
643 int nofree; | 629 int nofree; |
644 | 630 |
645 lisp_data_to_selection_data (reply.display, converted_selection, | 631 lisp_data_to_selection_data (SELECTION_EVENT_DISPLAY (event), |
632 converted_selection, | |
646 &data, &type, &size, &format, &nofree); | 633 &data, &type, &size, &format, &nofree); |
647 | 634 |
648 x_reply_selection_request (event, format, data, size, type); | 635 x_reply_selection_request (event, format, data, size, type); |
649 successful_p = Qt; | 636 successful_p = Qt; |
650 | 637 |
731 | 718 |
732 /* This stuff is so that INCR selections are reentrant (that is, so we can | 719 /* This stuff is so that INCR selections are reentrant (that is, so we can |
733 be servicing multiple INCR selection requests simultaneously.) I haven't | 720 be servicing multiple INCR selection requests simultaneously.) I haven't |
734 actually tested that yet. */ | 721 actually tested that yet. */ |
735 | 722 |
736 static int prop_location_tick; | 723 static int prop_location_identifier; |
737 | 724 |
738 static Lisp_Object property_change_reply; | 725 static Lisp_Object property_change_reply; |
739 static int property_change_reply_tick; | 726 static int property_change_reply_identifier; |
740 | 727 |
741 /* Keep a list of the property changes that are awaited. */ | 728 /* Keep a list of the property changes that are awaited. */ |
742 | 729 |
743 struct prop_location | 730 struct prop_location |
744 { | 731 { |
745 int tick; | 732 int identifier; |
746 Display *display; | 733 Display *display; |
747 Window window; | 734 Window window; |
748 Atom property; | 735 Atom property; |
749 int desired_state; | 736 int desired_state; |
750 struct prop_location *next; | 737 struct prop_location *next; |
751 }; | 738 }; |
752 | 739 |
753 static struct prop_location *property_change_wait_list; | 740 static struct prop_location *property_change_wait_list; |
754 | 741 |
755 static int | 742 static int |
756 property_deleted_p (tick) | 743 property_deleted_p (identifier) |
757 void *tick; | 744 void *identifier; |
758 { | 745 { |
759 struct prop_location *rest = property_change_wait_list; | 746 struct prop_location *rest = property_change_wait_list; |
760 while (rest) | 747 while (rest) |
761 if (rest->tick == (int) tick) | 748 if (rest->identifier == (int) identifier) |
762 return 0; | 749 return 0; |
763 else | 750 else |
764 rest = rest->next; | 751 rest = rest->next; |
765 return 1; | 752 return 1; |
766 } | 753 } |
794 Lisp_Object property; | 781 Lisp_Object property; |
795 int state; | 782 int state; |
796 { | 783 { |
797 struct prop_location *pl | 784 struct prop_location *pl |
798 = (struct prop_location *) xmalloc (sizeof (struct prop_location)); | 785 = (struct prop_location *) xmalloc (sizeof (struct prop_location)); |
799 pl->tick = ++prop_location_tick; | 786 pl->identifier = ++prop_location_identifier; |
800 pl->display = display; | 787 pl->display = display; |
801 pl->window = window; | 788 pl->window = window; |
802 pl->property = property; | 789 pl->property = property; |
803 pl->desired_state = state; | 790 pl->desired_state = state; |
804 pl->next = property_change_wait_list; | 791 pl->next = property_change_wait_list; |
805 property_change_wait_list = pl; | 792 property_change_wait_list = pl; |
806 return pl->tick; | 793 return pl->identifier; |
807 } | 794 } |
808 | 795 |
809 /* Delete an entry from the list of property changes we are waiting for. | 796 /* Delete an entry from the list of property changes we are waiting for. |
810 TICK is the number that uniquely identifies the entry. */ | 797 IDENTIFIER is the number that uniquely identifies the entry. */ |
811 | 798 |
812 static void | 799 static void |
813 unexpect_property_change (tick) | 800 unexpect_property_change (identifier) |
814 int tick; | 801 int identifier; |
815 { | 802 { |
816 struct prop_location *prev = 0, *rest = property_change_wait_list; | 803 struct prop_location *prev = 0, *rest = property_change_wait_list; |
817 while (rest) | 804 while (rest) |
818 { | 805 { |
819 if (rest->tick == tick) | 806 if (rest->identifier == identifier) |
820 { | 807 { |
821 if (prev) | 808 if (prev) |
822 prev->next = rest->next; | 809 prev->next = rest->next; |
823 else | 810 else |
824 property_change_wait_list = rest->next; | 811 property_change_wait_list = rest->next; |
828 prev = rest; | 815 prev = rest; |
829 rest = rest->next; | 816 rest = rest->next; |
830 } | 817 } |
831 } | 818 } |
832 | 819 |
820 /* Remove the property change expectation element for IDENTIFIER. */ | |
821 | |
822 static Lisp_Object | |
823 wait_for_property_change_unwind (identifierval) | |
824 Lisp_Object identifierval; | |
825 { | |
826 unexpect_property_change (XFASTINT (identifierval)); | |
827 } | |
828 | |
833 /* Actually wait for a property change. | 829 /* Actually wait for a property change. |
834 TICK should be the value that expect_property_change returned. */ | 830 IDENTIFIER should be the value that expect_property_change returned. */ |
835 | 831 |
836 static void | 832 static void |
837 wait_for_property_change (tick) | 833 wait_for_property_change (identifier) |
838 { | 834 { |
835 int secs, usecs; | |
836 int count = specpdl_ptr - specpdl; | |
837 | |
838 /* Make sure to do unexpect_property_change if we quit or err. */ | |
839 record_unwind_protect (wait_for_property_change_unwind, | |
840 make_number (identifier)); | |
841 | |
839 XCONS (property_change_reply)->car = Qnil; | 842 XCONS (property_change_reply)->car = Qnil; |
840 property_change_reply_tick = tick; | 843 property_change_reply_identifier = identifier; |
841 wait_reading_process_input (0, 0, property_change_reply, 0); | 844 secs = x_selection_timeout / 1000; |
845 usecs = (x_selection_timeout % 1000) * 1000; | |
846 wait_reading_process_input (secs, usecs, property_change_reply, 0); | |
847 | |
848 if (NILP (XCONS (property_change_reply)->car)) | |
849 error ("timed out waiting for property-notify event"); | |
850 | |
851 unbind_to (count, Qnil); | |
842 } | 852 } |
843 | 853 |
844 /* Called from XTread_socket in response to a PropertyNotify event. */ | 854 /* Called from XTread_socket in response to a PropertyNotify event. */ |
845 | 855 |
846 void | 856 void |
863 ->name->data); | 873 ->name->data); |
864 #endif | 874 #endif |
865 | 875 |
866 /* If this is the one wait_for_property_change is waiting for, | 876 /* If this is the one wait_for_property_change is waiting for, |
867 tell it to wake up. */ | 877 tell it to wake up. */ |
868 if (rest->tick == property_change_reply_tick) | 878 if (rest->identifier == property_change_reply_identifier) |
869 XCONS (property_change_reply)->car = Qt; | 879 XCONS (property_change_reply)->car = Qt; |
870 | 880 |
871 if (prev) | 881 if (prev) |
872 prev->next = rest->next; | 882 prev->next = rest->next; |
873 else | 883 else |
1022 result = XGetWindowProperty (display, window, property, | 1032 result = XGetWindowProperty (display, window, property, |
1023 0, 0, False, AnyPropertyType, | 1033 0, 0, False, AnyPropertyType, |
1024 actual_type_ret, actual_format_ret, | 1034 actual_type_ret, actual_format_ret, |
1025 actual_size_ret, | 1035 actual_size_ret, |
1026 &bytes_remaining, &tmp_data); | 1036 &bytes_remaining, &tmp_data); |
1027 UNBLOCK_INPUT; | |
1028 if (result != Success) | 1037 if (result != Success) |
1029 { | 1038 { |
1039 UNBLOCK_INPUT; | |
1030 *data_ret = 0; | 1040 *data_ret = 0; |
1031 *bytes_ret = 0; | 1041 *bytes_ret = 0; |
1032 return; | 1042 return; |
1033 } | 1043 } |
1034 BLOCK_INPUT; | 1044 xfree ((char *) tmp_data); |
1035 XFree ((char *) tmp_data); | |
1036 UNBLOCK_INPUT; | |
1037 | 1045 |
1038 if (*actual_type_ret == None || *actual_format_ret == 0) | 1046 if (*actual_type_ret == None || *actual_format_ret == 0) |
1039 { | 1047 { |
1040 if (delete_p) XDeleteProperty (display, window, property); | 1048 UNBLOCK_INPUT; |
1041 return; | 1049 return; |
1042 } | 1050 } |
1043 | 1051 |
1044 total_size = bytes_remaining + 1; | 1052 total_size = bytes_remaining + 1; |
1045 *data_ret = (unsigned char *) xmalloc (total_size); | 1053 *data_ret = (unsigned char *) xmalloc (total_size); |
1046 | 1054 |
1047 /* Now read, until weve gotten it all. */ | 1055 /* Now read, until weve gotten it all. */ |
1048 BLOCK_INPUT; | |
1049 while (bytes_remaining) | 1056 while (bytes_remaining) |
1050 { | 1057 { |
1051 #if 0 | 1058 #if 0 |
1052 int last = bytes_remaining; | 1059 int last = bytes_remaining; |
1053 #endif | 1060 #endif |
1054 result | 1061 result |
1055 = XGetWindowProperty (display, window, property, | 1062 = XGetWindowProperty (display, window, property, |
1056 offset/4, buffer_size/4, | 1063 offset/4, buffer_size/4, |
1057 (delete_p ? True : False), | 1064 False, |
1058 AnyPropertyType, | 1065 AnyPropertyType, |
1059 actual_type_ret, actual_format_ret, | 1066 actual_type_ret, actual_format_ret, |
1060 actual_size_ret, &bytes_remaining, &tmp_data); | 1067 actual_size_ret, &bytes_remaining, &tmp_data); |
1061 #if 0 | 1068 #if 0 |
1062 fprintf (stderr, "<< read %d\n", last-bytes_remaining); | 1069 fprintf (stderr, "<< read %d\n", last-bytes_remaining); |
1067 */ | 1074 */ |
1068 if (result != Success) break; | 1075 if (result != Success) break; |
1069 *actual_size_ret *= *actual_format_ret / 8; | 1076 *actual_size_ret *= *actual_format_ret / 8; |
1070 bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret); | 1077 bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret); |
1071 offset += *actual_size_ret; | 1078 offset += *actual_size_ret; |
1072 XFree ((char *) tmp_data); | 1079 xfree ((char *) tmp_data); |
1073 } | 1080 } |
1081 | |
1082 XFlushQueue (); | |
1074 UNBLOCK_INPUT; | 1083 UNBLOCK_INPUT; |
1075 *bytes_ret = offset; | 1084 *bytes_ret = offset; |
1076 } | 1085 } |
1077 | 1086 |
1078 static void | 1087 static void |
1095 *size_bytes_ret = min_size_bytes; | 1104 *size_bytes_ret = min_size_bytes; |
1096 *data_ret = (unsigned char *) xmalloc (*size_bytes_ret); | 1105 *data_ret = (unsigned char *) xmalloc (*size_bytes_ret); |
1097 #if 0 | 1106 #if 0 |
1098 fprintf (stderr, "\nread INCR %d\n", min_size_bytes); | 1107 fprintf (stderr, "\nread INCR %d\n", min_size_bytes); |
1099 #endif | 1108 #endif |
1100 /* At this point, we have read an INCR property, and deleted it (which | 1109 |
1101 is how we ack its receipt: the sending window will be selecting | 1110 /* At this point, we have read an INCR property. |
1102 PropertyNotify events on our window to notice this.) | 1111 Delete the property to ack it. |
1112 (But first, prepare to receive the next event in this handshake.) | |
1103 | 1113 |
1104 Now, we must loop, waiting for the sending window to put a value on | 1114 Now, we must loop, waiting for the sending window to put a value on |
1105 that property, then reading the property, then deleting it to ack. | 1115 that property, then reading the property, then deleting it to ack. |
1106 We are done when the sender places a property of length 0. | 1116 We are done when the sender places a property of length 0. |
1107 */ | 1117 */ |
1118 BLOCK_INPUT; | |
1119 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask); | |
1120 XDeleteProperty (display, window, property); | |
1108 prop_id = expect_property_change (display, window, property, | 1121 prop_id = expect_property_change (display, window, property, |
1109 PropertyNewValue); | 1122 PropertyNewValue); |
1123 XFlushQueue (); | |
1124 UNBLOCK_INPUT; | |
1125 | |
1110 while (1) | 1126 while (1) |
1111 { | 1127 { |
1112 unsigned char *tmp_data; | 1128 unsigned char *tmp_data; |
1113 int tmp_size_bytes; | 1129 int tmp_size_bytes; |
1114 wait_for_property_change (prop_id); | 1130 wait_for_property_change (prop_id); |
1115 /* expect it again immediately, because x_get_window_property may | 1131 /* expect it again immediately, because x_get_window_property may |
1116 .. no it wont, I dont get it. | 1132 .. no it wont, I dont get it. |
1117 .. Ok, I get it now, the Xt code that implements INCR is broken. | 1133 .. Ok, I get it now, the Xt code that implements INCR is broken. |
1118 */ | 1134 */ |
1119 prop_id = expect_property_change (display, window, property, | |
1120 PropertyNewValue); | |
1121 x_get_window_property (display, window, property, | 1135 x_get_window_property (display, window, property, |
1122 &tmp_data, &tmp_size_bytes, | 1136 &tmp_data, &tmp_size_bytes, |
1123 type_ret, format_ret, size_ret, 1); | 1137 type_ret, format_ret, size_ret, 1); |
1124 | 1138 |
1125 if (tmp_size_bytes == 0) /* we're done */ | 1139 if (tmp_size_bytes == 0) /* we're done */ |
1126 { | 1140 { |
1127 #if 0 | 1141 #if 0 |
1128 fprintf (stderr, " read INCR done\n"); | 1142 fprintf (stderr, " read INCR done\n"); |
1129 #endif | 1143 #endif |
1144 if (! waiting_for_other_props_on_window (display, window)) | |
1145 XSelectInput (display, window, STANDARD_EVENT_SET); | |
1130 unexpect_property_change (prop_id); | 1146 unexpect_property_change (prop_id); |
1131 if (tmp_data) xfree (tmp_data); | 1147 if (tmp_data) xfree (tmp_data); |
1132 break; | 1148 break; |
1133 } | 1149 } |
1150 | |
1151 BLOCK_INPUT; | |
1152 XDeleteProperty (display, window, property); | |
1153 prop_id = expect_property_change (display, window, property, | |
1154 PropertyNewValue); | |
1155 XFlushQueue (); | |
1156 UNBLOCK_INPUT; | |
1157 | |
1134 #if 0 | 1158 #if 0 |
1135 fprintf (stderr, " read INCR %d\n", tmp_size_bytes); | 1159 fprintf (stderr, " read INCR %d\n", tmp_size_bytes); |
1136 #endif | 1160 #endif |
1137 if (*size_bytes_ret < offset + tmp_size_bytes) | 1161 if (*size_bytes_ret < offset + tmp_size_bytes) |
1138 { | 1162 { |
1203 receive_incremental_selection (display, window, property, target_type, | 1227 receive_incremental_selection (display, window, property, target_type, |
1204 min_size_bytes, &data, &bytes, | 1228 min_size_bytes, &data, &bytes, |
1205 &actual_type, &actual_format, | 1229 &actual_type, &actual_format, |
1206 &actual_size); | 1230 &actual_size); |
1207 } | 1231 } |
1232 | |
1233 BLOCK_INPUT; | |
1234 XDeleteProperty (display, window, property); | |
1235 XFlushQueue (); | |
1236 UNBLOCK_INPUT; | |
1208 | 1237 |
1209 /* It's been read. Now convert it to a lisp object in some semi-rational | 1238 /* It's been read. Now convert it to a lisp object in some semi-rational |
1210 manner. */ | 1239 manner. */ |
1211 val = selection_data_to_lisp_data (display, data, bytes, | 1240 val = selection_data_to_lisp_data (display, data, bytes, |
1212 actual_type, actual_format); | 1241 actual_type, actual_format); |
1897 staticpro (&reading_selection_reply); | 1926 staticpro (&reading_selection_reply); |
1898 reading_selection_window = 0; | 1927 reading_selection_window = 0; |
1899 reading_which_selection = 0; | 1928 reading_which_selection = 0; |
1900 | 1929 |
1901 property_change_wait_list = 0; | 1930 property_change_wait_list = 0; |
1902 prop_location_tick = 0; | 1931 prop_location_identifier = 0; |
1903 property_change_reply = Fcons (Qnil, Qnil); | 1932 property_change_reply = Fcons (Qnil, Qnil); |
1904 staticpro (&property_change_reply); | 1933 staticpro (&property_change_reply); |
1905 | 1934 |
1906 Vselection_alist = Qnil; | 1935 Vselection_alist = Qnil; |
1907 staticpro (&Vselection_alist); | 1936 staticpro (&Vselection_alist); |