aboutsummaryrefslogtreecommitdiffstats
path: root/src/macselect.c
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2005-12-10 01:49:44 +0000
committerYAMAMOTO Mitsuharu2005-12-10 01:49:44 +0000
commit28714a27a112b8caa209894aa0a40329e7bbd586 (patch)
tree808171a78d00a00d57212c1172cff9b2ba4c4906 /src/macselect.c
parent31b6888a5c4dabd5df94947bb54b7ba9f0611a3b (diff)
downloademacs-28714a27a112b8caa209894aa0a40329e7bbd586.tar.gz
emacs-28714a27a112b8caa209894aa0a40329e7bbd586.zip
Include keymap.h.
(mac_ready_for_apple_events): New variable. (Vmac_apple_event_map, Qmac_apple_event_class) (Qmac_apple_event_id): New variables. (syms_of_macselect): Initialize them. (Qundefined, mac_store_apple_event): Add externs. (struct apple_event_binding): New struct. (find_event_binding_fun, find_event_binding) (mac_find_apple_event_spec, defer_apple_events) (mac_handle_apple_event, init_apple_event_handler) (copy_scrap_flavor_data): New functions. (Fmac_process_deferred_apple_events): New defun. (syms_of_macselect): Defsubr it. (mac_store_services_event): Fix extern. (mac_handle_service_event): Don't allocate Lisp objects during asynchronous input processing. Use mac_store_services_event instead of mac_store_application_menu_event.
Diffstat (limited to 'src/macselect.c')
-rw-r--r--src/macselect.c493
1 files changed, 411 insertions, 82 deletions
diff --git a/src/macselect.c b/src/macselect.c
index 63221ba3a90..dd9603f8321 100644
--- a/src/macselect.c
+++ b/src/macselect.c
@@ -23,6 +23,7 @@ Boston, MA 02110-1301, USA. */
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 27
27#if !TARGET_API_MAC_CARBON 28#if !TARGET_API_MAC_CARBON
28#include <Endian.h> 29#include <Endian.h>
@@ -908,6 +909,253 @@ and t is the same as `SECONDARY'. */)
908} 909}
909 910
910 911
912int mac_ready_for_apple_events = 0;
913static Lisp_Object Vmac_apple_event_map;
914static Lisp_Object Qmac_apple_event_class, Qmac_apple_event_id;
915static struct
916{
917 AppleEvent *buf;
918 int size, count;
919} deferred_apple_events;
920extern Lisp_Object Qundefined;
921extern OSErr mac_store_apple_event P_ ((Lisp_Object, Lisp_Object,
922 const AEDesc *));
923
924struct apple_event_binding
925{
926 UInt32 code; /* Apple event class or ID. */
927 Lisp_Object key, binding;
928};
929
930static void
931find_event_binding_fun (key, binding, args, data)
932 Lisp_Object key, binding, args;
933 void *data;
934{
935 struct apple_event_binding *event_binding =
936 (struct apple_event_binding *)data;
937 Lisp_Object code_string;
938
939 if (!SYMBOLP (key))
940 return;
941 code_string = Fget (key, args);
942 if (STRINGP (code_string) && SBYTES (code_string) == 4
943 && (EndianU32_BtoN (*((UInt32 *) SDATA (code_string)))
944 == event_binding->code))
945 {
946 event_binding->key = key;
947 event_binding->binding = binding;
948 }
949}
950
951static void
952find_event_binding (keymap, event_binding, class_p)
953 Lisp_Object keymap;
954 struct apple_event_binding *event_binding;
955 int class_p;
956{
957 if (event_binding->code == 0)
958 event_binding->binding =
959 access_keymap (keymap, event_binding->key, 0, 1, 0);
960 else
961 {
962 event_binding->binding = Qnil;
963 map_keymap (keymap, find_event_binding_fun,
964 class_p ? Qmac_apple_event_class : Qmac_apple_event_id,
965 event_binding, 0);
966 }
967}
968
969void
970mac_find_apple_event_spec (class, id, class_key, id_key, binding)
971 AEEventClass class;
972 AEEventID id;
973 Lisp_Object *class_key, *id_key, *binding;
974{
975 struct apple_event_binding event_binding;
976 Lisp_Object keymap;
977
978 *binding = Qnil;
979
980 keymap = get_keymap (Vmac_apple_event_map, 0, 0);
981 if (NILP (keymap))
982 return;
983
984 event_binding.code = class;
985 event_binding.key = *class_key;
986 event_binding.binding = Qnil;
987 find_event_binding (keymap, &event_binding, 1);
988 *class_key = event_binding.key;
989 keymap = get_keymap (event_binding.binding, 0, 0);
990 if (NILP (keymap))
991 return;
992
993 event_binding.code = id;
994 event_binding.key = *id_key;
995 event_binding.binding = Qnil;
996 find_event_binding (keymap, &event_binding, 0);
997 *id_key = event_binding.key;
998 *binding = event_binding.binding;
999}
1000
1001static OSErr
1002defer_apple_events (apple_event, reply)
1003 const AppleEvent *apple_event, *reply;
1004{
1005 OSErr err;
1006
1007 err = AESuspendTheCurrentEvent (apple_event);
1008
1009 /* Mac OS 10.3 Xcode manual says AESuspendTheCurrentEvent makes
1010 copies of the Apple event and the reply, but Mac OS 10.4 Xcode
1011 manual says it doesn't. Anyway we create copies of them and save
1012 it in `deferred_apple_events'. */
1013 if (err == noErr)
1014 {
1015 if (deferred_apple_events.buf == NULL)
1016 {
1017 deferred_apple_events.size = 16;
1018 deferred_apple_events.count = 0;
1019 deferred_apple_events.buf =
1020 xmalloc (sizeof (AppleEvent) * deferred_apple_events.size);
1021 if (deferred_apple_events.buf == NULL)
1022 err = memFullErr;
1023 }
1024 else if (deferred_apple_events.count == deferred_apple_events.size)
1025 {
1026 AppleEvent *newbuf;
1027
1028 deferred_apple_events.size *= 2;
1029 newbuf = xrealloc (deferred_apple_events.buf,
1030 sizeof (AppleEvent) * deferred_apple_events.size);
1031 if (newbuf)
1032 deferred_apple_events.buf = newbuf;
1033 else
1034 err = memFullErr;
1035 }
1036 }
1037
1038 if (err == noErr)
1039 {
1040 int count = deferred_apple_events.count;
1041
1042 AEDuplicateDesc (apple_event, deferred_apple_events.buf + count);
1043 AEDuplicateDesc (reply, deferred_apple_events.buf + count + 1);
1044 deferred_apple_events.count += 2;
1045 }
1046
1047 return err;
1048}
1049
1050static pascal OSErr
1051mac_handle_apple_event (apple_event, reply, refcon)
1052 const AppleEvent *apple_event;
1053 AppleEvent *reply;
1054 SInt32 refcon;
1055{
1056 OSErr err;
1057 AEEventClass event_class;
1058 AEEventID event_id;
1059 Lisp_Object class_key, id_key, binding;
1060
1061 /* We can't handle an Apple event that requests a reply, but this
1062 seems to be too restrictive. */
1063#if 0
1064 if (reply->descriptorType != typeNull)
1065 return errAEEventNotHandled;
1066#endif
1067
1068 if (!mac_ready_for_apple_events)
1069 {
1070 err = defer_apple_events (apple_event, reply);
1071 if (err != noErr)
1072 return errAEEventNotHandled;
1073 return noErr;
1074 }
1075
1076 err = AEGetAttributePtr (apple_event, keyEventClassAttr, typeType, NULL,
1077 &event_class, sizeof (AEEventClass), NULL);
1078 if (err == noErr)
1079 err = AEGetAttributePtr (apple_event, keyEventIDAttr, typeType, NULL,
1080 &event_id, sizeof (AEEventID), NULL);
1081 if (err == noErr)
1082 {
1083 mac_find_apple_event_spec (event_class, event_id,
1084 &class_key, &id_key, &binding);
1085 if (!NILP (binding) && !EQ (binding, Qundefined))
1086 {
1087 if (INTEGERP (binding))
1088 return XINT (binding);
1089 err = mac_store_apple_event (class_key, id_key, apple_event);
1090 if (err == noErr)
1091 return noErr;
1092 }
1093 }
1094 return errAEEventNotHandled;
1095}
1096
1097void
1098init_apple_event_handler ()
1099{
1100 OSErr err;
1101 long result;
1102
1103 /* Make sure we have Apple events before starting. */
1104 err = Gestalt (gestaltAppleEventsAttr, &result);
1105 if (err != noErr)
1106 abort ();
1107
1108 if (!(result & (1 << gestaltAppleEventsPresent)))
1109 abort ();
1110
1111 err = AEInstallEventHandler (typeWildCard, typeWildCard,
1112#if TARGET_API_MAC_CARBON
1113 NewAEEventHandlerUPP (mac_handle_apple_event),
1114#else
1115 NewAEEventHandlerProc (mac_handle_apple_event),
1116#endif
1117 0L, false);
1118 if (err != noErr)
1119 abort ();
1120}
1121
1122DEFUN ("mac-process-deferred-apple-events", Fmac_process_deferred_apple_events, Smac_process_deferred_apple_events, 0, 0, 0,
1123 doc: /* Process Apple events that are deferred at the startup time. */)
1124 ()
1125{
1126 OSErr err;
1127 Lisp_Object result = Qnil;
1128 long i, count;
1129 AppleEvent apple_event, reply;
1130 AEKeyword keyword;
1131
1132 if (mac_ready_for_apple_events)
1133 return Qnil;
1134
1135 BLOCK_INPUT;
1136 mac_ready_for_apple_events = 1;
1137 if (deferred_apple_events.buf)
1138 {
1139 for (i = 0; i < deferred_apple_events.count; i += 2)
1140 {
1141 AEResumeTheCurrentEvent (deferred_apple_events.buf + i,
1142 deferred_apple_events.buf + i + 1,
1143 ((AEEventHandlerUPP)
1144 kAEUseStandardDispatch), 0);
1145 AEDisposeDesc (deferred_apple_events.buf + i);
1146 AEDisposeDesc (deferred_apple_events.buf + i + 1);
1147 }
1148 xfree (deferred_apple_events.buf);
1149 bzero (&deferred_apple_events, sizeof (deferred_apple_events));
1150
1151 result = Qt;
1152 }
1153 UNBLOCK_INPUT;
1154
1155 return result;
1156}
1157
1158
911#ifdef MAC_OSX 1159#ifdef MAC_OSX
912void 1160void
913init_service_handler () 1161init_service_handler ()
@@ -920,7 +1168,56 @@ init_service_handler ()
920 GetEventTypeCount (specs), specs, NULL, NULL); 1168 GetEventTypeCount (specs), specs, NULL, NULL);
921} 1169}
922 1170
923extern void mac_store_services_event P_ ((EventRef)); 1171extern OSErr mac_store_services_event P_ ((EventRef));
1172
1173static OSStatus
1174copy_scrap_flavor_data (from_scrap, to_scrap, flavor_type)
1175 ScrapRef from_scrap, to_scrap;
1176 ScrapFlavorType flavor_type;
1177{
1178 OSStatus err;
1179 Size size, size_allocated;
1180 char *buf = NULL;
1181
1182 err = GetScrapFlavorSize (from_scrap, flavor_type, &size);
1183 if (err == noErr)
1184 buf = xmalloc (size);
1185 while (buf)
1186 {
1187 size_allocated = size;
1188 err = GetScrapFlavorData (from_scrap, flavor_type, &size, buf);
1189 if (err != noErr)
1190 {
1191 xfree (buf);
1192 buf = NULL;
1193 }
1194 else if (size_allocated < size)
1195 {
1196 char *newbuf = xrealloc (buf, size);
1197
1198 if (newbuf)
1199 buf = newbuf;
1200 else
1201 {
1202 xfree (buf);
1203 buf = NULL;
1204 }
1205 }
1206 else
1207 break;
1208 }
1209 if (err == noErr)
1210 if (buf == NULL)
1211 err = memFullErr;
1212 else
1213 {
1214 err = PutScrapFlavor (to_scrap, flavor_type, kScrapFlavorMaskNone,
1215 size, buf);
1216 xfree (buf);
1217 }
1218
1219 return err;
1220}
924 1221
925static OSStatus 1222static OSStatus
926mac_handle_service_event (call_ref, event, data) 1223mac_handle_service_event (call_ref, event, data)
@@ -929,7 +1226,12 @@ mac_handle_service_event (call_ref, event, data)
929 void *data; 1226 void *data;
930{ 1227{
931 OSStatus err = noErr; 1228 OSStatus err = noErr;
932 ScrapRef cur_scrap; 1229 ScrapRef cur_scrap, specific_scrap;
1230 UInt32 event_kind = GetEventKind (event);
1231 CFMutableArrayRef copy_types, paste_types;
1232 CFStringRef type;
1233 Lisp_Object rest;
1234 ScrapFlavorType flavor_type;
933 1235
934 /* Check if Vmac_services_selection is a valid selection that has a 1236 /* Check if Vmac_services_selection is a valid selection that has a
935 corresponding scrap. */ 1237 corresponding scrap. */
@@ -940,86 +1242,103 @@ mac_handle_service_event (call_ref, event, data)
940 if (!(err == noErr && cur_scrap)) 1242 if (!(err == noErr && cur_scrap))
941 return eventNotHandledErr; 1243 return eventNotHandledErr;
942 1244
943 switch (GetEventKind (event)) 1245 switch (event_kind)
944 { 1246 {
945 case kEventServiceGetTypes: 1247 case kEventServiceGetTypes:
946 { 1248 /* Set paste types. */
947 CFMutableArrayRef copy_types, paste_types; 1249 err = GetEventParameter (event, kEventParamServicePasteTypes,
948 CFStringRef type; 1250 typeCFMutableArrayRef, NULL,
949 Lisp_Object rest; 1251 sizeof (CFMutableArrayRef), NULL,
950 ScrapFlavorType flavor_type; 1252 &paste_types);
951 1253 if (err != noErr)
952 /* Set paste types. */ 1254 break;
953 err = GetEventParameter (event, kEventParamServicePasteTypes, 1255
954 typeCFMutableArrayRef, NULL, 1256 for (rest = Vselection_converter_alist; CONSP (rest);
955 sizeof (CFMutableArrayRef), NULL, 1257 rest = XCDR (rest))
956 &paste_types); 1258 if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))
957 if (err == noErr) 1259 && (flavor_type =
958 for (rest = Vselection_converter_alist; CONSP (rest); 1260 get_flavor_type_from_symbol (XCAR (XCAR (rest)))))
959 rest = XCDR (rest)) 1261 {
960 if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest))) 1262 type = CreateTypeStringWithOSType (flavor_type);
961 && (flavor_type = 1263 if (type)
962 get_flavor_type_from_symbol (XCAR (XCAR (rest)))))
963 { 1264 {
964 type = CreateTypeStringWithOSType (flavor_type); 1265 CFArrayAppendValue (paste_types, type);
965 if (type) 1266 CFRelease (type);
966 {
967 CFArrayAppendValue (paste_types, type);
968 CFRelease (type);
969 }
970 } 1267 }
1268 }
971 1269
972 /* Set copy types. */ 1270 /* Set copy types. */
973 err = GetEventParameter (event, kEventParamServiceCopyTypes, 1271 err = GetEventParameter (event, kEventParamServiceCopyTypes,
974 typeCFMutableArrayRef, NULL, 1272 typeCFMutableArrayRef, NULL,
975 sizeof (CFMutableArrayRef), NULL, 1273 sizeof (CFMutableArrayRef), NULL,
976 &copy_types); 1274 &copy_types);
977 if (err == noErr 1275 if (err != noErr)
978 && !NILP (Fx_selection_owner_p (Vmac_services_selection))) 1276 break;
979 for (rest = get_scrap_target_type_list (cur_scrap); 1277
980 CONSP (rest) && SYMBOLP (XCAR (rest)); rest = XCDR (rest)) 1278 if (NILP (Fx_selection_owner_p (Vmac_services_selection)))
981 { 1279 break;
982 flavor_type = get_flavor_type_from_symbol (XCAR (rest)); 1280 else
983 if (flavor_type) 1281 goto copy_all_flavors;
984 {
985 type = CreateTypeStringWithOSType (flavor_type);
986 if (type)
987 {
988 CFArrayAppendValue (copy_types, type);
989 CFRelease (type);
990 }
991 }
992 }
993 }
994 break;
995 1282
996 case kEventServiceCopy: 1283 case kEventServiceCopy:
997 { 1284 err = GetEventParameter (event, kEventParamScrapRef,
998 ScrapRef specific_scrap; 1285 typeScrapRef, NULL,
999 Lisp_Object rest, data; 1286 sizeof (ScrapRef), NULL, &specific_scrap);
1000 1287 if (err != noErr
1001 err = GetEventParameter (event, kEventParamScrapRef, 1288 || NILP (Fx_selection_owner_p (Vmac_services_selection)))
1002 typeScrapRef, NULL, 1289 {
1003 sizeof (ScrapRef), NULL, &specific_scrap);
1004 if (err == noErr
1005 && !NILP (Fx_selection_owner_p (Vmac_services_selection)))
1006 for (rest = get_scrap_target_type_list (cur_scrap);
1007 CONSP (rest) && SYMBOLP (XCAR (rest)); rest = XCDR (rest))
1008 {
1009 data = get_scrap_string (cur_scrap, XCAR (rest));
1010 if (STRINGP (data))
1011 err = put_scrap_string (specific_scrap, XCAR (rest), data);
1012 }
1013 else
1014 err = eventNotHandledErr; 1290 err = eventNotHandledErr;
1291 break;
1292 }
1293
1294 copy_all_flavors:
1295 {
1296 UInt32 count, i;
1297 ScrapFlavorInfo *flavor_info = NULL;
1298 ScrapFlavorFlags flags;
1299
1300 err = GetScrapFlavorCount (cur_scrap, &count);
1301 if (err == noErr)
1302 flavor_info = xmalloc (sizeof (ScrapFlavorInfo) * count);
1303 if (flavor_info)
1304 {
1305 err = GetScrapFlavorInfoList (cur_scrap, &count, flavor_info);
1306 if (err != noErr)
1307 {
1308 xfree (flavor_info);
1309 flavor_info = NULL;
1310 }
1311 }
1312 if (flavor_info == NULL)
1313 break;
1314
1315 for (i = 0; i < count; i++)
1316 {
1317 flavor_type = flavor_info[i].flavorType;
1318 err = GetScrapFlavorFlags (cur_scrap, flavor_type, &flags);
1319 if (err == noErr && !(flags & kScrapFlavorMaskSenderOnly))
1320 {
1321 if (event_kind == kEventServiceCopy)
1322 err = copy_scrap_flavor_data (cur_scrap, specific_scrap,
1323 flavor_type);
1324 else /* event_kind == kEventServiceGetTypes */
1325 {
1326 type = CreateTypeStringWithOSType (flavor_type);
1327 if (type)
1328 {
1329 CFArrayAppendValue (copy_types, type);
1330 CFRelease (type);
1331 }
1332 }
1333 }
1334 }
1335 xfree (flavor_info);
1015 } 1336 }
1016 break; 1337 break;
1017 1338
1018 case kEventServicePaste: 1339 case kEventServicePaste:
1019 case kEventServicePerform: 1340 case kEventServicePerform:
1020 { 1341 {
1021 ScrapRef specific_scrap;
1022 Lisp_Object rest, data;
1023 int data_exists_p = 0; 1342 int data_exists_p = 0;
1024 1343
1025 err = GetEventParameter (event, kEventParamScrapRef, typeScrapRef, 1344 err = GetEventParameter (event, kEventParamScrapRef, typeScrapRef,
@@ -1033,25 +1352,24 @@ mac_handle_service_event (call_ref, event, data)
1033 { 1352 {
1034 if (! (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest))))) 1353 if (! (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))))
1035 continue; 1354 continue;
1036 data = get_scrap_string (specific_scrap, XCAR (XCAR (rest))); 1355 flavor_type = get_flavor_type_from_symbol (XCAR (XCAR (rest)));
1037 if (STRINGP (data)) 1356 if (flavor_type == 0)
1038 { 1357 continue;
1039 err = put_scrap_string (cur_scrap, XCAR (XCAR (rest)), 1358 err = copy_scrap_flavor_data (specific_scrap, cur_scrap,
1040 data); 1359 flavor_type);
1041 if (err != noErr) 1360 if (err == noErr)
1042 break; 1361 data_exists_p = 1;
1043 data_exists_p = 1;
1044 }
1045 } 1362 }
1046 if (err == noErr) 1363 if (!data_exists_p)
1047 if (data_exists_p) 1364 err = eventNotHandledErr;
1048 mac_store_application_menu_event (event); 1365 else
1049 else 1366 err = mac_store_services_event (event);
1050 err = eventNotHandledErr;
1051 } 1367 }
1052 break; 1368 break;
1053 } 1369 }
1054 1370
1371 if (err != noErr)
1372 err = eventNotHandledErr;
1055 return err; 1373 return err;
1056} 1374}
1057#endif 1375#endif
@@ -1065,6 +1383,7 @@ syms_of_macselect ()
1065 defsubr (&Sx_disown_selection_internal); 1383 defsubr (&Sx_disown_selection_internal);
1066 defsubr (&Sx_selection_owner_p); 1384 defsubr (&Sx_selection_owner_p);
1067 defsubr (&Sx_selection_exists_p); 1385 defsubr (&Sx_selection_exists_p);
1386 defsubr (&Smac_process_deferred_apple_events);
1068 1387
1069 Vselection_alist = Qnil; 1388 Vselection_alist = Qnil;
1070 staticpro (&Vselection_alist); 1389 staticpro (&Vselection_alist);
@@ -1106,6 +1425,10 @@ next communication only. After the communication, this variable is
1106set to nil. */); 1425set to nil. */);
1107 Vnext_selection_coding_system = Qnil; 1426 Vnext_selection_coding_system = Qnil;
1108 1427
1428 DEFVAR_LISP ("mac-apple-event-map", &Vmac_apple_event_map,
1429 doc: /* Keymap for Apple events handled by Emacs. */);
1430 Vmac_apple_event_map = Fmake_sparse_keymap (Qnil);
1431
1109#ifdef MAC_OSX 1432#ifdef MAC_OSX
1110 DEFVAR_LISP ("mac-services-selection", &Vmac_services_selection, 1433 DEFVAR_LISP ("mac-services-selection", &Vmac_services_selection,
1111 doc: /* Selection name for communication via Services menu. */); 1434 doc: /* Selection name for communication via Services menu. */);
@@ -1125,6 +1448,12 @@ set to nil. */);
1125 1448
1126 Qmac_ostype = intern ("mac-ostype"); 1449 Qmac_ostype = intern ("mac-ostype");
1127 staticpro (&Qmac_ostype); 1450 staticpro (&Qmac_ostype);
1451
1452 Qmac_apple_event_class = intern ("mac-apple-event-class");
1453 staticpro (&Qmac_apple_event_class);
1454
1455 Qmac_apple_event_id = intern ("mac-apple-event-id");
1456 staticpro (&Qmac_apple_event_id);
1128} 1457}
1129 1458
1130/* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732 1459/* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732