emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/src/macselect.c


From: YAMAMOTO Mitsuharu
Subject: [Emacs-diffs] Changes to emacs/src/macselect.c
Date: Fri, 09 Dec 2005 20:49:44 -0500

Index: emacs/src/macselect.c
diff -c emacs/src/macselect.c:1.7 emacs/src/macselect.c:1.8
*** emacs/src/macselect.c:1.7   Sat Jul 23 07:48:43 2005
--- emacs/src/macselect.c       Sat Dec 10 01:49:44 2005
***************
*** 23,28 ****
--- 23,29 ----
  #include "lisp.h"
  #include "macterm.h"
  #include "blockinput.h"
+ #include "keymap.h"
  
  #if !TARGET_API_MAC_CARBON
  #include <Endian.h>
***************
*** 908,913 ****
--- 909,1161 ----
  }
  
  
+ int mac_ready_for_apple_events = 0;
+ static Lisp_Object Vmac_apple_event_map;
+ static Lisp_Object Qmac_apple_event_class, Qmac_apple_event_id;
+ static struct
+ {
+   AppleEvent *buf;
+   int size, count;
+ } deferred_apple_events;
+ extern Lisp_Object Qundefined;
+ extern OSErr mac_store_apple_event P_ ((Lisp_Object, Lisp_Object,
+                                       const AEDesc *));
+ 
+ struct apple_event_binding
+ {
+   UInt32 code;                        /* Apple event class or ID.  */
+   Lisp_Object key, binding;
+ };
+ 
+ static void
+ find_event_binding_fun (key, binding, args, data)
+      Lisp_Object key, binding, args;
+      void *data;
+ {
+   struct apple_event_binding *event_binding =
+     (struct apple_event_binding *)data;
+   Lisp_Object code_string;
+ 
+   if (!SYMBOLP (key))
+     return;
+   code_string = Fget (key, args);
+   if (STRINGP (code_string) && SBYTES (code_string) == 4
+       && (EndianU32_BtoN (*((UInt32 *) SDATA (code_string)))
+         == event_binding->code))
+     {
+       event_binding->key = key;
+       event_binding->binding = binding;
+     }
+ }
+ 
+ static void
+ find_event_binding (keymap, event_binding, class_p)
+      Lisp_Object keymap;
+      struct apple_event_binding *event_binding;
+      int class_p;
+ {
+   if (event_binding->code == 0)
+     event_binding->binding =
+       access_keymap (keymap, event_binding->key, 0, 1, 0);
+   else
+     {
+       event_binding->binding = Qnil;
+       map_keymap (keymap, find_event_binding_fun,
+                 class_p ? Qmac_apple_event_class : Qmac_apple_event_id,
+                 event_binding, 0);
+     }
+ }
+ 
+ void
+ mac_find_apple_event_spec (class, id, class_key, id_key, binding)
+      AEEventClass class;
+      AEEventID id;
+      Lisp_Object *class_key, *id_key, *binding;
+ {
+   struct apple_event_binding event_binding;
+   Lisp_Object keymap;
+ 
+   *binding = Qnil;
+ 
+   keymap = get_keymap (Vmac_apple_event_map, 0, 0);
+   if (NILP (keymap))
+     return;
+ 
+   event_binding.code = class;
+   event_binding.key = *class_key;
+   event_binding.binding = Qnil;
+   find_event_binding (keymap, &event_binding, 1);
+   *class_key = event_binding.key;
+   keymap = get_keymap (event_binding.binding, 0, 0);
+   if (NILP (keymap))
+     return;
+ 
+   event_binding.code = id;
+   event_binding.key = *id_key;
+   event_binding.binding = Qnil;
+   find_event_binding (keymap, &event_binding, 0);
+   *id_key = event_binding.key;
+   *binding = event_binding.binding;
+ }
+ 
+ static OSErr
+ defer_apple_events (apple_event, reply)
+      const AppleEvent *apple_event, *reply;
+ {
+   OSErr err;
+ 
+   err = AESuspendTheCurrentEvent (apple_event);
+ 
+   /* Mac OS 10.3 Xcode manual says AESuspendTheCurrentEvent makes
+      copies of the Apple event and the reply, but Mac OS 10.4 Xcode
+      manual says it doesn't.  Anyway we create copies of them and save
+      it in `deferred_apple_events'.  */
+   if (err == noErr)
+     {
+       if (deferred_apple_events.buf == NULL)
+       {
+         deferred_apple_events.size = 16;
+         deferred_apple_events.count = 0;
+         deferred_apple_events.buf =
+           xmalloc (sizeof (AppleEvent) * deferred_apple_events.size);
+         if (deferred_apple_events.buf == NULL)
+           err = memFullErr;
+       }
+       else if (deferred_apple_events.count == deferred_apple_events.size)
+       {
+         AppleEvent *newbuf;
+ 
+         deferred_apple_events.size *= 2;
+         newbuf = xrealloc (deferred_apple_events.buf,
+                            sizeof (AppleEvent) * deferred_apple_events.size);
+         if (newbuf)
+           deferred_apple_events.buf = newbuf;
+         else
+           err = memFullErr;
+       }
+     }
+ 
+   if (err == noErr)
+     {
+       int count = deferred_apple_events.count;
+ 
+       AEDuplicateDesc (apple_event, deferred_apple_events.buf + count);
+       AEDuplicateDesc (reply, deferred_apple_events.buf + count + 1);
+       deferred_apple_events.count += 2;
+     }
+ 
+   return err;
+ }
+ 
+ static pascal OSErr
+ mac_handle_apple_event (apple_event, reply, refcon)
+      const AppleEvent *apple_event;
+      AppleEvent *reply;
+      SInt32 refcon;
+ {
+   OSErr err;
+   AEEventClass event_class;
+   AEEventID event_id;
+   Lisp_Object class_key, id_key, binding;
+ 
+   /* We can't handle an Apple event that requests a reply, but this
+      seems to be too restrictive.  */
+ #if 0
+   if (reply->descriptorType != typeNull)
+     return errAEEventNotHandled;
+ #endif
+ 
+   if (!mac_ready_for_apple_events)
+     {
+       err = defer_apple_events (apple_event, reply);
+       if (err != noErr)
+       return errAEEventNotHandled;
+       return noErr;
+     }
+ 
+   err = AEGetAttributePtr (apple_event, keyEventClassAttr, typeType, NULL,
+                          &event_class, sizeof (AEEventClass), NULL);
+   if (err == noErr)
+     err = AEGetAttributePtr (apple_event, keyEventIDAttr, typeType, NULL,
+                            &event_id, sizeof (AEEventID), NULL);
+   if (err == noErr)
+     {
+       mac_find_apple_event_spec (event_class, event_id,
+                                &class_key, &id_key, &binding);
+       if (!NILP (binding) && !EQ (binding, Qundefined))
+       {
+         if (INTEGERP (binding))
+           return XINT (binding);
+         err = mac_store_apple_event (class_key, id_key, apple_event);
+         if (err == noErr)
+           return noErr;
+       }
+     }
+   return errAEEventNotHandled;
+ }
+ 
+ void
+ init_apple_event_handler ()
+ {
+   OSErr err;
+   long result;
+ 
+   /* Make sure we have Apple events before starting.  */
+   err = Gestalt (gestaltAppleEventsAttr, &result);
+   if (err != noErr)
+     abort ();
+ 
+   if (!(result & (1 << gestaltAppleEventsPresent)))
+     abort ();
+ 
+   err = AEInstallEventHandler (typeWildCard, typeWildCard,
+ #if TARGET_API_MAC_CARBON
+                              NewAEEventHandlerUPP (mac_handle_apple_event),
+ #else
+                              NewAEEventHandlerProc (mac_handle_apple_event),
+ #endif
+                              0L, false);
+   if (err != noErr)
+     abort ();
+ }
+ 
+ DEFUN ("mac-process-deferred-apple-events", 
Fmac_process_deferred_apple_events, Smac_process_deferred_apple_events, 0, 0, 0,
+        doc: /* Process Apple events that are deferred at the startup time.  
*/)
+   ()
+ {
+   OSErr err;
+   Lisp_Object result = Qnil;
+   long i, count;
+   AppleEvent apple_event, reply;
+   AEKeyword keyword;
+ 
+   if (mac_ready_for_apple_events)
+     return Qnil;
+ 
+   BLOCK_INPUT;
+   mac_ready_for_apple_events = 1;
+   if (deferred_apple_events.buf)
+     {
+       for (i = 0; i < deferred_apple_events.count; i += 2)
+       {
+         AEResumeTheCurrentEvent (deferred_apple_events.buf + i,
+                                  deferred_apple_events.buf + i + 1,
+                                  ((AEEventHandlerUPP)
+                                   kAEUseStandardDispatch), 0);
+         AEDisposeDesc (deferred_apple_events.buf + i);
+         AEDisposeDesc (deferred_apple_events.buf + i + 1);
+       }
+       xfree (deferred_apple_events.buf);
+       bzero (&deferred_apple_events, sizeof (deferred_apple_events));
+ 
+       result = Qt;
+     }
+   UNBLOCK_INPUT;
+ 
+   return result;
+ }
+ 
+ 
  #ifdef MAC_OSX
  void
  init_service_handler ()
***************
*** 920,926 ****
                                  GetEventTypeCount (specs), specs, NULL, NULL);
  }
  
! extern void mac_store_services_event P_ ((EventRef));
  
  static OSStatus
  mac_handle_service_event (call_ref, event, data)
--- 1168,1223 ----
                                  GetEventTypeCount (specs), specs, NULL, NULL);
  }
  
! extern OSErr mac_store_services_event P_ ((EventRef));
! 
! static OSStatus
! copy_scrap_flavor_data (from_scrap, to_scrap, flavor_type)
!      ScrapRef from_scrap, to_scrap;
!      ScrapFlavorType flavor_type;
! {
!   OSStatus err;
!   Size size, size_allocated;
!   char *buf = NULL;
! 
!   err = GetScrapFlavorSize (from_scrap, flavor_type, &size);
!   if (err == noErr)
!     buf = xmalloc (size);
!   while (buf)
!     {
!       size_allocated = size;
!       err = GetScrapFlavorData (from_scrap, flavor_type, &size, buf);
!       if (err != noErr)
!       {
!         xfree (buf);
!         buf = NULL;
!       }
!       else if (size_allocated < size)
!       {
!         char *newbuf = xrealloc (buf, size);
! 
!         if (newbuf)
!           buf = newbuf;
!         else
!           {
!             xfree (buf);
!             buf = NULL;
!           }
!       }
!       else
!       break;
!     }
!   if (err == noErr)
!     if (buf == NULL)
!       err = memFullErr;
!     else
!       {
!       err = PutScrapFlavor (to_scrap, flavor_type, kScrapFlavorMaskNone,
!                             size, buf);
!       xfree (buf);
!       }
! 
!   return err;
! }
  
  static OSStatus
  mac_handle_service_event (call_ref, event, data)
***************
*** 929,935 ****
       void *data;
  {
    OSStatus err = noErr;
!   ScrapRef cur_scrap;
  
    /* Check if Vmac_services_selection is a valid selection that has a
       corresponding scrap.  */
--- 1226,1237 ----
       void *data;
  {
    OSStatus err = noErr;
!   ScrapRef cur_scrap, specific_scrap;
!   UInt32 event_kind = GetEventKind (event);
!   CFMutableArrayRef copy_types, paste_types;
!   CFStringRef type;
!   Lisp_Object rest;
!   ScrapFlavorType flavor_type;
  
    /* Check if Vmac_services_selection is a valid selection that has a
       corresponding scrap.  */
***************
*** 940,1025 ****
    if (!(err == noErr && cur_scrap))
      return eventNotHandledErr;
  
!   switch (GetEventKind (event))
      {
      case kEventServiceGetTypes:
!       {
!       CFMutableArrayRef copy_types, paste_types;
!       CFStringRef type;
!       Lisp_Object rest;
!       ScrapFlavorType flavor_type;
! 
!       /* Set paste types. */
!       err = GetEventParameter (event, kEventParamServicePasteTypes,
!                                typeCFMutableArrayRef, NULL,
!                                sizeof (CFMutableArrayRef), NULL,
!                                &paste_types);
!       if (err == noErr)
!         for (rest = Vselection_converter_alist; CONSP (rest);
!              rest = XCDR (rest))
!           if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))
!               && (flavor_type =
!                   get_flavor_type_from_symbol (XCAR (XCAR (rest)))))
              {
!               type = CreateTypeStringWithOSType (flavor_type);
!               if (type)
!                 {
!                   CFArrayAppendValue (paste_types, type);
!                   CFRelease (type);
!                 }
              }
  
!       /* Set copy types.  */
!       err = GetEventParameter (event, kEventParamServiceCopyTypes,
!                                typeCFMutableArrayRef, NULL,
!                                sizeof (CFMutableArrayRef), NULL,
!                                &copy_types);
!       if (err == noErr
!           && !NILP (Fx_selection_owner_p (Vmac_services_selection)))
!         for (rest = get_scrap_target_type_list (cur_scrap);
!              CONSP (rest) && SYMBOLP (XCAR (rest)); rest = XCDR (rest))
!           {
!             flavor_type = get_flavor_type_from_symbol (XCAR (rest));
!             if (flavor_type)
!               {
!                 type = CreateTypeStringWithOSType (flavor_type);
!                 if (type)
!                   {
!                     CFArrayAppendValue (copy_types, type);
!                     CFRelease (type);
!                   }
!               }
!           }
!       }
!       break;
  
      case kEventServiceCopy:
        {
!       ScrapRef specific_scrap;
!       Lisp_Object rest, data;
  
!       err = GetEventParameter (event, kEventParamScrapRef,
!                                typeScrapRef, NULL,
!                                sizeof (ScrapRef), NULL, &specific_scrap);
!       if (err == noErr
!           && !NILP (Fx_selection_owner_p (Vmac_services_selection)))
!         for (rest = get_scrap_target_type_list (cur_scrap);
!              CONSP (rest) && SYMBOLP (XCAR (rest)); rest = XCDR (rest))
!           {
!             data = get_scrap_string (cur_scrap, XCAR (rest));
!             if (STRINGP (data))
!               err = put_scrap_string (specific_scrap, XCAR (rest), data);
!           }
!       else
!         err = eventNotHandledErr;
        }
        break;
  
      case kEventServicePaste:
      case kEventServicePerform:
        {
-         ScrapRef specific_scrap;
-       Lisp_Object rest, data;
        int data_exists_p = 0;
  
          err = GetEventParameter (event, kEventParamScrapRef, typeScrapRef,
--- 1242,1344 ----
    if (!(err == noErr && cur_scrap))
      return eventNotHandledErr;
  
!   switch (event_kind)
      {
      case kEventServiceGetTypes:
!       /* Set paste types. */
!       err = GetEventParameter (event, kEventParamServicePasteTypes,
!                              typeCFMutableArrayRef, NULL,
!                              sizeof (CFMutableArrayRef), NULL,
!                              &paste_types);
!       if (err != noErr)
!       break;
! 
!       for (rest = Vselection_converter_alist; CONSP (rest);
!          rest = XCDR (rest))
!       if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))
!           && (flavor_type =
!               get_flavor_type_from_symbol (XCAR (XCAR (rest)))))
!         {
!           type = CreateTypeStringWithOSType (flavor_type);
!           if (type)
              {
!               CFArrayAppendValue (paste_types, type);
!               CFRelease (type);
              }
+         }
  
!       /* Set copy types.  */
!       err = GetEventParameter (event, kEventParamServiceCopyTypes,
!                              typeCFMutableArrayRef, NULL,
!                              sizeof (CFMutableArrayRef), NULL,
!                              &copy_types);
!       if (err != noErr)
!       break;
! 
!       if (NILP (Fx_selection_owner_p (Vmac_services_selection)))
!       break;
!       else
!       goto copy_all_flavors;
  
      case kEventServiceCopy:
+       err = GetEventParameter (event, kEventParamScrapRef,
+                              typeScrapRef, NULL,
+                              sizeof (ScrapRef), NULL, &specific_scrap);
+       if (err != noErr
+         || NILP (Fx_selection_owner_p (Vmac_services_selection)))
+       {
+         err = eventNotHandledErr;
+         break;
+       }
+ 
+     copy_all_flavors:
        {
!       UInt32 count, i;
!       ScrapFlavorInfo *flavor_info = NULL;
!       ScrapFlavorFlags flags;
  
!       err = GetScrapFlavorCount (cur_scrap, &count);
!       if (err == noErr)
!         flavor_info = xmalloc (sizeof (ScrapFlavorInfo) * count);
!       if (flavor_info)
!         {
!           err = GetScrapFlavorInfoList (cur_scrap, &count, flavor_info);
!           if (err != noErr)
!             {
!               xfree (flavor_info);
!               flavor_info = NULL;
!             }
!         }
!       if (flavor_info == NULL)
!         break;
! 
!       for (i = 0; i < count; i++)
!         {
!           flavor_type = flavor_info[i].flavorType;
!           err = GetScrapFlavorFlags (cur_scrap, flavor_type, &flags);
!           if (err == noErr && !(flags & kScrapFlavorMaskSenderOnly))
!             {
!               if (event_kind == kEventServiceCopy)
!                 err = copy_scrap_flavor_data (cur_scrap, specific_scrap,
!                                               flavor_type);
!               else         /* event_kind == kEventServiceGetTypes */
!                 {
!                   type = CreateTypeStringWithOSType (flavor_type);
!                   if (type)
!                     {
!                       CFArrayAppendValue (copy_types, type);
!                       CFRelease (type);
!                     }
!                 }
!             }
!         }
!       xfree (flavor_info);
        }
        break;
  
      case kEventServicePaste:
      case kEventServicePerform:
        {
        int data_exists_p = 0;
  
          err = GetEventParameter (event, kEventParamScrapRef, typeScrapRef,
***************
*** 1033,1057 ****
            {
              if (! (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))))
                continue;
!             data = get_scrap_string (specific_scrap, XCAR (XCAR (rest)));
!             if (STRINGP (data))
!               {
!                 err = put_scrap_string (cur_scrap, XCAR (XCAR (rest)),
!                                         data);
!                 if (err != noErr)
!                   break;
!                 data_exists_p = 1;
!               }
            }
!       if (err == noErr)
!         if (data_exists_p)
!           mac_store_application_menu_event (event);
!         else
!           err = eventNotHandledErr;
        }
        break;
      }
  
    return err;
  }
  #endif
--- 1352,1375 ----
            {
              if (! (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))))
                continue;
!             flavor_type = get_flavor_type_from_symbol (XCAR (XCAR (rest)));
!             if (flavor_type == 0)
!               continue;
!             err = copy_scrap_flavor_data (specific_scrap, cur_scrap,
!                                           flavor_type);
!             if (err == noErr)
!               data_exists_p = 1;
            }
!       if (!data_exists_p)
!         err = eventNotHandledErr;
!       else
!         err = mac_store_services_event (event);
        }
        break;
      }
  
+   if (err != noErr)
+     err = eventNotHandledErr;
    return err;
  }
  #endif
***************
*** 1065,1070 ****
--- 1383,1389 ----
    defsubr (&Sx_disown_selection_internal);
    defsubr (&Sx_selection_owner_p);
    defsubr (&Sx_selection_exists_p);
+   defsubr (&Smac_process_deferred_apple_events);
  
    Vselection_alist = Qnil;
    staticpro (&Vselection_alist);
***************
*** 1106,1111 ****
--- 1425,1434 ----
  set to nil.  */);
    Vnext_selection_coding_system = Qnil;
  
+   DEFVAR_LISP ("mac-apple-event-map", &Vmac_apple_event_map,
+              doc: /* Keymap for Apple events handled by Emacs.  */);
+   Vmac_apple_event_map = Fmake_sparse_keymap (Qnil);
+ 
  #ifdef MAC_OSX
    DEFVAR_LISP ("mac-services-selection", &Vmac_services_selection,
               doc: /* Selection name for communication via Services menu.  */);
***************
*** 1125,1130 ****
--- 1448,1459 ----
  
    Qmac_ostype = intern ("mac-ostype");
    staticpro (&Qmac_ostype);
+ 
+   Qmac_apple_event_class = intern ("mac-apple-event-class");
+   staticpro (&Qmac_apple_event_class);
+ 
+   Qmac_apple_event_id = intern ("mac-apple-event-id");
+   staticpro (&Qmac_apple_event_id);
  }
  
  /* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732




reply via email to

[Prev in Thread] Current Thread [Next in Thread]