1 /* Selection processing for Emacs on Mac OS.
2 Copyright (C) 2005, 2006, 2007 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 2, 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
)) && SYMBOLP (target_type
= XCAR (XCAR (rest
)))
390 && (flavor_type
= scrap_has_target_type (scrap
, target_type
)))
392 result
= Fcons (target_type
, result
);
393 #if TARGET_API_MAC_CARBON
394 for (i
= 0; i
< count
; i
++)
395 if (flavor_info
[i
].flavorType
== flavor_type
)
397 flavor_info
[i
].flavorType
= 0;
403 #if TARGET_API_MAC_CARBON
406 for (i
= 0; i
< count
; i
++)
407 if (flavor_info
[i
].flavorType
)
409 type
= EndianU32_NtoB (flavor_info
[i
].flavorType
);
410 strings
= Fcons (make_unibyte_string ((char *) &type
, 4), strings
);
412 result
= nconc2 (result
, strings
);
420 /* Do protocol to assert ourself as a selection owner.
421 Update the Vselection_alist so that we can reply to later requests for
425 x_own_selection (selection_name
, selection_value
)
426 Lisp_Object selection_name
, selection_value
;
430 struct gcpro gcpro1
, gcpro2
;
431 Lisp_Object rest
, handler_fn
, value
, type
;
434 CHECK_SYMBOL (selection_name
);
436 GCPRO2 (selection_name
, selection_value
);
440 err
= get_scrap_from_symbol (selection_name
, 1, &scrap
);
441 if (err
== noErr
&& scrap
)
443 /* Don't allow a quit within the converter.
444 When the user types C-g, he would be surprised
445 if by luck it came during a converter. */
446 count
= SPECPDL_INDEX ();
447 specbind (Qinhibit_quit
, Qt
);
449 for (rest
= Vselection_converter_alist
; CONSP (rest
); rest
= XCDR (rest
))
451 if (!(CONSP (XCAR (rest
))
452 && SYMBOLP (type
= XCAR (XCAR (rest
)))
453 && valid_scrap_target_type_p (type
)
454 && SYMBOLP (handler_fn
= XCDR (XCAR (rest
)))))
457 if (!NILP (handler_fn
))
458 value
= call3 (handler_fn
, selection_name
,
459 type
, selection_value
);
462 err
= put_scrap_string (scrap
, type
, value
);
463 else if (CONSP (value
)
464 && EQ (XCAR (value
), type
)
465 && STRINGP (XCDR (value
)))
466 err
= put_scrap_string (scrap
, type
, XCDR (value
));
469 unbind_to (count
, Qnil
);
472 err
= put_scrap_private_timestamp (scrap
, last_event_timestamp
);
479 if (scrap
&& err
!= noErr
)
480 error ("Can't set selection");
482 /* Now update the local cache */
484 Lisp_Object selection_time
;
485 Lisp_Object selection_data
;
486 Lisp_Object prev_value
;
488 selection_time
= long_to_cons (last_event_timestamp
);
489 selection_data
= Fcons (selection_name
,
490 Fcons (selection_value
,
491 Fcons (selection_time
,
492 Fcons (selected_frame
, Qnil
))));
493 prev_value
= assq_no_quit (selection_name
, Vselection_alist
);
495 Vselection_alist
= Fcons (selection_data
, Vselection_alist
);
497 /* If we already owned the selection, remove the old selection data.
498 Perhaps we should destructively modify it instead.
499 Don't use Fdelq as that may QUIT. */
500 if (!NILP (prev_value
))
502 Lisp_Object rest
; /* we know it's not the CAR, so it's easy. */
503 for (rest
= Vselection_alist
; !NILP (rest
); rest
= Fcdr (rest
))
504 if (EQ (prev_value
, Fcar (XCDR (rest
))))
506 XSETCDR (rest
, Fcdr (XCDR (rest
)));
513 /* Given a selection-name and desired type, look up our local copy of
514 the selection value and convert it to the type.
515 The value is nil or a string.
516 This function is used both for remote requests (LOCAL_REQUEST is zero)
517 and for local x-get-selection-internal (LOCAL_REQUEST is nonzero).
519 This calls random Lisp code, and may signal or gc. */
522 x_get_local_selection (selection_symbol
, target_type
, local_request
)
523 Lisp_Object selection_symbol
, target_type
;
526 Lisp_Object local_value
;
527 Lisp_Object handler_fn
, value
, type
, check
;
530 if (NILP (Fx_selection_owner_p (selection_symbol
)))
533 local_value
= assq_no_quit (selection_symbol
, Vselection_alist
);
535 /* TIMESTAMP is a special case 'cause that's easiest. */
536 if (EQ (target_type
, QTIMESTAMP
))
539 value
= XCAR (XCDR (XCDR (local_value
)));
542 else if (EQ (target_type
, QDELETE
))
545 Fx_disown_selection_internal
547 XCAR (XCDR (XCDR (local_value
))));
553 /* Don't allow a quit within the converter.
554 When the user types C-g, he would be surprised
555 if by luck it came during a converter. */
556 count
= SPECPDL_INDEX ();
557 specbind (Qinhibit_quit
, Qt
);
559 CHECK_SYMBOL (target_type
);
560 handler_fn
= Fcdr (Fassq (target_type
, Vselection_converter_alist
));
561 /* gcpro is not needed here since nothing but HANDLER_FN
562 is live, and that ought to be a symbol. */
564 if (!NILP (handler_fn
))
565 value
= call3 (handler_fn
,
566 selection_symbol
, (local_request
? Qnil
: target_type
),
567 XCAR (XCDR (local_value
)));
570 unbind_to (count
, Qnil
);
573 /* Make sure this value is of a type that we could transmit
574 to another X client. */
578 && SYMBOLP (XCAR (value
)))
580 check
= XCDR (value
);
588 /* Check for a value that cons_to_long could handle. */
589 else if (CONSP (check
)
590 && INTEGERP (XCAR (check
))
591 && (INTEGERP (XCDR (check
))
593 (CONSP (XCDR (check
))
594 && INTEGERP (XCAR (XCDR (check
)))
595 && NILP (XCDR (XCDR (check
))))))
598 signal_error ("Invalid data returned by selection-conversion function",
599 list2 (handler_fn
, value
));
603 /* Clear all selections that were made from frame F.
604 We do this when about to delete a frame. */
607 x_clear_frame_selections (f
)
613 XSETFRAME (frame
, f
);
615 /* Otherwise, we're really honest and truly being told to drop it.
616 Don't use Fdelq as that may QUIT;. */
618 /* Delete elements from the beginning of Vselection_alist. */
619 while (!NILP (Vselection_alist
)
620 && EQ (frame
, Fcar (Fcdr (Fcdr (Fcdr (Fcar (Vselection_alist
)))))))
622 /* Let random Lisp code notice that the selection has been stolen. */
623 Lisp_Object hooks
, selection_symbol
;
625 hooks
= Vx_lost_selection_functions
;
626 selection_symbol
= Fcar (Fcar (Vselection_alist
));
628 if (!EQ (hooks
, Qunbound
)
629 && !NILP (Fx_selection_owner_p (selection_symbol
)))
631 for (; CONSP (hooks
); hooks
= Fcdr (hooks
))
632 call1 (Fcar (hooks
), selection_symbol
);
633 #if 0 /* This can crash when deleting a frame
634 from x_connection_closed. Anyway, it seems unnecessary;
635 something else should cause a redisplay. */
636 redisplay_preserve_echo_area (21);
640 Vselection_alist
= Fcdr (Vselection_alist
);
643 /* Delete elements after the beginning of Vselection_alist. */
644 for (rest
= Vselection_alist
; !NILP (rest
); rest
= Fcdr (rest
))
645 if (EQ (frame
, Fcar (Fcdr (Fcdr (Fcdr (Fcar (XCDR (rest
))))))))
647 /* Let random Lisp code notice that the selection has been stolen. */
648 Lisp_Object hooks
, selection_symbol
;
650 hooks
= Vx_lost_selection_functions
;
651 selection_symbol
= Fcar (Fcar (XCDR (rest
)));
653 if (!EQ (hooks
, Qunbound
)
654 && !NILP (Fx_selection_owner_p (selection_symbol
)))
656 for (; CONSP (hooks
); hooks
= Fcdr (hooks
))
657 call1 (Fcar (hooks
), selection_symbol
);
658 #if 0 /* See above */
659 redisplay_preserve_echo_area (22);
662 XSETCDR (rest
, Fcdr (XCDR (rest
)));
667 /* Do protocol to read selection-data from the server.
668 Converts this to Lisp data and returns it. */
671 x_get_foreign_selection (selection_symbol
, target_type
, time_stamp
)
672 Lisp_Object selection_symbol
, target_type
, time_stamp
;
676 Lisp_Object result
= Qnil
;
680 err
= get_scrap_from_symbol (selection_symbol
, 0, &scrap
);
681 if (err
== noErr
&& scrap
)
683 if (EQ (target_type
, QTARGETS
))
685 result
= get_scrap_target_type_list (scrap
);
686 result
= Fvconcat (1, &result
);
690 result
= get_scrap_string (scrap
, target_type
);
691 if (STRINGP (result
))
692 Fput_text_property (make_number (0), make_number (SBYTES (result
)),
693 Qforeign_selection
, target_type
, result
);
703 DEFUN ("x-own-selection-internal", Fx_own_selection_internal
,
704 Sx_own_selection_internal
, 2, 2, 0,
705 doc
: /* Assert a selection of the given TYPE with the given VALUE.
706 TYPE is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
707 VALUE is typically a string, or a cons of two markers, but may be
708 anything that the functions on `selection-converter-alist' know about. */)
709 (selection_name
, selection_value
)
710 Lisp_Object selection_name
, selection_value
;
713 CHECK_SYMBOL (selection_name
);
714 if (NILP (selection_value
)) error ("SELECTION-VALUE may not be nil");
715 x_own_selection (selection_name
, selection_value
);
716 return selection_value
;
720 /* Request the selection value from the owner. If we are the owner,
721 simply return our selection value. If we are not the owner, this
722 will block until all of the data has arrived. */
724 DEFUN ("x-get-selection-internal", Fx_get_selection_internal
,
725 Sx_get_selection_internal
, 2, 3, 0,
726 doc
: /* Return text selected from some Mac application.
727 SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
728 TYPE is the type of data desired, typically `STRING'.
729 TIME_STAMP is ignored on Mac. */)
730 (selection_symbol
, target_type
, time_stamp
)
731 Lisp_Object selection_symbol
, target_type
, time_stamp
;
733 Lisp_Object val
= Qnil
;
734 struct gcpro gcpro1
, gcpro2
;
735 GCPRO2 (target_type
, val
); /* we store newly consed data into these */
737 CHECK_SYMBOL (selection_symbol
);
738 CHECK_SYMBOL (target_type
);
740 val
= x_get_local_selection (selection_symbol
, target_type
, 1);
744 val
= x_get_foreign_selection (selection_symbol
, target_type
, time_stamp
);
749 && SYMBOLP (XCAR (val
)))
752 if (CONSP (val
) && NILP (XCDR (val
)))
760 DEFUN ("x-disown-selection-internal", Fx_disown_selection_internal
,
761 Sx_disown_selection_internal
, 1, 2, 0,
762 doc
: /* If we own the selection SELECTION, disown it.
763 Disowning it means there is no such selection. */)
765 Lisp_Object selection
;
770 Lisp_Object local_selection_data
;
773 CHECK_SYMBOL (selection
);
775 if (NILP (Fx_selection_owner_p (selection
)))
776 return Qnil
; /* Don't disown the selection when we're not the owner. */
778 local_selection_data
= assq_no_quit (selection
, Vselection_alist
);
780 /* Don't use Fdelq as that may QUIT;. */
782 if (EQ (local_selection_data
, Fcar (Vselection_alist
)))
783 Vselection_alist
= Fcdr (Vselection_alist
);
787 for (rest
= Vselection_alist
; !NILP (rest
); rest
= Fcdr (rest
))
788 if (EQ (local_selection_data
, Fcar (XCDR (rest
))))
790 XSETCDR (rest
, Fcdr (XCDR (rest
)));
795 /* Let random lisp code notice that the selection has been stolen. */
799 rest
= Vx_lost_selection_functions
;
800 if (!EQ (rest
, Qunbound
))
802 for (; CONSP (rest
); rest
= Fcdr (rest
))
803 call1 (Fcar (rest
), selection
);
804 prepare_menu_bars ();
805 redisplay_preserve_echo_area (20);
811 err
= get_scrap_from_symbol (selection
, 0, &scrap
);
812 if (err
== noErr
&& scrap
)
813 clear_scrap (&scrap
);
821 DEFUN ("x-selection-owner-p", Fx_selection_owner_p
, Sx_selection_owner_p
,
823 doc
: /* Whether the current Emacs process owns the given SELECTION.
824 The arg should be the name of the selection in question, typically one of
825 the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.
826 For convenience, the symbol nil is the same as `PRIMARY',
827 and t is the same as `SECONDARY'. */)
829 Lisp_Object selection
;
833 Lisp_Object result
= Qnil
, local_selection_data
;
836 CHECK_SYMBOL (selection
);
837 if (EQ (selection
, Qnil
)) selection
= QPRIMARY
;
838 if (EQ (selection
, Qt
)) selection
= QSECONDARY
;
840 local_selection_data
= assq_no_quit (selection
, Vselection_alist
);
842 if (NILP (local_selection_data
))
847 err
= get_scrap_from_symbol (selection
, 0, &scrap
);
848 if (err
== noErr
&& scrap
)
850 unsigned long timestamp
;
852 err
= get_scrap_private_timestamp (scrap
, ×tamp
);
855 == cons_to_long (XCAR (XCDR (XCDR (local_selection_data
))))))
866 DEFUN ("x-selection-exists-p", Fx_selection_exists_p
, Sx_selection_exists_p
,
868 doc
: /* Whether there is an owner for the given SELECTION.
869 The arg should be the name of the selection in question, typically one of
870 the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.
871 For convenience, the symbol nil is the same as `PRIMARY',
872 and t is the same as `SECONDARY'. */)
874 Lisp_Object selection
;
878 Lisp_Object result
= Qnil
, rest
;
880 /* It should be safe to call this before we have an Mac frame. */
881 if (! FRAME_MAC_P (SELECTED_FRAME ()))
884 CHECK_SYMBOL (selection
);
885 if (!NILP (Fx_selection_owner_p (selection
)))
887 if (EQ (selection
, Qnil
)) selection
= QPRIMARY
;
888 if (EQ (selection
, Qt
)) selection
= QSECONDARY
;
892 err
= get_scrap_from_symbol (selection
, 0, &scrap
);
893 if (err
== noErr
&& scrap
)
894 for (rest
= Vselection_converter_alist
; CONSP (rest
); rest
= XCDR (rest
))
896 if (CONSP (XCAR (rest
)) && SYMBOLP (XCAR (XCAR (rest
)))
897 && scrap_has_target_type (scrap
, XCAR (XCAR (rest
))))
910 /***********************************************************************
912 ***********************************************************************/
913 int mac_ready_for_apple_events
= 0;
914 static Lisp_Object Vmac_apple_event_map
;
915 static Lisp_Object Qmac_apple_event_class
, Qmac_apple_event_id
;
916 static Lisp_Object Qemacs_suspension_id
;
917 extern Lisp_Object Qundefined
;
918 extern void mac_store_apple_event
P_ ((Lisp_Object
, Lisp_Object
,
921 struct apple_event_binding
923 UInt32 code
; /* Apple event class or ID. */
924 Lisp_Object key
, binding
;
927 struct suspended_ae_info
929 UInt32 expiration_tick
, suspension_id
;
930 AppleEvent apple_event
, reply
;
931 struct suspended_ae_info
*next
;
934 /* List of apple events deferred at the startup time. */
935 static struct suspended_ae_info
*deferred_apple_events
= NULL
;
937 /* List of suspended apple events, in order of expiration_tick. */
938 static struct suspended_ae_info
*suspended_apple_events
= NULL
;
941 find_event_binding_fun (key
, binding
, args
, data
)
942 Lisp_Object key
, binding
, args
;
945 struct apple_event_binding
*event_binding
=
946 (struct apple_event_binding
*)data
;
947 Lisp_Object code_string
;
951 code_string
= Fget (key
, args
);
952 if (STRINGP (code_string
) && SBYTES (code_string
) == 4
953 && (EndianU32_BtoN (*((UInt32
*) SDATA (code_string
)))
954 == event_binding
->code
))
956 event_binding
->key
= key
;
957 event_binding
->binding
= binding
;
962 find_event_binding (keymap
, event_binding
, class_p
)
964 struct apple_event_binding
*event_binding
;
967 if (event_binding
->code
== 0)
968 event_binding
->binding
=
969 access_keymap (keymap
, event_binding
->key
, 0, 1, 0);
972 event_binding
->binding
= Qnil
;
973 map_keymap (keymap
, find_event_binding_fun
,
974 class_p
? Qmac_apple_event_class
: Qmac_apple_event_id
,
980 mac_find_apple_event_spec (class, id
, class_key
, id_key
, binding
)
983 Lisp_Object
*class_key
, *id_key
, *binding
;
985 struct apple_event_binding event_binding
;
990 keymap
= get_keymap (Vmac_apple_event_map
, 0, 0);
994 event_binding
.code
= class;
995 event_binding
.key
= *class_key
;
996 event_binding
.binding
= Qnil
;
997 find_event_binding (keymap
, &event_binding
, 1);
998 *class_key
= event_binding
.key
;
999 keymap
= get_keymap (event_binding
.binding
, 0, 0);
1003 event_binding
.code
= id
;
1004 event_binding
.key
= *id_key
;
1005 event_binding
.binding
= Qnil
;
1006 find_event_binding (keymap
, &event_binding
, 0);
1007 *id_key
= event_binding
.key
;
1008 *binding
= event_binding
.binding
;
1012 defer_apple_events (apple_event
, reply
)
1013 const AppleEvent
*apple_event
, *reply
;
1016 struct suspended_ae_info
*new;
1018 new = xmalloc (sizeof (struct suspended_ae_info
));
1019 bzero (new, sizeof (struct suspended_ae_info
));
1020 new->apple_event
.descriptorType
= typeNull
;
1021 new->reply
.descriptorType
= typeNull
;
1023 err
= AESuspendTheCurrentEvent (apple_event
);
1025 /* Mac OS 10.3 Xcode manual says AESuspendTheCurrentEvent makes
1026 copies of the Apple event and the reply, but Mac OS 10.4 Xcode
1027 manual says it doesn't. Anyway we create copies of them and save
1028 them in `deferred_apple_events'. */
1030 err
= AEDuplicateDesc (apple_event
, &new->apple_event
);
1032 err
= AEDuplicateDesc (reply
, &new->reply
);
1035 new->next
= deferred_apple_events
;
1036 deferred_apple_events
= new;
1040 AEDisposeDesc (&new->apple_event
);
1041 AEDisposeDesc (&new->reply
);
1049 mac_handle_apple_event_1 (class, id
, apple_event
, reply
)
1050 Lisp_Object
class, id
;
1051 const AppleEvent
*apple_event
;
1055 static UInt32 suspension_id
= 0;
1056 struct suspended_ae_info
*new;
1058 new = xmalloc (sizeof (struct suspended_ae_info
));
1059 bzero (new, sizeof (struct suspended_ae_info
));
1060 new->apple_event
.descriptorType
= typeNull
;
1061 new->reply
.descriptorType
= typeNull
;
1063 err
= AESuspendTheCurrentEvent (apple_event
);
1065 err
= AEDuplicateDesc (apple_event
, &new->apple_event
);
1067 err
= AEDuplicateDesc (reply
, &new->reply
);
1069 err
= AEPutAttributePtr (&new->apple_event
, KEY_EMACS_SUSPENSION_ID_ATTR
,
1070 typeUInt32
, &suspension_id
, sizeof (UInt32
));
1074 SInt32 reply_requested
;
1076 err1
= AEGetAttributePtr (&new->apple_event
, keyReplyRequestedAttr
,
1077 typeSInt32
, NULL
, &reply_requested
,
1078 sizeof (SInt32
), NULL
);
1081 /* Emulate keyReplyRequestedAttr in older versions. */
1082 reply_requested
= reply
->descriptorType
!= typeNull
;
1083 err
= AEPutAttributePtr (&new->apple_event
, keyReplyRequestedAttr
,
1084 typeSInt32
, &reply_requested
,
1091 struct suspended_ae_info
**p
;
1093 new->suspension_id
= suspension_id
;
1095 err
= AEGetAttributePtr (apple_event
, keyTimeoutAttr
, typeSInt32
,
1096 NULL
, &timeout
, sizeof (SInt32
), NULL
);
1097 new->expiration_tick
= TickCount () + timeout
;
1099 for (p
= &suspended_apple_events
; *p
; p
= &(*p
)->next
)
1100 if ((*p
)->expiration_tick
>= new->expiration_tick
)
1105 mac_store_apple_event (class, id
, &new->apple_event
);
1109 AEDisposeDesc (&new->reply
);
1110 AEDisposeDesc (&new->apple_event
);
1118 mac_handle_apple_event (apple_event
, reply
, refcon
)
1119 const AppleEvent
*apple_event
;
1124 UInt32 suspension_id
;
1125 AEEventClass event_class
;
1127 Lisp_Object class_key
, id_key
, binding
;
1129 if (!mac_ready_for_apple_events
)
1131 err
= defer_apple_events (apple_event
, reply
);
1133 return errAEEventNotHandled
;
1137 err
= AEGetAttributePtr (apple_event
, KEY_EMACS_SUSPENSION_ID_ATTR
,
1139 &suspension_id
, sizeof (UInt32
), NULL
);
1141 /* Previously suspended event. Pass it to the next handler. */
1142 return errAEEventNotHandled
;
1144 err
= AEGetAttributePtr (apple_event
, keyEventClassAttr
, typeType
, NULL
,
1145 &event_class
, sizeof (AEEventClass
), NULL
);
1147 err
= AEGetAttributePtr (apple_event
, keyEventIDAttr
, typeType
, NULL
,
1148 &event_id
, sizeof (AEEventID
), NULL
);
1151 mac_find_apple_event_spec (event_class
, event_id
,
1152 &class_key
, &id_key
, &binding
);
1153 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
1155 if (INTEGERP (binding
))
1156 return XINT (binding
);
1157 err
= mac_handle_apple_event_1 (class_key
, id_key
,
1158 apple_event
, reply
);
1161 err
= errAEEventNotHandled
;
1166 return errAEEventNotHandled
;
1170 cleanup_suspended_apple_events (head
, all_p
)
1171 struct suspended_ae_info
**head
;
1174 UInt32 current_tick
= TickCount (), nresumed
= 0;
1175 struct suspended_ae_info
*p
, *next
;
1177 for (p
= *head
; p
; p
= next
)
1179 if (!all_p
&& p
->expiration_tick
> current_tick
)
1181 AESetTheCurrentEvent (&p
->apple_event
);
1182 AEResumeTheCurrentEvent (&p
->apple_event
, &p
->reply
,
1183 (AEEventHandlerUPP
) kAENoDispatch
, 0);
1184 AEDisposeDesc (&p
->reply
);
1185 AEDisposeDesc (&p
->apple_event
);
1196 cleanup_all_suspended_apple_events ()
1198 cleanup_suspended_apple_events (&deferred_apple_events
, 1);
1199 cleanup_suspended_apple_events (&suspended_apple_events
, 1);
1203 init_apple_event_handler ()
1208 /* Make sure we have Apple events before starting. */
1209 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
1213 if (!(result
& (1 << gestaltAppleEventsPresent
)))
1216 err
= AEInstallEventHandler (typeWildCard
, typeWildCard
,
1217 #if TARGET_API_MAC_CARBON
1218 NewAEEventHandlerUPP (mac_handle_apple_event
),
1220 NewAEEventHandlerProc (mac_handle_apple_event
),
1226 atexit (cleanup_all_suspended_apple_events
);
1230 get_suspension_id (apple_event
)
1231 Lisp_Object apple_event
;
1235 CHECK_CONS (apple_event
);
1236 CHECK_STRING_CAR (apple_event
);
1237 if (SBYTES (XCAR (apple_event
)) != 4
1238 || strcmp (SDATA (XCAR (apple_event
)), "aevt") != 0)
1239 error ("Not an apple event");
1241 tem
= assq_no_quit (Qemacs_suspension_id
, XCDR (apple_event
));
1243 error ("Suspension ID not available");
1247 && STRINGP (XCAR (tem
)) && SBYTES (XCAR (tem
)) == 4
1248 && strcmp (SDATA (XCAR (tem
)), "magn") == 0
1249 && STRINGP (XCDR (tem
)) && SBYTES (XCDR (tem
)) == 4))
1250 error ("Bad suspension ID format");
1252 return *((UInt32
*) SDATA (XCDR (tem
)));
1256 DEFUN ("mac-process-deferred-apple-events", Fmac_process_deferred_apple_events
, Smac_process_deferred_apple_events
, 0, 0, 0,
1257 doc
: /* Process Apple events that are deferred at the startup time. */)
1260 if (mac_ready_for_apple_events
)
1264 mac_ready_for_apple_events
= 1;
1265 if (deferred_apple_events
)
1267 struct suspended_ae_info
*prev
, *tail
, *next
;
1269 /* `nreverse' deferred_apple_events. */
1271 for (tail
= deferred_apple_events
; tail
; tail
= next
)
1278 /* Now `prev' points to the first cell. */
1279 for (tail
= prev
; tail
; tail
= next
)
1282 AEResumeTheCurrentEvent (&tail
->apple_event
, &tail
->reply
,
1283 ((AEEventHandlerUPP
)
1284 kAEUseStandardDispatch
), 0);
1285 AEDisposeDesc (&tail
->reply
);
1286 AEDisposeDesc (&tail
->apple_event
);
1290 deferred_apple_events
= NULL
;
1297 DEFUN ("mac-cleanup-expired-apple-events", Fmac_cleanup_expired_apple_events
, Smac_cleanup_expired_apple_events
, 0, 0, 0,
1298 doc
: /* Clean up expired Apple events.
1299 Return the number of expired events. */)
1305 nexpired
= cleanup_suspended_apple_events (&suspended_apple_events
, 0);
1308 return make_number (nexpired
);
1311 DEFUN ("mac-ae-set-reply-parameter", Fmac_ae_set_reply_parameter
, Smac_ae_set_reply_parameter
, 3, 3, 0,
1312 doc
: /* Set parameter KEYWORD to DESCRIPTOR on reply of APPLE-EVENT.
1313 KEYWORD is a 4-byte string. DESCRIPTOR is a Lisp representation of an
1314 Apple event descriptor. It has the form of (TYPE . DATA), where TYPE
1315 is a 4-byte string. Valid format of DATA is as follows:
1317 * If TYPE is "null", then DATA is nil.
1318 * If TYPE is "list", then DATA is a list (DESCRIPTOR1 ... DESCRIPTORn).
1319 * If TYPE is "reco", then DATA is a list ((KEYWORD1 . DESCRIPTOR1)
1320 ... (KEYWORDn . DESCRIPTORn)).
1321 * If TYPE is "aevt", then DATA is ignored and the descriptor is
1323 * Otherwise, DATA is a string.
1325 If a (sub-)descriptor is in an invalid format, it is silently treated
1328 Return t if the parameter is successfully set. Otherwise return nil. */)
1329 (apple_event
, keyword
, descriptor
)
1330 Lisp_Object apple_event
, keyword
, descriptor
;
1332 Lisp_Object result
= Qnil
;
1333 UInt32 suspension_id
;
1334 struct suspended_ae_info
*p
;
1336 suspension_id
= get_suspension_id (apple_event
);
1338 CHECK_STRING (keyword
);
1339 if (SBYTES (keyword
) != 4)
1340 error ("Apple event keyword must be a 4-byte string: %s",
1344 for (p
= suspended_apple_events
; p
; p
= p
->next
)
1345 if (p
->suspension_id
== suspension_id
)
1347 if (p
&& p
->reply
.descriptorType
!= typeNull
)
1351 err
= mac_ae_put_lisp (&p
->reply
,
1352 EndianU32_BtoN (*((UInt32
*) SDATA (keyword
))),
1362 DEFUN ("mac-resume-apple-event", Fmac_resume_apple_event
, Smac_resume_apple_event
, 1, 2, 0,
1363 doc
: /* Resume handling of APPLE-EVENT.
1364 Every Apple event handled by the Lisp interpreter is suspended first.
1365 This function resumes such a suspended event either to complete Apple
1366 event handling to give a reply, or to redispatch it to other handlers.
1368 If optional ERROR-CODE is an integer, it specifies the error number
1369 that is set in the reply. If ERROR-CODE is t, the resumed event is
1370 handled with the standard dispatching mechanism, but it is not handled
1371 by Emacs again, thus it is redispatched to other handlers.
1373 Return t if APPLE-EVENT is successfully resumed. Otherwise return
1374 nil, which means the event is already resumed or expired. */)
1375 (apple_event
, error_code
)
1376 Lisp_Object apple_event
, error_code
;
1378 Lisp_Object result
= Qnil
;
1379 UInt32 suspension_id
;
1380 struct suspended_ae_info
**p
, *ae
;
1382 suspension_id
= get_suspension_id (apple_event
);
1385 for (p
= &suspended_apple_events
; *p
; p
= &(*p
)->next
)
1386 if ((*p
)->suspension_id
== suspension_id
)
1392 if (INTEGERP (error_code
)
1393 && ae
->reply
.descriptorType
!= typeNull
)
1395 SInt32 errn
= XINT (error_code
);
1397 AEPutParamPtr (&ae
->reply
, keyErrorNumber
, typeSInt32
,
1398 &errn
, sizeof (SInt32
));
1400 AESetTheCurrentEvent (&ae
->apple_event
);
1401 AEResumeTheCurrentEvent (&ae
->apple_event
, &ae
->reply
,
1402 ((AEEventHandlerUPP
)
1403 (EQ (error_code
, Qt
) ?
1404 kAEUseStandardDispatch
: kAENoDispatch
)),
1406 AEDisposeDesc (&ae
->reply
);
1407 AEDisposeDesc (&ae
->apple_event
);
1417 /***********************************************************************
1418 Drag and drop support
1419 ***********************************************************************/
1420 #if TARGET_API_MAC_CARBON
1421 static Lisp_Object Vmac_dnd_known_types
;
1422 static pascal OSErr mac_do_track_drag
P_ ((DragTrackingMessage
, WindowRef
,
1424 static pascal OSErr mac_do_receive_drag
P_ ((WindowRef
, void *, DragRef
));
1425 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
1426 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
1428 extern void mac_store_drag_event
P_ ((WindowRef
, Point
, SInt16
,
1432 mac_do_track_drag (message
, window
, refcon
, drag
)
1433 DragTrackingMessage message
;
1439 static int can_accept
;
1440 UInt16 num_items
, index
;
1442 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
1443 return dragNotAcceptedErr
;
1447 case kDragTrackingEnterHandler
:
1448 err
= CountDragItems (drag
, &num_items
);
1452 for (index
= 1; index
<= num_items
; index
++)
1458 err
= GetDragItemReferenceNumber (drag
, index
, &item
);
1461 for (rest
= Vmac_dnd_known_types
; CONSP (rest
); rest
= XCDR (rest
))
1467 if (!(STRINGP (str
) && SBYTES (str
) == 4))
1469 type
= EndianU32_BtoN (*((UInt32
*) SDATA (str
)));
1471 err
= GetFlavorFlags (drag
, item
, type
, &flags
);
1481 case kDragTrackingEnterWindow
:
1484 RgnHandle hilite_rgn
= NewRgn ();
1490 GetWindowPortBounds (window
, &r
);
1491 OffsetRect (&r
, -r
.left
, -r
.top
);
1492 RectRgn (hilite_rgn
, &r
);
1493 ShowDragHilite (drag
, hilite_rgn
, true);
1494 DisposeRgn (hilite_rgn
);
1496 SetThemeCursor (kThemeCopyArrowCursor
);
1500 case kDragTrackingInWindow
:
1503 case kDragTrackingLeaveWindow
:
1506 HideDragHilite (drag
);
1507 SetThemeCursor (kThemeArrowCursor
);
1511 case kDragTrackingLeaveHandler
:
1516 return dragNotAcceptedErr
;
1521 mac_do_receive_drag (window
, refcon
, drag
)
1528 Lisp_Object rest
, str
;
1530 AppleEvent apple_event
;
1534 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
1535 return dragNotAcceptedErr
;
1538 for (rest
= Vmac_dnd_known_types
; CONSP (rest
); rest
= XCDR (rest
))
1541 if (STRINGP (str
) && SBYTES (str
) == 4)
1545 types
= xmalloc (sizeof (FlavorType
) * num_types
);
1547 for (rest
= Vmac_dnd_known_types
; CONSP (rest
); rest
= XCDR (rest
))
1550 if (STRINGP (str
) && SBYTES (str
) == 4)
1551 types
[i
++] = EndianU32_BtoN (*((UInt32
*) SDATA (str
)));
1554 err
= create_apple_event_from_drag_ref (drag
, num_types
, types
,
1559 err
= GetDragMouse (drag
, &mouse_pos
, NULL
);
1562 GlobalToLocal (&mouse_pos
);
1563 err
= GetDragModifiers (drag
, NULL
, NULL
, &modifiers
);
1567 UInt32 key_modifiers
= modifiers
;
1569 err
= AEPutParamPtr (&apple_event
, kEventParamKeyModifiers
,
1570 typeUInt32
, &key_modifiers
, sizeof (UInt32
));
1575 mac_store_drag_event (window
, mouse_pos
, 0, &apple_event
);
1576 AEDisposeDesc (&apple_event
);
1577 mac_wakeup_from_rne ();
1581 return dragNotAcceptedErr
;
1583 #endif /* TARGET_API_MAC_CARBON */
1586 install_drag_handler (window
)
1591 #if TARGET_API_MAC_CARBON
1592 if (mac_do_track_dragUPP
== NULL
)
1593 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
1594 if (mac_do_receive_dragUPP
== NULL
)
1595 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
1597 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
1599 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
1606 remove_drag_handler (window
)
1609 #if TARGET_API_MAC_CARBON
1610 if (mac_do_track_dragUPP
)
1611 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
1612 if (mac_do_receive_dragUPP
)
1613 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
1618 /***********************************************************************
1619 Services menu support
1620 ***********************************************************************/
1623 init_service_handler ()
1625 static const EventTypeSpec specs
[] =
1626 {{kEventClassService
, kEventServiceGetTypes
},
1627 {kEventClassService
, kEventServiceCopy
},
1628 {kEventClassService
, kEventServicePaste
},
1629 {kEventClassService
, kEventServicePerform
}};
1630 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
1631 GetEventTypeCount (specs
), specs
, NULL
, NULL
);
1634 extern OSStatus mac_store_service_event
P_ ((EventRef
));
1637 copy_scrap_flavor_data (from_scrap
, to_scrap
, flavor_type
)
1638 ScrapRef from_scrap
, to_scrap
;
1639 ScrapFlavorType flavor_type
;
1642 Size size
, size_allocated
;
1645 err
= GetScrapFlavorSize (from_scrap
, flavor_type
, &size
);
1647 buf
= xmalloc (size
);
1650 size_allocated
= size
;
1651 err
= GetScrapFlavorData (from_scrap
, flavor_type
, &size
, buf
);
1657 else if (size_allocated
< size
)
1658 buf
= xrealloc (buf
, size
);
1668 err
= PutScrapFlavor (to_scrap
, flavor_type
, kScrapFlavorMaskNone
,
1678 mac_handle_service_event (call_ref
, event
, data
)
1679 EventHandlerCallRef call_ref
;
1683 OSStatus err
= noErr
;
1684 ScrapRef cur_scrap
, specific_scrap
;
1685 UInt32 event_kind
= GetEventKind (event
);
1686 CFMutableArrayRef copy_types
, paste_types
;
1689 ScrapFlavorType flavor_type
;
1691 /* Check if Vmac_service_selection is a valid selection that has a
1692 corresponding scrap. */
1693 if (!SYMBOLP (Vmac_service_selection
))
1694 err
= eventNotHandledErr
;
1696 err
= get_scrap_from_symbol (Vmac_service_selection
, 0, &cur_scrap
);
1697 if (!(err
== noErr
&& cur_scrap
))
1698 return eventNotHandledErr
;
1702 case kEventServiceGetTypes
:
1703 /* Set paste types. */
1704 err
= GetEventParameter (event
, kEventParamServicePasteTypes
,
1705 typeCFMutableArrayRef
, NULL
,
1706 sizeof (CFMutableArrayRef
), NULL
,
1711 for (rest
= Vselection_converter_alist
; CONSP (rest
);
1713 if (CONSP (XCAR (rest
)) && SYMBOLP (XCAR (XCAR (rest
)))
1715 get_flavor_type_from_symbol (XCAR (XCAR (rest
)))))
1717 type
= CreateTypeStringWithOSType (flavor_type
);
1720 CFArrayAppendValue (paste_types
, type
);
1725 /* Set copy types. */
1726 err
= GetEventParameter (event
, kEventParamServiceCopyTypes
,
1727 typeCFMutableArrayRef
, NULL
,
1728 sizeof (CFMutableArrayRef
), NULL
,
1733 if (NILP (Fx_selection_owner_p (Vmac_service_selection
)))
1736 goto copy_all_flavors
;
1738 case kEventServiceCopy
:
1739 err
= GetEventParameter (event
, kEventParamScrapRef
,
1741 sizeof (ScrapRef
), NULL
, &specific_scrap
);
1743 || NILP (Fx_selection_owner_p (Vmac_service_selection
)))
1745 err
= eventNotHandledErr
;
1752 ScrapFlavorInfo
*flavor_info
= NULL
;
1753 ScrapFlavorFlags flags
;
1755 err
= GetScrapFlavorCount (cur_scrap
, &count
);
1757 flavor_info
= xmalloc (sizeof (ScrapFlavorInfo
) * count
);
1758 err
= GetScrapFlavorInfoList (cur_scrap
, &count
, flavor_info
);
1761 xfree (flavor_info
);
1764 if (flavor_info
== NULL
)
1767 for (i
= 0; i
< count
; i
++)
1769 flavor_type
= flavor_info
[i
].flavorType
;
1770 err
= GetScrapFlavorFlags (cur_scrap
, flavor_type
, &flags
);
1771 if (err
== noErr
&& !(flags
& kScrapFlavorMaskSenderOnly
))
1773 if (event_kind
== kEventServiceCopy
)
1774 err
= copy_scrap_flavor_data (cur_scrap
, specific_scrap
,
1776 else /* event_kind == kEventServiceGetTypes */
1778 type
= CreateTypeStringWithOSType (flavor_type
);
1781 CFArrayAppendValue (copy_types
, type
);
1787 xfree (flavor_info
);
1791 case kEventServicePaste
:
1792 case kEventServicePerform
:
1794 int data_exists_p
= 0;
1796 err
= GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
,
1797 NULL
, sizeof (ScrapRef
), NULL
,
1800 err
= clear_scrap (&cur_scrap
);
1802 for (rest
= Vselection_converter_alist
; CONSP (rest
);
1805 if (! (CONSP (XCAR (rest
)) && SYMBOLP (XCAR (XCAR (rest
)))))
1807 flavor_type
= get_flavor_type_from_symbol (XCAR (XCAR (rest
)));
1808 if (flavor_type
== 0)
1810 err
= copy_scrap_flavor_data (specific_scrap
, cur_scrap
,
1816 err
= eventNotHandledErr
;
1818 err
= mac_store_service_event (event
);
1824 err
= eventNotHandledErr
;
1831 syms_of_macselect ()
1833 defsubr (&Sx_get_selection_internal
);
1834 defsubr (&Sx_own_selection_internal
);
1835 defsubr (&Sx_disown_selection_internal
);
1836 defsubr (&Sx_selection_owner_p
);
1837 defsubr (&Sx_selection_exists_p
);
1838 defsubr (&Smac_process_deferred_apple_events
);
1839 defsubr (&Smac_cleanup_expired_apple_events
);
1840 defsubr (&Smac_resume_apple_event
);
1841 defsubr (&Smac_ae_set_reply_parameter
);
1843 Vselection_alist
= Qnil
;
1844 staticpro (&Vselection_alist
);
1846 DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist
,
1847 doc
: /* An alist associating selection-types with functions.
1848 These functions are called to convert the selection, with three args:
1849 the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');
1850 a desired type to which the selection should be converted;
1851 and the local selection value (whatever was given to `x-own-selection').
1853 The function should return the value to send to the Scrap Manager
1854 \(must be a string). A return value of nil
1855 means that the conversion could not be done.
1856 A return value which is the symbol `NULL'
1857 means that a side-effect was executed,
1858 and there is no meaningful selection value. */);
1859 Vselection_converter_alist
= Qnil
;
1861 DEFVAR_LISP ("x-lost-selection-functions", &Vx_lost_selection_functions
,
1862 doc
: /* A list of functions to be called when Emacs loses a selection.
1863 \(This happens when a Lisp program explicitly clears the selection.)
1864 The functions are called with one argument, the selection type
1865 \(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'). */);
1866 Vx_lost_selection_functions
= Qnil
;
1868 DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system
,
1869 doc
: /* Coding system for communicating with other programs.
1870 When sending or receiving text via cut_buffer, selection, and clipboard,
1871 the text is encoded or decoded by this coding system.
1872 The default value is determined by the system script code. */);
1873 Vselection_coding_system
= Qnil
;
1875 DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system
,
1876 doc
: /* Coding system for the next communication with other programs.
1877 Usually, `selection-coding-system' is used for communicating with
1878 other programs. But, if this variable is set, it is used for the
1879 next communication only. After the communication, this variable is
1881 Vnext_selection_coding_system
= Qnil
;
1883 DEFVAR_LISP ("mac-apple-event-map", &Vmac_apple_event_map
,
1884 doc
: /* Keymap for Apple events handled by Emacs. */);
1885 Vmac_apple_event_map
= Qnil
;
1887 #if TARGET_API_MAC_CARBON
1888 DEFVAR_LISP ("mac-dnd-known-types", &Vmac_dnd_known_types
,
1889 doc
: /* The types accepted by default for dropped data.
1890 The types are chosen in the order they appear in the list. */);
1891 Vmac_dnd_known_types
= list4 (build_string ("hfs "), build_string ("utxt"),
1892 build_string ("TEXT"), build_string ("TIFF"));
1894 Vmac_dnd_known_types
= Fcons (build_string ("furl"), Vmac_dnd_known_types
);
1899 DEFVAR_LISP ("mac-service-selection", &Vmac_service_selection
,
1900 doc
: /* Selection name for communication via Services menu. */);
1901 Vmac_service_selection
= intern ("PRIMARY");
1904 QPRIMARY
= intern ("PRIMARY"); staticpro (&QPRIMARY
);
1905 QSECONDARY
= intern ("SECONDARY"); staticpro (&QSECONDARY
);
1906 QTIMESTAMP
= intern ("TIMESTAMP"); staticpro (&QTIMESTAMP
);
1907 QTARGETS
= intern ("TARGETS"); staticpro (&QTARGETS
);
1909 Qforeign_selection
= intern ("foreign-selection");
1910 staticpro (&Qforeign_selection
);
1912 Qmac_scrap_name
= intern ("mac-scrap-name");
1913 staticpro (&Qmac_scrap_name
);
1915 Qmac_ostype
= intern ("mac-ostype");
1916 staticpro (&Qmac_ostype
);
1918 Qmac_apple_event_class
= intern ("mac-apple-event-class");
1919 staticpro (&Qmac_apple_event_class
);
1921 Qmac_apple_event_id
= intern ("mac-apple-event-id");
1922 staticpro (&Qmac_apple_event_id
);
1924 Qemacs_suspension_id
= intern ("emacs-suspension-id");
1925 staticpro (&Qemacs_suspension_id
);
1928 /* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732
1929 (do not change this comment) */