Commit | Line | Data |
---|---|---|
944cda79 | 1 | /* Selection processing for Emacs on Mac OS. |
8cabe764 | 2 | Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. |
944cda79 YM |
3 | |
4 | This file is part of GNU Emacs. | |
5 | ||
9ec0b715 | 6 | GNU Emacs is free software: you can redistribute it and/or modify |
944cda79 | 7 | it under the terms of the GNU General Public License as published by |
9ec0b715 GM |
8 | the Free Software Foundation, either version 3 of the License, or |
9 | (at your option) any later version. | |
944cda79 YM |
10 | |
11 | GNU Emacs is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
9ec0b715 | 17 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ |
944cda79 YM |
18 | |
19 | #include <config.h> | |
20 | ||
21 | #include "lisp.h" | |
22 | #include "macterm.h" | |
23 | #include "blockinput.h" | |
28714a27 | 24 | #include "keymap.h" |
944cda79 | 25 | |
5d6c5138 | 26 | #if !TARGET_API_MAC_CARBON |
944cda79 | 27 | #include <Endian.h> |
5d6c5138 YM |
28 | #endif |
29 | ||
944cda79 YM |
30 | static void x_own_selection P_ ((Lisp_Object, Lisp_Object)); |
31 | static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object, int)); | |
32 | static Lisp_Object x_get_foreign_selection P_ ((Lisp_Object, | |
33 | Lisp_Object, | |
34 | Lisp_Object)); | |
944cda79 YM |
35 | |
36 | Lisp_Object QPRIMARY, QSECONDARY, QTIMESTAMP, QTARGETS; | |
37 | ||
38 | static Lisp_Object Vx_lost_selection_functions; | |
a5b11587 | 39 | /* Coding system for communicating with other programs via selections. */ |
944cda79 YM |
40 | static Lisp_Object Vselection_coding_system; |
41 | ||
42 | /* Coding system for the next communicating with other programs. */ | |
43 | static Lisp_Object Vnext_selection_coding_system; | |
44 | ||
45 | static Lisp_Object Qforeign_selection; | |
46 | ||
47 | /* The timestamp of the last input event Emacs received from the | |
48 | window server. */ | |
49 | /* Defined in keyboard.c. */ | |
50 | extern unsigned long last_event_timestamp; | |
51 | ||
52 | /* This is an association list whose elements are of the form | |
a5b11587 | 53 | ( SELECTION-NAME SELECTION-VALUE SELECTION-TIMESTAMP FRAME OWNERSHIP-INFO) |
944cda79 YM |
54 | SELECTION-NAME is a lisp symbol. |
55 | SELECTION-VALUE is the value that emacs owns for that selection. | |
56 | It may be any kind of Lisp object. | |
57 | SELECTION-TIMESTAMP is the time at which emacs began owning this selection, | |
58 | as a cons of two 16-bit numbers (making a 32 bit time.) | |
59 | FRAME is the frame for which we made the selection. | |
a5b11587 YM |
60 | OWNERSHIP-INFO is a value saved when emacs owns for that selection. |
61 | If another application takes the ownership of that selection | |
62 | later, then newly examined ownership info value should be | |
63 | different from the saved one. | |
64 | If there is an entry in this alist, the current ownership info for | |
65 | the selection coincides with OWNERSHIP-INFO, then it can be | |
66 | assumed that Emacs owns that selection. | |
944cda79 YM |
67 | The only (eq) parts of this list that are visible from Lisp are the |
68 | selection-values. */ | |
69 | static Lisp_Object Vselection_alist; | |
70 | ||
944cda79 YM |
71 | /* This is an alist whose CARs are selection-types and whose CDRs are |
72 | the names of Lisp functions to call to convert the given Emacs | |
73 | selection value to a string representing the given selection type. | |
74 | This is for Lisp-level extension of the emacs selection | |
75 | handling. */ | |
5d6c5138 | 76 | Lisp_Object Vselection_converter_alist; |
944cda79 YM |
77 | |
78 | /* A selection name (represented as a Lisp symbol) can be associated | |
79 | with a named scrap via `mac-scrap-name' property. Likewise for a | |
80 | selection type with a scrap flavor type via `mac-ostype'. */ | |
5d6c5138 | 81 | Lisp_Object Qmac_scrap_name, Qmac_ostype; |
944cda79 | 82 | |
944cda79 YM |
83 | \f |
84 | /* Do protocol to assert ourself as a selection owner. | |
85 | Update the Vselection_alist so that we can reply to later requests for | |
86 | our selection. */ | |
87 | ||
88 | static void | |
89 | x_own_selection (selection_name, selection_value) | |
90 | Lisp_Object selection_name, selection_value; | |
91 | { | |
31f93085 | 92 | OSStatus err; |
a5b11587 | 93 | Selection sel; |
944cda79 | 94 | struct gcpro gcpro1, gcpro2; |
a5b11587 | 95 | Lisp_Object rest, handler_fn, value, target_type; |
944cda79 YM |
96 | int count; |
97 | ||
98 | CHECK_SYMBOL (selection_name); | |
99 | ||
100 | GCPRO2 (selection_name, selection_value); | |
101 | ||
102 | BLOCK_INPUT; | |
103 | ||
a5b11587 YM |
104 | err = mac_get_selection_from_symbol (selection_name, 1, &sel); |
105 | if (err == noErr && sel) | |
944cda79 YM |
106 | { |
107 | /* Don't allow a quit within the converter. | |
108 | When the user types C-g, he would be surprised | |
109 | if by luck it came during a converter. */ | |
110 | count = SPECPDL_INDEX (); | |
111 | specbind (Qinhibit_quit, Qt); | |
112 | ||
113 | for (rest = Vselection_converter_alist; CONSP (rest); rest = XCDR (rest)) | |
114 | { | |
115 | if (!(CONSP (XCAR (rest)) | |
a5b11587 YM |
116 | && (target_type = XCAR (XCAR (rest)), |
117 | SYMBOLP (target_type)) | |
118 | && mac_valid_selection_target_p (target_type) | |
d18bee72 YM |
119 | && (handler_fn = XCDR (XCAR (rest)), |
120 | SYMBOLP (handler_fn)))) | |
944cda79 YM |
121 | continue; |
122 | ||
123 | if (!NILP (handler_fn)) | |
124 | value = call3 (handler_fn, selection_name, | |
a5b11587 YM |
125 | target_type, selection_value); |
126 | ||
127 | if (NILP (value)) | |
128 | continue; | |
944cda79 | 129 | |
a5b11587 YM |
130 | if (mac_valid_selection_value_p (value, target_type)) |
131 | err = mac_put_selection_value (sel, target_type, value); | |
956c0f10 | 132 | else if (CONSP (value) |
a5b11587 YM |
133 | && EQ (XCAR (value), target_type) |
134 | && mac_valid_selection_value_p (XCDR (value), target_type)) | |
135 | err = mac_put_selection_value (sel, target_type, XCDR (value)); | |
944cda79 YM |
136 | } |
137 | ||
138 | unbind_to (count, Qnil); | |
944cda79 YM |
139 | } |
140 | ||
141 | UNBLOCK_INPUT; | |
142 | ||
143 | UNGCPRO; | |
144 | ||
a5b11587 | 145 | if (sel && err != noErr) |
944cda79 YM |
146 | error ("Can't set selection"); |
147 | ||
148 | /* Now update the local cache */ | |
149 | { | |
150 | Lisp_Object selection_time; | |
151 | Lisp_Object selection_data; | |
a5b11587 | 152 | Lisp_Object ownership_info; |
944cda79 YM |
153 | Lisp_Object prev_value; |
154 | ||
155 | selection_time = long_to_cons (last_event_timestamp); | |
a5b11587 | 156 | if (sel) |
c04e33a6 YM |
157 | { |
158 | BLOCK_INPUT; | |
159 | ownership_info = mac_get_selection_ownership_info (sel); | |
160 | UNBLOCK_INPUT; | |
161 | } | |
a5b11587 YM |
162 | else |
163 | ownership_info = Qnil; /* dummy value for local-only selection */ | |
944cda79 YM |
164 | selection_data = Fcons (selection_name, |
165 | Fcons (selection_value, | |
166 | Fcons (selection_time, | |
a5b11587 YM |
167 | Fcons (selected_frame, |
168 | Fcons (ownership_info, | |
169 | Qnil))))); | |
944cda79 YM |
170 | prev_value = assq_no_quit (selection_name, Vselection_alist); |
171 | ||
172 | Vselection_alist = Fcons (selection_data, Vselection_alist); | |
173 | ||
174 | /* If we already owned the selection, remove the old selection data. | |
175 | Perhaps we should destructively modify it instead. | |
176 | Don't use Fdelq as that may QUIT. */ | |
177 | if (!NILP (prev_value)) | |
178 | { | |
179 | Lisp_Object rest; /* we know it's not the CAR, so it's easy. */ | |
99784d63 | 180 | for (rest = Vselection_alist; CONSP (rest); rest = XCDR (rest)) |
944cda79 YM |
181 | if (EQ (prev_value, Fcar (XCDR (rest)))) |
182 | { | |
183 | XSETCDR (rest, Fcdr (XCDR (rest))); | |
184 | break; | |
185 | } | |
186 | } | |
187 | } | |
188 | } | |
189 | \f | |
190 | /* Given a selection-name and desired type, look up our local copy of | |
191 | the selection value and convert it to the type. | |
192 | The value is nil or a string. | |
193 | This function is used both for remote requests (LOCAL_REQUEST is zero) | |
194 | and for local x-get-selection-internal (LOCAL_REQUEST is nonzero). | |
195 | ||
196 | This calls random Lisp code, and may signal or gc. */ | |
197 | ||
198 | static Lisp_Object | |
199 | x_get_local_selection (selection_symbol, target_type, local_request) | |
200 | Lisp_Object selection_symbol, target_type; | |
201 | int local_request; | |
202 | { | |
203 | Lisp_Object local_value; | |
204 | Lisp_Object handler_fn, value, type, check; | |
205 | int count; | |
206 | ||
207 | if (NILP (Fx_selection_owner_p (selection_symbol))) | |
208 | return Qnil; | |
209 | ||
210 | local_value = assq_no_quit (selection_symbol, Vselection_alist); | |
211 | ||
212 | /* TIMESTAMP is a special case 'cause that's easiest. */ | |
213 | if (EQ (target_type, QTIMESTAMP)) | |
214 | { | |
215 | handler_fn = Qnil; | |
216 | value = XCAR (XCDR (XCDR (local_value))); | |
217 | } | |
218 | #if 0 | |
219 | else if (EQ (target_type, QDELETE)) | |
220 | { | |
221 | handler_fn = Qnil; | |
222 | Fx_disown_selection_internal | |
223 | (selection_symbol, | |
224 | XCAR (XCDR (XCDR (local_value)))); | |
225 | value = QNULL; | |
226 | } | |
227 | #endif | |
228 | else | |
229 | { | |
230 | /* Don't allow a quit within the converter. | |
231 | When the user types C-g, he would be surprised | |
232 | if by luck it came during a converter. */ | |
233 | count = SPECPDL_INDEX (); | |
234 | specbind (Qinhibit_quit, Qt); | |
235 | ||
236 | CHECK_SYMBOL (target_type); | |
237 | handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); | |
238 | /* gcpro is not needed here since nothing but HANDLER_FN | |
239 | is live, and that ought to be a symbol. */ | |
240 | ||
241 | if (!NILP (handler_fn)) | |
242 | value = call3 (handler_fn, | |
243 | selection_symbol, (local_request ? Qnil : target_type), | |
244 | XCAR (XCDR (local_value))); | |
245 | else | |
246 | value = Qnil; | |
247 | unbind_to (count, Qnil); | |
248 | } | |
249 | ||
a5b11587 YM |
250 | if (local_request) |
251 | return value; | |
252 | ||
944cda79 | 253 | /* Make sure this value is of a type that we could transmit |
a5b11587 | 254 | to another application. */ |
944cda79 | 255 | |
a5b11587 | 256 | type = target_type; |
944cda79 YM |
257 | check = value; |
258 | if (CONSP (value) | |
259 | && SYMBOLP (XCAR (value))) | |
260 | type = XCAR (value), | |
261 | check = XCDR (value); | |
262 | ||
a5b11587 | 263 | if (NILP (value) || mac_valid_selection_value_p (check, type)) |
944cda79 | 264 | return value; |
4ae7943d KS |
265 | |
266 | signal_error ("Invalid data returned by selection-conversion function", | |
267 | list2 (handler_fn, value)); | |
944cda79 YM |
268 | } |
269 | ||
270 | \f | |
271 | /* Clear all selections that were made from frame F. | |
272 | We do this when about to delete a frame. */ | |
273 | ||
274 | void | |
275 | x_clear_frame_selections (f) | |
276 | FRAME_PTR f; | |
277 | { | |
278 | Lisp_Object frame; | |
279 | Lisp_Object rest; | |
280 | ||
281 | XSETFRAME (frame, f); | |
282 | ||
283 | /* Otherwise, we're really honest and truly being told to drop it. | |
284 | Don't use Fdelq as that may QUIT;. */ | |
285 | ||
286 | /* Delete elements from the beginning of Vselection_alist. */ | |
287 | while (!NILP (Vselection_alist) | |
288 | && EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (Vselection_alist))))))) | |
289 | { | |
290 | /* Let random Lisp code notice that the selection has been stolen. */ | |
291 | Lisp_Object hooks, selection_symbol; | |
292 | ||
293 | hooks = Vx_lost_selection_functions; | |
294 | selection_symbol = Fcar (Fcar (Vselection_alist)); | |
295 | ||
956c0f10 YM |
296 | if (!EQ (hooks, Qunbound) |
297 | && !NILP (Fx_selection_owner_p (selection_symbol))) | |
944cda79 YM |
298 | { |
299 | for (; CONSP (hooks); hooks = Fcdr (hooks)) | |
300 | call1 (Fcar (hooks), selection_symbol); | |
301 | #if 0 /* This can crash when deleting a frame | |
302 | from x_connection_closed. Anyway, it seems unnecessary; | |
303 | something else should cause a redisplay. */ | |
304 | redisplay_preserve_echo_area (21); | |
305 | #endif | |
306 | } | |
307 | ||
308 | Vselection_alist = Fcdr (Vselection_alist); | |
309 | } | |
310 | ||
311 | /* Delete elements after the beginning of Vselection_alist. */ | |
99784d63 | 312 | for (rest = Vselection_alist; CONSP (rest); rest = XCDR (rest)) |
944cda79 YM |
313 | if (EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (XCDR (rest)))))))) |
314 | { | |
315 | /* Let random Lisp code notice that the selection has been stolen. */ | |
316 | Lisp_Object hooks, selection_symbol; | |
317 | ||
318 | hooks = Vx_lost_selection_functions; | |
319 | selection_symbol = Fcar (Fcar (XCDR (rest))); | |
320 | ||
956c0f10 YM |
321 | if (!EQ (hooks, Qunbound) |
322 | && !NILP (Fx_selection_owner_p (selection_symbol))) | |
944cda79 YM |
323 | { |
324 | for (; CONSP (hooks); hooks = Fcdr (hooks)) | |
325 | call1 (Fcar (hooks), selection_symbol); | |
326 | #if 0 /* See above */ | |
327 | redisplay_preserve_echo_area (22); | |
328 | #endif | |
329 | } | |
330 | XSETCDR (rest, Fcdr (XCDR (rest))); | |
331 | break; | |
332 | } | |
333 | } | |
334 | \f | |
335 | /* Do protocol to read selection-data from the server. | |
336 | Converts this to Lisp data and returns it. */ | |
337 | ||
338 | static Lisp_Object | |
339 | x_get_foreign_selection (selection_symbol, target_type, time_stamp) | |
340 | Lisp_Object selection_symbol, target_type, time_stamp; | |
341 | { | |
31f93085 | 342 | OSStatus err; |
a5b11587 | 343 | Selection sel; |
944cda79 YM |
344 | Lisp_Object result = Qnil; |
345 | ||
346 | BLOCK_INPUT; | |
347 | ||
a5b11587 YM |
348 | err = mac_get_selection_from_symbol (selection_symbol, 0, &sel); |
349 | if (err == noErr && sel) | |
961bf590 YM |
350 | { |
351 | if (EQ (target_type, QTARGETS)) | |
352 | { | |
a5b11587 | 353 | result = mac_get_selection_target_list (sel); |
961bf590 YM |
354 | result = Fvconcat (1, &result); |
355 | } | |
356 | else | |
357 | { | |
a5b11587 | 358 | result = mac_get_selection_value (sel, target_type); |
961bf590 YM |
359 | if (STRINGP (result)) |
360 | Fput_text_property (make_number (0), make_number (SBYTES (result)), | |
361 | Qforeign_selection, target_type, result); | |
362 | } | |
363 | } | |
944cda79 YM |
364 | |
365 | UNBLOCK_INPUT; | |
366 | ||
367 | return result; | |
368 | } | |
369 | ||
370 | ||
371 | DEFUN ("x-own-selection-internal", Fx_own_selection_internal, | |
372 | Sx_own_selection_internal, 2, 2, 0, | |
373 | doc: /* Assert a selection of the given TYPE with the given VALUE. | |
374 | TYPE is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. | |
375 | VALUE is typically a string, or a cons of two markers, but may be | |
376 | anything that the functions on `selection-converter-alist' know about. */) | |
377 | (selection_name, selection_value) | |
378 | Lisp_Object selection_name, selection_value; | |
379 | { | |
380 | check_mac (); | |
381 | CHECK_SYMBOL (selection_name); | |
99f963e4 | 382 | if (NILP (selection_value)) error ("SELECTION-VALUE may not be nil"); |
944cda79 YM |
383 | x_own_selection (selection_name, selection_value); |
384 | return selection_value; | |
385 | } | |
386 | ||
387 | ||
388 | /* Request the selection value from the owner. If we are the owner, | |
389 | simply return our selection value. If we are not the owner, this | |
390 | will block until all of the data has arrived. */ | |
391 | ||
392 | DEFUN ("x-get-selection-internal", Fx_get_selection_internal, | |
393 | Sx_get_selection_internal, 2, 3, 0, | |
99f963e4 | 394 | doc: /* Return text selected from some Mac application. |
944cda79 YM |
395 | SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. |
396 | TYPE is the type of data desired, typically `STRING'. | |
397 | TIME_STAMP is ignored on Mac. */) | |
99f963e4 | 398 | (selection_symbol, target_type, time_stamp) |
944cda79 YM |
399 | Lisp_Object selection_symbol, target_type, time_stamp; |
400 | { | |
401 | Lisp_Object val = Qnil; | |
402 | struct gcpro gcpro1, gcpro2; | |
403 | GCPRO2 (target_type, val); /* we store newly consed data into these */ | |
404 | check_mac (); | |
405 | CHECK_SYMBOL (selection_symbol); | |
406 | CHECK_SYMBOL (target_type); | |
407 | ||
408 | val = x_get_local_selection (selection_symbol, target_type, 1); | |
409 | ||
410 | if (NILP (val)) | |
411 | { | |
412 | val = x_get_foreign_selection (selection_symbol, target_type, time_stamp); | |
413 | goto DONE; | |
414 | } | |
415 | ||
416 | if (CONSP (val) | |
417 | && SYMBOLP (XCAR (val))) | |
418 | { | |
419 | val = XCDR (val); | |
420 | if (CONSP (val) && NILP (XCDR (val))) | |
421 | val = XCAR (val); | |
422 | } | |
423 | DONE: | |
424 | UNGCPRO; | |
425 | return val; | |
426 | } | |
427 | ||
428 | DEFUN ("x-disown-selection-internal", Fx_disown_selection_internal, | |
429 | Sx_disown_selection_internal, 1, 2, 0, | |
430 | doc: /* If we own the selection SELECTION, disown it. | |
431 | Disowning it means there is no such selection. */) | |
432 | (selection, time) | |
433 | Lisp_Object selection; | |
434 | Lisp_Object time; | |
435 | { | |
31f93085 | 436 | OSStatus err; |
a5b11587 | 437 | Selection sel; |
944cda79 YM |
438 | Lisp_Object local_selection_data; |
439 | ||
440 | check_mac (); | |
441 | CHECK_SYMBOL (selection); | |
442 | ||
443 | if (NILP (Fx_selection_owner_p (selection))) | |
444 | return Qnil; /* Don't disown the selection when we're not the owner. */ | |
445 | ||
446 | local_selection_data = assq_no_quit (selection, Vselection_alist); | |
447 | ||
448 | /* Don't use Fdelq as that may QUIT;. */ | |
449 | ||
450 | if (EQ (local_selection_data, Fcar (Vselection_alist))) | |
451 | Vselection_alist = Fcdr (Vselection_alist); | |
452 | else | |
453 | { | |
454 | Lisp_Object rest; | |
99784d63 | 455 | for (rest = Vselection_alist; CONSP (rest); rest = XCDR (rest)) |
944cda79 YM |
456 | if (EQ (local_selection_data, Fcar (XCDR (rest)))) |
457 | { | |
458 | XSETCDR (rest, Fcdr (XCDR (rest))); | |
459 | break; | |
460 | } | |
461 | } | |
462 | ||
463 | /* Let random lisp code notice that the selection has been stolen. */ | |
464 | ||
465 | { | |
466 | Lisp_Object rest; | |
467 | rest = Vx_lost_selection_functions; | |
468 | if (!EQ (rest, Qunbound)) | |
469 | { | |
470 | for (; CONSP (rest); rest = Fcdr (rest)) | |
471 | call1 (Fcar (rest), selection); | |
472 | prepare_menu_bars (); | |
473 | redisplay_preserve_echo_area (20); | |
474 | } | |
475 | } | |
476 | ||
477 | BLOCK_INPUT; | |
478 | ||
a5b11587 YM |
479 | err = mac_get_selection_from_symbol (selection, 0, &sel); |
480 | if (err == noErr && sel) | |
481 | mac_clear_selection (&sel); | |
944cda79 YM |
482 | |
483 | UNBLOCK_INPUT; | |
484 | ||
485 | return Qt; | |
486 | } | |
487 | ||
488 | ||
489 | DEFUN ("x-selection-owner-p", Fx_selection_owner_p, Sx_selection_owner_p, | |
490 | 0, 1, 0, | |
99f963e4 | 491 | doc: /* Whether the current Emacs process owns the given SELECTION. |
944cda79 YM |
492 | The arg should be the name of the selection in question, typically one of |
493 | the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. | |
494 | For convenience, the symbol nil is the same as `PRIMARY', | |
495 | and t is the same as `SECONDARY'. */) | |
496 | (selection) | |
497 | Lisp_Object selection; | |
498 | { | |
31f93085 | 499 | OSStatus err; |
a5b11587 | 500 | Selection sel; |
944cda79 YM |
501 | Lisp_Object result = Qnil, local_selection_data; |
502 | ||
503 | check_mac (); | |
504 | CHECK_SYMBOL (selection); | |
505 | if (EQ (selection, Qnil)) selection = QPRIMARY; | |
506 | if (EQ (selection, Qt)) selection = QSECONDARY; | |
507 | ||
508 | local_selection_data = assq_no_quit (selection, Vselection_alist); | |
509 | ||
510 | if (NILP (local_selection_data)) | |
511 | return Qnil; | |
512 | ||
513 | BLOCK_INPUT; | |
514 | ||
a5b11587 YM |
515 | err = mac_get_selection_from_symbol (selection, 0, &sel); |
516 | if (err == noErr && sel) | |
944cda79 | 517 | { |
a5b11587 | 518 | Lisp_Object ownership_info; |
944cda79 | 519 | |
a5b11587 YM |
520 | ownership_info = XCAR (XCDR (XCDR (XCDR (XCDR (local_selection_data))))); |
521 | if (!NILP (Fequal (ownership_info, | |
522 | mac_get_selection_ownership_info (sel)))) | |
944cda79 YM |
523 | result = Qt; |
524 | } | |
525 | else | |
526 | result = Qt; | |
527 | ||
528 | UNBLOCK_INPUT; | |
529 | ||
530 | return result; | |
531 | } | |
532 | ||
533 | DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p, | |
534 | 0, 1, 0, | |
99f963e4 | 535 | doc: /* Whether there is an owner for the given SELECTION. |
944cda79 YM |
536 | The arg should be the name of the selection in question, typically one of |
537 | the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. | |
538 | For convenience, the symbol nil is the same as `PRIMARY', | |
539 | and t is the same as `SECONDARY'. */) | |
540 | (selection) | |
541 | Lisp_Object selection; | |
542 | { | |
31f93085 | 543 | OSStatus err; |
a5b11587 | 544 | Selection sel; |
944cda79 YM |
545 | Lisp_Object result = Qnil, rest; |
546 | ||
547 | /* It should be safe to call this before we have an Mac frame. */ | |
548 | if (! FRAME_MAC_P (SELECTED_FRAME ())) | |
549 | return Qnil; | |
550 | ||
551 | CHECK_SYMBOL (selection); | |
552 | if (!NILP (Fx_selection_owner_p (selection))) | |
553 | return Qt; | |
554 | if (EQ (selection, Qnil)) selection = QPRIMARY; | |
555 | if (EQ (selection, Qt)) selection = QSECONDARY; | |
556 | ||
557 | BLOCK_INPUT; | |
558 | ||
a5b11587 YM |
559 | err = mac_get_selection_from_symbol (selection, 0, &sel); |
560 | if (err == noErr && sel) | |
944cda79 YM |
561 | for (rest = Vselection_converter_alist; CONSP (rest); rest = XCDR (rest)) |
562 | { | |
563 | if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest))) | |
a5b11587 | 564 | && mac_selection_has_target_p (sel, XCAR (XCAR (rest)))) |
944cda79 YM |
565 | { |
566 | result = Qt; | |
567 | break; | |
568 | } | |
569 | } | |
570 | ||
571 | UNBLOCK_INPUT; | |
572 | ||
573 | return result; | |
574 | } | |
575 | ||
576 | \f | |
0ffd2c76 YM |
577 | /*********************************************************************** |
578 | Apple event support | |
579 | ***********************************************************************/ | |
28714a27 | 580 | int mac_ready_for_apple_events = 0; |
5d6c5138 YM |
581 | Lisp_Object Vmac_apple_event_map; |
582 | Lisp_Object Qmac_apple_event_class, Qmac_apple_event_id; | |
0ffd2c76 | 583 | static Lisp_Object Qemacs_suspension_id; |
28714a27 | 584 | extern Lisp_Object Qundefined; |
044f1b64 YM |
585 | extern void mac_store_apple_event P_ ((Lisp_Object, Lisp_Object, |
586 | const AEDesc *)); | |
28714a27 YM |
587 | |
588 | struct apple_event_binding | |
589 | { | |
590 | UInt32 code; /* Apple event class or ID. */ | |
591 | Lisp_Object key, binding; | |
592 | }; | |
593 | ||
0ffd2c76 YM |
594 | struct suspended_ae_info |
595 | { | |
596 | UInt32 expiration_tick, suspension_id; | |
597 | AppleEvent apple_event, reply; | |
598 | struct suspended_ae_info *next; | |
599 | }; | |
600 | ||
31f93085 | 601 | /* List of apple events deferred at the startup time. */ |
0ffd2c76 YM |
602 | static struct suspended_ae_info *deferred_apple_events = NULL; |
603 | ||
604 | /* List of suspended apple events, in order of expiration_tick. */ | |
605 | static struct suspended_ae_info *suspended_apple_events = NULL; | |
606 | ||
28714a27 YM |
607 | static void |
608 | find_event_binding_fun (key, binding, args, data) | |
609 | Lisp_Object key, binding, args; | |
610 | void *data; | |
611 | { | |
612 | struct apple_event_binding *event_binding = | |
613 | (struct apple_event_binding *)data; | |
614 | Lisp_Object code_string; | |
615 | ||
616 | if (!SYMBOLP (key)) | |
617 | return; | |
618 | code_string = Fget (key, args); | |
619 | if (STRINGP (code_string) && SBYTES (code_string) == 4 | |
620 | && (EndianU32_BtoN (*((UInt32 *) SDATA (code_string))) | |
621 | == event_binding->code)) | |
622 | { | |
623 | event_binding->key = key; | |
624 | event_binding->binding = binding; | |
625 | } | |
626 | } | |
627 | ||
628 | static void | |
629 | find_event_binding (keymap, event_binding, class_p) | |
630 | Lisp_Object keymap; | |
631 | struct apple_event_binding *event_binding; | |
632 | int class_p; | |
633 | { | |
634 | if (event_binding->code == 0) | |
635 | event_binding->binding = | |
636 | access_keymap (keymap, event_binding->key, 0, 1, 0); | |
637 | else | |
638 | { | |
639 | event_binding->binding = Qnil; | |
640 | map_keymap (keymap, find_event_binding_fun, | |
641 | class_p ? Qmac_apple_event_class : Qmac_apple_event_id, | |
642 | event_binding, 0); | |
643 | } | |
644 | } | |
645 | ||
646 | void | |
647 | mac_find_apple_event_spec (class, id, class_key, id_key, binding) | |
648 | AEEventClass class; | |
649 | AEEventID id; | |
650 | Lisp_Object *class_key, *id_key, *binding; | |
651 | { | |
652 | struct apple_event_binding event_binding; | |
653 | Lisp_Object keymap; | |
654 | ||
655 | *binding = Qnil; | |
656 | ||
657 | keymap = get_keymap (Vmac_apple_event_map, 0, 0); | |
658 | if (NILP (keymap)) | |
659 | return; | |
660 | ||
661 | event_binding.code = class; | |
662 | event_binding.key = *class_key; | |
663 | event_binding.binding = Qnil; | |
664 | find_event_binding (keymap, &event_binding, 1); | |
665 | *class_key = event_binding.key; | |
666 | keymap = get_keymap (event_binding.binding, 0, 0); | |
667 | if (NILP (keymap)) | |
668 | return; | |
669 | ||
670 | event_binding.code = id; | |
671 | event_binding.key = *id_key; | |
672 | event_binding.binding = Qnil; | |
673 | find_event_binding (keymap, &event_binding, 0); | |
674 | *id_key = event_binding.key; | |
675 | *binding = event_binding.binding; | |
676 | } | |
677 | ||
678 | static OSErr | |
679 | defer_apple_events (apple_event, reply) | |
680 | const AppleEvent *apple_event, *reply; | |
681 | { | |
682 | OSErr err; | |
0ffd2c76 YM |
683 | struct suspended_ae_info *new; |
684 | ||
685 | new = xmalloc (sizeof (struct suspended_ae_info)); | |
686 | bzero (new, sizeof (struct suspended_ae_info)); | |
687 | new->apple_event.descriptorType = typeNull; | |
688 | new->reply.descriptorType = typeNull; | |
28714a27 YM |
689 | |
690 | err = AESuspendTheCurrentEvent (apple_event); | |
691 | ||
692 | /* Mac OS 10.3 Xcode manual says AESuspendTheCurrentEvent makes | |
693 | copies of the Apple event and the reply, but Mac OS 10.4 Xcode | |
694 | manual says it doesn't. Anyway we create copies of them and save | |
961bf590 | 695 | them in `deferred_apple_events'. */ |
0ffd2c76 YM |
696 | if (err == noErr) |
697 | err = AEDuplicateDesc (apple_event, &new->apple_event); | |
698 | if (err == noErr) | |
699 | err = AEDuplicateDesc (reply, &new->reply); | |
28714a27 YM |
700 | if (err == noErr) |
701 | { | |
0ffd2c76 YM |
702 | new->next = deferred_apple_events; |
703 | deferred_apple_events = new; | |
704 | } | |
705 | else | |
706 | { | |
707 | AEDisposeDesc (&new->apple_event); | |
708 | AEDisposeDesc (&new->reply); | |
709 | xfree (new); | |
710 | } | |
711 | ||
712 | return err; | |
713 | } | |
714 | ||
715 | static OSErr | |
716 | mac_handle_apple_event_1 (class, id, apple_event, reply) | |
717 | Lisp_Object class, id; | |
718 | const AppleEvent *apple_event; | |
719 | AppleEvent *reply; | |
720 | { | |
721 | OSErr err; | |
722 | static UInt32 suspension_id = 0; | |
723 | struct suspended_ae_info *new; | |
724 | ||
725 | new = xmalloc (sizeof (struct suspended_ae_info)); | |
726 | bzero (new, sizeof (struct suspended_ae_info)); | |
727 | new->apple_event.descriptorType = typeNull; | |
728 | new->reply.descriptorType = typeNull; | |
729 | ||
730 | err = AESuspendTheCurrentEvent (apple_event); | |
731 | if (err == noErr) | |
732 | err = AEDuplicateDesc (apple_event, &new->apple_event); | |
733 | if (err == noErr) | |
734 | err = AEDuplicateDesc (reply, &new->reply); | |
735 | if (err == noErr) | |
736 | err = AEPutAttributePtr (&new->apple_event, KEY_EMACS_SUSPENSION_ID_ATTR, | |
737 | typeUInt32, &suspension_id, sizeof (UInt32)); | |
738 | if (err == noErr) | |
739 | { | |
740 | OSErr err1; | |
741 | SInt32 reply_requested; | |
742 | ||
743 | err1 = AEGetAttributePtr (&new->apple_event, keyReplyRequestedAttr, | |
744 | typeSInt32, NULL, &reply_requested, | |
745 | sizeof (SInt32), NULL); | |
746 | if (err1 != noErr) | |
28714a27 | 747 | { |
0ffd2c76 YM |
748 | /* Emulate keyReplyRequestedAttr in older versions. */ |
749 | reply_requested = reply->descriptorType != typeNull; | |
750 | err = AEPutAttributePtr (&new->apple_event, keyReplyRequestedAttr, | |
751 | typeSInt32, &reply_requested, | |
752 | sizeof (SInt32)); | |
28714a27 YM |
753 | } |
754 | } | |
28714a27 YM |
755 | if (err == noErr) |
756 | { | |
0ffd2c76 YM |
757 | SInt32 timeout = 0; |
758 | struct suspended_ae_info **p; | |
759 | ||
760 | new->suspension_id = suspension_id; | |
761 | suspension_id++; | |
762 | err = AEGetAttributePtr (apple_event, keyTimeoutAttr, typeSInt32, | |
763 | NULL, &timeout, sizeof (SInt32), NULL); | |
764 | new->expiration_tick = TickCount () + timeout; | |
765 | ||
766 | for (p = &suspended_apple_events; *p; p = &(*p)->next) | |
767 | if ((*p)->expiration_tick >= new->expiration_tick) | |
768 | break; | |
769 | new->next = *p; | |
770 | *p = new; | |
28714a27 | 771 | |
0ffd2c76 YM |
772 | mac_store_apple_event (class, id, &new->apple_event); |
773 | } | |
774 | else | |
775 | { | |
776 | AEDisposeDesc (&new->reply); | |
777 | AEDisposeDesc (&new->apple_event); | |
778 | xfree (new); | |
28714a27 YM |
779 | } |
780 | ||
781 | return err; | |
782 | } | |
783 | ||
5d6c5138 | 784 | pascal OSErr |
28714a27 YM |
785 | mac_handle_apple_event (apple_event, reply, refcon) |
786 | const AppleEvent *apple_event; | |
787 | AppleEvent *reply; | |
788 | SInt32 refcon; | |
789 | { | |
790 | OSErr err; | |
0ffd2c76 | 791 | UInt32 suspension_id; |
28714a27 YM |
792 | AEEventClass event_class; |
793 | AEEventID event_id; | |
794 | Lisp_Object class_key, id_key, binding; | |
795 | ||
28714a27 YM |
796 | if (!mac_ready_for_apple_events) |
797 | { | |
798 | err = defer_apple_events (apple_event, reply); | |
799 | if (err != noErr) | |
800 | return errAEEventNotHandled; | |
801 | return noErr; | |
802 | } | |
803 | ||
0ffd2c76 YM |
804 | err = AEGetAttributePtr (apple_event, KEY_EMACS_SUSPENSION_ID_ATTR, |
805 | typeUInt32, NULL, | |
806 | &suspension_id, sizeof (UInt32), NULL); | |
807 | if (err == noErr) | |
808 | /* Previously suspended event. Pass it to the next handler. */ | |
809 | return errAEEventNotHandled; | |
810 | ||
28714a27 YM |
811 | err = AEGetAttributePtr (apple_event, keyEventClassAttr, typeType, NULL, |
812 | &event_class, sizeof (AEEventClass), NULL); | |
813 | if (err == noErr) | |
814 | err = AEGetAttributePtr (apple_event, keyEventIDAttr, typeType, NULL, | |
815 | &event_id, sizeof (AEEventID), NULL); | |
816 | if (err == noErr) | |
817 | { | |
818 | mac_find_apple_event_spec (event_class, event_id, | |
819 | &class_key, &id_key, &binding); | |
820 | if (!NILP (binding) && !EQ (binding, Qundefined)) | |
821 | { | |
822 | if (INTEGERP (binding)) | |
823 | return XINT (binding); | |
0ffd2c76 YM |
824 | err = mac_handle_apple_event_1 (class_key, id_key, |
825 | apple_event, reply); | |
28714a27 | 826 | } |
412f3f18 YM |
827 | else |
828 | err = errAEEventNotHandled; | |
28714a27 | 829 | } |
0ffd2c76 YM |
830 | if (err == noErr) |
831 | return noErr; | |
832 | else | |
833 | return errAEEventNotHandled; | |
834 | } | |
835 | ||
836 | static int | |
837 | cleanup_suspended_apple_events (head, all_p) | |
838 | struct suspended_ae_info **head; | |
839 | int all_p; | |
840 | { | |
841 | UInt32 current_tick = TickCount (), nresumed = 0; | |
842 | struct suspended_ae_info *p, *next; | |
843 | ||
844 | for (p = *head; p; p = next) | |
845 | { | |
846 | if (!all_p && p->expiration_tick > current_tick) | |
847 | break; | |
848 | AESetTheCurrentEvent (&p->apple_event); | |
849 | AEResumeTheCurrentEvent (&p->apple_event, &p->reply, | |
850 | (AEEventHandlerUPP) kAENoDispatch, 0); | |
851 | AEDisposeDesc (&p->reply); | |
852 | AEDisposeDesc (&p->apple_event); | |
853 | nresumed++; | |
854 | next = p->next; | |
855 | xfree (p); | |
856 | } | |
857 | *head = p; | |
858 | ||
859 | return nresumed; | |
860 | } | |
861 | ||
5d6c5138 | 862 | void |
0ffd2c76 YM |
863 | cleanup_all_suspended_apple_events () |
864 | { | |
865 | cleanup_suspended_apple_events (&deferred_apple_events, 1); | |
866 | cleanup_suspended_apple_events (&suspended_apple_events, 1); | |
28714a27 YM |
867 | } |
868 | ||
0ffd2c76 YM |
869 | static UInt32 |
870 | get_suspension_id (apple_event) | |
871 | Lisp_Object apple_event; | |
872 | { | |
873 | Lisp_Object tem; | |
874 | ||
875 | CHECK_CONS (apple_event); | |
876 | CHECK_STRING_CAR (apple_event); | |
877 | if (SBYTES (XCAR (apple_event)) != 4 | |
878 | || strcmp (SDATA (XCAR (apple_event)), "aevt") != 0) | |
879 | error ("Not an apple event"); | |
880 | ||
881 | tem = assq_no_quit (Qemacs_suspension_id, XCDR (apple_event)); | |
882 | if (NILP (tem)) | |
883 | error ("Suspension ID not available"); | |
884 | ||
885 | tem = XCDR (tem); | |
886 | if (!(CONSP (tem) | |
887 | && STRINGP (XCAR (tem)) && SBYTES (XCAR (tem)) == 4 | |
888 | && strcmp (SDATA (XCAR (tem)), "magn") == 0 | |
889 | && STRINGP (XCDR (tem)) && SBYTES (XCDR (tem)) == 4)) | |
890 | error ("Bad suspension ID format"); | |
891 | ||
892 | return *((UInt32 *) SDATA (XCDR (tem))); | |
893 | } | |
894 | ||
895 | ||
28714a27 YM |
896 | DEFUN ("mac-process-deferred-apple-events", Fmac_process_deferred_apple_events, Smac_process_deferred_apple_events, 0, 0, 0, |
897 | doc: /* Process Apple events that are deferred at the startup time. */) | |
898 | () | |
899 | { | |
28714a27 YM |
900 | if (mac_ready_for_apple_events) |
901 | return Qnil; | |
902 | ||
903 | BLOCK_INPUT; | |
904 | mac_ready_for_apple_events = 1; | |
0ffd2c76 | 905 | if (deferred_apple_events) |
28714a27 | 906 | { |
0ffd2c76 YM |
907 | struct suspended_ae_info *prev, *tail, *next; |
908 | ||
909 | /* `nreverse' deferred_apple_events. */ | |
910 | prev = NULL; | |
911 | for (tail = deferred_apple_events; tail; tail = next) | |
28714a27 | 912 | { |
0ffd2c76 YM |
913 | next = tail->next; |
914 | tail->next = prev; | |
915 | prev = tail; | |
916 | } | |
917 | ||
918 | /* Now `prev' points to the first cell. */ | |
919 | for (tail = prev; tail; tail = next) | |
920 | { | |
921 | next = tail->next; | |
922 | AEResumeTheCurrentEvent (&tail->apple_event, &tail->reply, | |
28714a27 YM |
923 | ((AEEventHandlerUPP) |
924 | kAEUseStandardDispatch), 0); | |
0ffd2c76 YM |
925 | AEDisposeDesc (&tail->reply); |
926 | AEDisposeDesc (&tail->apple_event); | |
927 | xfree (tail); | |
28714a27 | 928 | } |
28714a27 | 929 | |
0ffd2c76 YM |
930 | deferred_apple_events = NULL; |
931 | } | |
932 | UNBLOCK_INPUT; | |
933 | ||
934 | return Qt; | |
935 | } | |
936 | ||
937 | DEFUN ("mac-cleanup-expired-apple-events", Fmac_cleanup_expired_apple_events, Smac_cleanup_expired_apple_events, 0, 0, 0, | |
938 | doc: /* Clean up expired Apple events. | |
939 | Return the number of expired events. */) | |
940 | () | |
941 | { | |
942 | int nexpired; | |
943 | ||
944 | BLOCK_INPUT; | |
945 | nexpired = cleanup_suspended_apple_events (&suspended_apple_events, 0); | |
946 | UNBLOCK_INPUT; | |
947 | ||
948 | return make_number (nexpired); | |
949 | } | |
950 | ||
951 | DEFUN ("mac-ae-set-reply-parameter", Fmac_ae_set_reply_parameter, Smac_ae_set_reply_parameter, 3, 3, 0, | |
952 | doc: /* Set parameter KEYWORD to DESCRIPTOR on reply of APPLE-EVENT. | |
953 | KEYWORD is a 4-byte string. DESCRIPTOR is a Lisp representation of an | |
954 | Apple event descriptor. It has the form of (TYPE . DATA), where TYPE | |
955 | is a 4-byte string. Valid format of DATA is as follows: | |
956 | ||
957 | * If TYPE is "null", then DATA is nil. | |
958 | * If TYPE is "list", then DATA is a list (DESCRIPTOR1 ... DESCRIPTORn). | |
959 | * If TYPE is "reco", then DATA is a list ((KEYWORD1 . DESCRIPTOR1) | |
960 | ... (KEYWORDn . DESCRIPTORn)). | |
961 | * If TYPE is "aevt", then DATA is ignored and the descriptor is | |
962 | treated as null. | |
963 | * Otherwise, DATA is a string. | |
964 | ||
965 | If a (sub-)descriptor is in an invalid format, it is silently treated | |
966 | as null. | |
967 | ||
968 | Return t if the parameter is successfully set. Otherwise return nil. */) | |
969 | (apple_event, keyword, descriptor) | |
970 | Lisp_Object apple_event, keyword, descriptor; | |
971 | { | |
972 | Lisp_Object result = Qnil; | |
973 | UInt32 suspension_id; | |
974 | struct suspended_ae_info *p; | |
975 | ||
976 | suspension_id = get_suspension_id (apple_event); | |
977 | ||
978 | CHECK_STRING (keyword); | |
979 | if (SBYTES (keyword) != 4) | |
980 | error ("Apple event keyword must be a 4-byte string: %s", | |
981 | SDATA (keyword)); | |
982 | ||
983 | BLOCK_INPUT; | |
984 | for (p = suspended_apple_events; p; p = p->next) | |
985 | if (p->suspension_id == suspension_id) | |
986 | break; | |
987 | if (p && p->reply.descriptorType != typeNull) | |
988 | { | |
989 | OSErr err; | |
990 | ||
991 | err = mac_ae_put_lisp (&p->reply, | |
992 | EndianU32_BtoN (*((UInt32 *) SDATA (keyword))), | |
993 | descriptor); | |
994 | if (err == noErr) | |
995 | result = Qt; | |
996 | } | |
997 | UNBLOCK_INPUT; | |
998 | ||
999 | return result; | |
1000 | } | |
1001 | ||
1002 | DEFUN ("mac-resume-apple-event", Fmac_resume_apple_event, Smac_resume_apple_event, 1, 2, 0, | |
1003 | doc: /* Resume handling of APPLE-EVENT. | |
1004 | Every Apple event handled by the Lisp interpreter is suspended first. | |
1005 | This function resumes such a suspended event either to complete Apple | |
1006 | event handling to give a reply, or to redispatch it to other handlers. | |
1007 | ||
1008 | If optional ERROR-CODE is an integer, it specifies the error number | |
1009 | that is set in the reply. If ERROR-CODE is t, the resumed event is | |
1010 | handled with the standard dispatching mechanism, but it is not handled | |
1011 | by Emacs again, thus it is redispatched to other handlers. | |
1012 | ||
1013 | Return t if APPLE-EVENT is successfully resumed. Otherwise return | |
1014 | nil, which means the event is already resumed or expired. */) | |
1015 | (apple_event, error_code) | |
1016 | Lisp_Object apple_event, error_code; | |
1017 | { | |
1018 | Lisp_Object result = Qnil; | |
1019 | UInt32 suspension_id; | |
1020 | struct suspended_ae_info **p, *ae; | |
1021 | ||
1022 | suspension_id = get_suspension_id (apple_event); | |
1023 | ||
1024 | BLOCK_INPUT; | |
1025 | for (p = &suspended_apple_events; *p; p = &(*p)->next) | |
1026 | if ((*p)->suspension_id == suspension_id) | |
1027 | break; | |
1028 | if (*p) | |
1029 | { | |
1030 | ae = *p; | |
1031 | *p = (*p)->next; | |
1032 | if (INTEGERP (error_code) | |
bd619af5 | 1033 | && ae->reply.descriptorType != typeNull) |
0ffd2c76 YM |
1034 | { |
1035 | SInt32 errn = XINT (error_code); | |
1036 | ||
1037 | AEPutParamPtr (&ae->reply, keyErrorNumber, typeSInt32, | |
1038 | &errn, sizeof (SInt32)); | |
1039 | } | |
1040 | AESetTheCurrentEvent (&ae->apple_event); | |
1041 | AEResumeTheCurrentEvent (&ae->apple_event, &ae->reply, | |
1042 | ((AEEventHandlerUPP) | |
1043 | (EQ (error_code, Qt) ? | |
1044 | kAEUseStandardDispatch : kAENoDispatch)), | |
1045 | 0); | |
1046 | AEDisposeDesc (&ae->reply); | |
1047 | AEDisposeDesc (&ae->apple_event); | |
1048 | xfree (ae); | |
28714a27 YM |
1049 | result = Qt; |
1050 | } | |
1051 | UNBLOCK_INPUT; | |
1052 | ||
1053 | return result; | |
1054 | } | |
1055 | ||
1056 | \f | |
0ffd2c76 YM |
1057 | /*********************************************************************** |
1058 | Drag and drop support | |
1059 | ***********************************************************************/ | |
044f1b64 | 1060 | #if TARGET_API_MAC_CARBON |
5d6c5138 | 1061 | Lisp_Object Vmac_dnd_known_types; |
044f1b64 YM |
1062 | #endif /* TARGET_API_MAC_CARBON */ |
1063 | ||
044f1b64 | 1064 | \f |
0ffd2c76 YM |
1065 | /*********************************************************************** |
1066 | Services menu support | |
1067 | ***********************************************************************/ | |
944cda79 | 1068 | #ifdef MAC_OSX |
5d6c5138 YM |
1069 | /* Selection name for communication via Services menu. */ |
1070 | Lisp_Object Vmac_service_selection; | |
944cda79 YM |
1071 | #endif |
1072 | ||
944cda79 YM |
1073 | void |
1074 | syms_of_macselect () | |
1075 | { | |
1076 | defsubr (&Sx_get_selection_internal); | |
1077 | defsubr (&Sx_own_selection_internal); | |
1078 | defsubr (&Sx_disown_selection_internal); | |
1079 | defsubr (&Sx_selection_owner_p); | |
1080 | defsubr (&Sx_selection_exists_p); | |
28714a27 | 1081 | defsubr (&Smac_process_deferred_apple_events); |
0ffd2c76 YM |
1082 | defsubr (&Smac_cleanup_expired_apple_events); |
1083 | defsubr (&Smac_resume_apple_event); | |
1084 | defsubr (&Smac_ae_set_reply_parameter); | |
944cda79 YM |
1085 | |
1086 | Vselection_alist = Qnil; | |
1087 | staticpro (&Vselection_alist); | |
1088 | ||
1089 | DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist, | |
1090 | doc: /* An alist associating selection-types with functions. | |
1091 | These functions are called to convert the selection, with three args: | |
1092 | the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD'); | |
1093 | a desired type to which the selection should be converted; | |
1094 | and the local selection value (whatever was given to `x-own-selection'). | |
1095 | ||
1096 | The function should return the value to send to the Scrap Manager | |
99f963e4 | 1097 | \(must be a string). A return value of nil |
d18bee72 | 1098 | means that the conversion could not be done. */); |
944cda79 YM |
1099 | Vselection_converter_alist = Qnil; |
1100 | ||
1101 | DEFVAR_LISP ("x-lost-selection-functions", &Vx_lost_selection_functions, | |
1102 | doc: /* A list of functions to be called when Emacs loses a selection. | |
1103 | \(This happens when a Lisp program explicitly clears the selection.) | |
1104 | The functions are called with one argument, the selection type | |
1105 | \(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'). */); | |
1106 | Vx_lost_selection_functions = Qnil; | |
1107 | ||
1108 | DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system, | |
1109 | doc: /* Coding system for communicating with other programs. | |
1110 | When sending or receiving text via cut_buffer, selection, and clipboard, | |
1111 | the text is encoded or decoded by this coding system. | |
1112 | The default value is determined by the system script code. */); | |
1113 | Vselection_coding_system = Qnil; | |
1114 | ||
1115 | DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, | |
1116 | doc: /* Coding system for the next communication with other programs. | |
1117 | Usually, `selection-coding-system' is used for communicating with | |
1118 | other programs. But, if this variable is set, it is used for the | |
1119 | next communication only. After the communication, this variable is | |
1120 | set to nil. */); | |
1121 | Vnext_selection_coding_system = Qnil; | |
1122 | ||
28714a27 YM |
1123 | DEFVAR_LISP ("mac-apple-event-map", &Vmac_apple_event_map, |
1124 | doc: /* Keymap for Apple events handled by Emacs. */); | |
4d4983fd | 1125 | Vmac_apple_event_map = Qnil; |
28714a27 | 1126 | |
044f1b64 YM |
1127 | #if TARGET_API_MAC_CARBON |
1128 | DEFVAR_LISP ("mac-dnd-known-types", &Vmac_dnd_known_types, | |
1129 | doc: /* The types accepted by default for dropped data. | |
1130 | The types are chosen in the order they appear in the list. */); | |
5d6c5138 | 1131 | Vmac_dnd_known_types = mac_dnd_default_known_types (); |
044f1b64 YM |
1132 | #endif |
1133 | ||
3f2bf04a | 1134 | #ifdef MAC_OSX |
c2e93c82 | 1135 | DEFVAR_LISP ("mac-service-selection", &Vmac_service_selection, |
944cda79 | 1136 | doc: /* Selection name for communication via Services menu. */); |
c2e93c82 | 1137 | Vmac_service_selection = intern ("PRIMARY"); |
3f2bf04a | 1138 | #endif |
944cda79 YM |
1139 | |
1140 | QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY); | |
1141 | QSECONDARY = intern ("SECONDARY"); staticpro (&QSECONDARY); | |
1142 | QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP); | |
1143 | QTARGETS = intern ("TARGETS"); staticpro (&QTARGETS); | |
1144 | ||
1145 | Qforeign_selection = intern ("foreign-selection"); | |
1146 | staticpro (&Qforeign_selection); | |
1147 | ||
1148 | Qmac_scrap_name = intern ("mac-scrap-name"); | |
1149 | staticpro (&Qmac_scrap_name); | |
1150 | ||
1151 | Qmac_ostype = intern ("mac-ostype"); | |
1152 | staticpro (&Qmac_ostype); | |
28714a27 YM |
1153 | |
1154 | Qmac_apple_event_class = intern ("mac-apple-event-class"); | |
1155 | staticpro (&Qmac_apple_event_class); | |
1156 | ||
1157 | Qmac_apple_event_id = intern ("mac-apple-event-id"); | |
1158 | staticpro (&Qmac_apple_event_id); | |
0ffd2c76 YM |
1159 | |
1160 | Qemacs_suspension_id = intern ("emacs-suspension-id"); | |
1161 | staticpro (&Qemacs_suspension_id); | |
944cda79 | 1162 | } |
0ed4adfc MB |
1163 | |
1164 | /* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732 | |
1165 | (do not change this comment) */ |