1 /* Selection processing for Emacs on Mac OS.
2 Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
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.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
23 #include "blockinput.h"
26 #if !TARGET_API_MAC_CARBON
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
,
36 Lisp_Object QPRIMARY
, QSECONDARY
, QTIMESTAMP
, QTARGETS
;
38 static Lisp_Object Vx_lost_selection_functions
;
39 /* Coding system for communicating with other programs via selections. */
40 static Lisp_Object Vselection_coding_system
;
42 /* Coding system for the next communicating with other programs. */
43 static Lisp_Object Vnext_selection_coding_system
;
45 static Lisp_Object Qforeign_selection
;
47 /* The timestamp of the last input event Emacs received from the
49 /* Defined in keyboard.c. */
50 extern unsigned long last_event_timestamp
;
52 /* This is an association list whose elements are of the form
53 ( SELECTION-NAME SELECTION-VALUE SELECTION-TIMESTAMP FRAME OWNERSHIP-INFO)
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.
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.
67 The only (eq) parts of this list that are visible from Lisp are the
69 static Lisp_Object Vselection_alist
;
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
76 Lisp_Object Vselection_converter_alist
;
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'. */
81 Lisp_Object Qmac_scrap_name
, Qmac_ostype
;
84 /* Do protocol to assert ourself as a selection owner.
85 Update the Vselection_alist so that we can reply to later requests for
89 x_own_selection (selection_name
, selection_value
)
90 Lisp_Object selection_name
, selection_value
;
94 struct gcpro gcpro1
, gcpro2
;
95 Lisp_Object rest
, handler_fn
, value
, target_type
;
98 CHECK_SYMBOL (selection_name
);
100 GCPRO2 (selection_name
, selection_value
);
104 err
= mac_get_selection_from_symbol (selection_name
, 1, &sel
);
105 if (err
== noErr
&& sel
)
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
);
113 for (rest
= Vselection_converter_alist
; CONSP (rest
); rest
= XCDR (rest
))
115 if (!(CONSP (XCAR (rest
))
116 && (target_type
= XCAR (XCAR (rest
)),
117 SYMBOLP (target_type
))
118 && mac_valid_selection_target_p (target_type
)
119 && (handler_fn
= XCDR (XCAR (rest
)),
120 SYMBOLP (handler_fn
))))
123 if (!NILP (handler_fn
))
124 value
= call3 (handler_fn
, selection_name
,
125 target_type
, selection_value
);
130 if (mac_valid_selection_value_p (value
, target_type
))
131 err
= mac_put_selection_value (sel
, target_type
, value
);
132 else if (CONSP (value
)
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
));
138 unbind_to (count
, Qnil
);
145 if (sel
&& err
!= noErr
)
146 error ("Can't set selection");
148 /* Now update the local cache */
150 Lisp_Object selection_time
;
151 Lisp_Object selection_data
;
152 Lisp_Object ownership_info
;
153 Lisp_Object prev_value
;
155 selection_time
= long_to_cons (last_event_timestamp
);
159 ownership_info
= mac_get_selection_ownership_info (sel
);
163 ownership_info
= Qnil
; /* dummy value for local-only selection */
164 selection_data
= Fcons (selection_name
,
165 Fcons (selection_value
,
166 Fcons (selection_time
,
167 Fcons (selected_frame
,
168 Fcons (ownership_info
,
170 prev_value
= assq_no_quit (selection_name
, Vselection_alist
);
172 Vselection_alist
= Fcons (selection_data
, Vselection_alist
);
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
))
179 Lisp_Object rest
; /* we know it's not the CAR, so it's easy. */
180 for (rest
= Vselection_alist
; CONSP (rest
); rest
= XCDR (rest
))
181 if (EQ (prev_value
, Fcar (XCDR (rest
))))
183 XSETCDR (rest
, Fcdr (XCDR (rest
)));
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).
196 This calls random Lisp code, and may signal or gc. */
199 x_get_local_selection (selection_symbol
, target_type
, local_request
)
200 Lisp_Object selection_symbol
, target_type
;
203 Lisp_Object local_value
;
204 Lisp_Object handler_fn
, value
, type
, check
;
207 if (NILP (Fx_selection_owner_p (selection_symbol
)))
210 local_value
= assq_no_quit (selection_symbol
, Vselection_alist
);
212 /* TIMESTAMP is a special case 'cause that's easiest. */
213 if (EQ (target_type
, QTIMESTAMP
))
216 value
= XCAR (XCDR (XCDR (local_value
)));
219 else if (EQ (target_type
, QDELETE
))
222 Fx_disown_selection_internal
224 XCAR (XCDR (XCDR (local_value
))));
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
);
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. */
241 if (!NILP (handler_fn
))
242 value
= call3 (handler_fn
,
243 selection_symbol
, (local_request
? Qnil
: target_type
),
244 XCAR (XCDR (local_value
)));
247 unbind_to (count
, Qnil
);
253 /* Make sure this value is of a type that we could transmit
254 to another application. */
259 && SYMBOLP (XCAR (value
)))
261 check
= XCDR (value
);
263 if (NILP (value
) || mac_valid_selection_value_p (check
, type
))
266 signal_error ("Invalid data returned by selection-conversion function",
267 list2 (handler_fn
, value
));
271 /* Clear all selections that were made from frame F.
272 We do this when about to delete a frame. */
275 x_clear_frame_selections (f
)
281 XSETFRAME (frame
, f
);
283 /* Otherwise, we're really honest and truly being told to drop it.
284 Don't use Fdelq as that may QUIT;. */
286 /* Delete elements from the beginning of Vselection_alist. */
287 while (!NILP (Vselection_alist
)
288 && EQ (frame
, Fcar (Fcdr (Fcdr (Fcdr (Fcar (Vselection_alist
)))))))
290 /* Let random Lisp code notice that the selection has been stolen. */
291 Lisp_Object hooks
, selection_symbol
;
293 hooks
= Vx_lost_selection_functions
;
294 selection_symbol
= Fcar (Fcar (Vselection_alist
));
296 if (!EQ (hooks
, Qunbound
)
297 && !NILP (Fx_selection_owner_p (selection_symbol
)))
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);
308 Vselection_alist
= Fcdr (Vselection_alist
);
311 /* Delete elements after the beginning of Vselection_alist. */
312 for (rest
= Vselection_alist
; CONSP (rest
); rest
= XCDR (rest
))
313 if (EQ (frame
, Fcar (Fcdr (Fcdr (Fcdr (Fcar (XCDR (rest
))))))))
315 /* Let random Lisp code notice that the selection has been stolen. */
316 Lisp_Object hooks
, selection_symbol
;
318 hooks
= Vx_lost_selection_functions
;
319 selection_symbol
= Fcar (Fcar (XCDR (rest
)));
321 if (!EQ (hooks
, Qunbound
)
322 && !NILP (Fx_selection_owner_p (selection_symbol
)))
324 for (; CONSP (hooks
); hooks
= Fcdr (hooks
))
325 call1 (Fcar (hooks
), selection_symbol
);
326 #if 0 /* See above */
327 redisplay_preserve_echo_area (22);
330 XSETCDR (rest
, Fcdr (XCDR (rest
)));
335 /* Do protocol to read selection-data from the server.
336 Converts this to Lisp data and returns it. */
339 x_get_foreign_selection (selection_symbol
, target_type
, time_stamp
)
340 Lisp_Object selection_symbol
, target_type
, time_stamp
;
344 Lisp_Object result
= Qnil
;
348 err
= mac_get_selection_from_symbol (selection_symbol
, 0, &sel
);
349 if (err
== noErr
&& sel
)
351 if (EQ (target_type
, QTARGETS
))
353 result
= mac_get_selection_target_list (sel
);
354 result
= Fvconcat (1, &result
);
358 result
= mac_get_selection_value (sel
, target_type
);
359 if (STRINGP (result
))
360 Fput_text_property (make_number (0), make_number (SBYTES (result
)),
361 Qforeign_selection
, target_type
, result
);
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
;
381 CHECK_SYMBOL (selection_name
);
382 if (NILP (selection_value
)) error ("SELECTION-VALUE may not be nil");
383 x_own_selection (selection_name
, selection_value
);
384 return selection_value
;
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. */
392 DEFUN ("x-get-selection-internal", Fx_get_selection_internal
,
393 Sx_get_selection_internal
, 2, 3, 0,
394 doc
: /* Return text selected from some Mac application.
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. */)
398 (selection_symbol
, target_type
, time_stamp
)
399 Lisp_Object selection_symbol
, target_type
, time_stamp
;
401 Lisp_Object val
= Qnil
;
402 struct gcpro gcpro1
, gcpro2
;
403 GCPRO2 (target_type
, val
); /* we store newly consed data into these */
405 CHECK_SYMBOL (selection_symbol
);
406 CHECK_SYMBOL (target_type
);
408 val
= x_get_local_selection (selection_symbol
, target_type
, 1);
412 val
= x_get_foreign_selection (selection_symbol
, target_type
, time_stamp
);
417 && SYMBOLP (XCAR (val
)))
420 if (CONSP (val
) && NILP (XCDR (val
)))
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. */)
433 Lisp_Object selection
;
438 Lisp_Object local_selection_data
;
441 CHECK_SYMBOL (selection
);
443 if (NILP (Fx_selection_owner_p (selection
)))
444 return Qnil
; /* Don't disown the selection when we're not the owner. */
446 local_selection_data
= assq_no_quit (selection
, Vselection_alist
);
448 /* Don't use Fdelq as that may QUIT;. */
450 if (EQ (local_selection_data
, Fcar (Vselection_alist
)))
451 Vselection_alist
= Fcdr (Vselection_alist
);
455 for (rest
= Vselection_alist
; CONSP (rest
); rest
= XCDR (rest
))
456 if (EQ (local_selection_data
, Fcar (XCDR (rest
))))
458 XSETCDR (rest
, Fcdr (XCDR (rest
)));
463 /* Let random lisp code notice that the selection has been stolen. */
467 rest
= Vx_lost_selection_functions
;
468 if (!EQ (rest
, Qunbound
))
470 for (; CONSP (rest
); rest
= Fcdr (rest
))
471 call1 (Fcar (rest
), selection
);
472 prepare_menu_bars ();
473 redisplay_preserve_echo_area (20);
479 err
= mac_get_selection_from_symbol (selection
, 0, &sel
);
480 if (err
== noErr
&& sel
)
481 mac_clear_selection (&sel
);
489 DEFUN ("x-selection-owner-p", Fx_selection_owner_p
, Sx_selection_owner_p
,
491 doc
: /* Whether the current Emacs process owns the given SELECTION.
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'. */)
497 Lisp_Object selection
;
501 Lisp_Object result
= Qnil
, local_selection_data
;
504 CHECK_SYMBOL (selection
);
505 if (EQ (selection
, Qnil
)) selection
= QPRIMARY
;
506 if (EQ (selection
, Qt
)) selection
= QSECONDARY
;
508 local_selection_data
= assq_no_quit (selection
, Vselection_alist
);
510 if (NILP (local_selection_data
))
515 err
= mac_get_selection_from_symbol (selection
, 0, &sel
);
516 if (err
== noErr
&& sel
)
518 Lisp_Object ownership_info
;
520 ownership_info
= XCAR (XCDR (XCDR (XCDR (XCDR (local_selection_data
)))));
521 if (!NILP (Fequal (ownership_info
,
522 mac_get_selection_ownership_info (sel
))))
533 DEFUN ("x-selection-exists-p", Fx_selection_exists_p
, Sx_selection_exists_p
,
535 doc
: /* Whether there is an owner for the given SELECTION.
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'. */)
541 Lisp_Object selection
;
545 Lisp_Object result
= Qnil
, rest
;
547 /* It should be safe to call this before we have an Mac frame. */
548 if (! FRAME_MAC_P (SELECTED_FRAME ()))
551 CHECK_SYMBOL (selection
);
552 if (!NILP (Fx_selection_owner_p (selection
)))
554 if (EQ (selection
, Qnil
)) selection
= QPRIMARY
;
555 if (EQ (selection
, Qt
)) selection
= QSECONDARY
;
559 err
= mac_get_selection_from_symbol (selection
, 0, &sel
);
560 if (err
== noErr
&& sel
)
561 for (rest
= Vselection_converter_alist
; CONSP (rest
); rest
= XCDR (rest
))
563 if (CONSP (XCAR (rest
)) && SYMBOLP (XCAR (XCAR (rest
)))
564 && mac_selection_has_target_p (sel
, XCAR (XCAR (rest
))))
577 /***********************************************************************
579 ***********************************************************************/
580 int mac_ready_for_apple_events
= 0;
581 Lisp_Object Vmac_apple_event_map
;
582 Lisp_Object Qmac_apple_event_class
, Qmac_apple_event_id
;
583 static Lisp_Object Qemacs_suspension_id
;
584 extern Lisp_Object Qundefined
;
585 extern void mac_store_apple_event
P_ ((Lisp_Object
, Lisp_Object
,
588 struct apple_event_binding
590 UInt32 code
; /* Apple event class or ID. */
591 Lisp_Object key
, binding
;
594 struct suspended_ae_info
596 UInt32 expiration_tick
, suspension_id
;
597 AppleEvent apple_event
, reply
;
598 struct suspended_ae_info
*next
;
601 /* List of apple events deferred at the startup time. */
602 static struct suspended_ae_info
*deferred_apple_events
= NULL
;
604 /* List of suspended apple events, in order of expiration_tick. */
605 static struct suspended_ae_info
*suspended_apple_events
= NULL
;
608 find_event_binding_fun (key
, binding
, args
, data
)
609 Lisp_Object key
, binding
, args
;
612 struct apple_event_binding
*event_binding
=
613 (struct apple_event_binding
*)data
;
614 Lisp_Object code_string
;
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
))
623 event_binding
->key
= key
;
624 event_binding
->binding
= binding
;
629 find_event_binding (keymap
, event_binding
, class_p
)
631 struct apple_event_binding
*event_binding
;
634 if (event_binding
->code
== 0)
635 event_binding
->binding
=
636 access_keymap (keymap
, event_binding
->key
, 0, 1, 0);
639 event_binding
->binding
= Qnil
;
640 map_keymap (keymap
, find_event_binding_fun
,
641 class_p
? Qmac_apple_event_class
: Qmac_apple_event_id
,
647 mac_find_apple_event_spec (class, id
, class_key
, id_key
, binding
)
650 Lisp_Object
*class_key
, *id_key
, *binding
;
652 struct apple_event_binding event_binding
;
657 keymap
= get_keymap (Vmac_apple_event_map
, 0, 0);
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);
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
;
679 defer_apple_events (apple_event
, reply
)
680 const AppleEvent
*apple_event
, *reply
;
683 struct suspended_ae_info
*new;
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
;
690 err
= AESuspendTheCurrentEvent (apple_event
);
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
695 them in `deferred_apple_events'. */
697 err
= AEDuplicateDesc (apple_event
, &new->apple_event
);
699 err
= AEDuplicateDesc (reply
, &new->reply
);
702 new->next
= deferred_apple_events
;
703 deferred_apple_events
= new;
707 AEDisposeDesc (&new->apple_event
);
708 AEDisposeDesc (&new->reply
);
716 mac_handle_apple_event_1 (class, id
, apple_event
, reply
)
717 Lisp_Object
class, id
;
718 const AppleEvent
*apple_event
;
722 static UInt32 suspension_id
= 0;
723 struct suspended_ae_info
*new;
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
;
730 err
= AESuspendTheCurrentEvent (apple_event
);
732 err
= AEDuplicateDesc (apple_event
, &new->apple_event
);
734 err
= AEDuplicateDesc (reply
, &new->reply
);
736 err
= AEPutAttributePtr (&new->apple_event
, KEY_EMACS_SUSPENSION_ID_ATTR
,
737 typeUInt32
, &suspension_id
, sizeof (UInt32
));
741 SInt32 reply_requested
;
743 err1
= AEGetAttributePtr (&new->apple_event
, keyReplyRequestedAttr
,
744 typeSInt32
, NULL
, &reply_requested
,
745 sizeof (SInt32
), NULL
);
748 /* Emulate keyReplyRequestedAttr in older versions. */
749 reply_requested
= reply
->descriptorType
!= typeNull
;
750 err
= AEPutAttributePtr (&new->apple_event
, keyReplyRequestedAttr
,
751 typeSInt32
, &reply_requested
,
758 struct suspended_ae_info
**p
;
760 new->suspension_id
= suspension_id
;
762 err
= AEGetAttributePtr (apple_event
, keyTimeoutAttr
, typeSInt32
,
763 NULL
, &timeout
, sizeof (SInt32
), NULL
);
764 new->expiration_tick
= TickCount () + timeout
;
766 for (p
= &suspended_apple_events
; *p
; p
= &(*p
)->next
)
767 if ((*p
)->expiration_tick
>= new->expiration_tick
)
772 mac_store_apple_event (class, id
, &new->apple_event
);
776 AEDisposeDesc (&new->reply
);
777 AEDisposeDesc (&new->apple_event
);
785 mac_handle_apple_event (apple_event
, reply
, refcon
)
786 const AppleEvent
*apple_event
;
791 UInt32 suspension_id
;
792 AEEventClass event_class
;
794 Lisp_Object class_key
, id_key
, binding
;
796 if (!mac_ready_for_apple_events
)
798 err
= defer_apple_events (apple_event
, reply
);
800 return errAEEventNotHandled
;
804 err
= AEGetAttributePtr (apple_event
, KEY_EMACS_SUSPENSION_ID_ATTR
,
806 &suspension_id
, sizeof (UInt32
), NULL
);
808 /* Previously suspended event. Pass it to the next handler. */
809 return errAEEventNotHandled
;
811 err
= AEGetAttributePtr (apple_event
, keyEventClassAttr
, typeType
, NULL
,
812 &event_class
, sizeof (AEEventClass
), NULL
);
814 err
= AEGetAttributePtr (apple_event
, keyEventIDAttr
, typeType
, NULL
,
815 &event_id
, sizeof (AEEventID
), NULL
);
818 mac_find_apple_event_spec (event_class
, event_id
,
819 &class_key
, &id_key
, &binding
);
820 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
822 if (INTEGERP (binding
))
823 return XINT (binding
);
824 err
= mac_handle_apple_event_1 (class_key
, id_key
,
828 err
= errAEEventNotHandled
;
833 return errAEEventNotHandled
;
837 cleanup_suspended_apple_events (head
, all_p
)
838 struct suspended_ae_info
**head
;
841 UInt32 current_tick
= TickCount (), nresumed
= 0;
842 struct suspended_ae_info
*p
, *next
;
844 for (p
= *head
; p
; p
= next
)
846 if (!all_p
&& p
->expiration_tick
> current_tick
)
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
);
863 cleanup_all_suspended_apple_events ()
865 cleanup_suspended_apple_events (&deferred_apple_events
, 1);
866 cleanup_suspended_apple_events (&suspended_apple_events
, 1);
870 get_suspension_id (apple_event
)
871 Lisp_Object apple_event
;
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");
881 tem
= assq_no_quit (Qemacs_suspension_id
, XCDR (apple_event
));
883 error ("Suspension ID not available");
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");
892 return *((UInt32
*) SDATA (XCDR (tem
)));
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. */)
900 if (mac_ready_for_apple_events
)
904 mac_ready_for_apple_events
= 1;
905 if (deferred_apple_events
)
907 struct suspended_ae_info
*prev
, *tail
, *next
;
909 /* `nreverse' deferred_apple_events. */
911 for (tail
= deferred_apple_events
; tail
; tail
= next
)
918 /* Now `prev' points to the first cell. */
919 for (tail
= prev
; tail
; tail
= next
)
922 AEResumeTheCurrentEvent (&tail
->apple_event
, &tail
->reply
,
924 kAEUseStandardDispatch
), 0);
925 AEDisposeDesc (&tail
->reply
);
926 AEDisposeDesc (&tail
->apple_event
);
930 deferred_apple_events
= NULL
;
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. */)
945 nexpired
= cleanup_suspended_apple_events (&suspended_apple_events
, 0);
948 return make_number (nexpired
);
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:
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
963 * Otherwise, DATA is a string.
965 If a (sub-)descriptor is in an invalid format, it is silently treated
968 Return t if the parameter is successfully set. Otherwise return nil. */)
969 (apple_event
, keyword
, descriptor
)
970 Lisp_Object apple_event
, keyword
, descriptor
;
972 Lisp_Object result
= Qnil
;
973 UInt32 suspension_id
;
974 struct suspended_ae_info
*p
;
976 suspension_id
= get_suspension_id (apple_event
);
978 CHECK_STRING (keyword
);
979 if (SBYTES (keyword
) != 4)
980 error ("Apple event keyword must be a 4-byte string: %s",
984 for (p
= suspended_apple_events
; p
; p
= p
->next
)
985 if (p
->suspension_id
== suspension_id
)
987 if (p
&& p
->reply
.descriptorType
!= typeNull
)
991 err
= mac_ae_put_lisp (&p
->reply
,
992 EndianU32_BtoN (*((UInt32
*) SDATA (keyword
))),
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.
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.
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
;
1018 Lisp_Object result
= Qnil
;
1019 UInt32 suspension_id
;
1020 struct suspended_ae_info
**p
, *ae
;
1022 suspension_id
= get_suspension_id (apple_event
);
1025 for (p
= &suspended_apple_events
; *p
; p
= &(*p
)->next
)
1026 if ((*p
)->suspension_id
== suspension_id
)
1032 if (INTEGERP (error_code
)
1033 && ae
->reply
.descriptorType
!= typeNull
)
1035 SInt32 errn
= XINT (error_code
);
1037 AEPutParamPtr (&ae
->reply
, keyErrorNumber
, typeSInt32
,
1038 &errn
, sizeof (SInt32
));
1040 AESetTheCurrentEvent (&ae
->apple_event
);
1041 AEResumeTheCurrentEvent (&ae
->apple_event
, &ae
->reply
,
1042 ((AEEventHandlerUPP
)
1043 (EQ (error_code
, Qt
) ?
1044 kAEUseStandardDispatch
: kAENoDispatch
)),
1046 AEDisposeDesc (&ae
->reply
);
1047 AEDisposeDesc (&ae
->apple_event
);
1057 /***********************************************************************
1058 Drag and drop support
1059 ***********************************************************************/
1060 #if TARGET_API_MAC_CARBON
1061 Lisp_Object Vmac_dnd_known_types
;
1062 #endif /* TARGET_API_MAC_CARBON */
1065 /***********************************************************************
1066 Services menu support
1067 ***********************************************************************/
1069 /* Selection name for communication via Services menu. */
1070 Lisp_Object Vmac_service_selection
;
1074 syms_of_macselect ()
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
);
1081 defsubr (&Smac_process_deferred_apple_events
);
1082 defsubr (&Smac_cleanup_expired_apple_events
);
1083 defsubr (&Smac_resume_apple_event
);
1084 defsubr (&Smac_ae_set_reply_parameter
);
1086 Vselection_alist
= Qnil
;
1087 staticpro (&Vselection_alist
);
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').
1096 The function should return the value to send to the Scrap Manager
1097 \(must be a string). A return value of nil
1098 means that the conversion could not be done. */);
1099 Vselection_converter_alist
= Qnil
;
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
;
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
;
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
1121 Vnext_selection_coding_system
= Qnil
;
1123 DEFVAR_LISP ("mac-apple-event-map", &Vmac_apple_event_map
,
1124 doc
: /* Keymap for Apple events handled by Emacs. */);
1125 Vmac_apple_event_map
= Qnil
;
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. */);
1131 Vmac_dnd_known_types
= mac_dnd_default_known_types ();
1135 DEFVAR_LISP ("mac-service-selection", &Vmac_service_selection
,
1136 doc
: /* Selection name for communication via Services menu. */);
1137 Vmac_service_selection
= intern ("PRIMARY");
1140 QPRIMARY
= intern ("PRIMARY"); staticpro (&QPRIMARY
);
1141 QSECONDARY
= intern ("SECONDARY"); staticpro (&QSECONDARY
);
1142 QTIMESTAMP
= intern ("TIMESTAMP"); staticpro (&QTIMESTAMP
);
1143 QTARGETS
= intern ("TARGETS"); staticpro (&QTARGETS
);
1145 Qforeign_selection
= intern ("foreign-selection");
1146 staticpro (&Qforeign_selection
);
1148 Qmac_scrap_name
= intern ("mac-scrap-name");
1149 staticpro (&Qmac_scrap_name
);
1151 Qmac_ostype
= intern ("mac-ostype");
1152 staticpro (&Qmac_ostype
);
1154 Qmac_apple_event_class
= intern ("mac-apple-event-class");
1155 staticpro (&Qmac_apple_event_class
);
1157 Qmac_apple_event_id
= intern ("mac-apple-event-id");
1158 staticpro (&Qmac_apple_event_id
);
1160 Qemacs_suspension_id
= intern ("emacs-suspension-id");
1161 staticpro (&Qemacs_suspension_id
);
1164 /* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732
1165 (do not change this comment) */