diff options
Diffstat (limited to 'src/mac.c')
| -rw-r--r-- | src/mac.c | 324 |
1 files changed, 324 insertions, 0 deletions
| @@ -259,6 +259,216 @@ posix_to_mac_pathname (const char *ufn, char *mfn, int mfnbuflen) | |||
| 259 | 259 | ||
| 260 | 260 | ||
| 261 | /*********************************************************************** | 261 | /*********************************************************************** |
| 262 | Conversions on Apple event objects | ||
| 263 | ***********************************************************************/ | ||
| 264 | |||
| 265 | static Lisp_Object Qundecoded_file_name; | ||
| 266 | |||
| 267 | static Lisp_Object | ||
| 268 | mac_aelist_to_lisp (desc_list) | ||
| 269 | AEDescList *desc_list; | ||
| 270 | { | ||
| 271 | OSErr err; | ||
| 272 | long count; | ||
| 273 | Lisp_Object result, elem; | ||
| 274 | DescType desc_type; | ||
| 275 | Size size; | ||
| 276 | AEKeyword keyword; | ||
| 277 | AEDesc desc; | ||
| 278 | |||
| 279 | err = AECountItems (desc_list, &count); | ||
| 280 | if (err != noErr) | ||
| 281 | return Qnil; | ||
| 282 | result = Qnil; | ||
| 283 | while (count > 0) | ||
| 284 | { | ||
| 285 | err = AESizeOfNthItem (desc_list, count, &desc_type, &size); | ||
| 286 | if (err == noErr) | ||
| 287 | switch (desc_type) | ||
| 288 | { | ||
| 289 | case typeAEList: | ||
| 290 | case typeAERecord: | ||
| 291 | case typeAppleEvent: | ||
| 292 | err = AEGetNthDesc (desc_list, count, typeWildCard, | ||
| 293 | &keyword, &desc); | ||
| 294 | if (err != noErr) | ||
| 295 | break; | ||
| 296 | elem = mac_aelist_to_lisp (&desc); | ||
| 297 | AEDisposeDesc (&desc); | ||
| 298 | break; | ||
| 299 | |||
| 300 | default: | ||
| 301 | if (desc_type == typeNull) | ||
| 302 | elem = Qnil; | ||
| 303 | else | ||
| 304 | { | ||
| 305 | elem = make_uninit_string (size); | ||
| 306 | err = AEGetNthPtr (desc_list, count, typeWildCard, &keyword, | ||
| 307 | &desc_type, SDATA (elem), size, &size); | ||
| 308 | } | ||
| 309 | if (err != noErr) | ||
| 310 | break; | ||
| 311 | desc_type = EndianU32_NtoB (desc_type); | ||
| 312 | elem = Fcons (make_unibyte_string ((char *) &desc_type, 4), elem); | ||
| 313 | break; | ||
| 314 | } | ||
| 315 | |||
| 316 | if (err != noErr) | ||
| 317 | elem = Qnil; | ||
| 318 | else if (desc_list->descriptorType != typeAEList) | ||
| 319 | { | ||
| 320 | keyword = EndianU32_NtoB (keyword); | ||
| 321 | elem = Fcons (make_unibyte_string ((char *) &keyword, 4), elem); | ||
| 322 | } | ||
| 323 | |||
| 324 | result = Fcons (elem, result); | ||
| 325 | count--; | ||
| 326 | } | ||
| 327 | |||
| 328 | desc_type = EndianU32_NtoB (desc_list->descriptorType); | ||
| 329 | return Fcons (make_unibyte_string ((char *) &desc_type, 4), result); | ||
| 330 | } | ||
| 331 | |||
| 332 | Lisp_Object | ||
| 333 | mac_aedesc_to_lisp (desc) | ||
| 334 | AEDesc *desc; | ||
| 335 | { | ||
| 336 | OSErr err; | ||
| 337 | DescType desc_type = desc->descriptorType; | ||
| 338 | Lisp_Object result; | ||
| 339 | |||
| 340 | switch (desc_type) | ||
| 341 | { | ||
| 342 | case typeNull: | ||
| 343 | result = Qnil; | ||
| 344 | break; | ||
| 345 | |||
| 346 | case typeAEList: | ||
| 347 | case typeAERecord: | ||
| 348 | case typeAppleEvent: | ||
| 349 | return mac_aelist_to_lisp (desc); | ||
| 350 | #if 0 | ||
| 351 | /* The following one is much simpler, but creates and disposes | ||
| 352 | of Apple event descriptors many times. */ | ||
| 353 | { | ||
| 354 | long count; | ||
| 355 | Lisp_Object elem; | ||
| 356 | AEKeyword keyword; | ||
| 357 | AEDesc desc1; | ||
| 358 | |||
| 359 | err = AECountItems (desc, &count); | ||
| 360 | if (err != noErr) | ||
| 361 | break; | ||
| 362 | result = Qnil; | ||
| 363 | while (count > 0) | ||
| 364 | { | ||
| 365 | err = AEGetNthDesc (desc, count, typeWildCard, &keyword, &desc1); | ||
| 366 | if (err != noErr) | ||
| 367 | break; | ||
| 368 | elem = mac_aedesc_to_lisp (&desc1); | ||
| 369 | AEDisposeDesc (&desc1); | ||
| 370 | if (desc_type != typeAEList) | ||
| 371 | { | ||
| 372 | keyword = EndianU32_NtoB (keyword); | ||
| 373 | elem = Fcons (make_unibyte_string ((char *) &keyword, 4), elem); | ||
| 374 | } | ||
| 375 | result = Fcons (elem, result); | ||
| 376 | count--; | ||
| 377 | } | ||
| 378 | } | ||
| 379 | #endif | ||
| 380 | break; | ||
| 381 | |||
| 382 | default: | ||
| 383 | #if TARGET_API_MAC_CARBON | ||
| 384 | result = make_uninit_string (AEGetDescDataSize (desc)); | ||
| 385 | err = AEGetDescData (desc, SDATA (result), SBYTES (result)); | ||
| 386 | #else | ||
| 387 | result = make_uninit_string (GetHandleSize (desc->dataHandle)); | ||
| 388 | memcpy (SDATA (result), *(desc->dataHandle), SBYTES (result)); | ||
| 389 | #endif | ||
| 390 | break; | ||
| 391 | } | ||
| 392 | |||
| 393 | if (err != noErr) | ||
| 394 | return Qnil; | ||
| 395 | |||
| 396 | desc_type = EndianU32_NtoB (desc_type); | ||
| 397 | return Fcons (make_unibyte_string ((char *) &desc_type, 4), result); | ||
| 398 | } | ||
| 399 | |||
| 400 | #if TARGET_API_MAC_CARBON | ||
| 401 | OSErr | ||
| 402 | create_apple_event_from_event_ref (event, num_params, names, | ||
| 403 | types, sizes, result) | ||
| 404 | EventRef event; | ||
| 405 | UInt32 num_params; | ||
| 406 | EventParamName *names; | ||
| 407 | EventParamType *types; | ||
| 408 | UInt32 *sizes; | ||
| 409 | AppleEvent *result; | ||
| 410 | { | ||
| 411 | OSErr err; | ||
| 412 | static const ProcessSerialNumber psn = {0, kCurrentProcess}; | ||
| 413 | AEAddressDesc address_desc; | ||
| 414 | UInt32 i; | ||
| 415 | CFStringRef string; | ||
| 416 | CFDataRef data; | ||
| 417 | char *buf; | ||
| 418 | |||
| 419 | err = AECreateDesc (typeProcessSerialNumber, &psn, | ||
| 420 | sizeof (ProcessSerialNumber), &address_desc); | ||
| 421 | if (err == noErr) | ||
| 422 | { | ||
| 423 | err = AECreateAppleEvent (0, 0, /* Dummy class and ID. */ | ||
| 424 | &address_desc, /* NULL is not allowed | ||
| 425 | on Mac OS Classic. */ | ||
| 426 | kAutoGenerateReturnID, | ||
| 427 | kAnyTransactionID, result); | ||
| 428 | AEDisposeDesc (&address_desc); | ||
| 429 | } | ||
| 430 | if (err != noErr) | ||
| 431 | return err; | ||
| 432 | |||
| 433 | for (i = 0; i < num_params; i++) | ||
| 434 | switch (types[i]) | ||
| 435 | { | ||
| 436 | #ifdef MAC_OSX | ||
| 437 | case typeCFStringRef: | ||
| 438 | err = GetEventParameter (event, names[i], typeCFStringRef, NULL, | ||
| 439 | sizeof (CFStringRef), NULL, &string); | ||
| 440 | if (err != noErr) | ||
| 441 | break; | ||
| 442 | data = CFStringCreateExternalRepresentation (NULL, string, | ||
| 443 | kCFStringEncodingUTF8, | ||
| 444 | '?'); | ||
| 445 | if (data == NULL) | ||
| 446 | break; | ||
| 447 | /* typeUTF8Text is not available on Mac OS X 10.1. */ | ||
| 448 | AEPutParamPtr (result, names[i], 'utf8', | ||
| 449 | CFDataGetBytePtr (data), CFDataGetLength (data)); | ||
| 450 | CFRelease (data); | ||
| 451 | break; | ||
| 452 | #endif | ||
| 453 | |||
| 454 | default: | ||
| 455 | buf = xmalloc (sizes[i]); | ||
| 456 | if (buf == NULL) | ||
| 457 | break; | ||
| 458 | err = GetEventParameter (event, names[i], types[i], NULL, | ||
| 459 | sizes[i], NULL, buf); | ||
| 460 | if (err == noErr) | ||
| 461 | AEPutParamPtr (result, names[i], types[i], buf, sizes[i]); | ||
| 462 | xfree (buf); | ||
| 463 | break; | ||
| 464 | } | ||
| 465 | |||
| 466 | return noErr; | ||
| 467 | } | ||
| 468 | #endif | ||
| 469 | |||
| 470 | |||
| 471 | /*********************************************************************** | ||
| 262 | Conversion between Lisp and Core Foundation objects | 472 | Conversion between Lisp and Core Foundation objects |
| 263 | ***********************************************************************/ | 473 | ***********************************************************************/ |
| 264 | 474 | ||
| @@ -3887,6 +4097,116 @@ DEFUN ("posix-file-name-to-mac", Fposix_file_name_to_mac, | |||
| 3887 | } | 4097 | } |
| 3888 | 4098 | ||
| 3889 | 4099 | ||
| 4100 | DEFUN ("mac-coerce-ae-data", Fmac_coerce_ae_data, Smac_coerce_ae_data, 3, 3, 0, | ||
| 4101 | doc: /* Coerce Apple event data SRC-DATA of type SRC-TYPE to DST-TYPE. | ||
| 4102 | Each type should be a string of length 4 or the symbol | ||
| 4103 | `undecoded-file-name'. */) | ||
| 4104 | (src_type, src_data, dst_type) | ||
| 4105 | Lisp_Object src_type, src_data, dst_type; | ||
| 4106 | { | ||
| 4107 | OSErr err; | ||
| 4108 | Lisp_Object result = Qnil; | ||
| 4109 | DescType src_desc_type, dst_desc_type; | ||
| 4110 | AEDesc dst_desc; | ||
| 4111 | #ifdef MAC_OSX | ||
| 4112 | FSRef fref; | ||
| 4113 | #else | ||
| 4114 | FSSpec fs; | ||
| 4115 | #endif | ||
| 4116 | |||
| 4117 | CHECK_STRING (src_data); | ||
| 4118 | if (EQ (src_type, Qundecoded_file_name)) | ||
| 4119 | { | ||
| 4120 | #ifdef MAC_OSX | ||
| 4121 | src_desc_type = typeFileURL; | ||
| 4122 | #else | ||
| 4123 | src_desc_type = typeFSS; | ||
| 4124 | #endif | ||
| 4125 | } | ||
| 4126 | else | ||
| 4127 | src_desc_type = mac_get_code_from_arg (src_type, 0); | ||
| 4128 | |||
| 4129 | if (EQ (dst_type, Qundecoded_file_name)) | ||
| 4130 | { | ||
| 4131 | #ifdef MAC_OSX | ||
| 4132 | dst_desc_type = typeFSRef; | ||
| 4133 | #else | ||
| 4134 | dst_desc_type = typeFSS; | ||
| 4135 | #endif | ||
| 4136 | } | ||
| 4137 | else | ||
| 4138 | dst_desc_type = mac_get_code_from_arg (dst_type, 0); | ||
| 4139 | |||
| 4140 | BLOCK_INPUT; | ||
| 4141 | if (EQ (src_type, Qundecoded_file_name)) | ||
| 4142 | { | ||
| 4143 | #ifdef MAC_OSX | ||
| 4144 | CFStringRef str; | ||
| 4145 | CFURLRef url = NULL; | ||
| 4146 | CFDataRef data = NULL; | ||
| 4147 | |||
| 4148 | str = cfstring_create_with_utf8_cstring (SDATA (src_data)); | ||
| 4149 | if (str) | ||
| 4150 | { | ||
| 4151 | url = CFURLCreateWithFileSystemPath (NULL, str, | ||
| 4152 | kCFURLPOSIXPathStyle, false); | ||
| 4153 | CFRelease (str); | ||
| 4154 | } | ||
| 4155 | if (url) | ||
| 4156 | { | ||
| 4157 | data = CFURLCreateData (NULL, url, kCFStringEncodingUTF8, true); | ||
| 4158 | CFRelease (url); | ||
| 4159 | } | ||
| 4160 | if (data) | ||
| 4161 | err = AECoercePtr (src_desc_type, CFDataGetBytePtr (data), | ||
| 4162 | CFDataGetLength (data), | ||
| 4163 | dst_desc_type, &dst_desc); | ||
| 4164 | else | ||
| 4165 | err = memFullErr; | ||
| 4166 | #else | ||
| 4167 | err = posix_pathname_to_fsspec (SDATA (src_data), &fs); | ||
| 4168 | if (err == noErr) | ||
| 4169 | AECoercePtr (src_desc_type, &fs, sizeof (FSSpec), | ||
| 4170 | dst_desc_type, &dst_desc); | ||
| 4171 | #endif | ||
| 4172 | } | ||
| 4173 | else | ||
| 4174 | err = AECoercePtr (src_desc_type, SDATA (src_data), SBYTES (src_data), | ||
| 4175 | dst_desc_type, &dst_desc); | ||
| 4176 | |||
| 4177 | if (err == noErr) | ||
| 4178 | { | ||
| 4179 | if (EQ (dst_type, Qundecoded_file_name)) | ||
| 4180 | { | ||
| 4181 | char file_name[MAXPATHLEN]; | ||
| 4182 | |||
| 4183 | #ifdef MAC_OSX | ||
| 4184 | err = AEGetDescData (&dst_desc, &fref, sizeof (FSRef)); | ||
| 4185 | if (err == noErr) | ||
| 4186 | err = FSRefMakePath (&fref, file_name, sizeof (file_name)); | ||
| 4187 | #else | ||
| 4188 | #if TARGET_API_MAC_CARBON | ||
| 4189 | err = AEGetDescData (&dst_desc, &fs, sizeof (FSSpec)); | ||
| 4190 | #else | ||
| 4191 | memcpy (&fs, *(dst_desc.dataHandle), sizeof (FSSpec)); | ||
| 4192 | #endif | ||
| 4193 | if (err == noErr) | ||
| 4194 | err = fsspec_to_posix_pathname (&fs, file_name, | ||
| 4195 | sizeof (file_name) - 1); | ||
| 4196 | #endif | ||
| 4197 | if (err == noErr) | ||
| 4198 | result = make_unibyte_string (file_name, strlen (file_name)); | ||
| 4199 | } | ||
| 4200 | else | ||
| 4201 | result = Fcdr (mac_aedesc_to_lisp (&dst_desc)); | ||
| 4202 | AEDisposeDesc (&dst_desc); | ||
| 4203 | } | ||
| 4204 | UNBLOCK_INPUT; | ||
| 4205 | |||
| 4206 | return result; | ||
| 4207 | } | ||
| 4208 | |||
| 4209 | |||
| 3890 | #if TARGET_API_MAC_CARBON | 4210 | #if TARGET_API_MAC_CARBON |
| 3891 | static Lisp_Object Qxml, Qmime_charset; | 4211 | static Lisp_Object Qxml, Qmime_charset; |
| 3892 | static Lisp_Object QNFD, QNFKD, QNFC, QNFKC, QHFS_plus_D, QHFS_plus_C; | 4212 | static Lisp_Object QNFD, QNFKD, QNFC, QNFKC, QHFS_plus_D, QHFS_plus_C; |
| @@ -4676,6 +4996,9 @@ init_mac_osx_environment () | |||
| 4676 | void | 4996 | void |
| 4677 | syms_of_mac () | 4997 | syms_of_mac () |
| 4678 | { | 4998 | { |
| 4999 | Qundecoded_file_name = intern ("undecoded-file-name"); | ||
| 5000 | staticpro (&Qundecoded_file_name); | ||
| 5001 | |||
| 4679 | #if TARGET_API_MAC_CARBON | 5002 | #if TARGET_API_MAC_CARBON |
| 4680 | Qstring = intern ("string"); staticpro (&Qstring); | 5003 | Qstring = intern ("string"); staticpro (&Qstring); |
| 4681 | Qnumber = intern ("number"); staticpro (&Qnumber); | 5004 | Qnumber = intern ("number"); staticpro (&Qnumber); |
| @@ -4699,6 +5022,7 @@ syms_of_mac () | |||
| 4699 | QHFS_plus_C = intern ("HFS+C"); staticpro (&QHFS_plus_C); | 5022 | QHFS_plus_C = intern ("HFS+C"); staticpro (&QHFS_plus_C); |
| 4700 | #endif | 5023 | #endif |
| 4701 | 5024 | ||
| 5025 | defsubr (&Smac_coerce_ae_data); | ||
| 4702 | #if TARGET_API_MAC_CARBON | 5026 | #if TARGET_API_MAC_CARBON |
| 4703 | defsubr (&Smac_get_preference); | 5027 | defsubr (&Smac_get_preference); |
| 4704 | defsubr (&Smac_code_convert_string); | 5028 | defsubr (&Smac_code_convert_string); |