Mercurial > hg > xemacs-beta
comparison src/select.c @ 442:abe6d1db359e r21-2-36
Import from CVS: tag r21-2-36
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:35:02 +0200 |
parents | 8de8e3f6228a |
children | 576fb035e263 |
comparison
equal
deleted
inserted
replaced
441:72a7cfa4a488 | 442:abe6d1db359e |
---|---|
24 #include <config.h> | 24 #include <config.h> |
25 #include "lisp.h" | 25 #include "lisp.h" |
26 | 26 |
27 #include "buffer.h" | 27 #include "buffer.h" |
28 #include "device.h" | 28 #include "device.h" |
29 #include "extents.h" | |
29 #include "console.h" | 30 #include "console.h" |
30 #include "objects.h" | 31 #include "objects.h" |
31 | 32 |
32 #include "frame.h" | 33 #include "frame.h" |
33 #include "opaque.h" | 34 #include "opaque.h" |
34 #include "select.h" | 35 #include "select.h" |
35 | 36 |
37 /* X Atoms */ | |
36 Lisp_Object QPRIMARY, QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP, | 38 Lisp_Object QPRIMARY, QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP, |
37 QTEXT, QDELETE, QMULTIPLE, QINCR, QEMACS_TMP, QTARGETS, QATOM, QNULL, | 39 QTEXT, QDELETE, QMULTIPLE, QINCR, QEMACS_TMP, QTARGETS, QATOM, QNULL, |
38 QATOM_PAIR, QCOMPOUND_TEXT; | 40 QATOM_PAIR, QCOMPOUND_TEXT; |
39 | 41 |
42 /* Windows clipboard formats */ | |
43 Lisp_Object QCF_TEXT, QCF_BITMAP, QCF_METAFILEPICT, QCF_SYLK, QCF_DIF, | |
44 QCF_TIFF, QCF_OEMTEXT, QCF_DIB, QCF_DIBV5, QCF_PALETTE, QCF_PENDATA, | |
45 QCF_RIFF, QCF_WAVE, QCF_UNICODETEXT, QCF_ENHMETAFILE, QCF_HDROP, QCF_LOCALE, | |
46 QCF_OWNERDISPLAY, QCF_DSPTEXT, QCF_DSPBITMAP, QCF_DSPMETAFILEPICT, | |
47 QCF_DSPENHMETAFILE; | |
48 | |
49 /* Selection strategy symbols */ | |
50 Lisp_Object Qreplace_all, Qreplace_existing; | |
51 | |
40 /* "Selection owner couldn't convert selection" */ | 52 /* "Selection owner couldn't convert selection" */ |
41 Lisp_Object Qselection_conversion_error; | 53 Lisp_Object Qselection_conversion_error; |
42 | 54 |
43 /* This is an alist whose CARs are selection-types (whose names are the same | 55 /* A couple of Lisp functions */ |
44 as the names of X Atoms) and whose CDRs are the names of Lisp functions to | 56 Lisp_Object Qselect_convert_in, Qselect_convert_out, Qselect_coerce; |
45 call to convert the given Emacs selection value to a string representing | 57 |
46 the given selection type. This is for elisp-level extension of the emacs | 58 /* These are alists whose CARs are selection-types (whose names are the same |
47 selection handling. | 59 as the names of X Atoms or Windows clipboard formats) and whose CDRs are |
60 the names of Lisp functions to call to convert the given Emacs selection | |
61 value to a string representing the given selection type. This is for | |
62 elisp-level extension of the emacs selection handling. | |
48 */ | 63 */ |
49 Lisp_Object Vselection_converter_alist; | 64 Lisp_Object Vselection_converter_out_alist; |
65 Lisp_Object Vselection_converter_in_alist; | |
66 Lisp_Object Vselection_coercion_alist; | |
67 Lisp_Object Vselection_appender_alist; | |
68 Lisp_Object Vselection_buffer_killed_alist; | |
69 Lisp_Object Vselection_coercible_types; | |
50 | 70 |
51 Lisp_Object Vlost_selection_hooks; | 71 Lisp_Object Vlost_selection_hooks; |
52 | 72 |
53 /* This is an association list whose elements are of the form | 73 /* This is an association list whose elements are of the form |
54 ( selection-name selection-value selection-timestamp ) | 74 ( selection-name selection-value selection-timestamp ) |
55 selection-name is a lisp symbol, whose name is the name of an X Atom. | 75 selection-name is a lisp symbol, whose name is the name of an X Atom. |
56 selection-value is the value that emacs owns for that selection. | 76 selection-value is a list of cons pairs that emacs owns for that selection. |
57 It may be any kind of Lisp object. | 77 Each pair consists of (type . value), where type is nil or a |
78 selection data type, and value is any type of Lisp object. | |
58 selection-timestamp is the time at which emacs began owning this selection, | 79 selection-timestamp is the time at which emacs began owning this selection, |
59 as a cons of two 16-bit numbers (making a 32 bit time). | 80 as a cons of two 16-bit numbers (making a 32 bit time). |
60 If there is an entry in this alist, then it can be assumed that emacs owns | 81 If there is an entry in this alist, then it can be assumed that emacs owns |
61 that selection. | 82 that selection. |
62 The only (eq) parts of this list that are visible from elisp are the | 83 The only (eq) parts of this list that are visible from elisp are the |
63 selection-values. | 84 selection-values. |
64 */ | 85 */ |
65 Lisp_Object Vselection_alist; | 86 Lisp_Object Vselection_alist; |
66 | 87 |
88 /* Given a selection-name and desired type, this looks up our local copy of | |
89 the selection value and converts it to the type. */ | |
67 static Lisp_Object | 90 static Lisp_Object |
68 clean_local_selection_data (Lisp_Object obj) | |
69 { | |
70 if (CONSP (obj) && | |
71 INTP (XCAR (obj)) && | |
72 CONSP (XCDR (obj)) && | |
73 INTP (XCAR (XCDR (obj))) && | |
74 NILP (XCDR (XCDR (obj)))) | |
75 obj = Fcons (XCAR (obj), XCDR (obj)); | |
76 | |
77 if (CONSP (obj) && | |
78 INTP (XCAR (obj)) && | |
79 INTP (XCDR (obj))) | |
80 { | |
81 if (XINT (XCAR (obj)) == 0) | |
82 return XCDR (obj); | |
83 if (XINT (XCAR (obj)) == -1) | |
84 return make_int (- XINT (XCDR (obj))); | |
85 } | |
86 if (VECTORP (obj)) | |
87 { | |
88 int i; | |
89 int len = XVECTOR_LENGTH (obj); | |
90 Lisp_Object copy; | |
91 if (len == 1) | |
92 return clean_local_selection_data (XVECTOR_DATA (obj) [0]); | |
93 copy = make_vector (len, Qnil); | |
94 for (i = 0; i < len; i++) | |
95 XVECTOR_DATA (copy) [i] = | |
96 clean_local_selection_data (XVECTOR_DATA (obj) [i]); | |
97 return copy; | |
98 } | |
99 return obj; | |
100 } | |
101 | |
102 /* Given a selection-name and desired type, this looks up our local copy of | |
103 the selection value and converts it to the type. It returns nil or a | |
104 string. This calls random elisp code, and may signal or gc. | |
105 */ | |
106 Lisp_Object | |
107 get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type) | 91 get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type) |
108 { | 92 { |
109 /* This function can GC */ | |
110 Lisp_Object handler_fn, value, check; | |
111 Lisp_Object local_value = assq_no_quit (selection_symbol, Vselection_alist); | 93 Lisp_Object local_value = assq_no_quit (selection_symbol, Vselection_alist); |
112 | 94 |
113 if (NILP (local_value)) return Qnil; | 95 if (!NILP (local_value)) |
114 | 96 { |
115 /* TIMESTAMP and MULTIPLE are special cases 'cause that's easiest. */ | 97 Lisp_Object value_list = XCAR (XCDR (local_value)); |
116 if (EQ (target_type, QTIMESTAMP)) | 98 Lisp_Object value; |
117 { | 99 |
118 handler_fn = Qnil; | 100 /* First try to find an entry of the appropriate type */ |
119 value = XCAR (XCDR (XCDR (local_value))); | 101 value = assq_no_quit (target_type, value_list); |
120 } | 102 |
121 | 103 if (!NILP (value)) |
122 #if 0 /* #### MULTIPLE doesn't work yet and probably never will */ | 104 return XCDR (value); |
123 else if (CONSP (target_type) && | 105 } |
124 XCAR (target_type) == QMULTIPLE) | 106 |
125 { | 107 return Qnil; |
126 Lisp_Object pairs = XCDR (target_type); | 108 } |
127 int len = XVECTOR_LENGTH (pairs); | 109 |
128 int i; | 110 /* #### Should perhaps handle 'MULTIPLE. The code below is now completely |
129 /* If the target is MULTIPLE, then target_type looks like | 111 broken due to a re-organization of get_local_selection, but I've left |
130 (MULTIPLE . [[SELECTION1 TARGET1] [SELECTION2 TARGET2] ... ]) | 112 it here should anyone show an interest - ajh */ |
131 We modify the second element of each pair in the vector and | 113 #if 0 |
132 return it as [[SELECTION1 <value1>] [SELECTION2 <value2>] ... ] | 114 else if (CONSP (target_type) && |
133 */ | 115 XCAR (target_type) == QMULTIPLE) |
134 for (i = 0; i < len; i++) | |
135 { | 116 { |
136 Lisp_Object pair = XVECTOR_DATA (pairs) [i]; | 117 Lisp_Object pairs = XCDR (target_type); |
137 XVECTOR_DATA (pair) [1] = | 118 int len = XVECTOR_LENGTH (pairs); |
138 x_get_local_selection (XVECTOR_DATA (pair) [0], | 119 int i; |
139 XVECTOR_DATA (pair) [1]); | 120 /* If the target is MULTIPLE, then target_type looks like |
121 (MULTIPLE . [[SELECTION1 TARGET1] [SELECTION2 TARGET2] ... ]) | |
122 We modify the second element of each pair in the vector and | |
123 return it as [[SELECTION1 <value1>] [SELECTION2 <value2>] ... ] | |
124 */ | |
125 for (i = 0; i < len; i++) | |
126 { | |
127 Lisp_Object pair = XVECTOR_DATA (pairs) [i]; | |
128 XVECTOR_DATA (pair) [1] = | |
129 x_get_local_selection (XVECTOR_DATA (pair) [0], | |
130 XVECTOR_DATA (pair) [1]); | |
131 } | |
132 return pairs; | |
140 } | 133 } |
141 return pairs; | |
142 } | |
143 #endif | 134 #endif |
144 else | 135 |
145 { | 136 DEFUN ("own-selection-internal", Fown_selection_internal, 2, 5, 0, /* |
146 CHECK_SYMBOL (target_type); | 137 Assert a selection of the given NAME with the given VALUE, and |
147 handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); | 138 optional window-system DATA-TYPE. HOW-TO-ADD specifies how the |
148 if (NILP (handler_fn)) return Qnil; | 139 selection will be combined with any existing selection(s) - see |
149 value = call3 (handler_fn, | 140 `own-selection' for more information. |
150 selection_symbol, target_type, | 141 NAME is a symbol, typically PRIMARY, SECONDARY, or CLIPBOARD. |
151 XCAR (XCDR (local_value))); | |
152 } | |
153 | |
154 /* This lets the selection function to return (TYPE . VALUE). For example, | |
155 when the selected type is LINE_NUMBER, the returned type is SPAN, not | |
156 INTEGER. | |
157 */ | |
158 check = value; | |
159 if (CONSP (value) && SYMBOLP (XCAR (value))) | |
160 check = XCDR (value); | |
161 | |
162 /* Strings, vectors, and symbols are converted to selection data format in | |
163 the obvious way. Integers are converted to 16 bit quantities if they're | |
164 small enough, otherwise 32 bits are used. | |
165 */ | |
166 if (STRINGP (check) || | |
167 VECTORP (check) || | |
168 SYMBOLP (check) || | |
169 INTP (check) || | |
170 CHARP (check) || | |
171 NILP (value)) | |
172 return value; | |
173 | |
174 /* (N . M) or (N M) get turned into a 32 bit quantity. So if you want to | |
175 always return a small quantity as 32 bits, your converter routine needs | |
176 to return a cons. | |
177 */ | |
178 else if (CONSP (check) && | |
179 INTP (XCAR (check)) && | |
180 (INTP (XCDR (check)) || | |
181 (CONSP (XCDR (check)) && | |
182 INTP (XCAR (XCDR (check))) && | |
183 NILP (XCDR (XCDR (check)))))) | |
184 return value; | |
185 /* Otherwise the lisp converter function returned something unrecognized. | |
186 */ | |
187 else | |
188 signal_error (Qerror, | |
189 list3 (build_string | |
190 ("unrecognized selection-conversion type"), | |
191 handler_fn, | |
192 value)); | |
193 | |
194 return Qnil; /* suppress compiler warning */ | |
195 } | |
196 | |
197 DEFUN ("own-selection-internal", Fown_selection_internal, 2, 3, 0, /* | |
198 Assert a selection of the given TYPE with the given VALUE. | |
199 TYPE is a symbol, typically PRIMARY, SECONDARY, or CLIPBOARD. | |
200 VALUE is typically a string, or a cons of two markers, but may be | 142 VALUE is typically a string, or a cons of two markers, but may be |
201 anything that the functions on selection-converter-alist know about. | 143 anything that the functions on selection-converter-out-alist know about. |
202 */ | 144 */ |
203 (selection_name, selection_value, device)) | 145 (selection_name, selection_value, how_to_add, data_type, device)) |
204 { | 146 { |
205 Lisp_Object selection_time, selection_data, prev_value; | 147 Lisp_Object selection_time, selection_data, prev_value = Qnil, |
148 value_list = Qnil; | |
149 Lisp_Object prev_real_value = Qnil; | |
206 struct gcpro gcpro1; | 150 struct gcpro gcpro1; |
207 | 151 |
208 CHECK_SYMBOL (selection_name); | 152 CHECK_SYMBOL (selection_name); |
209 if (NILP (selection_value)) error ("selection-value may not be nil."); | 153 if (NILP (selection_value)) error ("selection-value may not be nil."); |
210 | 154 |
211 if (NILP (device)) | 155 if (NILP (device)) |
212 device = Fselected_device (Qnil); | 156 device = Fselected_device (Qnil); |
213 | 157 |
214 /* Now update the local cache */ | 158 if (!EQ (how_to_add, Qappend) && !EQ (how_to_add, Qt) |
215 selection_data = list3 (selection_name, | 159 && !EQ (how_to_add, Qreplace_existing) |
216 selection_value, | 160 && !EQ (how_to_add, Qreplace_all) && !NILP (how_to_add)) |
217 Qnil); | 161 error ("how-to-add must be nil, append, replace_all, " |
218 GCPRO1 (selection_data); | 162 "replace_existing or t."); |
219 | 163 |
220 prev_value = assq_no_quit (selection_name, Vselection_alist); | 164 #ifdef MULE |
221 Vselection_alist = Fcons (selection_data, Vselection_alist); | 165 if (NILP (data_type)) |
222 | 166 data_type = QCOMPOUND_TEXT; |
223 /* If we already owned the selection, remove the old selection data. | 167 #else |
224 Perhaps we should destructively modify it instead. | 168 if (NILP (data_type)) |
225 Don't use Fdelq() as that may QUIT;. | 169 data_type = QSTRING; |
226 */ | 170 #endif |
227 if (!NILP (prev_value)) | 171 |
228 { | 172 /* Examine the how-to-add argument */ |
229 Lisp_Object rest; /* we know it's not the CAR, so it's easy. */ | 173 if (EQ (how_to_add, Qreplace_all) || NILP (how_to_add)) |
230 for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest)) | 174 { |
231 if (EQ (prev_value, Fcar (XCDR (rest)))) | 175 Lisp_Object local_selection_data = assq_no_quit (selection_name, |
176 Vselection_alist); | |
177 | |
178 if (!NILP (local_selection_data)) | |
179 { | |
180 /* Don't use Fdelq() as that may QUIT;. */ | |
181 if (EQ (local_selection_data, Fcar (Vselection_alist))) | |
182 Vselection_alist = Fcdr (Vselection_alist); | |
183 else | |
184 { | |
185 Lisp_Object rest; | |
186 for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest)) | |
187 if (EQ (local_selection_data, Fcar (XCDR (rest)))) | |
188 { | |
189 XCDR (rest) = Fcdr (XCDR (rest)); | |
190 break; | |
191 } | |
192 } | |
193 } | |
194 } | |
195 else | |
196 { | |
197 /* Look for a previous value */ | |
198 prev_value = assq_no_quit (selection_name, Vselection_alist); | |
199 | |
200 if (!NILP (prev_value)) | |
201 value_list = XCAR (XCDR (prev_value)); | |
202 | |
203 if (!NILP (value_list)) | |
204 prev_real_value = assq_no_quit (data_type, value_list); | |
205 } | |
206 | |
207 /* Append values if necessary */ | |
208 if (!NILP (value_list) && (EQ (how_to_add, Qappend) || EQ (how_to_add, Qt))) | |
209 { | |
210 /* Did we have anything of this type previously? */ | |
211 if (!NILP (prev_real_value)) | |
212 { | |
213 if ((NILP (data_type) && STRINGP (selection_value) | |
214 && STRINGP (XCDR (prev_real_value))) | |
215 || !NILP (data_type)) | |
216 { | |
217 Lisp_Object function = assq_no_quit (data_type, | |
218 Vselection_appender_alist); | |
219 | |
220 if (NILP (function)) | |
221 error ("cannot append selections of supplied types."); | |
222 | |
223 function = XCDR (function); | |
224 | |
225 selection_value = call4 (function, | |
226 selection_name, | |
227 data_type, | |
228 XCDR (prev_real_value), | |
229 selection_value); | |
230 | |
231 if (NILP (selection_value)) | |
232 error ("cannot append selections of supplied types."); | |
233 } | |
234 else | |
235 error ("cannot append selections of supplied types."); | |
236 } | |
237 | |
238 selection_data = Fcons (data_type, selection_value); | |
239 value_list = Fcons (selection_data, value_list); | |
240 } | |
241 | |
242 if (!NILP (prev_real_value)) | |
243 { | |
244 Lisp_Object rest; /* We know it isn't the CAR, so it's easy. */ | |
245 | |
246 /* Delete the old type entry from the list */ | |
247 for (rest = value_list; !NILP (rest); rest = Fcdr (rest)) | |
248 if (EQ (prev_real_value, Fcar (XCDR (rest)))) | |
232 { | 249 { |
233 XCDR (rest) = Fcdr (XCDR (rest)); | 250 XCDR (rest) = Fcdr (XCDR (rest)); |
234 break; | 251 break; |
235 } | 252 } |
236 } | 253 } |
237 | 254 else |
238 /* have to do device specific stuff last so that methods can access the | 255 { |
256 value_list = Fcons (Fcons (data_type, selection_value), | |
257 value_list); | |
258 } | |
259 | |
260 /* Complete the local cache update; note that we destructively | |
261 modify the current list entry if there is one */ | |
262 if (NILP (prev_value)) | |
263 { | |
264 selection_data = list3 (selection_name, value_list, Qnil); | |
265 Vselection_alist = Fcons (selection_data, Vselection_alist); | |
266 } | |
267 else | |
268 { | |
269 selection_data = prev_value; | |
270 Fsetcar (XCDR (selection_data), value_list); | |
271 } | |
272 | |
273 GCPRO1 (selection_data); | |
274 | |
275 /* have to do device specific stuff last so that methods can access the | |
239 selection_alist */ | 276 selection_alist */ |
240 if (HAS_DEVMETH_P (XDEVICE (device), own_selection)) | 277 if (HAS_DEVMETH_P (XDEVICE (device), own_selection)) |
241 selection_time = DEVMETH (XDEVICE (device), own_selection, | 278 selection_time = DEVMETH (XDEVICE (device), own_selection, |
242 (selection_name, selection_value)); | 279 (selection_name, selection_value, |
280 how_to_add, data_type)); | |
243 else | 281 else |
244 selection_time = Qnil; | 282 selection_time = Qnil; |
245 | 283 |
246 Fsetcar (XCDR (XCDR (selection_data)), selection_time); | 284 Fsetcar (XCDR (XCDR (selection_data)), selection_time); |
247 | 285 |
248 UNGCPRO; | 286 UNGCPRO; |
249 | 287 |
250 return selection_value; | 288 return selection_value; |
289 } | |
290 | |
291 DEFUN ("register-selection-data-type", Fregister_selection_data_type, 1,2,0, /* | |
292 Register a new selection data type DATA-TYPE, optionally on the specified | |
293 DEVICE. Returns the device-specific data type identifier, or nil if the | |
294 device does not support this feature or the registration fails. */ | |
295 (data_type, device)) | |
296 { | |
297 /* Check arguments */ | |
298 CHECK_STRING (data_type); | |
299 | |
300 if (NILP (device)) | |
301 device = Fselected_device (Qnil); | |
302 | |
303 if (HAS_DEVMETH_P (XDEVICE (device), register_selection_data_type)) | |
304 return DEVMETH (XDEVICE (device), register_selection_data_type, | |
305 (data_type)); | |
306 else | |
307 return Qnil; | |
308 } | |
309 | |
310 DEFUN ("selection-data-type-name", Fselection_data_type_name, 1, 2, 0, /* | |
311 Retrieve the name of the specified selection data type DATA-TYPE, optionally | |
312 on the specified DEVICE. Returns either a string or a symbol on success, and | |
313 nil if the device does not support this feature or the type is not known. */ | |
314 (data_type, device)) | |
315 { | |
316 if (NILP (device)) | |
317 device = Fselected_device (Qnil); | |
318 | |
319 if (HAS_DEVMETH_P (XDEVICE (device), selection_data_type_name)) | |
320 return DEVMETH (XDEVICE (device), selection_data_type_name, (data_type)); | |
321 else | |
322 return Qnil; | |
323 } | |
324 | |
325 DEFUN ("available-selection-types", Favailable_selection_types, 1, 2, 0, /* | |
326 Retrieve a list of currently available types of selection associated with | |
327 the given SELECTION-NAME, optionally on the specified DEVICE. This list | |
328 does not take into account any possible conversions that might take place, | |
329 so it should be taken as a minimal estimate of what is available. | |
330 */ | |
331 (selection_name, device)) | |
332 { | |
333 Lisp_Object types = Qnil, rest; | |
334 struct gcpro gcpro1; | |
335 | |
336 CHECK_SYMBOL (selection_name); | |
337 | |
338 if (NILP (device)) | |
339 device = Fselected_device (Qnil); | |
340 | |
341 GCPRO1 (types); | |
342 | |
343 /* First check the device */ | |
344 if (HAS_DEVMETH_P (XDEVICE (device), available_selection_types)) | |
345 types = DEVMETH (XDEVICE (device), available_selection_types, | |
346 (selection_name)); | |
347 | |
348 /* Now look in the list */ | |
349 rest = assq_no_quit (selection_name, Vselection_alist); | |
350 | |
351 if (NILP (rest)) | |
352 { | |
353 UNGCPRO; | |
354 | |
355 return types; | |
356 } | |
357 | |
358 /* Examine the types and cons them onto the front of the list */ | |
359 for (rest = XCAR (XCDR (rest)); !NILP (rest); rest = XCDR (rest)) | |
360 { | |
361 Lisp_Object value = XCDR (XCAR (rest)); | |
362 Lisp_Object type = XCAR (XCAR (rest)); | |
363 | |
364 types = Fcons (type, types); | |
365 | |
366 if ((STRINGP (value) || EXTENTP (value)) | |
367 && (NILP (type) || EQ (type, QSTRING) | |
368 || EQ (type, QTEXT) || EQ (type, QCOMPOUND_TEXT))) | |
369 types = Fcons (QTEXT, Fcons (QCOMPOUND_TEXT, Fcons (QSTRING, types))); | |
370 else if (INTP (value) && NILP (type)) | |
371 types = Fcons (QINTEGER, types); | |
372 else if (SYMBOLP (value) && NILP (type)) | |
373 types = Fcons (QATOM, types); | |
374 } | |
375 | |
376 UNGCPRO; | |
377 | |
378 return types; | |
251 } | 379 } |
252 | 380 |
253 /* remove a selection from our local copy | 381 /* remove a selection from our local copy |
254 */ | 382 */ |
255 void | 383 void |
256 handle_selection_clear (Lisp_Object selection_symbol) | 384 handle_selection_clear (Lisp_Object selection_symbol) |
257 { | 385 { |
258 Lisp_Object local_selection_data = assq_no_quit (selection_symbol, Vselection_alist); | 386 Lisp_Object local_selection_data = assq_no_quit (selection_symbol, |
387 Vselection_alist); | |
259 | 388 |
260 /* Well, we already believe that we don't own it, so that's just fine. */ | 389 /* Well, we already believe that we don't own it, so that's just fine. */ |
261 if (NILP (local_selection_data)) return; | 390 if (NILP (local_selection_data)) return; |
262 | 391 |
263 /* Otherwise, we're really honest and truly being told to drop it. | 392 /* Otherwise, we're really honest and truly being told to drop it. |
303 if (NILP (device)) | 432 if (NILP (device)) |
304 device = Fselected_device (Qnil); | 433 device = Fselected_device (Qnil); |
305 | 434 |
306 MAYBE_DEVMETH (XDEVICE (device), disown_selection, | 435 MAYBE_DEVMETH (XDEVICE (device), disown_selection, |
307 (selection_name, selection_time)); | 436 (selection_name, selection_time)); |
308 | 437 |
309 handle_selection_clear (selection_name); | 438 handle_selection_clear (selection_name); |
310 | 439 |
311 return Qt; | 440 return Qt; |
312 } | 441 } |
313 | 442 |
324 else if (EQ (selection, Qt)) selection = QSECONDARY; | 453 else if (EQ (selection, Qt)) selection = QSECONDARY; |
325 | 454 |
326 return NILP (Fassq (selection, Vselection_alist)) ? Qnil : Qt; | 455 return NILP (Fassq (selection, Vselection_alist)) ? Qnil : Qt; |
327 } | 456 } |
328 | 457 |
329 DEFUN ("selection-exists-p", Fselection_exists_p, 0, 2, 0, /* | 458 DEFUN ("selection-exists-p", Fselection_exists_p, 0, 3, 0, /* |
330 Whether there is an owner for the given Selection. | 459 Whether there is an owner for the given Selection. |
331 The arg should be the name of the selection in question, typically one of | 460 The arg should be the name of the selection in question, typically one of |
332 the symbols PRIMARY, SECONDARY, or CLIPBOARD. (For convenience, the symbol | 461 the symbols PRIMARY, SECONDARY, or CLIPBOARD. (For convenience, the symbol |
333 nil is the same as PRIMARY, and t is the same as SECONDARY.) | 462 nil is the same as PRIMARY, and t is the same as SECONDARY.) |
463 Optionally the DEVICE and the window-system DATA-TYPE may be specified. | |
334 */ | 464 */ |
335 (selection, device)) | 465 (selection, data_type, device)) |
336 { | 466 { |
337 CHECK_SYMBOL (selection); | 467 CHECK_SYMBOL (selection); |
338 if (!NILP (Fselection_owner_p (selection))) | 468 if (NILP (data_type) |
469 && !NILP (Fselection_owner_p (selection))) | |
339 return Qt; | 470 return Qt; |
340 | 471 |
341 if (NILP (device)) | 472 if (NILP (device)) |
342 device = Fselected_device (Qnil); | 473 device = Fselected_device (Qnil); |
343 | 474 |
344 return HAS_DEVMETH_P (XDEVICE (device), selection_exists_p) ? | 475 return HAS_DEVMETH_P (XDEVICE (device), selection_exists_p) ? |
345 DEVMETH (XDEVICE (device), selection_exists_p, (selection)) | 476 DEVMETH (XDEVICE (device), selection_exists_p, (selection, data_type)) |
346 : Qnil; | 477 : Qnil; |
478 } | |
479 | |
480 /* Get the timestamp of the given selection */ | |
481 DEFUN ("get-selection-timestamp", Fget_selection_timestamp, 1, 1, 0, /* | |
482 Return the timestamp associated with the specified SELECTION, if it exists. | |
483 Note that the timestamp is a device-specific object, and may not actually be | |
484 visible from Lisp. | |
485 */ | |
486 (selection)) | |
487 { | |
488 Lisp_Object local_value = assq_no_quit (selection, Vselection_alist); | |
489 | |
490 if (!NILP (local_value)) | |
491 return XCAR (XCDR (XCDR (local_value))); | |
492 | |
493 return Qnil; | |
347 } | 494 } |
348 | 495 |
349 /* Request the selection value from the owner. If we are the owner, | 496 /* Request the selection value from the owner. If we are the owner, |
350 simply return our selection value. If we are not the owner, this | 497 simply return our selection value. If we are not the owner, this |
351 will block until all of the data has arrived. | 498 will block until all of the data has arrived. |
360 (selection_symbol, target_type, device)) | 507 (selection_symbol, target_type, device)) |
361 { | 508 { |
362 /* This function can GC */ | 509 /* This function can GC */ |
363 Lisp_Object val = Qnil; | 510 Lisp_Object val = Qnil; |
364 struct gcpro gcpro1, gcpro2; | 511 struct gcpro gcpro1, gcpro2; |
365 GCPRO2 (target_type, val); /* we store newly consed data into these */ | 512 GCPRO2 (target_type, val); |
366 CHECK_SYMBOL (selection_symbol); | 513 CHECK_SYMBOL (selection_symbol); |
367 | 514 |
368 if (NILP (device)) | 515 if (NILP (device)) |
369 device = Fselected_device (Qnil); | 516 device = Fselected_device (Qnil); |
517 | |
518 #ifdef MULE | |
519 if (NILP (target_type)) | |
520 target_type = QCOMPOUND_TEXT; | |
521 #else | |
522 if (NILP (target_type)) | |
523 target_type = QSTRING; | |
524 #endif | |
370 | 525 |
371 #if 0 /* #### MULTIPLE doesn't work yet and probably never will */ | 526 #if 0 /* #### MULTIPLE doesn't work yet and probably never will */ |
372 if (CONSP (target_type) && | 527 if (CONSP (target_type) && |
373 XCAR (target_type) == QMULTIPLE) | 528 XCAR (target_type) == QMULTIPLE) |
374 { | 529 { |
375 CHECK_VECTOR (XCDR (target_type)); | 530 CHECK_VECTOR (XCDR (target_type)); |
376 /* So we don't destructively modify this... */ | 531 /* So we don't destructively modify this... */ |
377 target_type = copy_multiple_data (target_type); | 532 target_type = copy_multiple_data (target_type); |
378 } | 533 } |
379 else | |
380 #endif | 534 #endif |
381 CHECK_SYMBOL (target_type); | 535 |
536 /* Used to check that target_type was a symbol. This is no longer | |
537 necessarily the case, because the type might be registered with | |
538 the device (in which case target_type would be a device-specific | |
539 identifier - probably an integer) - ajh */ | |
382 | 540 |
383 val = get_local_selection (selection_symbol, target_type); | 541 val = get_local_selection (selection_symbol, target_type); |
384 | 542 |
385 if (NILP (val) && (HAS_DEVMETH_P (XDEVICE (device), get_foreign_selection))) | 543 if (!NILP (val)) |
386 { | 544 { |
545 /* If we get something from the local cache, we may need to convert | |
546 it slightly - to do this, we call select-coerce */ | |
547 val = call3 (Qselect_coerce, selection_symbol, target_type, val); | |
548 } | |
549 else if (HAS_DEVMETH_P (XDEVICE (device), get_foreign_selection)) | |
550 { | |
551 /* Nothing in the local cache; try the window system */ | |
387 val = DEVMETH (XDEVICE (device), get_foreign_selection, | 552 val = DEVMETH (XDEVICE (device), get_foreign_selection, |
388 (selection_symbol, target_type)); | 553 (selection_symbol, target_type)); |
389 } | 554 } |
390 else | 555 |
391 { | 556 if (NILP (val)) |
392 if (CONSP (val) && SYMBOLP (XCAR (val))) | 557 { |
558 /* Still nothing. Try coercion. */ | |
559 | |
560 /* Try looking in selection-coercible-types to see if any of | |
561 them are present for this selection. We try them *in order*; | |
562 the first for which a conversion succeeds gets returned. */ | |
563 EXTERNAL_LIST_LOOP_2 (element, Vselection_coercible_types) | |
393 { | 564 { |
394 val = XCDR (val); | 565 val = get_local_selection (selection_symbol, element); |
395 if (CONSP (val) && NILP (XCDR (val))) | 566 |
396 val = XCAR (val); | 567 if (NILP (val)) |
568 continue; | |
569 | |
570 val = call3 (Qselect_coerce, selection_symbol, target_type, val); | |
571 | |
572 if (!NILP (val)) | |
573 break; | |
397 } | 574 } |
398 val = clean_local_selection_data (val); | 575 } |
399 } | 576 |
577 /* Used to call clean_local_selection here... but that really belonged | |
578 in Lisp (so the equivalent is now built-in to the INTEGER conversion | |
579 function select-convert-from-integer) - ajh */ | |
580 | |
400 UNGCPRO; | 581 UNGCPRO; |
401 return val; | 582 return val; |
402 } | 583 } |
403 | 584 |
585 /* These are convenient interfaces to the lisp code in select.el; | |
586 this way we can rename them easily rather than having to hunt everywhere. | |
587 Also, this gives us access to get_local_selection so that convert_out | |
588 can retrieve the internal selection value automatically if passed a | |
589 value of Qnil. */ | |
590 Lisp_Object | |
591 select_convert_in (Lisp_Object selection, | |
592 Lisp_Object type, | |
593 Lisp_Object value) | |
594 { | |
595 return call3 (Qselect_convert_in, selection, type, value); | |
596 } | |
597 | |
598 Lisp_Object | |
599 select_coerce (Lisp_Object selection, | |
600 Lisp_Object type, | |
601 Lisp_Object value) | |
602 { | |
603 return call3 (Qselect_coerce, selection, type, value); | |
604 } | |
605 | |
606 Lisp_Object | |
607 select_convert_out (Lisp_Object selection, | |
608 Lisp_Object type, | |
609 Lisp_Object value) | |
610 { | |
611 if (NILP (value)) | |
612 value = get_local_selection (selection, type); | |
613 | |
614 if (NILP (value)) | |
615 { | |
616 /* Try looking in selection-coercible-types to see if any of | |
617 them are present for this selection. We try them *in order*; | |
618 the first for which a conversion succeeds gets returned. */ | |
619 EXTERNAL_LIST_LOOP_2 (element, Vselection_coercible_types) | |
620 { | |
621 Lisp_Object ret; | |
622 | |
623 value = get_local_selection (selection, element); | |
624 | |
625 if (NILP (value)) | |
626 continue; | |
627 | |
628 ret = call3 (Qselect_convert_out, selection, type, value); | |
629 | |
630 if (!NILP (ret)) | |
631 return ret; | |
632 } | |
633 | |
634 return Qnil; | |
635 } | |
636 | |
637 return call3 (Qselect_convert_out, selection, type, value); | |
638 } | |
639 | |
640 | |
641 /* Gets called from kill-buffer; this lets us dispose of buffer-dependent | |
642 selections (or alternatively make them independent of the buffer) when | |
643 it gets vaped. */ | |
644 void | |
645 select_notify_buffer_kill (Lisp_Object buffer) | |
646 { | |
647 Lisp_Object rest; | |
648 struct gcpro gcpro1, gcpro2, gcpro3; | |
649 | |
650 /* For each element of Vselection_alist */ | |
651 for (rest = Vselection_alist; | |
652 !NILP (rest);) | |
653 { | |
654 Lisp_Object selection, values, prev = Qnil; | |
655 | |
656 selection = XCAR (rest); | |
657 | |
658 for (values = XCAR (XCDR (selection)); | |
659 !NILP (values); | |
660 values = XCDR (values)) | |
661 { | |
662 Lisp_Object value, handler_fn; | |
663 | |
664 /* Extract the (type . value) pair. */ | |
665 value = XCAR (values); | |
666 | |
667 /* Find the handler function (if any). */ | |
668 handler_fn = Fcdr (Fassq (XCAR (value), | |
669 Vselection_buffer_killed_alist)); | |
670 | |
671 if (!NILP (handler_fn)) | |
672 { | |
673 Lisp_Object newval; | |
674 | |
675 /* Protect ourselves, just in case some tomfool calls | |
676 own-selection from with the buffer-killed handler, then | |
677 causes a GC. Just as a note, *don't do this*. */ | |
678 GCPRO3 (rest, values, value); | |
679 | |
680 newval = call4 (handler_fn, XCAR (selection), XCAR (value), | |
681 XCDR (value), buffer); | |
682 | |
683 UNGCPRO; | |
684 | |
685 /* Set or delete the value (by destructively modifying | |
686 the list). */ | |
687 if (!NILP (newval)) | |
688 { | |
689 Fsetcdr (value, newval); | |
690 | |
691 prev = values; | |
692 } | |
693 else | |
694 { | |
695 if (NILP (prev)) | |
696 Fsetcar (XCDR (selection), XCDR (values)); | |
697 else | |
698 Fsetcdr (prev, XCDR (values)); | |
699 } | |
700 } | |
701 else | |
702 prev = values; | |
703 } | |
704 | |
705 /* If we have no values for this selection */ | |
706 if (NILP (XCAR (XCDR (selection)))) | |
707 { | |
708 /* Move on to the next element *first* */ | |
709 rest = XCDR (rest); | |
710 | |
711 /* Protect it and disown this selection */ | |
712 GCPRO1 (rest); | |
713 | |
714 Fdisown_selection_internal (XCAR (selection), Qnil, Qnil); | |
715 | |
716 UNGCPRO; | |
717 } | |
718 else | |
719 rest = XCDR (rest); | |
720 } | |
721 } | |
722 | |
723 | |
404 void | 724 void |
405 syms_of_select (void) | 725 syms_of_select (void) |
406 { | 726 { |
407 DEFSUBR (Fown_selection_internal); | 727 DEFSUBR (Fown_selection_internal); |
408 DEFSUBR (Fget_selection_internal); | 728 DEFSUBR (Fget_selection_internal); |
729 DEFSUBR (Fget_selection_timestamp); | |
409 DEFSUBR (Fselection_exists_p); | 730 DEFSUBR (Fselection_exists_p); |
410 DEFSUBR (Fdisown_selection_internal); | 731 DEFSUBR (Fdisown_selection_internal); |
411 DEFSUBR (Fselection_owner_p); | 732 DEFSUBR (Fselection_owner_p); |
412 | 733 DEFSUBR (Favailable_selection_types); |
734 DEFSUBR (Fregister_selection_data_type); | |
735 DEFSUBR (Fselection_data_type_name); | |
736 | |
737 /* Lisp Functions */ | |
738 defsymbol (&Qselect_convert_in, "select-convert-in"); | |
739 defsymbol (&Qselect_convert_out, "select-convert-out"); | |
740 defsymbol (&Qselect_coerce, "select-coerce"); | |
741 | |
742 /* X Atoms */ | |
413 defsymbol (&QPRIMARY, "PRIMARY"); | 743 defsymbol (&QPRIMARY, "PRIMARY"); |
414 defsymbol (&QSECONDARY, "SECONDARY"); | 744 defsymbol (&QSECONDARY, "SECONDARY"); |
415 defsymbol (&QSTRING, "STRING"); | 745 defsymbol (&QSTRING, "STRING"); |
416 defsymbol (&QINTEGER, "INTEGER"); | 746 defsymbol (&QINTEGER, "INTEGER"); |
417 defsymbol (&QCLIPBOARD, "CLIPBOARD"); | 747 defsymbol (&QCLIPBOARD, "CLIPBOARD"); |
425 defsymbol (&QATOM, "ATOM"); | 755 defsymbol (&QATOM, "ATOM"); |
426 defsymbol (&QATOM_PAIR, "ATOM_PAIR"); | 756 defsymbol (&QATOM_PAIR, "ATOM_PAIR"); |
427 defsymbol (&QCOMPOUND_TEXT, "COMPOUND_TEXT"); | 757 defsymbol (&QCOMPOUND_TEXT, "COMPOUND_TEXT"); |
428 defsymbol (&QNULL, "NULL"); | 758 defsymbol (&QNULL, "NULL"); |
429 | 759 |
430 deferror (&Qselection_conversion_error, | 760 /* Windows formats - these all start with CF_ */ |
431 "selection-conversion-error", | 761 defsymbol (&QCF_TEXT, "CF_TEXT"); |
432 "selection-conversion error", Qio_error); | 762 defsymbol (&QCF_BITMAP, "CF_BITMAP"); |
763 defsymbol (&QCF_METAFILEPICT, "CF_METAFILEPICT"); | |
764 defsymbol (&QCF_SYLK, "CF_SYLK"); | |
765 defsymbol (&QCF_DIF, "CF_DIF"); | |
766 defsymbol (&QCF_TIFF, "CF_TIFF"); | |
767 defsymbol (&QCF_OEMTEXT, "CF_OEMTEXT"); | |
768 defsymbol (&QCF_DIB, "CF_DIB"); | |
769 defsymbol (&QCF_DIBV5, "CF_DIBV5"); | |
770 defsymbol (&QCF_PALETTE, "CF_PALETTE"); | |
771 defsymbol (&QCF_PENDATA, "CF_PENDATA"); | |
772 defsymbol (&QCF_RIFF, "CF_RIFF"); | |
773 defsymbol (&QCF_WAVE, "CF_WAVE"); | |
774 defsymbol (&QCF_UNICODETEXT, "CF_UNICODETEXT"); | |
775 defsymbol (&QCF_ENHMETAFILE, "CF_ENHMETAFILE"); | |
776 defsymbol (&QCF_HDROP, "CF_HDROP"); | |
777 defsymbol (&QCF_LOCALE, "CF_LOCALE"); | |
778 defsymbol (&QCF_OWNERDISPLAY, "CF_OWNERDISPLAY"); | |
779 defsymbol (&QCF_DSPTEXT, "CF_DSPTEXT"); | |
780 defsymbol (&QCF_DSPBITMAP, "CF_DSPBITMAP"); | |
781 defsymbol (&QCF_DSPMETAFILEPICT, "CF_DSPMETAFILEPICT"); | |
782 defsymbol (&QCF_DSPENHMETAFILE, "CF_DSPENHMETAFILE"); | |
783 | |
784 /* Selection strategies */ | |
785 defsymbol (&Qreplace_all, "replace-all"); | |
786 defsymbol (&Qreplace_existing, "replace-existing"); | |
787 | |
788 DEFERROR_STANDARD (Qselection_conversion_error, Qio_error); | |
433 } | 789 } |
434 | 790 |
435 void | 791 void |
436 vars_of_select (void) | 792 vars_of_select (void) |
437 { | 793 { |
438 Vselection_alist = Qnil; | 794 Vselection_alist = Qnil; |
439 staticpro (&Vselection_alist); | 795 staticpro (&Vselection_alist); |
440 | 796 |
441 DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist /* | 797 DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_out_alist /* |
798 An alist associating selection-types (such as STRING and TIMESTAMP) with | |
799 functions. This is an alias for `selection-converter-out-alist', and should | |
800 be considered obsolete. Use the new name instead. */ ); | |
801 | |
802 DEFVAR_LISP ("selection-converter-out-alist", | |
803 &Vselection_converter_out_alist /* | |
442 An alist associating selection-types (such as STRING and TIMESTAMP) with | 804 An alist associating selection-types (such as STRING and TIMESTAMP) with |
443 functions. These functions will be called with three args: the name | 805 functions. These functions will be called with three args: the name |
444 of the selection (typically PRIMARY, SECONDARY, or CLIPBOARD); a | 806 of the selection (typically PRIMARY, SECONDARY, or CLIPBOARD); a |
445 desired type to which the selection should be converted; and the local | 807 desired type to which the selection should be converted; and the local |
446 selection value (whatever had been passed to `own-selection'). For | 808 selection value (whatever had been passed to `own-selection'). |
447 historical reasons these functions should return the value to send to | 809 |
448 an X server, which should be one of: | 810 The return type of these functions depends upon the device in question; |
811 for mswindows, a string should be returned containing data in the requested | |
812 format, or nil to indicate that the conversion could not be done. Additionally, | |
813 it is permissible to return a cons of the form (DATA-TYPE . STRING) suggesting | |
814 a new data type to use instead. | |
815 | |
816 For X, the return value should be one of: | |
449 | 817 |
450 -- nil (the conversion could not be done) | 818 -- nil (the conversion could not be done) |
451 -- a cons of a symbol and any of the following values; the symbol | 819 -- a cons of a symbol and any of the following values; the symbol |
452 explicitly specifies the type that will be sent. | 820 explicitly specifies the type that will be sent. |
453 -- a string (If the type is not specified, then if Mule support exists, | 821 -- a string (If the type is not specified, then if Mule support exists, |
477 If the type is not specified, a type of 'INTEGER | 845 If the type is not specified, a type of 'INTEGER |
478 will be sent.) | 846 will be sent.) |
479 -- a vector of integers and/or conses (HIGH . LOW) of integers | 847 -- a vector of integers and/or conses (HIGH . LOW) of integers |
480 (Will be converted into a list of 16-bit integers. | 848 (Will be converted into a list of 16-bit integers. |
481 If the type is not specified, a type of 'INTEGER | 849 If the type is not specified, a type of 'INTEGER |
482 will be sent.) */ ); | 850 will be sent.) |
483 Vselection_converter_alist = Qnil; | 851 */ ); |
852 Vselection_converter_out_alist = Qnil; | |
853 | |
854 DEFVAR_LISP ("selection-converter-in-alist", | |
855 &Vselection_converter_in_alist /* | |
856 An alist associating selection-types (such as STRING and TIMESTAMP) with | |
857 functions. These functions will be called with three args: the name | |
858 of the selection (typically PRIMARY, SECONDARY or CLIPBOARD); the | |
859 type from which the selection should be converted; and the selection | |
860 value. These functions should return a suitable representation of the | |
861 value, or nil to indicate that the conversion was not possible. | |
862 | |
863 See also `selection-converter-out-alist'. */ ); | |
864 Vselection_converter_in_alist = Qnil; | |
865 | |
866 DEFVAR_LISP ("selection-coercion-alist", | |
867 &Vselection_coercion_alist /* | |
868 An alist associating selection-types (such as STRING and TIMESTAMP) with | |
869 functions. These functions will be called with three args; the name | |
870 of the selection (typically PRIMARY, SECONDARY or CLIPBOARD); the type | |
871 from which the selection should be converted, and the selection value. | |
872 The value passed will be *exactly the same value* that was given to | |
873 `own-selection'; it should be converted into something suitable for | |
874 return to a program calling `get-selection' with the appropriate | |
875 parameters. | |
876 | |
877 See also `selection-converter-in-alist' and | |
878 `selection-converter-out-alist'. */); | |
879 Vselection_coercion_alist = Qnil; | |
880 | |
881 DEFVAR_LISP ("selection-appender-alist", | |
882 &Vselection_appender_alist /* | |
883 An alist associating selection-types (such as STRING and TIMESTAMP) with | |
884 functions. These functions will be called with four args; the name | |
885 of the selection (typically PRIMARY, SECONDARY or CLIPBOARD); the type | |
886 of the selection; and two selection values. The functions are expected to | |
887 return a value representing the catenation of the two values, or nil to | |
888 indicate that this was not possible. */ ); | |
889 Vselection_appender_alist = Qnil; | |
890 | |
891 DEFVAR_LISP ("selection-buffer-killed-alist", | |
892 &Vselection_buffer_killed_alist /* | |
893 An alist associating selection-types (such as STRING and TIMESTAMP) with | |
894 functions. These functions will be called whenever a buffer is killed, | |
895 with four args: the name of the selection (typically PRIMARY, SECONDARY | |
896 or CLIPBOARD); the type of the selection; the value of the selection; and | |
897 the buffer that has just been killed. These functions should return a new | |
898 selection value, or nil to indicate that the selection value should be | |
899 deleted. */ ); | |
900 Vselection_buffer_killed_alist = Qnil; | |
901 | |
902 DEFVAR_LISP ("selection-coercible-types", | |
903 &Vselection_coercible_types /* | |
904 A list of selection types that are coercible---that is, types that may be | |
905 automatically converted to another type. Selection values with types in this | |
906 list may be subject to conversion attempts to other types. */ ); | |
907 Vselection_coercible_types = Qnil; | |
484 | 908 |
485 DEFVAR_LISP ("lost-selection-hooks", &Vlost_selection_hooks /* | 909 DEFVAR_LISP ("lost-selection-hooks", &Vlost_selection_hooks /* |
486 A function or functions to be called after we have been notified | 910 A function or functions to be called after we have been notified |
487 that we have lost the selection. The function(s) will be called with one | 911 that we have lost the selection. The function(s) will be called with one |
488 argument, a symbol naming the selection (typically PRIMARY, SECONDARY, or | 912 argument, a symbol naming the selection (typically PRIMARY, SECONDARY, or |
489 CLIPBOARD). | 913 CLIPBOARD). |
490 */ ); | 914 */ ); |
491 Vlost_selection_hooks = Qunbound; | 915 Vlost_selection_hooks = Qunbound; |
492 } | 916 } |
493 |