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, or (at your option)
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; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA. */
25 #include "blockinput.h"
28 #if !TARGET_API_MAC_CARBON
31 typedef ResType ScrapFlavorType
;
32 #endif /* !TARGET_API_MAC_CARBON */
34 static OSStatus get_scrap_from_symbol
P_ ((Lisp_Object
, int, ScrapRef
*));
35 static ScrapFlavorType get_flavor_type_from_symbol
P_ ((Lisp_Object
));
36 static int valid_scrap_target_type_p
P_ ((Lisp_Object
));
37 static OSStatus clear_scrap
P_ ((ScrapRef
*));
38 static OSStatus put_scrap_string
P_ ((ScrapRef
, Lisp_Object
, Lisp_Object
));
39 static OSStatus put_scrap_private_timestamp
P_ ((ScrapRef
, unsigned long));
40 static ScrapFlavorType scrap_has_target_type
P_ ((ScrapRef
, Lisp_Object
));
41 static Lisp_Object get_scrap_string
P_ ((ScrapRef
, Lisp_Object
));
42 static OSStatus get_scrap_private_timestamp
P_ ((ScrapRef
, unsigned long *));
43 static Lisp_Object get_scrap_target_type_list
P_ ((ScrapRef
));
44 static void x_own_selection
P_ ((Lisp_Object
, Lisp_Object
));
45 static Lisp_Object x_get_local_selection
P_ ((Lisp_Object
, Lisp_Object
, int));
46 static Lisp_Object x_get_foreign_selection
P_ ((Lisp_Object
,
49 EXFUN (Fx_selection_owner_p
, 1);
51 static OSStatus mac_handle_service_event
P_ ((EventHandlerCallRef
,
53 void init_service_handler
P_ ((void));
56 Lisp_Object QPRIMARY
, QSECONDARY
, QTIMESTAMP
, QTARGETS
;
58 static Lisp_Object Vx_lost_selection_functions
;
59 /* Coding system for communicating with other programs via scrap. */
60 static Lisp_Object Vselection_coding_system
;
62 /* Coding system for the next communicating with other programs. */
63 static Lisp_Object Vnext_selection_coding_system
;
65 static Lisp_Object Qforeign_selection
;
67 /* The timestamp of the last input event Emacs received from the
69 /* Defined in keyboard.c. */
70 extern unsigned long last_event_timestamp
;
72 /* This is an association list whose elements are of the form
73 ( SELECTION-NAME SELECTION-VALUE SELECTION-TIMESTAMP FRAME)
74 SELECTION-NAME is a lisp symbol.
75 SELECTION-VALUE is the value that emacs owns for that selection.
76 It may be any kind of Lisp object.
77 SELECTION-TIMESTAMP is the time at which emacs began owning this selection,
78 as a cons of two 16-bit numbers (making a 32 bit time.)
79 FRAME is the frame for which we made the selection.
80 If there is an entry in this alist, and the data for the flavor
81 type SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP in the corresponding scrap
82 (if exists) coincides with SELECTION-TIMESTAMP, then it can be
83 assumed that Emacs owns that selection.
84 The only (eq) parts of this list that are visible from Lisp are the
86 static Lisp_Object Vselection_alist
;
88 #define SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP 'Etsp'
90 /* This is an alist whose CARs are selection-types and whose CDRs are
91 the names of Lisp functions to call to convert the given Emacs
92 selection value to a string representing the given selection type.
93 This is for Lisp-level extension of the emacs selection
95 static Lisp_Object Vselection_converter_alist
;
97 /* A selection name (represented as a Lisp symbol) can be associated
98 with a named scrap via `mac-scrap-name' property. Likewise for a
99 selection type with a scrap flavor type via `mac-ostype'. */
100 static Lisp_Object Qmac_scrap_name
, Qmac_ostype
;
103 /* Selection name for communication via Services menu. */
104 static Lisp_Object Vmac_service_selection
;
107 /* Get a reference to the scrap corresponding to the symbol SYM. The
108 reference is set to *SCRAP, and it becomes NULL if there's no
109 corresponding scrap. Clear the scrap if CLEAR_P is non-zero. */
112 get_scrap_from_symbol (sym
, clear_p
, scrap
)
117 OSStatus err
= noErr
;
118 Lisp_Object str
= Fget (sym
, Qmac_scrap_name
);
124 #if TARGET_API_MAC_CARBON
126 CFStringRef scrap_name
= cfstring_create_with_string (str
);
127 OptionBits options
= (clear_p
? kScrapClearNamedScrap
128 : kScrapGetNamedScrap
);
130 err
= GetScrapByName (scrap_name
, options
, scrap
);
131 CFRelease (scrap_name
);
134 err
= ClearCurrentScrap ();
136 err
= GetCurrentScrap (scrap
);
137 #endif /* !MAC_OSX */
138 #else /* !TARGET_API_MAC_CARBON */
143 #endif /* !TARGET_API_MAC_CARBON */
149 /* Get a scrap flavor type from the symbol SYM. Return 0 if no
150 corresponding flavor type. */
152 static ScrapFlavorType
153 get_flavor_type_from_symbol (sym
)
156 Lisp_Object str
= Fget (sym
, Qmac_ostype
);
158 if (STRINGP (str
) && SBYTES (str
) == 4)
159 return EndianU32_BtoN (*((UInt32
*) SDATA (str
)));
164 /* Check if the symbol SYM has a corresponding scrap flavor type. */
167 valid_scrap_target_type_p (sym
)
170 return get_flavor_type_from_symbol (sym
) != 0;
173 /* Clear the scrap whose reference is *SCRAP. */
175 static INLINE OSStatus
179 #if TARGET_API_MAC_CARBON
181 return ClearScrap (scrap
);
183 return ClearCurrentScrap ();
185 #else /* !TARGET_API_MAC_CARBON */
187 #endif /* !TARGET_API_MAC_CARBON */
190 /* Put Lisp String STR to the scrap SCRAP. The target type is
191 specified by TYPE. */
194 put_scrap_string (scrap
, type
, str
)
196 Lisp_Object type
, str
;
198 ScrapFlavorType flavor_type
= get_flavor_type_from_symbol (type
);
200 if (flavor_type
== 0)
203 #if TARGET_API_MAC_CARBON
204 return PutScrapFlavor (scrap
, flavor_type
, kScrapFlavorMaskNone
,
205 SBYTES (str
), SDATA (str
));
206 #else /* !TARGET_API_MAC_CARBON */
207 return PutScrap (SBYTES (str
), flavor_type
, SDATA (str
));
208 #endif /* !TARGET_API_MAC_CARBON */
211 /* Put TIMESTAMP to the scrap SCRAP. The timestamp is used for
212 checking if the scrap is owned by the process. */
214 static INLINE OSStatus
215 put_scrap_private_timestamp (scrap
, timestamp
)
217 unsigned long timestamp
;
219 #if TARGET_API_MAC_CARBON
220 return PutScrapFlavor (scrap
, SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP
,
221 kScrapFlavorMaskSenderOnly
,
222 sizeof (timestamp
), ×tamp
);
223 #else /* !TARGET_API_MAC_CARBON */
224 return PutScrap (sizeof (timestamp
), SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP
,
226 #endif /* !TARGET_API_MAC_CARBON */
229 /* Check if data for the target type TYPE is available in SCRAP. */
231 static ScrapFlavorType
232 scrap_has_target_type (scrap
, type
)
237 ScrapFlavorType flavor_type
= get_flavor_type_from_symbol (type
);
241 #if TARGET_API_MAC_CARBON
242 ScrapFlavorFlags flags
;
244 err
= GetScrapFlavorFlags (scrap
, flavor_type
, &flags
);
247 #else /* !TARGET_API_MAC_CARBON */
250 size
= GetScrap (NULL
, flavor_type
, &offset
);
253 #endif /* !TARGET_API_MAC_CARBON */
259 /* Get data for the target type TYPE from SCRAP and create a Lisp
260 string. Return nil if failed to get data. */
263 get_scrap_string (scrap
, type
)
268 Lisp_Object result
= Qnil
;
269 ScrapFlavorType flavor_type
= get_flavor_type_from_symbol (type
);
270 #if TARGET_API_MAC_CARBON
275 err
= GetScrapFlavorSize (scrap
, flavor_type
, &size
);
280 result
= make_uninit_string (size
);
281 err
= GetScrapFlavorData (scrap
, flavor_type
,
282 &size
, SDATA (result
));
285 else if (size
< SBYTES (result
))
286 result
= make_unibyte_string (SDATA (result
), size
);
288 while (STRINGP (result
) && size
> SBYTES (result
));
296 size
= GetScrap (NULL
, flavor_type
, &offset
);
299 handle
= NewHandle (size
);
301 size
= GetScrap (handle
, flavor_type
, &offset
);
303 result
= make_unibyte_string (*handle
, size
);
304 DisposeHandle (handle
);
311 /* Get timestamp from the scrap SCRAP and set to *TIMPSTAMP. */
314 get_scrap_private_timestamp (scrap
, timestamp
)
316 unsigned long *timestamp
;
318 OSStatus err
= noErr
;
319 #if TARGET_API_MAC_CARBON
320 ScrapFlavorFlags flags
;
322 err
= GetScrapFlavorFlags (scrap
, SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP
, &flags
);
325 if (!(flags
& kScrapFlavorMaskSenderOnly
))
329 Size size
= sizeof (*timestamp
);
331 err
= GetScrapFlavorData (scrap
, SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP
,
333 if (err
== noErr
&& size
!= sizeof (*timestamp
))
337 #else /* !TARGET_API_MAC_CARBON */
341 size
= GetScrap (NULL
, SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP
, &offset
);
342 if (size
== sizeof (*timestamp
))
344 handle
= NewHandle (size
);
346 size
= GetScrap (handle
, SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP
, &offset
);
347 if (size
== sizeof (*timestamp
))
348 *timestamp
= *((unsigned long *) *handle
);
349 DisposeHandle (handle
);
351 if (size
!= sizeof (*timestamp
))
353 #endif /* !TARGET_API_MAC_CARBON */
358 /* Get the list of target types in SCRAP. The return value is a list
359 of target type symbols possibly followed by scrap flavor type
363 get_scrap_target_type_list (scrap
)
366 Lisp_Object result
= Qnil
, rest
, target_type
;
367 #if TARGET_API_MAC_CARBON
369 UInt32 count
, i
, type
;
370 ScrapFlavorInfo
*flavor_info
= NULL
;
371 Lisp_Object strings
= Qnil
;
373 err
= GetScrapFlavorCount (scrap
, &count
);
375 flavor_info
= xmalloc (sizeof (ScrapFlavorInfo
) * count
);
376 err
= GetScrapFlavorInfoList (scrap
, &count
, flavor_info
);
382 if (flavor_info
== NULL
)
385 for (rest
= Vselection_converter_alist
; CONSP (rest
); rest
= XCDR (rest
))
387 ScrapFlavorType flavor_type
= 0;
389 if (CONSP (XCAR (rest
))
390 && (target_type
= XCAR (XCAR (rest
)),
391 SYMBOLP (target_type
))
392 && (flavor_type
= scrap_has_target_type (scrap
, target_type
)))
394 result
= Fcons (target_type
, result
);
395 #if TARGET_API_MAC_CARBON
396 for (i
= 0; i
< count
; i
++)
397 if (flavor_info
[i
].flavorType
== flavor_type
)
399 flavor_info
[i
].flavorType
= 0;
405 #if TARGET_API_MAC_CARBON
408 for (i
= 0; i
< count
; i
++)
409 if (flavor_info
[i
].flavorType
)
411 type
= EndianU32_NtoB (flavor_info
[i
].flavorType
);
412 strings
= Fcons (make_unibyte_string ((char *) &type
, 4), strings
);
414 result
= nconc2 (result
, strings
);
422 /* Do protocol to assert ourself as a selection owner.
423 Update the Vselection_alist so that we can reply to later requests for
427 x_own_selection (selection_name
, selection_value
)
428 Lisp_Object selection_name
, selection_value
;
432 struct gcpro gcpro1
, gcpro2
;
433 Lisp_Object rest
, handler_fn
, value
, type
;
436 CHECK_SYMBOL (selection_name
);
438 GCPRO2 (selection_name
, selection_value
);
442 err
= get_scrap_from_symbol (selection_name
, 1, &scrap
);
443 if (err
== noErr
&& scrap
)
445 /* Don't allow a quit within the converter.
446 When the user types C-g, he would be surprised
447 if by luck it came during a converter. */
448 count
= SPECPDL_INDEX ();
449 specbind (Qinhibit_quit
, Qt
);
451 for (rest
= Vselection_converter_alist
; CONSP (rest
); rest
= XCDR (rest
))
453 if (!(CONSP (XCAR (rest
))
454 && (type
= XCAR (XCAR (rest
)),
456 && valid_scrap_target_type_p (type
)
457 && (handler_fn
= XCDR (XCAR (rest
)),
458 SYMBOLP (handler_fn
))))
461 if (!NILP (handler_fn
))
462 value
= call3 (handler_fn
, selection_name
,
463 type
, selection_value
);
466 err
= put_scrap_string (scrap
, type
, value
);
467 else if (CONSP (value
)
468 && EQ (XCAR (value
), type
)
469 && STRINGP (XCDR (value
)))
470 err
= put_scrap_string (scrap
, type
, XCDR (value
));
473 unbind_to (count
, Qnil
);
476 err
= put_scrap_private_timestamp (scrap
, last_event_timestamp
);
483 if (scrap
&& err
!= noErr
)
484 error ("Can't set selection");
486 /* Now update the local cache */
488 Lisp_Object selection_time
;
489 Lisp_Object selection_data
;
490 Lisp_Object prev_value
;
492 selection_time
= long_to_cons (last_event_timestamp
);
493 selection_data
= Fcons (selection_name
,
494 Fcons (selection_value
,
495 Fcons (selection_time
,
496 Fcons (selected_frame
, Qnil
))));
497 prev_value
= assq_no_quit (selection_name
, Vselection_alist
);
499 Vselection_alist
= Fcons (selection_data
, Vselection_alist
);
501 /* If we already owned the selection, remove the old selection data.
502 Perhaps we should destructively modify it instead.
503 Don't use Fdelq as that may QUIT. */
504 if (!NILP (prev_value
))
506 Lisp_Object rest
; /* we know it's not the CAR, so it's easy. */
507 for (rest
= Vselection_alist
; !NILP (rest
); rest
= Fcdr (rest
))
508 if (EQ (prev_value
, Fcar (XCDR (rest
))))
510 XSETCDR (rest
, Fcdr (XCDR (rest
)));
517 /* Given a selection-name and desired type, look up our local copy of
518 the selection value and convert it to the type.
519 The value is nil or a string.
520 This function is used both for remote requests (LOCAL_REQUEST is zero)
521 and for local x-get-selection-internal (LOCAL_REQUEST is nonzero).
523 This calls random Lisp code, and may signal or gc. */
526 x_get_local_selection (selection_symbol
, target_type
, local_request
)
527 Lisp_Object selection_symbol
, target_type
;
530 Lisp_Object local_value
;
531 Lisp_Object handler_fn
, value
, type
, check
;
534 if (NILP (Fx_selection_owner_p (selection_symbol
)))
537 local_value
= assq_no_quit (selection_symbol
, Vselection_alist
);
539 /* TIMESTAMP is a special case 'cause that's easiest. */
540 if (EQ (target_type
, QTIMESTAMP
))
543 value
= XCAR (XCDR (XCDR (local_value
)));
546 else if (EQ (target_type
, QDELETE
))
549 Fx_disown_selection_internal
551 XCAR (XCDR (XCDR (local_value
))));
557 /* Don't allow a quit within the converter.
558 When the user types C-g, he would be surprised
559 if by luck it came during a converter. */
560 count
= SPECPDL_INDEX ();
561 specbind (Qinhibit_quit
, Qt
);
563 CHECK_SYMBOL (target_type
);
564 handler_fn
= Fcdr (Fassq (target_type
, Vselection_converter_alist
));
565 /* gcpro is not needed here since nothing but HANDLER_FN
566 is live, and that ought to be a symbol. */
568 if (!NILP (handler_fn
))
569 value
= call3 (handler_fn
,
570 selection_symbol
, (local_request
? Qnil
: target_type
),
571 XCAR (XCDR (local_value
)));
574 unbind_to (count
, Qnil
);
577 /* Make sure this value is of a type that we could transmit
578 to another X client. */
582 && SYMBOLP (XCAR (value
)))
584 check
= XCDR (value
);
592 /* Check for a value that cons_to_long could handle. */
593 else if (CONSP (check
)
594 && INTEGERP (XCAR (check
))
595 && (INTEGERP (XCDR (check
))
597 (CONSP (XCDR (check
))
598 && INTEGERP (XCAR (XCDR (check
)))
599 && NILP (XCDR (XCDR (check
))))))
602 signal_error ("Invalid data returned by selection-conversion function",
603 list2 (handler_fn
, value
));
607 /* Clear all selections that were made from frame F.
608 We do this when about to delete a frame. */
611 x_clear_frame_selections (f
)
617 XSETFRAME (frame
, f
);
619 /* Otherwise, we're really honest and truly being told to drop it.
620 Don't use Fdelq as that may QUIT;. */
622 /* Delete elements from the beginning of Vselection_alist. */
623 while (!NILP (Vselection_alist
)
624 && EQ (frame
, Fcar (Fcdr (Fcdr (Fcdr (Fcar (Vselection_alist
)))))))
626 /* Let random Lisp code notice that the selection has been stolen. */
627 Lisp_Object hooks
, selection_symbol
;
629 hooks
= Vx_lost_selection_functions
;
630 selection_symbol
= Fcar (Fcar (Vselection_alist
));
632 if (!EQ (hooks
, Qunbound
)
633 && !NILP (Fx_selection_owner_p (selection_symbol
)))
635 for (; CONSP (hooks
); hooks
= Fcdr (hooks
))
636 call1 (Fcar (hooks
), selection_symbol
);
637 #if 0 /* This can crash when deleting a frame
638 from x_connection_closed. Anyway, it seems unnecessary;
639 something else should cause a redisplay. */
640 redisplay_preserve_echo_area (21);
644 Vselection_alist
= Fcdr (Vselection_alist
);
647 /* Delete elements after the beginning of Vselection_alist. */
648 for (rest
= Vselection_alist
; !NILP (rest
); rest
= Fcdr (rest
))
649 if (EQ (frame
, Fcar (Fcdr (Fcdr (Fcdr (Fcar (XCDR (rest
))))))))
651 /* Let random Lisp code notice that the selection has been stolen. */
652 Lisp_Object hooks
, selection_symbol
;
654 hooks
= Vx_lost_selection_functions
;
655 selection_symbol
= Fcar (Fcar (XCDR (rest
)));
657 if (!EQ (hooks
, Qunbound
)
658 && !NILP (Fx_selection_owner_p (selection_symbol
)))
660 for (; CONSP (hooks
); hooks
= Fcdr (hooks
))
661 call1 (Fcar (hooks
), selection_symbol
);
662 #if 0 /* See above */
663 redisplay_preserve_echo_area (22);
666 XSETCDR (rest
, Fcdr (XCDR (rest
)));
671 /* Do protocol to read selection-data from the server.
672 Converts this to Lisp data and returns it. */
675 x_get_foreign_selection (selection_symbol
, target_type
, time_stamp
)
676 Lisp_Object selection_symbol
, target_type
, time_stamp
;
680 Lisp_Object result
= Qnil
;
684 err
= get_scrap_from_symbol (selection_symbol
, 0, &scrap
);
685 if (err
== noErr
&& scrap
)
687 if (EQ (target_type
, QTARGETS
))
689 result
= get_scrap_target_type_list (scrap
);
690 result
= Fvconcat (1, &result
);
694 result
= get_scrap_string (scrap
, target_type
);
695 if (STRINGP (result
))
696 Fput_text_property (make_number (0), make_number (SBYTES (result
)),
697 Qforeign_selection
, target_type
, result
);
707 DEFUN ("x-own-selection-internal", Fx_own_selection_internal
,
708 Sx_own_selection_internal
, 2, 2, 0,
709 doc
: /* Assert a selection of the given TYPE with the given VALUE.
710 TYPE is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
711 VALUE is typically a string, or a cons of two markers, but may be
712 anything that the functions on `selection-converter-alist' know about. */)
713 (selection_name
, selection_value
)
714 Lisp_Object selection_name
, selection_value
;
717 CHECK_SYMBOL (selection_name
);
718 if (NILP (selection_value
)) error ("SELECTION-VALUE may not be nil");
719 x_own_selection (selection_name
, selection_value
);
720 return selection_value
;
724 /* Request the selection value from the owner. If we are the owner,
725 simply return our selection value. If we are not the owner, this
726 will block until all of the data has arrived. */
728 DEFUN ("x-get-selection-internal", Fx_get_selection_internal
,
729 Sx_get_selection_internal
, 2, 3, 0,
730 doc
: /* Return text selected from some Mac application.
731 SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
732 TYPE is the type of data desired, typically `STRING'.
733 TIME_STAMP is ignored on Mac. */)
734 (selection_symbol
, target_type
, time_stamp
)
735 Lisp_Object selection_symbol
, target_type
, time_stamp
;
737 Lisp_Object val
= Qnil
;
738 struct gcpro gcpro1
, gcpro2
;
739 GCPRO2 (target_type
, val
); /* we store newly consed data into these */
741 CHECK_SYMBOL (selection_symbol
);
742 CHECK_SYMBOL (target_type
);
744 val
= x_get_local_selection (selection_symbol
, target_type
, 1);
748 val
= x_get_foreign_selection (selection_symbol
, target_type
, time_stamp
);
753 && SYMBOLP (XCAR (val
)))
756 if (CONSP (val
) && NILP (XCDR (val
)))
764 DEFUN ("x-disown-selection-internal", Fx_disown_selection_internal
,
765 Sx_disown_selection_internal
, 1, 2, 0,
766 doc
: /* If we own the selection SELECTION, disown it.
767 Disowning it means there is no such selection. */)
769 Lisp_Object selection
;
774 Lisp_Object local_selection_data
;
777 CHECK_SYMBOL (selection
);
779 if (NILP (Fx_selection_owner_p (selection
)))
780 return Qnil
; /* Don't disown the selection when we're not the owner. */
782 local_selection_data
= assq_no_quit (selection
, Vselection_alist
);
784 /* Don't use Fdelq as that may QUIT;. */
786 if (EQ (local_selection_data
, Fcar (Vselection_alist
)))
787 Vselection_alist
= Fcdr (Vselection_alist
);
791 for (rest
= Vselection_alist
; !NILP (rest
); rest
= Fcdr (rest
))
792 if (EQ (local_selection_data
, Fcar (XCDR (rest
))))
794 XSETCDR (rest
, Fcdr (XCDR (rest
)));
799 /* Let random lisp code notice that the selection has been stolen. */
803 rest
= Vx_lost_selection_functions
;
804 if (!EQ (rest
, Qunbound
))
806 for (; CONSP (rest
); rest
= Fcdr (rest
))
807 call1 (Fcar (rest
), selection
);
808 prepare_menu_bars ();
809 redisplay_preserve_echo_area (20);
815 err
= get_scrap_from_symbol (selection
, 0, &scrap
);
816 if (err
== noErr
&& scrap
)
817 clear_scrap (&scrap
);
825 DEFUN ("x-selection-owner-p", Fx_selection_owner_p
, Sx_selection_owner_p
,
827 doc
: /* Whether the current Emacs process owns the given SELECTION.
828 The arg should be the name of the selection in question, typically one of
829 the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.
830 For convenience, the symbol nil is the same as `PRIMARY',
831 and t is the same as `SECONDARY'. */)
833 Lisp_Object selection
;
837 Lisp_Object result
= Qnil
, local_selection_data
;
840 CHECK_SYMBOL (selection
);
841 if (EQ (selection
, Qnil
)) selection
= QPRIMARY
;
842 if (EQ (selection
, Qt
)) selection
= QSECONDARY
;
844 local_selection_data
= assq_no_quit (selection
, Vselection_alist
);
846 if (NILP (local_selection_data
))
851 err
= get_scrap_from_symbol (selection
, 0, &scrap
);
852 if (err
== noErr
&& scrap
)
854 unsigned long timestamp
;
856 err
= get_scrap_private_timestamp (scrap
, ×tamp
);
859 == cons_to_long (XCAR (XCDR (XCDR (local_selection_data
))))))
870 DEFUN ("x-selection-exists-p", Fx_selection_exists_p
, Sx_selection_exists_p
,
872 doc
: /* Whether there is an owner for the given SELECTION.
873 The arg should be the name of the selection in question, typically one of
874 the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.
875 For convenience, the symbol nil is the same as `PRIMARY',
876 and t is the same as `SECONDARY'. */)
878 Lisp_Object selection
;
882 Lisp_Object result
= Qnil
, rest
;
884 /* It should be safe to call this before we have an Mac frame. */
885 if (! FRAME_MAC_P (SELECTED_FRAME ()))
888 CHECK_SYMBOL (selection
);
889 if (!NILP (Fx_selection_owner_p (selection
)))
891 if (EQ (selection
, Qnil
)) selection
= QPRIMARY
;
892 if (EQ (selection
, Qt
)) selection
= QSECONDARY
;
896 err
= get_scrap_from_symbol (selection
, 0, &scrap
);
897 if (err
== noErr
&& scrap
)
898 for (rest
= Vselection_converter_alist
; CONSP (rest
); rest
= XCDR (rest
))
900 if (CONSP (XCAR (rest
)) && SYMBOLP (XCAR (XCAR (rest
)))
901 && scrap_has_target_type (scrap
, XCAR (XCAR (rest
))))
914 /***********************************************************************
916 ***********************************************************************/
917 int mac_ready_for_apple_events
= 0;
918 static Lisp_Object Vmac_apple_event_map
;
919 static Lisp_Object Qmac_apple_event_class
, Qmac_apple_event_id
;
920 static Lisp_Object Qemacs_suspension_id
;
921 extern Lisp_Object Qundefined
;
922 extern void mac_store_apple_event
P_ ((Lisp_Object
, Lisp_Object
,
925 struct apple_event_binding
927 UInt32 code
; /* Apple event class or ID. */
928 Lisp_Object key
, binding
;
931 struct suspended_ae_info
933 UInt32 expiration_tick
, suspension_id
;
934 AppleEvent apple_event
, reply
;
935 struct suspended_ae_info
*next
;
938 /* List of apple events deferred at the startup time. */
939 static struct suspended_ae_info
*deferred_apple_events
= NULL
;
941 /* List of suspended apple events, in order of expiration_tick. */
942 static struct suspended_ae_info
*suspended_apple_events
= NULL
;
945 find_event_binding_fun (key
, binding
, args
, data
)
946 Lisp_Object key
, binding
, args
;
949 struct apple_event_binding
*event_binding
=
950 (struct apple_event_binding
*)data
;
951 Lisp_Object code_string
;
955 code_string
= Fget (key
, args
);
956 if (STRINGP (code_string
) && SBYTES (code_string
) == 4
957 && (EndianU32_BtoN (*((UInt32
*) SDATA (code_string
)))
958 == event_binding
->code
))
960 event_binding
->key
= key
;
961 event_binding
->binding
= binding
;
966 find_event_binding (keymap
, event_binding
, class_p
)
968 struct apple_event_binding
*event_binding
;
971 if (event_binding
->code
== 0)
972 event_binding
->binding
=
973 access_keymap (keymap
, event_binding
->key
, 0, 1, 0);
976 event_binding
->binding
= Qnil
;
977 map_keymap (keymap
, find_event_binding_fun
,
978 class_p
? Qmac_apple_event_class
: Qmac_apple_event_id
,
984 mac_find_apple_event_spec (class, id
, class_key
, id_key
, binding
)
987 Lisp_Object
*class_key
, *id_key
, *binding
;
989 struct apple_event_binding event_binding
;
994 keymap
= get_keymap (Vmac_apple_event_map
, 0, 0);
998 event_binding
.code
= class;
999 event_binding
.key
= *class_key
;
1000 event_binding
.binding
= Qnil
;
1001 find_event_binding (keymap
, &event_binding
, 1);
1002 *class_key
= event_binding
.key
;
1003 keymap
= get_keymap (event_binding
.binding
, 0, 0);
1007 event_binding
.code
= id
;
1008 event_binding
.key
= *id_key
;
1009 event_binding
.binding
= Qnil
;
1010 find_event_binding (keymap
, &event_binding
, 0);
1011 *id_key
= event_binding
.key
;
1012 *binding
= event_binding
.binding
;
1016 defer_apple_events (apple_event
, reply
)
1017 const AppleEvent
*apple_event
, *reply
;
1020 struct suspended_ae_info
*new;
1022 new = xmalloc (sizeof (struct suspended_ae_info
));
1023 bzero (new, sizeof (struct suspended_ae_info
));
1024 new->apple_event
.descriptorType
= typeNull
;
1025 new->reply
.descriptorType
= typeNull
;
1027 err
= AESuspendTheCurrentEvent (apple_event
);
1029 /* Mac OS 10.3 Xcode manual says AESuspendTheCurrentEvent makes
1030 copies of the Apple event and the reply, but Mac OS 10.4 Xcode
1031 manual says it doesn't. Anyway we create copies of them and save
1032 them in `deferred_apple_events'. */
1034 err
= AEDuplicateDesc (apple_event
, &new->apple_event
);
1036 err
= AEDuplicateDesc (reply
, &new->reply
);
1039 new->next
= deferred_apple_events
;
1040 deferred_apple_events
= new;
1044 AEDisposeDesc (&new->apple_event
);
1045 AEDisposeDesc (&new->reply
);
1053 mac_handle_apple_event_1 (class, id
, apple_event
, reply
)
1054 Lisp_Object
class, id
;
1055 const AppleEvent
*apple_event
;
1059 static UInt32 suspension_id
= 0;
1060 struct suspended_ae_info
*new;
1062 new = xmalloc (sizeof (struct suspended_ae_info
));
1063 bzero (new, sizeof (struct suspended_ae_info
));
1064 new->apple_event
.descriptorType
= typeNull
;
1065 new->reply
.descriptorType
= typeNull
;
1067 err
= AESuspendTheCurrentEvent (apple_event
);
1069 err
= AEDuplicateDesc (apple_event
, &new->apple_event
);
1071 err
= AEDuplicateDesc (reply
, &new->reply
);
1073 err
= AEPutAttributePtr (&new->apple_event
, KEY_EMACS_SUSPENSION_ID_ATTR
,
1074 typeUInt32
, &suspension_id
, sizeof (UInt32
));
1078 SInt32 reply_requested
;
1080 err1
= AEGetAttributePtr (&new->apple_event
, keyReplyRequestedAttr
,
1081 typeSInt32
, NULL
, &reply_requested
,
1082 sizeof (SInt32
), NULL
);
1085 /* Emulate keyReplyRequestedAttr in older versions. */
1086 reply_requested
= reply
->descriptorType
!= typeNull
;
1087 err
= AEPutAttributePtr (&new->apple_event
, keyReplyRequestedAttr
,
1088 typeSInt32
, &reply_requested
,
1095 struct suspended_ae_info
**p
;
1097 new->suspension_id
= suspension_id
;
1099 err
= AEGetAttributePtr (apple_event
, keyTimeoutAttr
, typeSInt32
,
1100 NULL
, &timeout
, sizeof (SInt32
), NULL
);
1101 new->expiration_tick
= TickCount () + timeout
;
1103 for (p
= &suspended_apple_events
; *p
; p
= &(*p
)->next
)
1104 if ((*p
)->expiration_tick
>= new->expiration_tick
)
1109 mac_store_apple_event (class, id
, &new->apple_event
);
1113 AEDisposeDesc (&new->reply
);
1114 AEDisposeDesc (&new->apple_event
);
1122 mac_handle_apple_event (apple_event
, reply
, refcon
)
1123 const AppleEvent
*apple_event
;
1128 UInt32 suspension_id
;
1129 AEEventClass event_class
;
1131 Lisp_Object class_key
, id_key
, binding
;
1133 if (!mac_ready_for_apple_events
)
1135 err
= defer_apple_events (apple_event
, reply
);
1137 return errAEEventNotHandled
;
1141 err
= AEGetAttributePtr (apple_event
, KEY_EMACS_SUSPENSION_ID_ATTR
,
1143 &suspension_id
, sizeof (UInt32
), NULL
);
1145 /* Previously suspended event. Pass it to the next handler. */
1146 return errAEEventNotHandled
;
1148 err
= AEGetAttributePtr (apple_event
, keyEventClassAttr
, typeType
, NULL
,
1149 &event_class
, sizeof (AEEventClass
), NULL
);
1151 err
= AEGetAttributePtr (apple_event
, keyEventIDAttr
, typeType
, NULL
,
1152 &event_id
, sizeof (AEEventID
), NULL
);
1155 mac_find_apple_event_spec (event_class
, event_id
,
1156 &class_key
, &id_key
, &binding
);
1157 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
1159 if (INTEGERP (binding
))
1160 return XINT (binding
);
1161 err
= mac_handle_apple_event_1 (class_key
, id_key
,
1162 apple_event
, reply
);
1165 err
= errAEEventNotHandled
;
1170 return errAEEventNotHandled
;
1174 cleanup_suspended_apple_events (head
, all_p
)
1175 struct suspended_ae_info
**head
;
1178 UInt32 current_tick
= TickCount (), nresumed
= 0;
1179 struct suspended_ae_info
*p
, *next
;
1181 for (p
= *head
; p
; p
= next
)
1183 if (!all_p
&& p
->expiration_tick
> current_tick
)
1185 AESetTheCurrentEvent (&p
->apple_event
);
1186 AEResumeTheCurrentEvent (&p
->apple_event
, &p
->reply
,
1187 (AEEventHandlerUPP
) kAENoDispatch
, 0);
1188 AEDisposeDesc (&p
->reply
);
1189 AEDisposeDesc (&p
->apple_event
);
1200 cleanup_all_suspended_apple_events ()
1202 cleanup_suspended_apple_events (&deferred_apple_events
, 1);
1203 cleanup_suspended_apple_events (&suspended_apple_events
, 1);
1207 init_apple_event_handler ()
1212 /* Make sure we have Apple events before starting. */
1213 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
1217 if (!(result
& (1 << gestaltAppleEventsPresent
)))
1220 err
= AEInstallEventHandler (typeWildCard
, typeWildCard
,
1221 #if TARGET_API_MAC_CARBON
1222 NewAEEventHandlerUPP (mac_handle_apple_event
),
1224 NewAEEventHandlerProc (mac_handle_apple_event
),
1230 atexit (cleanup_all_suspended_apple_events
);
1234 get_suspension_id (apple_event
)
1235 Lisp_Object apple_event
;
1239 CHECK_CONS (apple_event
);
1240 CHECK_STRING_CAR (apple_event
);
1241 if (SBYTES (XCAR (apple_event
)) != 4
1242 || strcmp (SDATA (XCAR (apple_event
)), "aevt") != 0)
1243 error ("Not an apple event");
1245 tem
= assq_no_quit (Qemacs_suspension_id
, XCDR (apple_event
));
1247 error ("Suspension ID not available");
1251 && STRINGP (XCAR (tem
)) && SBYTES (XCAR (tem
)) == 4
1252 && strcmp (SDATA (XCAR (tem
)), "magn") == 0
1253 && STRINGP (XCDR (tem
)) && SBYTES (XCDR (tem
)) == 4))
1254 error ("Bad suspension ID format");
1256 return *((UInt32
*) SDATA (XCDR (tem
)));
1260 DEFUN ("mac-process-deferred-apple-events", Fmac_process_deferred_apple_events
, Smac_process_deferred_apple_events
, 0, 0, 0,
1261 doc
: /* Process Apple events that are deferred at the startup time. */)
1264 if (mac_ready_for_apple_events
)
1268 mac_ready_for_apple_events
= 1;
1269 if (deferred_apple_events
)
1271 struct suspended_ae_info
*prev
, *tail
, *next
;
1273 /* `nreverse' deferred_apple_events. */
1275 for (tail
= deferred_apple_events
; tail
; tail
= next
)
1282 /* Now `prev' points to the first cell. */
1283 for (tail
= prev
; tail
; tail
= next
)
1286 AEResumeTheCurrentEvent (&tail
->apple_event
, &tail
->reply
,
1287 ((AEEventHandlerUPP
)
1288 kAEUseStandardDispatch
), 0);
1289 AEDisposeDesc (&tail
->reply
);
1290 AEDisposeDesc (&tail
->apple_event
);
1294 deferred_apple_events
= NULL
;
1301 DEFUN ("mac-cleanup-expired-apple-events", Fmac_cleanup_expired_apple_events
, Smac_cleanup_expired_apple_events
, 0, 0, 0,
1302 doc
: /* Clean up expired Apple events.
1303 Return the number of expired events. */)
1309 nexpired
= cleanup_suspended_apple_events (&suspended_apple_events
, 0);
1312 return make_number (nexpired
);
1315 DEFUN ("mac-ae-set-reply-parameter", Fmac_ae_set_reply_parameter
, Smac_ae_set_reply_parameter
, 3, 3, 0,
1316 doc
: /* Set parameter KEYWORD to DESCRIPTOR on reply of APPLE-EVENT.
1317 KEYWORD is a 4-byte string. DESCRIPTOR is a Lisp representation of an
1318 Apple event descriptor. It has the form of (TYPE . DATA), where TYPE
1319 is a 4-byte string. Valid format of DATA is as follows:
1321 * If TYPE is "null", then DATA is nil.
1322 * If TYPE is "list", then DATA is a list (DESCRIPTOR1 ... DESCRIPTORn).
1323 * If TYPE is "reco", then DATA is a list ((KEYWORD1 . DESCRIPTOR1)
1324 ... (KEYWORDn . DESCRIPTORn)).
1325 * If TYPE is "aevt", then DATA is ignored and the descriptor is
1327 * Otherwise, DATA is a string.
1329 If a (sub-)descriptor is in an invalid format, it is silently treated
1332 Return t if the parameter is successfully set. Otherwise return nil. */)
1333 (apple_event
, keyword
, descriptor
)
1334 Lisp_Object apple_event
, keyword
, descriptor
;
1336 Lisp_Object result
= Qnil
;
1337 UInt32 suspension_id
;
1338 struct suspended_ae_info
*p
;
1340 suspension_id
= get_suspension_id (apple_event
);
1342 CHECK_STRING (keyword
);
1343 if (SBYTES (keyword
) != 4)
1344 error ("Apple event keyword must be a 4-byte string: %s",
1348 for (p
= suspended_apple_events
; p
; p
= p
->next
)
1349 if (p
->suspension_id
== suspension_id
)
1351 if (p
&& p
->reply
.descriptorType
!= typeNull
)
1355 err
= mac_ae_put_lisp (&p
->reply
,
1356 EndianU32_BtoN (*((UInt32
*) SDATA (keyword
))),
1366 DEFUN ("mac-resume-apple-event", Fmac_resume_apple_event
, Smac_resume_apple_event
, 1, 2, 0,
1367 doc
: /* Resume handling of APPLE-EVENT.
1368 Every Apple event handled by the Lisp interpreter is suspended first.
1369 This function resumes such a suspended event either to complete Apple
1370 event handling to give a reply, or to redispatch it to other handlers.
1372 If optional ERROR-CODE is an integer, it specifies the error number
1373 that is set in the reply. If ERROR-CODE is t, the resumed event is
1374 handled with the standard dispatching mechanism, but it is not handled
1375 by Emacs again, thus it is redispatched to other handlers.
1377 Return t if APPLE-EVENT is successfully resumed. Otherwise return
1378 nil, which means the event is already resumed or expired. */)
1379 (apple_event
, error_code
)
1380 Lisp_Object apple_event
, error_code
;
1382 Lisp_Object result
= Qnil
;
1383 UInt32 suspension_id
;
1384 struct suspended_ae_info
**p
, *ae
;
1386 suspension_id
= get_suspension_id (apple_event
);
1389 for (p
= &suspended_apple_events
; *p
; p
= &(*p
)->next
)
1390 if ((*p
)->suspension_id
== suspension_id
)
1396 if (INTEGERP (error_code
)
1397 && ae
->reply
.descriptorType
!= typeNull
)
1399 SInt32 errn
= XINT (error_code
);
1401 AEPutParamPtr (&ae
->reply
, keyErrorNumber
, typeSInt32
,
1402 &errn
, sizeof (SInt32
));
1404 AESetTheCurrentEvent (&ae
->apple_event
);
1405 AEResumeTheCurrentEvent (&ae
->apple_event
, &ae
->reply
,
1406 ((AEEventHandlerUPP
)
1407 (EQ (error_code
, Qt
) ?
1408 kAEUseStandardDispatch
: kAENoDispatch
)),
1410 AEDisposeDesc (&ae
->reply
);
1411 AEDisposeDesc (&ae
->apple_event
);
1421 /***********************************************************************
1422 Drag and drop support
1423 ***********************************************************************/
1424 #if TARGET_API_MAC_CARBON
1425 static Lisp_Object Vmac_dnd_known_types
;
1426 static pascal OSErr mac_do_track_drag
P_ ((DragTrackingMessage
, WindowRef
,
1428 static pascal OSErr mac_do_receive_drag
P_ ((WindowRef
, void *, DragRef
));
1429 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
1430 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
1432 extern void mac_store_drag_event
P_ ((WindowRef
, Point
, SInt16
,
1436 mac_do_track_drag (message
, window
, refcon
, drag
)
1437 DragTrackingMessage message
;
1443 static int can_accept
;
1444 UInt16 num_items
, index
;
1446 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
1447 return dragNotAcceptedErr
;
1451 case kDragTrackingEnterHandler
:
1452 err
= CountDragItems (drag
, &num_items
);
1456 for (index
= 1; index
<= num_items
; index
++)
1462 err
= GetDragItemReferenceNumber (drag
, index
, &item
);
1465 for (rest
= Vmac_dnd_known_types
; CONSP (rest
); rest
= XCDR (rest
))
1471 if (!(STRINGP (str
) && SBYTES (str
) == 4))
1473 type
= EndianU32_BtoN (*((UInt32
*) SDATA (str
)));
1475 err
= GetFlavorFlags (drag
, item
, type
, &flags
);
1485 case kDragTrackingEnterWindow
:
1488 RgnHandle hilite_rgn
= NewRgn ();
1494 GetWindowPortBounds (window
, &r
);
1495 OffsetRect (&r
, -r
.left
, -r
.top
);
1496 RectRgn (hilite_rgn
, &r
);
1497 ShowDragHilite (drag
, hilite_rgn
, true);
1498 DisposeRgn (hilite_rgn
);
1500 SetThemeCursor (kThemeCopyArrowCursor
);
1504 case kDragTrackingInWindow
:
1507 case kDragTrackingLeaveWindow
:
1510 HideDragHilite (drag
);
1511 SetThemeCursor (kThemeArrowCursor
);
1515 case kDragTrackingLeaveHandler
:
1520 return dragNotAcceptedErr
;
1525 mac_do_receive_drag (window
, refcon
, drag
)
1532 Lisp_Object rest
, str
;
1534 AppleEvent apple_event
;
1538 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
1539 return dragNotAcceptedErr
;
1542 for (rest
= Vmac_dnd_known_types
; CONSP (rest
); rest
= XCDR (rest
))
1545 if (STRINGP (str
) && SBYTES (str
) == 4)
1549 types
= xmalloc (sizeof (FlavorType
) * num_types
);
1551 for (rest
= Vmac_dnd_known_types
; CONSP (rest
); rest
= XCDR (rest
))
1554 if (STRINGP (str
) && SBYTES (str
) == 4)
1555 types
[i
++] = EndianU32_BtoN (*((UInt32
*) SDATA (str
)));
1558 err
= create_apple_event_from_drag_ref (drag
, num_types
, types
,
1563 err
= GetDragMouse (drag
, &mouse_pos
, NULL
);
1566 GlobalToLocal (&mouse_pos
);
1567 err
= GetDragModifiers (drag
, NULL
, NULL
, &modifiers
);
1571 UInt32 key_modifiers
= modifiers
;
1573 err
= AEPutParamPtr (&apple_event
, kEventParamKeyModifiers
,
1574 typeUInt32
, &key_modifiers
, sizeof (UInt32
));
1579 mac_store_drag_event (window
, mouse_pos
, 0, &apple_event
);
1580 AEDisposeDesc (&apple_event
);
1581 mac_wakeup_from_rne ();
1585 return dragNotAcceptedErr
;
1587 #endif /* TARGET_API_MAC_CARBON */
1590 install_drag_handler (window
)
1595 #if TARGET_API_MAC_CARBON
1596 if (mac_do_track_dragUPP
== NULL
)
1597 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
1598 if (mac_do_receive_dragUPP
== NULL
)
1599 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
1601 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
1603 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
1610 remove_drag_handler (window
)
1613 #if TARGET_API_MAC_CARBON
1614 if (mac_do_track_dragUPP
)
1615 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
1616 if (mac_do_receive_dragUPP
)
1617 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
1622 /***********************************************************************
1623 Services menu support
1624 ***********************************************************************/
1627 init_service_handler ()
1629 static const EventTypeSpec specs
[] =
1630 {{kEventClassService
, kEventServiceGetTypes
},
1631 {kEventClassService
, kEventServiceCopy
},
1632 {kEventClassService
, kEventServicePaste
},
1633 {kEventClassService
, kEventServicePerform
}};
1634 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
1635 GetEventTypeCount (specs
), specs
, NULL
, NULL
);
1638 extern OSStatus mac_store_service_event
P_ ((EventRef
));
1641 copy_scrap_flavor_data (from_scrap
, to_scrap
, flavor_type
)
1642 ScrapRef from_scrap
, to_scrap
;
1643 ScrapFlavorType flavor_type
;
1646 Size size
, size_allocated
;
1649 err
= GetScrapFlavorSize (from_scrap
, flavor_type
, &size
);
1651 buf
= xmalloc (size
);
1654 size_allocated
= size
;
1655 err
= GetScrapFlavorData (from_scrap
, flavor_type
, &size
, buf
);
1661 else if (size_allocated
< size
)
1662 buf
= xrealloc (buf
, size
);
1672 err
= PutScrapFlavor (to_scrap
, flavor_type
, kScrapFlavorMaskNone
,
1682 mac_handle_service_event (call_ref
, event
, data
)
1683 EventHandlerCallRef call_ref
;
1687 OSStatus err
= noErr
;
1688 ScrapRef cur_scrap
, specific_scrap
;
1689 UInt32 event_kind
= GetEventKind (event
);
1690 CFMutableArrayRef copy_types
, paste_types
;
1693 ScrapFlavorType flavor_type
;
1695 /* Check if Vmac_service_selection is a valid selection that has a
1696 corresponding scrap. */
1697 if (!SYMBOLP (Vmac_service_selection
))
1698 err
= eventNotHandledErr
;
1700 err
= get_scrap_from_symbol (Vmac_service_selection
, 0, &cur_scrap
);
1701 if (!(err
== noErr
&& cur_scrap
))
1702 return eventNotHandledErr
;
1706 case kEventServiceGetTypes
:
1707 /* Set paste types. */
1708 err
= GetEventParameter (event
, kEventParamServicePasteTypes
,
1709 typeCFMutableArrayRef
, NULL
,
1710 sizeof (CFMutableArrayRef
), NULL
,
1715 for (rest
= Vselection_converter_alist
; CONSP (rest
);
1717 if (CONSP (XCAR (rest
)) && SYMBOLP (XCAR (XCAR (rest
)))
1719 get_flavor_type_from_symbol (XCAR (XCAR (rest
)))))
1721 type
= CreateTypeStringWithOSType (flavor_type
);
1724 CFArrayAppendValue (paste_types
, type
);
1729 /* Set copy types. */
1730 err
= GetEventParameter (event
, kEventParamServiceCopyTypes
,
1731 typeCFMutableArrayRef
, NULL
,
1732 sizeof (CFMutableArrayRef
), NULL
,
1737 if (NILP (Fx_selection_owner_p (Vmac_service_selection
)))
1740 goto copy_all_flavors
;
1742 case kEventServiceCopy
:
1743 err
= GetEventParameter (event
, kEventParamScrapRef
,
1745 sizeof (ScrapRef
), NULL
, &specific_scrap
);
1747 || NILP (Fx_selection_owner_p (Vmac_service_selection
)))
1749 err
= eventNotHandledErr
;
1756 ScrapFlavorInfo
*flavor_info
= NULL
;
1757 ScrapFlavorFlags flags
;
1759 err
= GetScrapFlavorCount (cur_scrap
, &count
);
1761 flavor_info
= xmalloc (sizeof (ScrapFlavorInfo
) * count
);
1762 err
= GetScrapFlavorInfoList (cur_scrap
, &count
, flavor_info
);
1765 xfree (flavor_info
);
1768 if (flavor_info
== NULL
)
1771 for (i
= 0; i
< count
; i
++)
1773 flavor_type
= flavor_info
[i
].flavorType
;
1774 err
= GetScrapFlavorFlags (cur_scrap
, flavor_type
, &flags
);
1775 if (err
== noErr
&& !(flags
& kScrapFlavorMaskSenderOnly
))
1777 if (event_kind
== kEventServiceCopy
)
1778 err
= copy_scrap_flavor_data (cur_scrap
, specific_scrap
,
1780 else /* event_kind == kEventServiceGetTypes */
1782 type
= CreateTypeStringWithOSType (flavor_type
);
1785 CFArrayAppendValue (copy_types
, type
);
1791 xfree (flavor_info
);
1795 case kEventServicePaste
:
1796 case kEventServicePerform
:
1798 int data_exists_p
= 0;
1800 err
= GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
,
1801 NULL
, sizeof (ScrapRef
), NULL
,
1804 err
= clear_scrap (&cur_scrap
);
1806 for (rest
= Vselection_converter_alist
; CONSP (rest
);
1809 if (! (CONSP (XCAR (rest
)) && SYMBOLP (XCAR (XCAR (rest
)))))
1811 flavor_type
= get_flavor_type_from_symbol (XCAR (XCAR (rest
)));
1812 if (flavor_type
== 0)
1814 err
= copy_scrap_flavor_data (specific_scrap
, cur_scrap
,
1820 err
= eventNotHandledErr
;
1822 err
= mac_store_service_event (event
);
1828 err
= eventNotHandledErr
;
1835 syms_of_macselect ()
1837 defsubr (&Sx_get_selection_internal
);
1838 defsubr (&Sx_own_selection_internal
);
1839 defsubr (&Sx_disown_selection_internal
);
1840 defsubr (&Sx_selection_owner_p
);
1841 defsubr (&Sx_selection_exists_p
);
1842 defsubr (&Smac_process_deferred_apple_events
);
1843 defsubr (&Smac_cleanup_expired_apple_events
);
1844 defsubr (&Smac_resume_apple_event
);
1845 defsubr (&Smac_ae_set_reply_parameter
);
1847 Vselection_alist
= Qnil
;
1848 staticpro (&Vselection_alist
);
1850 DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist
,
1851 doc
: /* An alist associating selection-types with functions.
1852 These functions are called to convert the selection, with three args:
1853 the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');
1854 a desired type to which the selection should be converted;
1855 and the local selection value (whatever was given to `x-own-selection').
1857 The function should return the value to send to the Scrap Manager
1858 \(must be a string). A return value of nil
1859 means that the conversion could not be done. */);
1860 Vselection_converter_alist
= Qnil
;
1862 DEFVAR_LISP ("x-lost-selection-functions", &Vx_lost_selection_functions
,
1863 doc
: /* A list of functions to be called when Emacs loses a selection.
1864 \(This happens when a Lisp program explicitly clears the selection.)
1865 The functions are called with one argument, the selection type
1866 \(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'). */);
1867 Vx_lost_selection_functions
= Qnil
;
1869 DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system
,
1870 doc
: /* Coding system for communicating with other programs.
1871 When sending or receiving text via cut_buffer, selection, and clipboard,
1872 the text is encoded or decoded by this coding system.
1873 The default value is determined by the system script code. */);
1874 Vselection_coding_system
= Qnil
;
1876 DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system
,
1877 doc
: /* Coding system for the next communication with other programs.
1878 Usually, `selection-coding-system' is used for communicating with
1879 other programs. But, if this variable is set, it is used for the
1880 next communication only. After the communication, this variable is
1882 Vnext_selection_coding_system
= Qnil
;
1884 DEFVAR_LISP ("mac-apple-event-map", &Vmac_apple_event_map
,
1885 doc
: /* Keymap for Apple events handled by Emacs. */);
1886 Vmac_apple_event_map
= Qnil
;
1888 #if TARGET_API_MAC_CARBON
1889 DEFVAR_LISP ("mac-dnd-known-types", &Vmac_dnd_known_types
,
1890 doc
: /* The types accepted by default for dropped data.
1891 The types are chosen in the order they appear in the list. */);
1892 Vmac_dnd_known_types
= list4 (build_string ("hfs "), build_string ("utxt"),
1893 build_string ("TEXT"), build_string ("TIFF"));
1895 Vmac_dnd_known_types
= Fcons (build_string ("furl"), Vmac_dnd_known_types
);
1900 DEFVAR_LISP ("mac-service-selection", &Vmac_service_selection
,
1901 doc
: /* Selection name for communication via Services menu. */);
1902 Vmac_service_selection
= intern ("PRIMARY");
1905 QPRIMARY
= intern ("PRIMARY"); staticpro (&QPRIMARY
);
1906 QSECONDARY
= intern ("SECONDARY"); staticpro (&QSECONDARY
);
1907 QTIMESTAMP
= intern ("TIMESTAMP"); staticpro (&QTIMESTAMP
);
1908 QTARGETS
= intern ("TARGETS"); staticpro (&QTARGETS
);
1910 Qforeign_selection
= intern ("foreign-selection");
1911 staticpro (&Qforeign_selection
);
1913 Qmac_scrap_name
= intern ("mac-scrap-name");
1914 staticpro (&Qmac_scrap_name
);
1916 Qmac_ostype
= intern ("mac-ostype");
1917 staticpro (&Qmac_ostype
);
1919 Qmac_apple_event_class
= intern ("mac-apple-event-class");
1920 staticpro (&Qmac_apple_event_class
);
1922 Qmac_apple_event_id
= intern ("mac-apple-event-id");
1923 staticpro (&Qmac_apple_event_id
);
1925 Qemacs_suspension_id
= intern ("emacs-suspension-id");
1926 staticpro (&Qemacs_suspension_id
);
1929 /* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732
1930 (do not change this comment) */