aboutsummaryrefslogtreecommitdiffstats
path: root/src/macselect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/macselect.c')
-rw-r--r--src/macselect.c369
1 files changed, 326 insertions, 43 deletions
diff --git a/src/macselect.c b/src/macselect.c
index 1b6a1a46cc3..3afea1e9813 100644
--- a/src/macselect.c
+++ b/src/macselect.c
@@ -909,14 +909,13 @@ and t is the same as `SECONDARY'. */)
909} 909}
910 910
911 911
912/***********************************************************************
913 Apple event support
914***********************************************************************/
912int mac_ready_for_apple_events = 0; 915int mac_ready_for_apple_events = 0;
913static Lisp_Object Vmac_apple_event_map; 916static Lisp_Object Vmac_apple_event_map;
914static Lisp_Object Qmac_apple_event_class, Qmac_apple_event_id; 917static Lisp_Object Qmac_apple_event_class, Qmac_apple_event_id;
915static struct 918static Lisp_Object Qemacs_suspension_id;
916{
917 AppleEvent *buf;
918 int size, count;
919} deferred_apple_events;
920extern Lisp_Object Qundefined; 919extern Lisp_Object Qundefined;
921extern void mac_store_apple_event P_ ((Lisp_Object, Lisp_Object, 920extern void mac_store_apple_event P_ ((Lisp_Object, Lisp_Object,
922 const AEDesc *)); 921 const AEDesc *));
@@ -927,6 +926,19 @@ struct apple_event_binding
927 Lisp_Object key, binding; 926 Lisp_Object key, binding;
928}; 927};
929 928
929struct suspended_ae_info
930{
931 UInt32 expiration_tick, suspension_id;
932 AppleEvent apple_event, reply;
933 struct suspended_ae_info *next;
934};
935
936/* List of deferred apple events at the startup time. */
937static struct suspended_ae_info *deferred_apple_events = NULL;
938
939/* List of suspended apple events, in order of expiration_tick. */
940static struct suspended_ae_info *suspended_apple_events = NULL;
941
930static void 942static void
931find_event_binding_fun (key, binding, args, data) 943find_event_binding_fun (key, binding, args, data)
932 Lisp_Object key, binding, args; 944 Lisp_Object key, binding, args;
@@ -1003,6 +1015,12 @@ defer_apple_events (apple_event, reply)
1003 const AppleEvent *apple_event, *reply; 1015 const AppleEvent *apple_event, *reply;
1004{ 1016{
1005 OSErr err; 1017 OSErr err;
1018 struct suspended_ae_info *new;
1019
1020 new = xmalloc (sizeof (struct suspended_ae_info));
1021 bzero (new, sizeof (struct suspended_ae_info));
1022 new->apple_event.descriptorType = typeNull;
1023 new->reply.descriptorType = typeNull;
1006 1024
1007 err = AESuspendTheCurrentEvent (apple_event); 1025 err = AESuspendTheCurrentEvent (apple_event);
1008 1026
@@ -1011,30 +1029,88 @@ defer_apple_events (apple_event, reply)
1011 manual says it doesn't. Anyway we create copies of them and save 1029 manual says it doesn't. Anyway we create copies of them and save
1012 them in `deferred_apple_events'. */ 1030 them in `deferred_apple_events'. */
1013 if (err == noErr) 1031 if (err == noErr)
1032 err = AEDuplicateDesc (apple_event, &new->apple_event);
1033 if (err == noErr)
1034 err = AEDuplicateDesc (reply, &new->reply);
1035 if (err == noErr)
1014 { 1036 {
1015 if (deferred_apple_events.buf == NULL) 1037 new->next = deferred_apple_events;
1016 { 1038 deferred_apple_events = new;
1017 deferred_apple_events.size = 16; 1039 }
1018 deferred_apple_events.count = 0; 1040 else
1019 deferred_apple_events.buf = 1041 {
1020 xmalloc (sizeof (AppleEvent) * deferred_apple_events.size); 1042 AEDisposeDesc (&new->apple_event);
1021 } 1043 AEDisposeDesc (&new->reply);
1022 else if (deferred_apple_events.count == deferred_apple_events.size) 1044 xfree (new);
1045 }
1046
1047 return err;
1048}
1049
1050static OSErr
1051mac_handle_apple_event_1 (class, id, apple_event, reply)
1052 Lisp_Object class, id;
1053 const AppleEvent *apple_event;
1054 AppleEvent *reply;
1055{
1056 OSErr err;
1057 static UInt32 suspension_id = 0;
1058 struct suspended_ae_info *new;
1059
1060 new = xmalloc (sizeof (struct suspended_ae_info));
1061 bzero (new, sizeof (struct suspended_ae_info));
1062 new->apple_event.descriptorType = typeNull;
1063 new->reply.descriptorType = typeNull;
1064
1065 err = AESuspendTheCurrentEvent (apple_event);
1066 if (err == noErr)
1067 err = AEDuplicateDesc (apple_event, &new->apple_event);
1068 if (err == noErr)
1069 err = AEDuplicateDesc (reply, &new->reply);
1070 if (err == noErr)
1071 err = AEPutAttributePtr (&new->apple_event, KEY_EMACS_SUSPENSION_ID_ATTR,
1072 typeUInt32, &suspension_id, sizeof (UInt32));
1073 if (err == noErr)
1074 {
1075 OSErr err1;
1076 SInt32 reply_requested;
1077
1078 err1 = AEGetAttributePtr (&new->apple_event, keyReplyRequestedAttr,
1079 typeSInt32, NULL, &reply_requested,
1080 sizeof (SInt32), NULL);
1081 if (err1 != noErr)
1023 { 1082 {
1024 deferred_apple_events.size *= 2; 1083 /* Emulate keyReplyRequestedAttr in older versions. */
1025 deferred_apple_events.buf 1084 reply_requested = reply->descriptorType != typeNull;
1026 = xrealloc (deferred_apple_events.buf, 1085 err = AEPutAttributePtr (&new->apple_event, keyReplyRequestedAttr,
1027 sizeof (AppleEvent) * deferred_apple_events.size); 1086 typeSInt32, &reply_requested,
1087 sizeof (SInt32));
1028 } 1088 }
1029 } 1089 }
1030
1031 if (err == noErr) 1090 if (err == noErr)
1032 { 1091 {
1033 int count = deferred_apple_events.count; 1092 SInt32 timeout = 0;
1093 struct suspended_ae_info **p;
1094
1095 new->suspension_id = suspension_id;
1096 suspension_id++;
1097 err = AEGetAttributePtr (apple_event, keyTimeoutAttr, typeSInt32,
1098 NULL, &timeout, sizeof (SInt32), NULL);
1099 new->expiration_tick = TickCount () + timeout;
1100
1101 for (p = &suspended_apple_events; *p; p = &(*p)->next)
1102 if ((*p)->expiration_tick >= new->expiration_tick)
1103 break;
1104 new->next = *p;
1105 *p = new;
1034 1106
1035 AEDuplicateDesc (apple_event, deferred_apple_events.buf + count); 1107 mac_store_apple_event (class, id, &new->apple_event);
1036 AEDuplicateDesc (reply, deferred_apple_events.buf + count + 1); 1108 }
1037 deferred_apple_events.count += 2; 1109 else
1110 {
1111 AEDisposeDesc (&new->reply);
1112 AEDisposeDesc (&new->apple_event);
1113 xfree (new);
1038 } 1114 }
1039 1115
1040 return err; 1116 return err;
@@ -1047,17 +1123,11 @@ mac_handle_apple_event (apple_event, reply, refcon)
1047 SInt32 refcon; 1123 SInt32 refcon;
1048{ 1124{
1049 OSErr err; 1125 OSErr err;
1126 UInt32 suspension_id;
1050 AEEventClass event_class; 1127 AEEventClass event_class;
1051 AEEventID event_id; 1128 AEEventID event_id;
1052 Lisp_Object class_key, id_key, binding; 1129 Lisp_Object class_key, id_key, binding;
1053 1130
1054 /* We can't handle an Apple event that requests a reply, but this
1055 seems to be too restrictive. */
1056#if 0
1057 if (reply->descriptorType != typeNull)
1058 return errAEEventNotHandled;
1059#endif
1060
1061 if (!mac_ready_for_apple_events) 1131 if (!mac_ready_for_apple_events)
1062 { 1132 {
1063 err = defer_apple_events (apple_event, reply); 1133 err = defer_apple_events (apple_event, reply);
@@ -1066,6 +1136,13 @@ mac_handle_apple_event (apple_event, reply, refcon)
1066 return noErr; 1136 return noErr;
1067 } 1137 }
1068 1138
1139 err = AEGetAttributePtr (apple_event, KEY_EMACS_SUSPENSION_ID_ATTR,
1140 typeUInt32, NULL,
1141 &suspension_id, sizeof (UInt32), NULL);
1142 if (err == noErr)
1143 /* Previously suspended event. Pass it to the next handler. */
1144 return errAEEventNotHandled;
1145
1069 err = AEGetAttributePtr (apple_event, keyEventClassAttr, typeType, NULL, 1146 err = AEGetAttributePtr (apple_event, keyEventClassAttr, typeType, NULL,
1070 &event_class, sizeof (AEEventClass), NULL); 1147 &event_class, sizeof (AEEventClass), NULL);
1071 if (err == noErr) 1148 if (err == noErr)
@@ -1079,11 +1156,49 @@ mac_handle_apple_event (apple_event, reply, refcon)
1079 { 1156 {
1080 if (INTEGERP (binding)) 1157 if (INTEGERP (binding))
1081 return XINT (binding); 1158 return XINT (binding);
1082 mac_store_apple_event (class_key, id_key, apple_event); 1159 err = mac_handle_apple_event_1 (class_key, id_key,
1083 return noErr; 1160 apple_event, reply);
1084 } 1161 }
1162 else
1163 err = errAEEventNotHandled;
1164 }
1165 if (err == noErr)
1166 return noErr;
1167 else
1168 return errAEEventNotHandled;
1169}
1170
1171static int
1172cleanup_suspended_apple_events (head, all_p)
1173 struct suspended_ae_info **head;
1174 int all_p;
1175{
1176 UInt32 current_tick = TickCount (), nresumed = 0;
1177 struct suspended_ae_info *p, *next;
1178
1179 for (p = *head; p; p = next)
1180 {
1181 if (!all_p && p->expiration_tick > current_tick)
1182 break;
1183 AESetTheCurrentEvent (&p->apple_event);
1184 AEResumeTheCurrentEvent (&p->apple_event, &p->reply,
1185 (AEEventHandlerUPP) kAENoDispatch, 0);
1186 AEDisposeDesc (&p->reply);
1187 AEDisposeDesc (&p->apple_event);
1188 nresumed++;
1189 next = p->next;
1190 xfree (p);
1085 } 1191 }
1086 return errAEEventNotHandled; 1192 *head = p;
1193
1194 return nresumed;
1195}
1196
1197static void
1198cleanup_all_suspended_apple_events ()
1199{
1200 cleanup_suspended_apple_events (&deferred_apple_events, 1);
1201 cleanup_suspended_apple_events (&suspended_apple_events, 1);
1087} 1202}
1088 1203
1089void 1204void
@@ -1109,34 +1224,190 @@ init_apple_event_handler ()
1109 0L, false); 1224 0L, false);
1110 if (err != noErr) 1225 if (err != noErr)
1111 abort (); 1226 abort ();
1227
1228 atexit (cleanup_all_suspended_apple_events);
1112} 1229}
1113 1230
1231static UInt32
1232get_suspension_id (apple_event)
1233 Lisp_Object apple_event;
1234{
1235 Lisp_Object tem;
1236
1237 CHECK_CONS (apple_event);
1238 CHECK_STRING_CAR (apple_event);
1239 if (SBYTES (XCAR (apple_event)) != 4
1240 || strcmp (SDATA (XCAR (apple_event)), "aevt") != 0)
1241 error ("Not an apple event");
1242
1243 tem = assq_no_quit (Qemacs_suspension_id, XCDR (apple_event));
1244 if (NILP (tem))
1245 error ("Suspension ID not available");
1246
1247 tem = XCDR (tem);
1248 if (!(CONSP (tem)
1249 && STRINGP (XCAR (tem)) && SBYTES (XCAR (tem)) == 4
1250 && strcmp (SDATA (XCAR (tem)), "magn") == 0
1251 && STRINGP (XCDR (tem)) && SBYTES (XCDR (tem)) == 4))
1252 error ("Bad suspension ID format");
1253
1254 return *((UInt32 *) SDATA (XCDR (tem)));
1255}
1256
1257
1114DEFUN ("mac-process-deferred-apple-events", Fmac_process_deferred_apple_events, Smac_process_deferred_apple_events, 0, 0, 0, 1258DEFUN ("mac-process-deferred-apple-events", Fmac_process_deferred_apple_events, Smac_process_deferred_apple_events, 0, 0, 0,
1115 doc: /* Process Apple events that are deferred at the startup time. */) 1259 doc: /* Process Apple events that are deferred at the startup time. */)
1116 () 1260 ()
1117{ 1261{
1118 Lisp_Object result = Qnil;
1119 long i;
1120
1121 if (mac_ready_for_apple_events) 1262 if (mac_ready_for_apple_events)
1122 return Qnil; 1263 return Qnil;
1123 1264
1124 BLOCK_INPUT; 1265 BLOCK_INPUT;
1125 mac_ready_for_apple_events = 1; 1266 mac_ready_for_apple_events = 1;
1126 if (deferred_apple_events.buf) 1267 if (deferred_apple_events)
1127 { 1268 {
1128 for (i = 0; i < deferred_apple_events.count; i += 2) 1269 struct suspended_ae_info *prev, *tail, *next;
1270
1271 /* `nreverse' deferred_apple_events. */
1272 prev = NULL;
1273 for (tail = deferred_apple_events; tail; tail = next)
1129 { 1274 {
1130 AEResumeTheCurrentEvent (deferred_apple_events.buf + i, 1275 next = tail->next;
1131 deferred_apple_events.buf + i + 1, 1276 tail->next = prev;
1277 prev = tail;
1278 }
1279
1280 /* Now `prev' points to the first cell. */
1281 for (tail = prev; tail; tail = next)
1282 {
1283 next = tail->next;
1284 AEResumeTheCurrentEvent (&tail->apple_event, &tail->reply,
1132 ((AEEventHandlerUPP) 1285 ((AEEventHandlerUPP)
1133 kAEUseStandardDispatch), 0); 1286 kAEUseStandardDispatch), 0);
1134 AEDisposeDesc (deferred_apple_events.buf + i); 1287 AEDisposeDesc (&tail->reply);
1135 AEDisposeDesc (deferred_apple_events.buf + i + 1); 1288 AEDisposeDesc (&tail->apple_event);
1289 xfree (tail);
1136 } 1290 }
1137 xfree (deferred_apple_events.buf);
1138 bzero (&deferred_apple_events, sizeof (deferred_apple_events));
1139 1291
1292 deferred_apple_events = NULL;
1293 }
1294 UNBLOCK_INPUT;
1295
1296 return Qt;
1297}
1298
1299DEFUN ("mac-cleanup-expired-apple-events", Fmac_cleanup_expired_apple_events, Smac_cleanup_expired_apple_events, 0, 0, 0,
1300 doc: /* Clean up expired Apple events.
1301Return the number of expired events. */)
1302 ()
1303{
1304 int nexpired;
1305
1306 BLOCK_INPUT;
1307 nexpired = cleanup_suspended_apple_events (&suspended_apple_events, 0);
1308 UNBLOCK_INPUT;
1309
1310 return make_number (nexpired);
1311}
1312
1313DEFUN ("mac-ae-set-reply-parameter", Fmac_ae_set_reply_parameter, Smac_ae_set_reply_parameter, 3, 3, 0,
1314 doc: /* Set parameter KEYWORD to DESCRIPTOR on reply of APPLE-EVENT.
1315KEYWORD is a 4-byte string. DESCRIPTOR is a Lisp representation of an
1316Apple event descriptor. It has the form of (TYPE . DATA), where TYPE
1317is a 4-byte string. Valid format of DATA is as follows:
1318
1319 * If TYPE is "null", then DATA is nil.
1320 * If TYPE is "list", then DATA is a list (DESCRIPTOR1 ... DESCRIPTORn).
1321 * If TYPE is "reco", then DATA is a list ((KEYWORD1 . DESCRIPTOR1)
1322 ... (KEYWORDn . DESCRIPTORn)).
1323 * If TYPE is "aevt", then DATA is ignored and the descriptor is
1324 treated as null.
1325 * Otherwise, DATA is a string.
1326
1327If a (sub-)descriptor is in an invalid format, it is silently treated
1328as null.
1329
1330Return t if the parameter is successfully set. Otherwise return nil. */)
1331 (apple_event, keyword, descriptor)
1332 Lisp_Object apple_event, keyword, descriptor;
1333{
1334 Lisp_Object result = Qnil;
1335 UInt32 suspension_id;
1336 struct suspended_ae_info *p;
1337
1338 suspension_id = get_suspension_id (apple_event);
1339
1340 CHECK_STRING (keyword);
1341 if (SBYTES (keyword) != 4)
1342 error ("Apple event keyword must be a 4-byte string: %s",
1343 SDATA (keyword));
1344
1345 BLOCK_INPUT;
1346 for (p = suspended_apple_events; p; p = p->next)
1347 if (p->suspension_id == suspension_id)
1348 break;
1349 if (p && p->reply.descriptorType != typeNull)
1350 {
1351 OSErr err;
1352
1353 err = mac_ae_put_lisp (&p->reply,
1354 EndianU32_BtoN (*((UInt32 *) SDATA (keyword))),
1355 descriptor);
1356 if (err == noErr)
1357 result = Qt;
1358 }
1359 UNBLOCK_INPUT;
1360
1361 return result;
1362}
1363
1364DEFUN ("mac-resume-apple-event", Fmac_resume_apple_event, Smac_resume_apple_event, 1, 2, 0,
1365 doc: /* Resume handling of APPLE-EVENT.
1366Every Apple event handled by the Lisp interpreter is suspended first.
1367This function resumes such a suspended event either to complete Apple
1368event handling to give a reply, or to redispatch it to other handlers.
1369
1370If optional ERROR-CODE is an integer, it specifies the error number
1371that is set in the reply. If ERROR-CODE is t, the resumed event is
1372handled with the standard dispatching mechanism, but it is not handled
1373by Emacs again, thus it is redispatched to other handlers.
1374
1375Return t if APPLE-EVENT is successfully resumed. Otherwise return
1376nil, which means the event is already resumed or expired. */)
1377 (apple_event, error_code)
1378 Lisp_Object apple_event, error_code;
1379{
1380 Lisp_Object result = Qnil;
1381 UInt32 suspension_id;
1382 struct suspended_ae_info **p, *ae;
1383
1384 suspension_id = get_suspension_id (apple_event);
1385
1386 BLOCK_INPUT;
1387 for (p = &suspended_apple_events; *p; p = &(*p)->next)
1388 if ((*p)->suspension_id == suspension_id)
1389 break;
1390 if (*p)
1391 {
1392 ae = *p;
1393 *p = (*p)->next;
1394 if (INTEGERP (error_code)
1395 && ae->apple_event.descriptorType != typeNull)
1396 {
1397 SInt32 errn = XINT (error_code);
1398
1399 AEPutParamPtr (&ae->reply, keyErrorNumber, typeSInt32,
1400 &errn, sizeof (SInt32));
1401 }
1402 AESetTheCurrentEvent (&ae->apple_event);
1403 AEResumeTheCurrentEvent (&ae->apple_event, &ae->reply,
1404 ((AEEventHandlerUPP)
1405 (EQ (error_code, Qt) ?
1406 kAEUseStandardDispatch : kAENoDispatch)),
1407 0);
1408 AEDisposeDesc (&ae->reply);
1409 AEDisposeDesc (&ae->apple_event);
1410 xfree (ae);
1140 result = Qt; 1411 result = Qt;
1141 } 1412 }
1142 UNBLOCK_INPUT; 1413 UNBLOCK_INPUT;
@@ -1145,6 +1416,9 @@ DEFUN ("mac-process-deferred-apple-events", Fmac_process_deferred_apple_events,
1145} 1416}
1146 1417
1147 1418
1419/***********************************************************************
1420 Drag and drop support
1421***********************************************************************/
1148#if TARGET_API_MAC_CARBON 1422#if TARGET_API_MAC_CARBON
1149static Lisp_Object Vmac_dnd_known_types; 1423static Lisp_Object Vmac_dnd_known_types;
1150static pascal OSErr mac_do_track_drag P_ ((DragTrackingMessage, WindowRef, 1424static pascal OSErr mac_do_track_drag P_ ((DragTrackingMessage, WindowRef,
@@ -1337,6 +1611,9 @@ remove_drag_handler (window)
1337} 1611}
1338 1612
1339 1613
1614/***********************************************************************
1615 Services menu support
1616***********************************************************************/
1340#ifdef MAC_OSX 1617#ifdef MAC_OSX
1341void 1618void
1342init_service_handler () 1619init_service_handler ()
@@ -1554,6 +1831,9 @@ syms_of_macselect ()
1554 defsubr (&Sx_selection_owner_p); 1831 defsubr (&Sx_selection_owner_p);
1555 defsubr (&Sx_selection_exists_p); 1832 defsubr (&Sx_selection_exists_p);
1556 defsubr (&Smac_process_deferred_apple_events); 1833 defsubr (&Smac_process_deferred_apple_events);
1834 defsubr (&Smac_cleanup_expired_apple_events);
1835 defsubr (&Smac_resume_apple_event);
1836 defsubr (&Smac_ae_set_reply_parameter);
1557 1837
1558 Vselection_alist = Qnil; 1838 Vselection_alist = Qnil;
1559 staticpro (&Vselection_alist); 1839 staticpro (&Vselection_alist);
@@ -1635,6 +1915,9 @@ The types are chosen in the order they appear in the list. */);
1635 1915
1636 Qmac_apple_event_id = intern ("mac-apple-event-id"); 1916 Qmac_apple_event_id = intern ("mac-apple-event-id");
1637 staticpro (&Qmac_apple_event_id); 1917 staticpro (&Qmac_apple_event_id);
1918
1919 Qemacs_suspension_id = intern ("emacs-suspension-id");
1920 staticpro (&Qemacs_suspension_id);
1638} 1921}
1639 1922
1640/* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732 1923/* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732