comparison src/macselect.c @ 80454:98811b17d3b9

[!TARGET_API_MAC_CARBON]: Don't include Scrap.h. (Selection): Move typedef to macgui.h. (Vselection_converter_alist, Qmac_scrap_name, Qmac_ostype) (Vmac_apple_event_map, Qmac_apple_event_class, Qmac_apple_event_id): Make variables non-static. (Vmac_dnd_known_types) [TARGET_API_MAC_CARBON]: Likewise. (mac_handle_apple_event, cleanup_all_suspended_apple_events): Make functions non-static. (Vmac_service_selection) [MAC_OSX]: Likewise. (mac_get_selection_from_symbol, get_flavor_type_from_symbol) (mac_valid_selection_target_p, mac_clear_selection) (mac_get_selection_ownership_info, mac_valid_selection_value_p) (mac_put_selection_value, mac_selection_has_target_p) (mac_get_selection_value, mac_get_selection_target_list) (init_apple_event_handler, install_drag_handler, remove_drag_handler): Move functions to mactoolbox.c. (mac_do_track_drag, mac_do_receive_drag) [TARGET_API_MAC_CARBON]: Likewise. (copy_scrap_flavor_data, mac_handle_service_event) (install_service_handler) [MAC_OSX]: Likewise. (syms_of_macselect) <Vmac_dnd_known_types>: Use mac_dnd_default_known_types.
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Sun, 06 Apr 2008 01:58:39 +0000
parents 1d3df1b9547b
children aee651d7cdc7 3af508d0bd74
comparison
equal deleted inserted replaced
80453:07666d9ede23 80454:98811b17d3b9
23 #include "lisp.h" 23 #include "lisp.h"
24 #include "macterm.h" 24 #include "macterm.h"
25 #include "blockinput.h" 25 #include "blockinput.h"
26 #include "keymap.h" 26 #include "keymap.h"
27 27
28 #if TARGET_API_MAC_CARBON 28 #if !TARGET_API_MAC_CARBON
29 typedef ScrapRef Selection;
30 #else /* !TARGET_API_MAC_CARBON */
31 #include <Scrap.h>
32 #include <Endian.h> 29 #include <Endian.h>
33 typedef int Selection; 30 #endif
34 #endif /* !TARGET_API_MAC_CARBON */ 31
35
36 static OSStatus mac_get_selection_from_symbol P_ ((Lisp_Object, int,
37 Selection *));
38 static ScrapFlavorType get_flavor_type_from_symbol P_ ((Lisp_Object,
39 Selection));
40 static int mac_valid_selection_target_p P_ ((Lisp_Object));
41 static OSStatus mac_clear_selection P_ ((Selection *));
42 static Lisp_Object mac_get_selection_ownership_info P_ ((Selection));
43 static int mac_valid_selection_value_p P_ ((Lisp_Object, Lisp_Object));
44 static OSStatus mac_put_selection_value P_ ((Selection, Lisp_Object,
45 Lisp_Object));
46 static int mac_selection_has_target_p P_ ((Selection, Lisp_Object));
47 static Lisp_Object mac_get_selection_value P_ ((Selection, Lisp_Object));
48 static Lisp_Object mac_get_selection_target_list P_ ((Selection));
49 static void x_own_selection P_ ((Lisp_Object, Lisp_Object)); 32 static void x_own_selection P_ ((Lisp_Object, Lisp_Object));
50 static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object, int)); 33 static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object, int));
51 static Lisp_Object x_get_foreign_selection P_ ((Lisp_Object, 34 static Lisp_Object x_get_foreign_selection P_ ((Lisp_Object,
52 Lisp_Object, 35 Lisp_Object,
53 Lisp_Object)); 36 Lisp_Object));
54 EXFUN (Fx_selection_owner_p, 1);
55 #ifdef MAC_OSX
56 static OSStatus mac_handle_service_event P_ ((EventHandlerCallRef,
57 EventRef, void *));
58 void init_service_handler P_ ((void));
59 #endif
60 37
61 Lisp_Object QPRIMARY, QSECONDARY, QTIMESTAMP, QTARGETS; 38 Lisp_Object QPRIMARY, QSECONDARY, QTIMESTAMP, QTARGETS;
62 39
63 static Lisp_Object Vx_lost_selection_functions; 40 static Lisp_Object Vx_lost_selection_functions;
64 /* Coding system for communicating with other programs via selections. */ 41 /* Coding system for communicating with other programs via selections. */
96 /* This is an alist whose CARs are selection-types and whose CDRs are 73 /* This is an alist whose CARs are selection-types and whose CDRs are
97 the names of Lisp functions to call to convert the given Emacs 74 the names of Lisp functions to call to convert the given Emacs
98 selection value to a string representing the given selection type. 75 selection value to a string representing the given selection type.
99 This is for Lisp-level extension of the emacs selection 76 This is for Lisp-level extension of the emacs selection
100 handling. */ 77 handling. */
101 static Lisp_Object Vselection_converter_alist; 78 Lisp_Object Vselection_converter_alist;
102 79
103 /* A selection name (represented as a Lisp symbol) can be associated 80 /* A selection name (represented as a Lisp symbol) can be associated
104 with a named scrap via `mac-scrap-name' property. Likewise for a 81 with a named scrap via `mac-scrap-name' property. Likewise for a
105 selection type with a scrap flavor type via `mac-ostype'. */ 82 selection type with a scrap flavor type via `mac-ostype'. */
106 static Lisp_Object Qmac_scrap_name, Qmac_ostype; 83 Lisp_Object Qmac_scrap_name, Qmac_ostype;
107 84
108 #ifdef MAC_OSX
109 /* Selection name for communication via Services menu. */
110 static Lisp_Object Vmac_service_selection;
111 #endif
112
113 /* Get a reference to the selection corresponding to the symbol SYM.
114 The reference is set to *SEL, and it becomes NULL if there's no
115 corresponding selection. Clear the selection if CLEAR_P is
116 non-zero. */
117
118 static OSStatus
119 mac_get_selection_from_symbol (sym, clear_p, sel)
120 Lisp_Object sym;
121 int clear_p;
122 Selection *sel;
123 {
124 OSStatus err = noErr;
125 Lisp_Object str = Fget (sym, Qmac_scrap_name);
126
127 if (!STRINGP (str))
128 *sel = NULL;
129 else
130 {
131 #if TARGET_API_MAC_CARBON
132 #ifdef MAC_OSX
133 CFStringRef scrap_name = cfstring_create_with_string (str);
134 OptionBits options = (clear_p ? kScrapClearNamedScrap
135 : kScrapGetNamedScrap);
136
137 err = GetScrapByName (scrap_name, options, sel);
138 CFRelease (scrap_name);
139 #else /* !MAC_OSX */
140 if (clear_p)
141 err = ClearCurrentScrap ();
142 if (err == noErr)
143 err = GetCurrentScrap (sel);
144 #endif /* !MAC_OSX */
145 #else /* !TARGET_API_MAC_CARBON */
146 if (clear_p)
147 err = ZeroScrap ();
148 if (err == noErr)
149 *sel = 1;
150 #endif /* !TARGET_API_MAC_CARBON */
151 }
152
153 return err;
154 }
155
156 /* Get a scrap flavor type from the symbol SYM. Return 0 if no
157 corresponding flavor type. If SEL is non-zero, the return value is
158 non-zero only when the SEL has the flavor type. */
159
160 static ScrapFlavorType
161 get_flavor_type_from_symbol (sym, sel)
162 Lisp_Object sym;
163 Selection sel;
164 {
165 Lisp_Object str = Fget (sym, Qmac_ostype);
166 ScrapFlavorType flavor_type;
167
168 if (STRINGP (str) && SBYTES (str) == 4)
169 flavor_type = EndianU32_BtoN (*((UInt32 *) SDATA (str)));
170 else
171 flavor_type = 0;
172
173 if (flavor_type && sel)
174 {
175 #if TARGET_API_MAC_CARBON
176 OSStatus err;
177 ScrapFlavorFlags flags;
178
179 err = GetScrapFlavorFlags (sel, flavor_type, &flags);
180 if (err != noErr)
181 flavor_type = 0;
182 #else /* !TARGET_API_MAC_CARBON */
183 SInt32 size, offset;
184
185 size = GetScrap (NULL, flavor_type, &offset);
186 if (size < 0)
187 flavor_type = 0;
188 #endif /* !TARGET_API_MAC_CARBON */
189 }
190
191 return flavor_type;
192 }
193
194 /* Check if the symbol SYM has a corresponding selection target type. */
195
196 static int
197 mac_valid_selection_target_p (sym)
198 Lisp_Object sym;
199 {
200 return get_flavor_type_from_symbol (sym, 0) != 0;
201 }
202
203 /* Clear the selection whose reference is *SEL. */
204
205 static OSStatus
206 mac_clear_selection (sel)
207 Selection *sel;
208 {
209 #if TARGET_API_MAC_CARBON
210 #ifdef MAC_OSX
211 return ClearScrap (sel);
212 #else
213 OSStatus err;
214
215 err = ClearCurrentScrap ();
216 if (err == noErr)
217 err = GetCurrentScrap (sel);
218 return err;
219 #endif
220 #else /* !TARGET_API_MAC_CARBON */
221 return ZeroScrap ();
222 #endif /* !TARGET_API_MAC_CARBON */
223 }
224
225 /* Get ownership information for SEL. Emacs can detect a change of
226 the ownership by comparing saved and current values of the
227 ownership information. */
228
229 static Lisp_Object
230 mac_get_selection_ownership_info (sel)
231 Selection sel;
232 {
233 #if TARGET_API_MAC_CARBON
234 return long_to_cons ((unsigned long) sel);
235 #else /* !TARGET_API_MAC_CARBON */
236 ScrapStuffPtr scrap_info = InfoScrap ();
237
238 return make_number (scrap_info->scrapCount);
239 #endif /* !TARGET_API_MAC_CARBON */
240 }
241
242 /* Return non-zero if VALUE is a valid selection value for TARGET. */
243
244 static int
245 mac_valid_selection_value_p (value, target)
246 Lisp_Object value, target;
247 {
248 return STRINGP (value);
249 }
250
251 /* Put Lisp Object VALUE to the selection SEL. The target type is
252 specified by TARGET. */
253
254 static OSStatus
255 mac_put_selection_value (sel, target, value)
256 Selection sel;
257 Lisp_Object target, value;
258 {
259 ScrapFlavorType flavor_type = get_flavor_type_from_symbol (target, 0);
260
261 if (flavor_type == 0 || !STRINGP (value))
262 return noTypeErr;
263
264 #if TARGET_API_MAC_CARBON
265 return PutScrapFlavor (sel, flavor_type, kScrapFlavorMaskNone,
266 SBYTES (value), SDATA (value));
267 #else /* !TARGET_API_MAC_CARBON */
268 return PutScrap (SBYTES (value), flavor_type, SDATA (value));
269 #endif /* !TARGET_API_MAC_CARBON */
270 }
271
272 /* Check if data for the target type TARGET is available in SEL. */
273
274 static int
275 mac_selection_has_target_p (sel, target)
276 Selection sel;
277 Lisp_Object target;
278 {
279 return get_flavor_type_from_symbol (target, sel) != 0;
280 }
281
282 /* Get data for the target type TARGET from SEL and create a Lisp
283 string. Return nil if failed to get data. */
284
285 static Lisp_Object
286 mac_get_selection_value (sel, target)
287 Selection sel;
288 Lisp_Object target;
289 {
290 OSStatus err;
291 Lisp_Object result = Qnil;
292 ScrapFlavorType flavor_type = get_flavor_type_from_symbol (target, sel);
293 #if TARGET_API_MAC_CARBON
294 Size size;
295
296 if (flavor_type)
297 {
298 err = GetScrapFlavorSize (sel, flavor_type, &size);
299 if (err == noErr)
300 {
301 do
302 {
303 result = make_uninit_string (size);
304 err = GetScrapFlavorData (sel, flavor_type,
305 &size, SDATA (result));
306 if (err != noErr)
307 result = Qnil;
308 else if (size < SBYTES (result))
309 result = make_unibyte_string (SDATA (result), size);
310 }
311 while (STRINGP (result) && size > SBYTES (result));
312 }
313 }
314 #else
315 Handle handle;
316 SInt32 size, offset;
317
318 if (flavor_type)
319 size = GetScrap (NULL, flavor_type, &offset);
320 if (size >= 0)
321 {
322 handle = NewHandle (size);
323 HLock (handle);
324 size = GetScrap (handle, flavor_type, &offset);
325 if (size >= 0)
326 result = make_unibyte_string (*handle, size);
327 DisposeHandle (handle);
328 }
329 #endif
330
331 return result;
332 }
333
334 /* Get the list of target types in SEL. The return value is a list of
335 target type symbols possibly followed by scrap flavor type
336 strings. */
337
338 static Lisp_Object
339 mac_get_selection_target_list (sel)
340 Selection sel;
341 {
342 Lisp_Object result = Qnil, rest, target;
343 #if TARGET_API_MAC_CARBON
344 OSStatus err;
345 UInt32 count, i, type;
346 ScrapFlavorInfo *flavor_info = NULL;
347 Lisp_Object strings = Qnil;
348
349 err = GetScrapFlavorCount (sel, &count);
350 if (err == noErr)
351 flavor_info = xmalloc (sizeof (ScrapFlavorInfo) * count);
352 err = GetScrapFlavorInfoList (sel, &count, flavor_info);
353 if (err != noErr)
354 {
355 xfree (flavor_info);
356 flavor_info = NULL;
357 }
358 if (flavor_info == NULL)
359 count = 0;
360 #endif
361 for (rest = Vselection_converter_alist; CONSP (rest); rest = XCDR (rest))
362 {
363 ScrapFlavorType flavor_type = 0;
364
365 if (CONSP (XCAR (rest))
366 && (target = XCAR (XCAR (rest)),
367 SYMBOLP (target))
368 && (flavor_type = get_flavor_type_from_symbol (target, sel)))
369 {
370 result = Fcons (target, result);
371 #if TARGET_API_MAC_CARBON
372 for (i = 0; i < count; i++)
373 if (flavor_info[i].flavorType == flavor_type)
374 {
375 flavor_info[i].flavorType = 0;
376 break;
377 }
378 #endif
379 }
380 }
381 #if TARGET_API_MAC_CARBON
382 if (flavor_info)
383 {
384 for (i = 0; i < count; i++)
385 if (flavor_info[i].flavorType)
386 {
387 type = EndianU32_NtoB (flavor_info[i].flavorType);
388 strings = Fcons (make_unibyte_string ((char *) &type, 4), strings);
389 }
390 result = nconc2 (result, strings);
391 xfree (flavor_info);
392 }
393 #endif
394
395 return result;
396 }
397 85
398 /* Do protocol to assert ourself as a selection owner. 86 /* Do protocol to assert ourself as a selection owner.
399 Update the Vselection_alist so that we can reply to later requests for 87 Update the Vselection_alist so that we can reply to later requests for
400 our selection. */ 88 our selection. */
401 89
890 578
891 /*********************************************************************** 579 /***********************************************************************
892 Apple event support 580 Apple event support
893 ***********************************************************************/ 581 ***********************************************************************/
894 int mac_ready_for_apple_events = 0; 582 int mac_ready_for_apple_events = 0;
895 static Lisp_Object Vmac_apple_event_map; 583 Lisp_Object Vmac_apple_event_map;
896 static Lisp_Object Qmac_apple_event_class, Qmac_apple_event_id; 584 Lisp_Object Qmac_apple_event_class, Qmac_apple_event_id;
897 static Lisp_Object Qemacs_suspension_id; 585 static Lisp_Object Qemacs_suspension_id;
898 extern Lisp_Object Qundefined; 586 extern Lisp_Object Qundefined;
899 extern void mac_store_apple_event P_ ((Lisp_Object, Lisp_Object, 587 extern void mac_store_apple_event P_ ((Lisp_Object, Lisp_Object,
900 const AEDesc *)); 588 const AEDesc *));
901 589
1093 } 781 }
1094 782
1095 return err; 783 return err;
1096 } 784 }
1097 785
1098 static pascal OSErr 786 pascal OSErr
1099 mac_handle_apple_event (apple_event, reply, refcon) 787 mac_handle_apple_event (apple_event, reply, refcon)
1100 const AppleEvent *apple_event; 788 const AppleEvent *apple_event;
1101 AppleEvent *reply; 789 AppleEvent *reply;
1102 SInt32 refcon; 790 SInt32 refcon;
1103 { 791 {
1171 *head = p; 859 *head = p;
1172 860
1173 return nresumed; 861 return nresumed;
1174 } 862 }
1175 863
1176 static void 864 void
1177 cleanup_all_suspended_apple_events () 865 cleanup_all_suspended_apple_events ()
1178 { 866 {
1179 cleanup_suspended_apple_events (&deferred_apple_events, 1); 867 cleanup_suspended_apple_events (&deferred_apple_events, 1);
1180 cleanup_suspended_apple_events (&suspended_apple_events, 1); 868 cleanup_suspended_apple_events (&suspended_apple_events, 1);
1181 }
1182
1183 void
1184 init_apple_event_handler ()
1185 {
1186 OSErr err;
1187 long result;
1188
1189 /* Make sure we have Apple events before starting. */
1190 err = Gestalt (gestaltAppleEventsAttr, &result);
1191 if (err != noErr)
1192 abort ();
1193
1194 if (!(result & (1 << gestaltAppleEventsPresent)))
1195 abort ();
1196
1197 err = AEInstallEventHandler (typeWildCard, typeWildCard,
1198 #if TARGET_API_MAC_CARBON
1199 NewAEEventHandlerUPP (mac_handle_apple_event),
1200 #else
1201 NewAEEventHandlerProc (mac_handle_apple_event),
1202 #endif
1203 0L, false);
1204 if (err != noErr)
1205 abort ();
1206
1207 atexit (cleanup_all_suspended_apple_events);
1208 } 869 }
1209 870
1210 static UInt32 871 static UInt32
1211 get_suspension_id (apple_event) 872 get_suspension_id (apple_event)
1212 Lisp_Object apple_event; 873 Lisp_Object apple_event;
1397 1058
1398 /*********************************************************************** 1059 /***********************************************************************
1399 Drag and drop support 1060 Drag and drop support
1400 ***********************************************************************/ 1061 ***********************************************************************/
1401 #if TARGET_API_MAC_CARBON 1062 #if TARGET_API_MAC_CARBON
1402 static Lisp_Object Vmac_dnd_known_types; 1063 Lisp_Object Vmac_dnd_known_types;
1403 static pascal OSErr mac_do_track_drag P_ ((DragTrackingMessage, WindowRef,
1404 void *, DragRef));
1405 static pascal OSErr mac_do_receive_drag P_ ((WindowRef, void *, DragRef));
1406 static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL;
1407 static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL;
1408
1409 extern void mac_store_drag_event P_ ((WindowRef, Point, SInt16,
1410 const AEDesc *));
1411
1412 static pascal OSErr
1413 mac_do_track_drag (message, window, refcon, drag)
1414 DragTrackingMessage message;
1415 WindowRef window;
1416 void *refcon;
1417 DragRef drag;
1418 {
1419 OSErr err = noErr;
1420 static int can_accept;
1421 UInt16 num_items, index;
1422
1423 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
1424 return dragNotAcceptedErr;
1425
1426 switch (message)
1427 {
1428 case kDragTrackingEnterHandler:
1429 err = CountDragItems (drag, &num_items);
1430 if (err != noErr)
1431 break;
1432 can_accept = 0;
1433 for (index = 1; index <= num_items; index++)
1434 {
1435 ItemReference item;
1436 FlavorFlags flags;
1437 Lisp_Object rest;
1438
1439 err = GetDragItemReferenceNumber (drag, index, &item);
1440 if (err != noErr)
1441 continue;
1442 for (rest = Vmac_dnd_known_types; CONSP (rest); rest = XCDR (rest))
1443 {
1444 Lisp_Object str;
1445 FlavorType type;
1446
1447 str = XCAR (rest);
1448 if (!(STRINGP (str) && SBYTES (str) == 4))
1449 continue;
1450 type = EndianU32_BtoN (*((UInt32 *) SDATA (str)));
1451
1452 err = GetFlavorFlags (drag, item, type, &flags);
1453 if (err == noErr)
1454 {
1455 can_accept = 1;
1456 break;
1457 }
1458 }
1459 }
1460 break;
1461
1462 case kDragTrackingEnterWindow:
1463 if (can_accept)
1464 {
1465 RgnHandle hilite_rgn = NewRgn ();
1466
1467 if (hilite_rgn)
1468 {
1469 Rect r;
1470
1471 GetWindowPortBounds (window, &r);
1472 OffsetRect (&r, -r.left, -r.top);
1473 RectRgn (hilite_rgn, &r);
1474 ShowDragHilite (drag, hilite_rgn, true);
1475 DisposeRgn (hilite_rgn);
1476 }
1477 SetThemeCursor (kThemeCopyArrowCursor);
1478 }
1479 break;
1480
1481 case kDragTrackingInWindow:
1482 break;
1483
1484 case kDragTrackingLeaveWindow:
1485 if (can_accept)
1486 {
1487 HideDragHilite (drag);
1488 SetThemeCursor (kThemeArrowCursor);
1489 }
1490 break;
1491
1492 case kDragTrackingLeaveHandler:
1493 break;
1494 }
1495
1496 if (err != noErr)
1497 return dragNotAcceptedErr;
1498 return noErr;
1499 }
1500
1501 static pascal OSErr
1502 mac_do_receive_drag (window, refcon, drag)
1503 WindowRef window;
1504 void *refcon;
1505 DragRef drag;
1506 {
1507 OSErr err;
1508 int num_types, i;
1509 Lisp_Object rest, str;
1510 FlavorType *types;
1511 AppleEvent apple_event;
1512 Point mouse_pos;
1513 SInt16 modifiers;
1514
1515 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
1516 return dragNotAcceptedErr;
1517
1518 num_types = 0;
1519 for (rest = Vmac_dnd_known_types; CONSP (rest); rest = XCDR (rest))
1520 {
1521 str = XCAR (rest);
1522 if (STRINGP (str) && SBYTES (str) == 4)
1523 num_types++;
1524 }
1525
1526 types = xmalloc (sizeof (FlavorType) * num_types);
1527 i = 0;
1528 for (rest = Vmac_dnd_known_types; CONSP (rest); rest = XCDR (rest))
1529 {
1530 str = XCAR (rest);
1531 if (STRINGP (str) && SBYTES (str) == 4)
1532 types[i++] = EndianU32_BtoN (*((UInt32 *) SDATA (str)));
1533 }
1534
1535 err = create_apple_event_from_drag_ref (drag, num_types, types,
1536 &apple_event);
1537 xfree (types);
1538
1539 if (err == noErr)
1540 err = GetDragMouse (drag, &mouse_pos, NULL);
1541 if (err == noErr)
1542 {
1543 GlobalToLocal (&mouse_pos);
1544 err = GetDragModifiers (drag, NULL, NULL, &modifiers);
1545 }
1546 if (err == noErr)
1547 {
1548 UInt32 key_modifiers = modifiers;
1549
1550 err = AEPutParamPtr (&apple_event, kEventParamKeyModifiers,
1551 typeUInt32, &key_modifiers, sizeof (UInt32));
1552 }
1553
1554 if (err == noErr)
1555 {
1556 mac_store_drag_event (window, mouse_pos, 0, &apple_event);
1557 AEDisposeDesc (&apple_event);
1558 mac_wakeup_from_rne ();
1559 return noErr;
1560 }
1561 else
1562 return dragNotAcceptedErr;
1563 }
1564 #endif /* TARGET_API_MAC_CARBON */ 1064 #endif /* TARGET_API_MAC_CARBON */
1565
1566 OSErr
1567 install_drag_handler (window)
1568 WindowRef window;
1569 {
1570 OSErr err = noErr;
1571
1572 #if TARGET_API_MAC_CARBON
1573 if (mac_do_track_dragUPP == NULL)
1574 mac_do_track_dragUPP = NewDragTrackingHandlerUPP (mac_do_track_drag);
1575 if (mac_do_receive_dragUPP == NULL)
1576 mac_do_receive_dragUPP = NewDragReceiveHandlerUPP (mac_do_receive_drag);
1577
1578 err = InstallTrackingHandler (mac_do_track_dragUPP, window, NULL);
1579 if (err == noErr)
1580 err = InstallReceiveHandler (mac_do_receive_dragUPP, window, NULL);
1581 #endif
1582
1583 return err;
1584 }
1585
1586 void
1587 remove_drag_handler (window)
1588 WindowRef window;
1589 {
1590 #if TARGET_API_MAC_CARBON
1591 if (mac_do_track_dragUPP)
1592 RemoveTrackingHandler (mac_do_track_dragUPP, window);
1593 if (mac_do_receive_dragUPP)
1594 RemoveReceiveHandler (mac_do_receive_dragUPP, window);
1595 #endif
1596 }
1597 1065
1598 1066
1599 /*********************************************************************** 1067 /***********************************************************************
1600 Services menu support 1068 Services menu support
1601 ***********************************************************************/ 1069 ***********************************************************************/
1602 #ifdef MAC_OSX 1070 #ifdef MAC_OSX
1603 OSStatus 1071 /* Selection name for communication via Services menu. */
1604 install_service_handler () 1072 Lisp_Object Vmac_service_selection;
1605 {
1606 static const EventTypeSpec specs[] =
1607 {{kEventClassService, kEventServiceGetTypes},
1608 {kEventClassService, kEventServiceCopy},
1609 {kEventClassService, kEventServicePaste},
1610 {kEventClassService, kEventServicePerform}};
1611
1612 return InstallApplicationEventHandler (NewEventHandlerUPP
1613 (mac_handle_service_event),
1614 GetEventTypeCount (specs),
1615 specs, NULL, NULL);
1616 }
1617
1618 extern OSStatus mac_store_service_event P_ ((EventRef));
1619
1620 static OSStatus
1621 copy_scrap_flavor_data (from_scrap, to_scrap, flavor_type)
1622 ScrapRef from_scrap, to_scrap;
1623 ScrapFlavorType flavor_type;
1624 {
1625 OSStatus err;
1626 Size size, size_allocated;
1627 char *buf = NULL;
1628
1629 err = GetScrapFlavorSize (from_scrap, flavor_type, &size);
1630 if (err == noErr)
1631 buf = xmalloc (size);
1632 while (buf)
1633 {
1634 size_allocated = size;
1635 err = GetScrapFlavorData (from_scrap, flavor_type, &size, buf);
1636 if (err != noErr)
1637 {
1638 xfree (buf);
1639 buf = NULL;
1640 }
1641 else if (size_allocated < size)
1642 buf = xrealloc (buf, size);
1643 else
1644 break;
1645 }
1646 if (err == noErr)
1647 {
1648 if (buf == NULL)
1649 err = memFullErr;
1650 else
1651 {
1652 err = PutScrapFlavor (to_scrap, flavor_type, kScrapFlavorMaskNone,
1653 size, buf);
1654 xfree (buf);
1655 }
1656 }
1657
1658 return err;
1659 }
1660
1661 static OSStatus
1662 mac_handle_service_event (call_ref, event, data)
1663 EventHandlerCallRef call_ref;
1664 EventRef event;
1665 void *data;
1666 {
1667 OSStatus err = noErr;
1668 ScrapRef cur_scrap, specific_scrap;
1669 UInt32 event_kind = GetEventKind (event);
1670 CFMutableArrayRef copy_types, paste_types;
1671 CFStringRef type;
1672 Lisp_Object rest;
1673 ScrapFlavorType flavor_type;
1674
1675 /* Check if Vmac_service_selection is a valid selection that has a
1676 corresponding scrap. */
1677 if (!SYMBOLP (Vmac_service_selection))
1678 err = eventNotHandledErr;
1679 else
1680 err = mac_get_selection_from_symbol (Vmac_service_selection, 0, &cur_scrap);
1681 if (!(err == noErr && cur_scrap))
1682 return eventNotHandledErr;
1683
1684 switch (event_kind)
1685 {
1686 case kEventServiceGetTypes:
1687 /* Set paste types. */
1688 err = GetEventParameter (event, kEventParamServicePasteTypes,
1689 typeCFMutableArrayRef, NULL,
1690 sizeof (CFMutableArrayRef), NULL,
1691 &paste_types);
1692 if (err != noErr)
1693 break;
1694
1695 for (rest = Vselection_converter_alist; CONSP (rest);
1696 rest = XCDR (rest))
1697 if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))
1698 && (flavor_type =
1699 get_flavor_type_from_symbol (XCAR (XCAR (rest)), 0)))
1700 {
1701 type = CreateTypeStringWithOSType (flavor_type);
1702 if (type)
1703 {
1704 CFArrayAppendValue (paste_types, type);
1705 CFRelease (type);
1706 }
1707 }
1708
1709 /* Set copy types. */
1710 err = GetEventParameter (event, kEventParamServiceCopyTypes,
1711 typeCFMutableArrayRef, NULL,
1712 sizeof (CFMutableArrayRef), NULL,
1713 &copy_types);
1714 if (err != noErr)
1715 break;
1716
1717 if (NILP (Fx_selection_owner_p (Vmac_service_selection)))
1718 break;
1719 else
1720 goto copy_all_flavors;
1721
1722 case kEventServiceCopy:
1723 err = GetEventParameter (event, kEventParamScrapRef,
1724 typeScrapRef, NULL,
1725 sizeof (ScrapRef), NULL, &specific_scrap);
1726 if (err != noErr
1727 || NILP (Fx_selection_owner_p (Vmac_service_selection)))
1728 {
1729 err = eventNotHandledErr;
1730 break;
1731 }
1732
1733 copy_all_flavors:
1734 {
1735 UInt32 count, i;
1736 ScrapFlavorInfo *flavor_info = NULL;
1737 ScrapFlavorFlags flags;
1738
1739 err = GetScrapFlavorCount (cur_scrap, &count);
1740 if (err == noErr)
1741 flavor_info = xmalloc (sizeof (ScrapFlavorInfo) * count);
1742 err = GetScrapFlavorInfoList (cur_scrap, &count, flavor_info);
1743 if (err != noErr)
1744 {
1745 xfree (flavor_info);
1746 flavor_info = NULL;
1747 }
1748 if (flavor_info == NULL)
1749 break;
1750
1751 for (i = 0; i < count; i++)
1752 {
1753 flavor_type = flavor_info[i].flavorType;
1754 err = GetScrapFlavorFlags (cur_scrap, flavor_type, &flags);
1755 if (err == noErr && !(flags & kScrapFlavorMaskSenderOnly))
1756 {
1757 if (event_kind == kEventServiceCopy)
1758 err = copy_scrap_flavor_data (cur_scrap, specific_scrap,
1759 flavor_type);
1760 else /* event_kind == kEventServiceGetTypes */
1761 {
1762 type = CreateTypeStringWithOSType (flavor_type);
1763 if (type)
1764 {
1765 CFArrayAppendValue (copy_types, type);
1766 CFRelease (type);
1767 }
1768 }
1769 }
1770 }
1771 xfree (flavor_info);
1772 }
1773 break;
1774
1775 case kEventServicePaste:
1776 case kEventServicePerform:
1777 {
1778 int data_exists_p = 0;
1779
1780 err = GetEventParameter (event, kEventParamScrapRef, typeScrapRef,
1781 NULL, sizeof (ScrapRef), NULL,
1782 &specific_scrap);
1783 if (err == noErr)
1784 err = mac_clear_selection (&cur_scrap);
1785 if (err == noErr)
1786 for (rest = Vselection_converter_alist; CONSP (rest);
1787 rest = XCDR (rest))
1788 {
1789 if (! (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))))
1790 continue;
1791 flavor_type = get_flavor_type_from_symbol (XCAR (XCAR (rest)),
1792 specific_scrap);
1793 if (flavor_type == 0)
1794 continue;
1795 err = copy_scrap_flavor_data (specific_scrap, cur_scrap,
1796 flavor_type);
1797 if (err == noErr)
1798 data_exists_p = 1;
1799 }
1800 if (!data_exists_p)
1801 err = eventNotHandledErr;
1802 else
1803 err = mac_store_service_event (event);
1804 }
1805 break;
1806 }
1807
1808 if (err != noErr)
1809 err = eventNotHandledErr;
1810 return err;
1811 }
1812 #endif 1073 #endif
1813
1814 1074
1815 void 1075 void
1816 syms_of_macselect () 1076 syms_of_macselect ()
1817 { 1077 {
1818 defsubr (&Sx_get_selection_internal); 1078 defsubr (&Sx_get_selection_internal);
1868 1128
1869 #if TARGET_API_MAC_CARBON 1129 #if TARGET_API_MAC_CARBON
1870 DEFVAR_LISP ("mac-dnd-known-types", &Vmac_dnd_known_types, 1130 DEFVAR_LISP ("mac-dnd-known-types", &Vmac_dnd_known_types,
1871 doc: /* The types accepted by default for dropped data. 1131 doc: /* The types accepted by default for dropped data.
1872 The types are chosen in the order they appear in the list. */); 1132 The types are chosen in the order they appear in the list. */);
1873 Vmac_dnd_known_types = list4 (build_string ("hfs "), build_string ("utxt"), 1133 Vmac_dnd_known_types = mac_dnd_default_known_types ();
1874 build_string ("TEXT"), build_string ("TIFF"));
1875 #ifdef MAC_OSX
1876 Vmac_dnd_known_types = Fcons (build_string ("furl"), Vmac_dnd_known_types);
1877 #endif
1878 #endif 1134 #endif
1879 1135
1880 #ifdef MAC_OSX 1136 #ifdef MAC_OSX
1881 DEFVAR_LISP ("mac-service-selection", &Vmac_service_selection, 1137 DEFVAR_LISP ("mac-service-selection", &Vmac_service_selection,
1882 doc: /* Selection name for communication via Services menu. */); 1138 doc: /* Selection name for communication via Services menu. */);