aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJim Blandy1992-09-29 18:30:35 +0000
committerJim Blandy1992-09-29 18:30:35 +0000
commit234a804bca326994adc2d83f01d064ee642228f9 (patch)
tree55701983e116c0000419416934cc4ef1ebb9d107 /src
parent72e609d0db47631ae8d140c6da099bbe8cf36c96 (diff)
downloademacs-234a804bca326994adc2d83f01d064ee642228f9.tar.gz
emacs-234a804bca326994adc2d83f01d064ee642228f9.zip
* xselect.c (Qcut_buffer0): Symbol removed; we're using a new
interface to the cut buffer now. (NUM_CUT_BUFFERS, cut_buffer_atom, cut_buffer_value, cut_buffer_cached, cut_buffer_just_set): New variables. (Fx_own_selection, Fx_selection_value): Dike out the code to handle CUT_BUFFER0 requests. (Fx_get_cut_buffer, Fx_set_cut_buffer, x_watch_cut_buffer_cache, x_invalidate_cut_buffer_cache): New functions. (syms_of_xselect): Don't bother to initialize Qcut_buffer0. Initialize and staticpro cut_buffer_value, and defsubr Sx_get_cut_buffer and Sx_set_cut_buffer. * xterm.c (XTread_socket): Pass PropertyNotify events from the root window to x_invalidate_cut_buffer_cache. (x_term_init): Call x_watch_cut_buffer_cache here.
Diffstat (limited to 'src')
-rw-r--r--src/xselect.c.old219
1 files changed, 208 insertions, 11 deletions
diff --git a/src/xselect.c.old b/src/xselect.c.old
index 81cdd755e8b..6adedd96cf3 100644
--- a/src/xselect.c.old
+++ b/src/xselect.c.old
@@ -53,10 +53,8 @@ Lisp_Object Vx_selection_value;
53/* The value of the current SECONDARY selection. */ 53/* The value of the current SECONDARY selection. */
54Lisp_Object Vx_secondary_selection_value; 54Lisp_Object Vx_secondary_selection_value;
55 55
56/* Types of selections we may make. Note that Qcut_buffer0 isn't really 56/* Types of selections we may make. */
57 a selection, but it acts like one for the sake of Fx_own_selection and 57Lisp_Object Qprimary, Qsecondary, Qclipboard;
58 Fx_selection_value. */
59Lisp_Object Qprimary, Qsecondary, Qclipboard, Qcut_buffer0;
60 58
61/* Emacs' selection property identifiers. */ 59/* Emacs' selection property identifiers. */
62Atom Xatom_emacs_selection; 60Atom Xatom_emacs_selection;
@@ -110,7 +108,52 @@ int incr_nbytes;
110unsigned char *incr_value; 108unsigned char *incr_value;
111unsigned char *incr_ptr; 109unsigned char *incr_ptr;
112 110
113/* SELECTION OWNER CODE */ 111/* Declarations for handling cut buffers.
112
113 Whenever we set a cut buffer or read a cut buffer's value, we cache
114 it in cut_buffer_value. We look for PropertyNotify events about
115 the CUT_BUFFER properties, and invalidate our cache accordingly.
116 We ignore PropertyNotify events that we suspect were caused by our
117 own changes to the cut buffers, so we can keep the cache valid
118 longer.
119
120 IS ALL THIS HAIR WORTH IT? Well, these functions get called every
121 time an element goes into or is retrieved from the kill ring, and
122 those ought to be quick. It's not fun in time or space to wait for
123 50k cut buffers to fly back and forth across the net. */
124
125/* The number of CUT_BUFFER properties defined under X. */
126#define NUM_CUT_BUFFERS (8)
127
128/* cut_buffer_atom[n] is the atom naming the nth cut buffer. */
129static Atom cut_buffer_atom[NUM_CUT_BUFFERS] = {
130 XA_CUT_BUFFER0, XA_CUT_BUFFER1, XA_CUT_BUFFER2, XA_CUT_BUFFER3,
131 XA_CUT_BUFFER4, XA_CUT_BUFFER5, XA_CUT_BUFFER6, XA_CUT_BUFFER7
132};
133
134/* cut_buffer_value is an eight-element vector;
135 (aref cut_buffer_value n) is the cached value of cut buffer n, or
136 Qnil if cut buffer n is unset. */
137static Lisp_Object cut_buffer_value;
138
139/* Bit N of cut_buffer_cached is true if (aref cut_buffer_value n) is
140 known to be valid. This is cleared by PropertyNotify events
141 handled by x_invalidate_cut_buffer_cache. It would be wonderful if
142 that routine could just set the appropriate element of
143 cut_buffer_value to some special value meaning "uncached", but that
144 would lose if a GC happened to be in progress.
145
146 Bit N of cut_buffer_just_set is true if cut buffer N has been set since
147 the last PropertyNotify event; since we get an event even when we set
148 the property ourselves, we should ignore one event after setting
149 a cut buffer, so we don't have to throw away our cache. */
150#ifdef __STDC__
151volatile
152#endif
153static cut_buffer_cached, cut_buffer_just_set;
154
155
156/* Acquiring ownership of a selection. */
114 157
115 158
116/* Request selection ownership if we do not already have it. */ 159/* Request selection ownership if we do not already have it. */
@@ -191,6 +234,7 @@ use X selections.")
191 } 234 }
192 UNBLOCK_INPUT; 235 UNBLOCK_INPUT;
193 } 236 }
237#if 0
194 else if (EQ (type, Qcut_buffer0)) 238 else if (EQ (type, Qcut_buffer0))
195 { 239 {
196 /* DECwindows and some other servers don't seem to like setting 240 /* DECwindows and some other servers don't seem to like setting
@@ -216,6 +260,7 @@ use X selections.")
216 } 260 }
217 UNBLOCK_INPUT; 261 UNBLOCK_INPUT;
218 } 262 }
263#endif
219 else 264 else
220 error ("Invalid X selection type"); 265 error ("Invalid X selection type");
221 266
@@ -257,11 +302,14 @@ x_disown_selection (old_owner, selection, changed_owner_time)
257 abort (); /* Inconsistent state. */ 302 abort (); /* Inconsistent state. */
258} 303}
259 304
305
306/* Answering selection requests. */
307
260int x_selection_alloc_error; 308int x_selection_alloc_error;
261int x_converting_selection; 309int x_converting_selection;
262 310
263/* Reply to some client's request for our selection data. Data is 311/* Reply to some client's request for our selection data.
264 placed in a property supplied by the requesting window. 312 Data is placed in a property supplied by the requesting window.
265 313
266 If the data exceeds the maximum amount the server can send, 314 If the data exceeds the maximum amount the server can send,
267 then prepare to send it incrementally, and reply to the client with 315 then prepare to send it incrementally, and reply to the client with
@@ -519,7 +567,8 @@ x_send_incremental (event)
519 } 567 }
520} 568}
521 569
522/* SELECTION REQUESTOR CODE */ 570
571/* Requesting the value of a selection. */
523 572
524/* Predicate function used to match a requested event. */ 573/* Predicate function used to match a requested event. */
525 574
@@ -579,7 +628,7 @@ selection, but optional argument TYPE may specify secondary or clipboard.")
579 if (NILP (type) || EQ (type, Qprimary)) 628 if (NILP (type) || EQ (type, Qprimary))
580 { 629 {
581 if (!NILP (Vx_selection_value)) 630 if (!NILP (Vx_selection_value))
582 return Vx_selection_value; 631 return Vx_selection_value;
583 632
584 return get_selection_value (XA_PRIMARY); 633 return get_selection_value (XA_PRIMARY);
585 } 634 }
@@ -597,6 +646,7 @@ selection, but optional argument TYPE may specify secondary or clipboard.")
597 646
598 return get_selection_value (Xatom_clipboard); 647 return get_selection_value (Xatom_clipboard);
599 } 648 }
649#if 0
600 else if (EQ (type, Qcut_buffer0)) 650 else if (EQ (type, Qcut_buffer0))
601 { 651 {
602 char *data; 652 char *data;
@@ -613,6 +663,7 @@ selection, but optional argument TYPE may specify secondary or clipboard.")
613 663
614 return string; 664 return string;
615 } 665 }
666#endif
616 else 667 else
617 error ("Invalid X selection type"); 668 error ("Invalid X selection type");
618} 669}
@@ -730,6 +781,148 @@ x_selection_arrival (event, requestor_window, requestor_time)
730 return Qnil; 781 return Qnil;
731} 782}
732 783
784
785/* Cut buffer management. */
786
787DEFUN ("x-get-cut-buffer", Fx_get_cut_buffer, Sx_get_cut_buffer, 0, 1, "",
788 "Return the value of cut buffer N, or nil if it is unset.\n\
789If N is omitted, it defaults to zero.\n\
790Note that cut buffers have some problems that selections don't; try to\n\
791write your code to use cut buffers only for backward compatibility,\n\
792and use selections for the serious work.")
793 (n)
794 Lisp_Object n;
795{
796 int buf_num;
797
798 if (NILP (n))
799 buf_num = 0;
800 else
801 {
802 CHECK_NUMBER (n, 0);
803 buf_num = XINT (n);
804 }
805
806 if (buf_num < 0 && buf_num > NUM_CUT_BUFFERS)
807 error ("cut buffer numbers must be from zero to seven.");
808
809 {
810 Lisp_Object value;
811
812 /* Note that no PropertyNotify events will be processed while
813 input is blocked. */
814 BLOCK_INPUT;
815
816 if (cut_buffer_cached & (1 << buf_num))
817 value = XVECTOR (cut_buffer_value)->contents[buf_num];
818 else
819 {
820 /* Our cache is invalid; retrieve the property's value from
821 the server. */
822 int buf_len;
823 char *buf = XFetchBuffer (x_current_display, &buf_len, buf_num);
824
825 if (buf_len == 0)
826 value = Qnil;
827 else
828 value = make_string (buf, buf_len);
829
830 XVECTOR (cut_buffer_value)->contents[buf_num] = value;
831 cut_buffer_cached |= (1 << buf_num);
832
833 XFree (buf);
834 }
835
836 UNBLOCK_INPUT;
837
838 return value;
839 }
840}
841
842DEFUN ("x-set-cut-buffer", Fx_set_cut_buffer, Sx_set_cut_buffer, 2, 2, "",
843 "Set the value of cut buffer N to STRING.\n\
844Note that cut buffers have some problems that selections don't; try to\n\
845write your code to use cut buffers only for backward compatibility,\n\
846and use selections for the serious work.")
847 (n, string)
848 Lisp_Object n, string;
849{
850 int buf_num;
851
852 CHECK_NUMBER (n, 0);
853 CHECK_STRING (string, 1);
854
855 buf_num = XINT (n);
856
857 if (buf_num < 0 || buf_num > 7)
858 error ("cut buffer numbers must be from zero to seven.");
859
860 BLOCK_INPUT;
861
862 /* DECwindows and some other servers don't seem to like setting
863 properties to values larger than about 20k. For very large
864 values, they signal an error, but for intermediate values they
865 just seem to hang.
866
867 We could just truncate the request, but it's better to let the
868 user know that the strategy he/she's using isn't going to work
869 than to have it work partially, but incorrectly. */
870
871 if (XSTRING (string)->size == 0
872 || XSTRING (string)->size > MAX_SELECTION (x_current_display))
873 {
874 XStoreBuffer (x_current_display, (char *) 0, 0, buf_num);
875 string = Qnil;
876 }
877 else
878 {
879 XStoreBuffer (x_current_display,
880 (char *) XSTRING (string)->data, XSTRING (string)->size,
881 buf_num);
882 }
883
884 XVECTOR (cut_buffer_value)->contents[buf_num] = string;
885 cut_buffer_cached |= (1 << buf_num);
886 cut_buffer_just_set |= (1 << buf_num);
887
888 UNBLOCK_INPUT;
889
890 return string;
891}
892
893/* Ask the server to send us an event if any cut buffer is modified. */
894
895void
896x_watch_cut_buffer_cache ()
897{
898 XSelectInput (x_current_display, ROOT_WINDOW, PropertyChangeMask);
899}
900
901/* The server has told us that a cut buffer has been modified; deal with that.
902 Note that this function is called at interrupt level. */
903void
904x_invalidate_cut_buffer_cache (XPropertyEvent *event)
905{
906 int i;
907
908 /* See which cut buffer this is about, if any. */
909 for (i = 0; i < NUM_CUT_BUFFERS; i++)
910 if (event->atom == cut_buffer_atom[i])
911 {
912 int mask = (1 << i);
913
914 if (cut_buffer_just_set & mask)
915 cut_buffer_just_set &= ~mask;
916 else
917 cut_buffer_cached &= ~mask;
918
919 break;
920 }
921}
922
923
924/* Bureaucracy. */
925
733void 926void
734syms_of_xselect () 927syms_of_xselect ()
735{ 928{
@@ -751,10 +944,14 @@ syms_of_xselect ()
751 staticpro (&Qsecondary); 944 staticpro (&Qsecondary);
752 Qclipboard = intern ("clipboard"); 945 Qclipboard = intern ("clipboard");
753 staticpro (&Qclipboard); 946 staticpro (&Qclipboard);
754 Qcut_buffer0 = intern ("cut-buffer0");
755 staticpro (&Qcut_buffer0);
756 947
757 defsubr (&Sx_own_selection); 948 defsubr (&Sx_own_selection);
758 defsubr (&Sx_selection_value); 949 defsubr (&Sx_selection_value);
950
951 cut_buffer_value = Fmake_vector (make_number (NUM_CUT_BUFFERS), Qnil);
952 staticpro (&cut_buffer_value);
953
954 defsubr (&Sx_get_cut_buffer);
955 defsubr (&Sx_set_cut_buffer);
759} 956}
760#endif /* X11 */ 957#endif /* X11 */