]> code.delx.au - gnu-emacs/blobdiff - src/mac.c
*** empty log message ***
[gnu-emacs] / src / mac.c
index 2b4e8dcbc642f8d1793e12db3c954102de0e2f97..75a606b60b3f47c6ca5bd9844fd9d938f3b30111 100644 (file)
--- a/src/mac.c
+++ b/src/mac.c
@@ -1,12 +1,12 @@
 /* Unix emulation routines for GNU Emacs on the Mac OS.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006 Free Software Foundation, Inc.
+                 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -46,11 +46,9 @@ Boston, MA 02110-1301, USA.  */
 #include <Folders.h>
 #include <Resources.h>
 #include <Aliases.h>
-#include <FixMath.h>
 #include <Timer.h>
 #include <OSA.h>
 #include <AppleScript.h>
-#include <Scrap.h>
 #include <Events.h>
 #include <Processes.h>
 #include <EPPC.h>
@@ -81,6 +79,17 @@ static ComponentInstance as_scripting_component;
 /* The single script context used for all script executions.  */
 static OSAID as_script_context;
 
+#ifndef MAC_OS_X
+#if TARGET_API_MAC_CARBON
+static int wakeup_from_rne_enabled_p = 0;
+#define ENABLE_WAKEUP_FROM_RNE (wakeup_from_rne_enabled_p = 1)
+#define DISABLE_WAKEUP_FROM_RNE (wakeup_from_rne_enabled_p = 0)
+#else
+#define ENABLE_WAKEUP_FROM_RNE 0
+#define DISABLE_WAKEUP_FROM_RNE 0
+#endif
+#endif
+
 #ifndef MAC_OSX
 static OSErr posix_pathname_to_fsspec P_ ((const char *, FSSpec *));
 static OSErr fsspec_to_posix_pathname P_ ((const FSSpec *, char *, int));
@@ -270,9 +279,29 @@ posix_to_mac_pathname (const char *ufn, char *mfn, int mfnbuflen)
 
 static Lisp_Object Qundecoded_file_name;
 
+static struct {
+  AEKeyword keyword;
+  char *name;
+  Lisp_Object symbol;
+} ae_attr_table [] =
+  {{keyTransactionIDAttr,      "transaction-id"},
+   {keyReturnIDAttr,           "return-id"},
+   {keyEventClassAttr,         "event-class"},
+   {keyEventIDAttr,            "event-id"},
+   {keyAddressAttr,            "address"},
+   {keyOptionalKeywordAttr,    "optional-keyword"},
+   {keyTimeoutAttr,            "timeout"},
+   {keyInteractLevelAttr,      "interact-level"},
+   {keyEventSourceAttr,                "event-source"},
+   /* {keyMissedKeywordAttr,   "missed-keyword"}, */
+   {keyOriginalAddressAttr,    "original-address"},
+   {keyReplyRequestedAttr,     "reply-requested"},
+   {KEY_EMACS_SUSPENSION_ID_ATTR, "emacs-suspension-id"}
+  };
+
 static Lisp_Object
 mac_aelist_to_lisp (desc_list)
-     AEDescList *desc_list;
+     const AEDescList *desc_list;
 {
   OSErr err;
   long count;
@@ -281,22 +310,36 @@ mac_aelist_to_lisp (desc_list)
   Size size;
   AEKeyword keyword;
   AEDesc desc;
+  int attribute_p = 0;
 
   err = AECountItems (desc_list, &count);
   if (err != noErr)
     return Qnil;
   result = Qnil;
+
+ again:
   while (count > 0)
     {
-      err = AESizeOfNthItem (desc_list, count, &desc_type, &size);
+      if (attribute_p)
+       {
+         keyword = ae_attr_table[count - 1].keyword;
+         err = AESizeOfAttribute (desc_list, keyword, &desc_type, &size);
+       }
+      else
+       err = AESizeOfNthItem (desc_list, count, &desc_type, &size);
+
       if (err == noErr)
        switch (desc_type)
          {
          case typeAEList:
          case typeAERecord:
          case typeAppleEvent:
-           err = AEGetNthDesc (desc_list, count, typeWildCard,
-                               &keyword, &desc);
+           if (attribute_p)
+             err = AEGetAttributeDesc (desc_list, keyword, typeWildCard,
+                                       &desc);
+           else
+             err = AEGetNthDesc (desc_list, count, typeWildCard,
+                                 &keyword, &desc);
            if (err != noErr)
              break;
            elem = mac_aelist_to_lisp (&desc);
@@ -309,8 +352,13 @@ mac_aelist_to_lisp (desc_list)
            else
              {
                elem = make_uninit_string (size);
-               err = AEGetNthPtr (desc_list, count, typeWildCard, &keyword,
-                                  &desc_type, SDATA (elem), size, &size);
+               if (attribute_p)
+                 err = AEGetAttributePtr (desc_list, keyword, typeWildCard,
+                                          &desc_type, SDATA (elem),
+                                          size, &size);
+               else
+                 err = AEGetNthPtr (desc_list, count, typeWildCard, &keyword,
+                                    &desc_type, SDATA (elem), size, &size);
              }
            if (err != noErr)
              break;
@@ -319,25 +367,42 @@ mac_aelist_to_lisp (desc_list)
            break;
        }
 
-      if (err != noErr)
-       elem = Qnil;
-      else if (desc_list->descriptorType != typeAEList)
+      if (err == noErr || desc_list->descriptorType == typeAEList)
        {
-         keyword = EndianU32_NtoB (keyword);
-         elem = Fcons (make_unibyte_string ((char *) &keyword, 4), elem);
+         if (err != noErr)
+           elem = Qnil;        /* Don't skip elements in AEList.  */
+         else if (desc_list->descriptorType != typeAEList)
+           {
+             if (attribute_p)
+               elem = Fcons (ae_attr_table[count-1].symbol, elem);
+             else
+               {
+                 keyword = EndianU32_NtoB (keyword);
+                 elem = Fcons (make_unibyte_string ((char *) &keyword, 4),
+                               elem);
+               }
+           }
+
+         result = Fcons (elem, result);
        }
 
-      result = Fcons (elem, result);
       count--;
     }
 
+  if (desc_list->descriptorType == typeAppleEvent && !attribute_p)
+    {
+      attribute_p = 1;
+      count = sizeof (ae_attr_table) / sizeof (ae_attr_table[0]);
+      goto again;
+    }
+
   desc_type = EndianU32_NtoB (desc_list->descriptorType);
   return Fcons (make_unibyte_string ((char *) &desc_type, 4), result);
 }
 
 Lisp_Object
 mac_aedesc_to_lisp (desc)
-     AEDesc *desc;
+     const AEDesc *desc;
 {
   OSErr err = noErr;
   DescType desc_type = desc->descriptorType;
@@ -403,6 +468,93 @@ mac_aedesc_to_lisp (desc)
   return Fcons (make_unibyte_string ((char *) &desc_type, 4), result);
 }
 
+OSErr
+mac_ae_put_lisp (desc, keyword_or_index, obj)
+     AEDescList *desc;
+     UInt32 keyword_or_index;
+     Lisp_Object obj;
+{
+  OSErr err;
+
+  if (!(desc->descriptorType == typeAppleEvent
+       || desc->descriptorType == typeAERecord
+       || desc->descriptorType == typeAEList))
+    return errAEWrongDataType;
+
+  if (CONSP (obj) && STRINGP (XCAR (obj)) && SBYTES (XCAR (obj)) == 4)
+    {
+      DescType desc_type1 = EndianU32_BtoN (*((UInt32 *) SDATA (XCAR (obj))));
+      Lisp_Object data = XCDR (obj), rest;
+      AEDesc desc1;
+
+      switch (desc_type1)
+       {
+       case typeNull:
+       case typeAppleEvent:
+         break;
+
+       case typeAEList:
+       case typeAERecord:
+         err = AECreateList (NULL, 0, desc_type1 == typeAERecord, &desc1);
+         if (err == noErr)
+           {
+             for (rest = data; CONSP (rest); rest = XCDR (rest))
+               {
+                 UInt32 keyword_or_index1 = 0;
+                 Lisp_Object elem = XCAR (rest);
+
+                 if (desc_type1 == typeAERecord)
+                   {
+                     if (CONSP (elem) && STRINGP (XCAR (elem))
+                         && SBYTES (XCAR (elem)) == 4)
+                       {
+                         keyword_or_index1 =
+                           EndianU32_BtoN (*((UInt32 *)
+                                             SDATA (XCAR (elem))));
+                         elem = XCDR (elem);
+                       }
+                     else
+                       continue;
+                   }
+
+                 err = mac_ae_put_lisp (&desc1, keyword_or_index1, elem);
+                 if (err != noErr)
+                   break;
+               }
+
+             if (err == noErr)
+               {
+                 if (desc->descriptorType == typeAEList)
+                   err = AEPutDesc (desc, keyword_or_index, &desc1);
+                 else
+                   err = AEPutParamDesc (desc, keyword_or_index, &desc1);
+               }
+
+             AEDisposeDesc (&desc1);
+           }
+         return err;
+
+       default:
+         if (!STRINGP (data))
+           break;
+         if (desc->descriptorType == typeAEList)
+           err = AEPutPtr (desc, keyword_or_index, desc_type1,
+                           SDATA (data), SBYTES (data));
+         else
+           err = AEPutParamPtr (desc, keyword_or_index, desc_type1,
+                                SDATA (data), SBYTES (data));
+         return err;
+       }
+    }
+
+  if (desc->descriptorType == typeAEList)
+    err = AEPutPtr (desc, keyword_or_index, typeNull, NULL, 0);
+  else
+    err = AEPutParamPtr (desc, keyword_or_index, typeNull, NULL, 0);
+
+  return err;
+}
+
 static pascal OSErr
 mac_coerce_file_name_ptr (type_code, data_ptr, data_size,
                          to_type, handler_refcon, result)
@@ -448,20 +600,31 @@ mac_coerce_file_name_ptr (type_code, data_ptr, data_size,
        }
       else
        err = memFullErr;
-#else
-      FSSpec fs;
-      char *buf;
 
-      buf = xmalloc (data_size + 1);
-      if (buf)
+      if (err != noErr)
        {
+         /* Just to be paranoid ...  */
+         FSRef fref;
+         char *buf;
+
+         buf = xmalloc (data_size + 1);
          memcpy (buf, data_ptr, data_size);
          buf[data_size] = '\0';
-         err = posix_pathname_to_fsspec (buf, &fs);
+         err = FSPathMakeRef (buf, &fref, NULL);
          xfree (buf);
+         if (err == noErr)
+           err = AECoercePtr (typeFSRef, &fref, sizeof (FSRef),
+                              to_type, result);
        }
-      else
-       err = memFullErr;
+#else
+      FSSpec fs;
+      char *buf;
+
+      buf = xmalloc (data_size + 1);
+      memcpy (buf, data_ptr, data_size);
+      buf[data_size] = '\0';
+      err = posix_pathname_to_fsspec (buf, &fs);
+      xfree (buf);
       if (err == noErr)
        err = AECoercePtr (typeFSS, &fs, sizeof (FSSpec), to_type, result);
 #endif
@@ -489,14 +652,11 @@ mac_coerce_file_name_ptr (type_code, data_ptr, data_size,
            {
              size = AEGetDescDataSize (&desc);
              buf = xmalloc (size);
-             if (buf)
-               {
-                 err = AEGetDescData (&desc, buf, size);
-                 if (err == noErr)
-                   url = CFURLCreateWithBytes (NULL, buf, size,
-                                               kCFStringEncodingUTF8, NULL);
-                 xfree (buf);
-               }
+             err = AEGetDescData (&desc, buf, size);
+             if (err == noErr)
+               url = CFURLCreateWithBytes (NULL, buf, size,
+                                           kCFStringEncodingUTF8, NULL);
+             xfree (buf);
              AEDisposeDesc (&desc);
            }
        }
@@ -518,6 +678,34 @@ mac_coerce_file_name_ptr (type_code, data_ptr, data_size,
                              CFDataGetLength (data), result);
          CFRelease (data);
        }
+
+      if (err != noErr)
+       {
+         /* Coercion from typeAlias to typeFileURL fails on Mac OS X
+            10.2.  In such cases, try typeFSRef as a target type.  */
+         char file_name[MAXPATHLEN];
+
+         if (type_code == typeFSRef && data_size == sizeof (FSRef))
+           err = FSRefMakePath (data_ptr, file_name, sizeof (file_name));
+         else
+           {
+             AEDesc desc;
+             FSRef fref;
+
+             err = AECoercePtr (type_code, data_ptr, data_size,
+                                typeFSRef, &desc);
+             if (err == noErr)
+               {
+                 err = AEGetDescData (&desc, &fref, sizeof (FSRef));
+                 AEDisposeDesc (&desc);
+               }
+             if (err == noErr)
+               err = FSRefMakePath (&fref, file_name, sizeof (file_name));
+           }
+         if (err == noErr)
+           err = AECreateDesc (TYPE_FILE_NAME, file_name,
+                               strlen (file_name), result);
+       }
 #else
       char file_name[MAXPATHLEN];
 
@@ -537,11 +725,11 @@ mac_coerce_file_name_ptr (type_code, data_ptr, data_size,
 #else
              fs = *(FSSpec *)(*(desc.dataHandle));
 #endif
-             if (err == noErr)
-               err = fsspec_to_posix_pathname (&fs, file_name,
-                                               sizeof (file_name) - 1);
              AEDisposeDesc (&desc);
            }
+         if (err == noErr)
+           err = fsspec_to_posix_pathname (&fs, file_name,
+                                           sizeof (file_name) - 1);
        }
       if (err == noErr)
        err = AECreateDesc (TYPE_FILE_NAME, file_name,
@@ -581,21 +769,16 @@ mac_coerce_file_name_desc (from_desc, to_type, handler_refcon, result)
       data_size = GetHandleSize (from_desc->dataHandle);
 #endif
       data_ptr = xmalloc (data_size);
-      if (data_ptr)
-       {
 #if TARGET_API_MAC_CARBON
-         err = AEGetDescData (from_desc, data_ptr, data_size);
+      err = AEGetDescData (from_desc, data_ptr, data_size);
 #else
-         memcpy (data_ptr, *(from_desc->dataHandle), data_size);
+      memcpy (data_ptr, *(from_desc->dataHandle), data_size);
 #endif
-         if (err == noErr)
-           err = mac_coerce_file_name_ptr (from_type, data_ptr,
-                                           data_size, to_type,
-                                           handler_refcon, result);
-         xfree (data_ptr);
-       }
-      else
-       err = memFullErr;
+      if (err == noErr)
+       err = mac_coerce_file_name_ptr (from_type, data_ptr,
+                                       data_size, to_type,
+                                       handler_refcon, result);
+      xfree (data_ptr);
     }
 
   if (err != noErr)
@@ -634,33 +817,46 @@ init_coercion_handler ()
 }
 
 #if TARGET_API_MAC_CARBON
-OSErr
-create_apple_event_from_event_ref (event, num_params, names, types, result)
-     EventRef event;
-     UInt32 num_params;
-     EventParamName *names;
-     EventParamType *types;
+static OSErr
+create_apple_event (class, id, result)
+     AEEventClass class;
+     AEEventID id;
      AppleEvent *result;
 {
   OSErr err;
   static const ProcessSerialNumber psn = {0, kCurrentProcess};
   AEAddressDesc address_desc;
-  UInt32 i, size;
-  CFStringRef string;
-  CFDataRef data;
-  char *buf;
 
   err = AECreateDesc (typeProcessSerialNumber, &psn,
                      sizeof (ProcessSerialNumber), &address_desc);
   if (err == noErr)
     {
-      err = AECreateAppleEvent (0, 0, /* Dummy class and ID.   */
+      err = AECreateAppleEvent (class, id,
                                &address_desc, /* NULL is not allowed
                                                  on Mac OS Classic. */
                                kAutoGenerateReturnID,
                                kAnyTransactionID, result);
       AEDisposeDesc (&address_desc);
     }
+
+  return err;
+}
+
+OSStatus
+create_apple_event_from_event_ref (event, num_params, names, types, result)
+     EventRef event;
+     UInt32 num_params;
+     const EventParamName *names;
+     const EventParamType *types;
+     AppleEvent *result;
+{
+  OSStatus err;
+  UInt32 i, size;
+  CFStringRef string;
+  CFDataRef data;
+  char *buf = NULL;
+
+  err = create_apple_event (0, 0, result); /* Dummy class and ID.  */
   if (err != noErr)
     return err;
 
@@ -678,8 +874,7 @@ create_apple_event_from_event_ref (event, num_params, names, types, result)
                                                     '?');
        if (data == NULL)
          break;
-       /* typeUTF8Text is not available on Mac OS X 10.1.  */
-       AEPutParamPtr (result, names[i], 'utf8',
+       AEPutParamPtr (result, names[i], typeUTF8Text,
                       CFDataGetBytePtr (data), CFDataGetLength (data));
        CFRelease (data);
        break;
@@ -690,21 +885,88 @@ create_apple_event_from_event_ref (event, num_params, names, types, result)
                                 0, &size, NULL);
        if (err != noErr)
          break;
-       buf = xmalloc (size);
-       if (buf == NULL)
-         break;
+       buf = xrealloc (buf, size);
        err = GetEventParameter (event, names[i], types[i], NULL,
                                 size, NULL, buf);
        if (err == noErr)
          AEPutParamPtr (result, names[i], types[i], buf, size);
-       xfree (buf);
        break;
       }
+  if (buf)
+    xfree (buf);
 
   return noErr;
 }
-#endif
 
+OSErr
+create_apple_event_from_drag_ref (drag, num_types, types, result)
+     DragRef drag;
+     UInt32 num_types;
+     const FlavorType *types;
+     AppleEvent *result;
+{
+  OSErr err;
+  UInt16 num_items;
+  AppleEvent items;
+  long index;
+  char *buf = NULL;
+
+  err = CountDragItems (drag, &num_items);
+  if (err != noErr)
+    return err;
+  err = AECreateList (NULL, 0, false, &items);
+  if (err != noErr)
+    return err;
+
+  for (index = 1; index <= num_items; index++)
+    {
+      ItemReference item;
+      DescType desc_type = typeNull;
+      Size size;
+
+      err = GetDragItemReferenceNumber (drag, index, &item);
+      if (err == noErr)
+       {
+         int i;
+
+         for (i = 0; i < num_types; i++)
+           {
+             err = GetFlavorDataSize (drag, item, types[i], &size);
+             if (err == noErr)
+               {
+                 buf = xrealloc (buf, size);
+                 err = GetFlavorData (drag, item, types[i], buf, &size, 0);
+               }
+             if (err == noErr)
+               {
+                 desc_type = types[i];
+                 break;
+               }
+           }
+       }
+      err = AEPutPtr (&items, index, desc_type,
+                     desc_type != typeNull ? buf : NULL,
+                     desc_type != typeNull ? size : 0);
+      if (err != noErr)
+       break;
+    }
+  if (buf)
+    xfree (buf);
+
+  if (err == noErr)
+    {
+      err = create_apple_event (0, 0, result); /* Dummy class and ID.  */
+      if (err == noErr)
+       err = AEPutParamDesc (result, keyDirectObject, &items);
+      if (err != noErr)
+       AEDisposeDesc (result);
+    }
+
+  AEDisposeDesc (&items);
+
+  return err;
+}
+#endif /* TARGET_API_MAC_CARBON */
 \f
 /***********************************************************************
         Conversion between Lisp and Core Foundation objects
@@ -867,18 +1129,15 @@ Lisp_Object
 cfdate_to_lisp (date)
      CFDateRef date;
 {
-  static const CFGregorianDate epoch_gdate = {1970, 1, 1, 0, 0, 0.0};
-  static CFAbsoluteTime epoch = 0.0, sec;
-  int high, low;
-
-  if (epoch == 0.0)
-    epoch = CFGregorianDateGetAbsoluteTime (epoch_gdate, NULL);
+  CFTimeInterval sec;
+  int high, low, microsec;
 
-  sec = CFDateGetAbsoluteTime (date) - epoch;
+  sec = CFDateGetAbsoluteTime (date) + kCFAbsoluteTimeIntervalSince1970;
   high = sec / 65536.0;
   low = sec - high * 65536.0;
+  microsec = (sec - floor (sec)) * 1000000.0;
 
-  return list3 (make_number (high), make_number (low), make_number (0));
+  return list3 (make_number (high), make_number (low), make_number (microsec));
 }
 
 
@@ -1064,7 +1323,7 @@ cfproperty_list_to_lisp (plist, with_tag, hash_bound)
 
 static void
 skip_white_space (p)
-     char **p;
+     const char **p;
 {
   /* WhiteSpace = {<space> | <horizontal tab>} */
   while (*P == ' ' || *P == '\t')
@@ -1073,7 +1332,7 @@ skip_white_space (p)
 
 static int
 parse_comment (p)
-     char **p;
+     const char **p;
 {
   /* Comment = "!" {<any character except null or newline>} */
   if (*P == '!')
@@ -1091,7 +1350,7 @@ parse_comment (p)
 /* Don't interpret filename.  Just skip until the newline.  */
 static int
 parse_include_file (p)
-     char **p;
+     const char **p;
 {
   /* IncludeFile = "#" WhiteSpace "include" WhiteSpace FileName WhiteSpace */
   if (*P == '#')
@@ -1108,7 +1367,7 @@ parse_include_file (p)
 
 static char
 parse_binding (p)
-     char **p;
+     const char **p;
 {
   /* Binding = "." | "*"  */
   if (*P == '.' || *P == '*')
@@ -1126,7 +1385,7 @@ parse_binding (p)
 
 static Lisp_Object
 parse_component (p)
-     char **p;
+     const char **p;
 {
   /*  Component = "?" | ComponentName
       ComponentName = NameChar {NameChar}
@@ -1138,7 +1397,7 @@ parse_component (p)
     }
   else if (isalnum (*P) || *P == '_' || *P == '-')
     {
-      char *start = P++;
+      const char *start = P++;
 
       while (isalnum (*P) || *P == '_' || *P == '-')
        P++;
@@ -1151,7 +1410,7 @@ parse_component (p)
 
 static Lisp_Object
 parse_resource_name (p)
-     char **p;
+     const char **p;
 {
   Lisp_Object result = Qnil, component;
   char binding;
@@ -1185,7 +1444,7 @@ parse_resource_name (p)
 
 static Lisp_Object
 parse_value (p)
-     char **p;
+     const char **p;
 {
   char *q, *buf;
   Lisp_Object seq = Qnil, result;
@@ -1275,7 +1534,7 @@ parse_value (p)
 
 static Lisp_Object
 parse_resource_line (p)
-     char **p;
+     const char **p;
 {
   Lisp_Object quarks, value;
 
@@ -1378,7 +1637,7 @@ xrm_q_put_resource (database, quarks, value)
 void
 xrm_merge_string_database (database, data)
      XrmDatabase database;
-     char *data;
+     const char *data;
 {
   Lisp_Object quarks_value;
 
@@ -1454,7 +1713,7 @@ xrm_q_get_resource (database, quark_name, quark_class)
 Lisp_Object
 xrm_get_resource (database, name, class)
      XrmDatabase database;
-     char *name, *class;
+     const char *name, *class;
 {
   Lisp_Object key, query_cache, quark_name, quark_class, tmp;
   int i, nn, nc;
@@ -1543,7 +1802,7 @@ xrm_cfproperty_list_to_value (plist)
 
 XrmDatabase
 xrm_get_preference_database (application)
-     char *application;
+     const char *application;
 {
 #if TARGET_API_MAC_CARBON
   CFStringRef app_id, *keys, user_doms[2], host_doms[2];
@@ -1566,8 +1825,6 @@ xrm_get_preference_database (application)
 
   GCPRO3 (database, quarks, value);
 
-  BLOCK_INPUT;
-
   app_id = kCFPreferencesCurrentApplication;
   if (application)
     {
@@ -1575,6 +1832,8 @@ xrm_get_preference_database (application)
       if (app_id == NULL)
        goto out;
     }
+  if (!CFPreferencesAppSynchronize (app_id))
+    goto out;
 
   key_set = CFSetCreateMutable (NULL, 0, &kCFCopyStringSetCallBacks);
   if (key_set == NULL)
@@ -1596,8 +1855,6 @@ xrm_get_preference_database (application)
 
   count = CFSetGetCount (key_set);
   keys = xmalloc (sizeof (CFStringRef) * count);
-  if (keys == NULL)
-    goto out;
   CFSetGetValues (key_set, (const void **)keys);
   for (index = 0; index < count; index++)
     {
@@ -1619,8 +1876,6 @@ xrm_get_preference_database (application)
     CFRelease (key_set);
   CFRelease (app_id);
 
-  UNBLOCK_INPUT;
-
   UNGCPRO;
 
   return database;
@@ -2003,7 +2258,7 @@ sys_open (const char *path, int oflag)
       int res = open (mac_pathname, oflag);
       /* if (oflag == O_WRONLY || oflag == O_RDWR) */
       if (oflag & O_CREAT)
-        fsetfileinfo (mac_pathname, 'EMAx', 'TEXT');
+        fsetfileinfo (mac_pathname, MAC_EMACS_CREATOR_CODE, 'TEXT');
       return res;
 #else /* not __MRC__ */
       return open (mac_pathname, oflag);
@@ -2029,7 +2284,7 @@ sys_creat (const char *path, mode_t mode)
     {
 #ifdef __MRC__
       int result = creat (mac_pathname);
-      fsetfileinfo (mac_pathname, 'EMAx', 'TEXT');
+      fsetfileinfo (mac_pathname, MAC_EMACS_CREATOR_CODE, 'TEXT');
       return result;
 #else /* not __MRC__ */
       return creat (mac_pathname, mode);
@@ -2157,82 +2412,78 @@ sys_fopen (const char *name, const char *mode)
     {
 #ifdef __MRC__
       if (mode[0] == 'w' || mode[0] == 'a')
-        fsetfileinfo (mac_pathname, 'EMAx', 'TEXT');
+        fsetfileinfo (mac_pathname, MAC_EMACS_CREATOR_CODE, 'TEXT');
 #endif /* not __MRC__ */
       return fopen (mac_pathname, mode);
     }
 }
 
 
-#include "keyboard.h"
-extern Boolean mac_wait_next_event (EventRecord *, UInt32, Boolean);
+extern Boolean mac_wait_next_event P_ ((EventRecord *, UInt32, Boolean));
 
 int
-select (n,  rfds, wfds, efds, timeout)
-  int n;
-  SELECT_TYPE *rfds;
-  SELECT_TYPE *wfds;
-  SELECT_TYPE *efds;
-  struct timeval *timeout;
+select (nfds, rfds, wfds, efds, timeout)
+     int nfds;
+     SELECT_TYPE *rfds, *wfds, *efds;
+     EMACS_TIME *timeout;
 {
-  OSErr err;
-#if TARGET_API_MAC_CARBON
-  EventTimeout timeout_sec =
-    (timeout
-     ? (EMACS_SECS (*timeout) * kEventDurationSecond
-       + EMACS_USECS (*timeout) * kEventDurationMicrosecond)
-     : kEventDurationForever);
-
-  BLOCK_INPUT;
-  err = ReceiveNextEvent (0, NULL, timeout_sec, kEventLeaveInQueue, NULL);
-  UNBLOCK_INPUT;
-#else /* not TARGET_API_MAC_CARBON */
-  EventRecord e;
-  UInt32 sleep_time = EMACS_SECS (*timeout) * 60 +
-    ((EMACS_USECS (*timeout) * 60) / 1000000);
+  OSStatus err = noErr;
 
   /* Can only handle wait for keyboard input.  */
-  if (n > 1 || wfds || efds)
+  if (nfds > 1 || wfds || efds)
     return -1;
 
-  /* Also return true if an event other than a keyDown has occurred.
-     This causes kbd_buffer_get_event in keyboard.c to call
-     read_avail_input which in turn calls XTread_socket to poll for
-     these events.  Otherwise these never get processed except but a
-     very slow poll timer.  */
-  if (mac_wait_next_event (&e, sleep_time, false))
-    err = noErr;
-  else
-    err = -9875;               /* eventLoopTimedOutErr */
+  /* Try detect_input_pending before ReceiveNextEvent in the same
+     BLOCK_INPUT block, in case that some input has already been read
+     asynchronously.  */
+  BLOCK_INPUT;
+  ENABLE_WAKEUP_FROM_RNE;
+  if (!detect_input_pending ())
+    {
+#if TARGET_API_MAC_CARBON
+      EventTimeout timeoutval =
+       (timeout
+        ? (EMACS_SECS (*timeout) * kEventDurationSecond
+           + EMACS_USECS (*timeout) * kEventDurationMicrosecond)
+        : kEventDurationForever);
+
+      if (timeoutval == 0.0)
+       err = eventLoopTimedOutErr;
+      else
+       err = ReceiveNextEvent (0, NULL, timeoutval,
+                               kEventLeaveInQueue, NULL);
+#else /* not TARGET_API_MAC_CARBON */
+      EventRecord e;
+      UInt32 sleep_time = EMACS_SECS (*timeout) * 60 +
+       ((EMACS_USECS (*timeout) * 60) / 1000000);
+
+      if (sleep_time == 0)
+       err = -9875;            /* eventLoopTimedOutErr */
+      else
+       {
+         if (mac_wait_next_event (&e, sleep_time, false))
+           err = noErr;
+         else
+           err = -9875;        /* eventLoopTimedOutErr */
+       }
 #endif /* not TARGET_API_MAC_CARBON */
+    }
+  DISABLE_WAKEUP_FROM_RNE;
+  UNBLOCK_INPUT;
 
-  if (FD_ISSET (0, rfds))
-    if (err == noErr)
-      return 1;
-    else
-      {
-       FD_ZERO (rfds);
-       return 0;
-      }
+  if (err == noErr)
+    {
+      /* Pretend that `select' is interrupted by a signal.  */
+      detect_input_pending ();
+      errno = EINTR;
+      return -1;
+    }
   else
-    if (err == noErr)
-      {
-       if (input_polling_used ())
-         {
-           /* It could be confusing if a real alarm arrives while
-              processing the fake one.  Turn it off and let the
-              handler reset it.  */
-           extern void poll_for_input_1 P_ ((void));
-           int old_poll_suppress_count = poll_suppress_count;
-           poll_suppress_count = 1;
-           poll_for_input_1 ();
-           poll_suppress_count = old_poll_suppress_count;
-         }
-       errno = EINTR;
-       return -1;
-      }
-    else
+    {
+      if (rfds)
+       FD_ZERO (rfds);
       return 0;
+    }
 }
 
 
@@ -3943,7 +4194,7 @@ DEFUN ("mac-get-file-creator", Fmac_get_file_creator, Smac_get_file_creator, 1,
      (filename)
      Lisp_Object filename;
 {
-  OSErr        status;
+  OSStatus status;
 #ifdef MAC_OSX
   FSRef fref;
 #else
@@ -3997,7 +4248,7 @@ DEFUN ("mac-get-file-type", Fmac_get_file_type, Smac_get_file_type, 1, 1, 0,
      (filename)
      Lisp_Object filename;
 {
-  OSErr        status;
+  OSStatus status;
 #ifdef MAC_OSX
   FSRef fref;
 #else
@@ -4053,7 +4304,7 @@ assumed. Return non-nil if successful.  */)
      (filename, code)
      Lisp_Object filename, code;
 {
-  OSErr        status;
+  OSStatus status;
 #ifdef MAC_OSX
   FSRef fref;
 #else
@@ -4062,7 +4313,7 @@ assumed. Return non-nil if successful.  */)
   OSType cCode;
   CHECK_STRING (filename);
 
-  cCode = mac_get_code_from_arg(code, 'EMAx');
+  cCode = mac_get_code_from_arg(code, MAC_EMACS_CREATOR_CODE);
 
   if (NILP(Ffile_exists_p(filename)) || !NILP(Ffile_directory_p(filename))) {
     return Qnil;
@@ -4113,7 +4364,7 @@ CODE must be a 4-character string.  Return non-nil if successful.  */)
      (filename, code)
      Lisp_Object filename, code;
 {
-  OSErr        status;
+  OSStatus status;
 #ifdef MAC_OSX
   FSRef fref;
 #else
@@ -4368,6 +4619,7 @@ otherwise.  */)
   CFStringRef app_id, key_str;
   CFPropertyListRef app_plist = NULL, plist;
   Lisp_Object result = Qnil, tmp;
+  struct gcpro gcpro1, gcpro2;
 
   if (STRINGP (key))
     key = Fcons (key, Qnil);
@@ -4376,8 +4628,7 @@ otherwise.  */)
       CHECK_CONS (key);
       for (tmp = key; CONSP (tmp); tmp = XCDR (tmp))
        CHECK_STRING_CAR (tmp);
-      if (!NILP (tmp))
-       wrong_type_argument (Qlistp, key);
+      CHECK_LIST_END (tmp, key);
     }
   if (!NILP (application))
     CHECK_STRING (application);
@@ -4385,6 +4636,8 @@ otherwise.  */)
   if (!NILP (hash_bound))
     CHECK_NUMBER (hash_bound);
 
+  GCPRO2 (key, format);
+
   BLOCK_INPUT;
 
   app_id = kCFPreferencesCurrentApplication;
@@ -4394,6 +4647,9 @@ otherwise.  */)
       if (app_id == NULL)
        goto out;
     }
+  if (!CFPreferencesAppSynchronize (app_id))
+    goto out;
+
   key_str = cfstring_create_with_string (XCAR (key));
   if (key_str == NULL)
     goto out;
@@ -4439,6 +4695,8 @@ otherwise.  */)
 
   UNBLOCK_INPUT;
 
+  UNGCPRO;
+
   return result;
 }
 
@@ -4527,7 +4785,7 @@ cfstring_create_normalized (str, symbol)
       UnicodeMapping map;
       CFIndex length;
       UniChar *in_text, *buffer = NULL, *out_buf = NULL;
-      OSErr err = noErr;
+      OSStatus err = noErr;
       ByteCount out_read, out_size, out_len;
 
       map.unicodeEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault,
@@ -4547,27 +4805,21 @@ cfstring_create_normalized (str, symbol)
       if (in_text == NULL)
        {
          buffer = xmalloc (sizeof (UniChar) * length);
-         if (buffer)
-           {
-             CFStringGetCharacters (str, CFRangeMake (0, length), buffer);
-             in_text = buffer;
-           }
+         CFStringGetCharacters (str, CFRangeMake (0, length), buffer);
+         in_text = buffer;
        }
 
       if (in_text)
-       err = CreateUnicodeToTextInfo(&map, &uni);
+       err = CreateUnicodeToTextInfo (&map, &uni);
       while (err == noErr)
        {
          out_buf = xmalloc (out_size);
-         if (out_buf == NULL)
-           err = mFulErr;
-         else
-           err = ConvertFromUnicodeToText (uni, length * sizeof (UniChar),
-                                           in_text,
-                                           kUnicodeDefaultDirectionMask,
-                                           0, NULL, NULL, NULL,
-                                           out_size, &out_read, &out_len,
-                                           out_buf);
+         err = ConvertFromUnicodeToText (uni, length * sizeof (UniChar),
+                                         in_text,
+                                         kUnicodeDefaultDirectionMask,
+                                         0, NULL, NULL, NULL,
+                                         out_size, &out_read, &out_len,
+                                         out_buf);
          if (err == noErr && out_read < length * sizeof (UniChar))
            {
              xfree (out_buf);
@@ -4600,8 +4852,8 @@ DEFUN ("mac-code-convert-string", Fmac_code_convert_string, Smac_code_convert_st
        doc: /* Convert STRING from SOURCE encoding to TARGET encoding.
 The conversion is performed using the converter provided by the system.
 Each encoding is specified by either a coding system symbol, a mime
-charset string, or an integer as a CFStringEncoding value.  Nil for
-encoding means UTF-16 in native byte order, no byte order mark.
+charset string, or an integer as a CFStringEncoding value.  An encoding
+of nil means UTF-16 in native byte order, no byte order mark.
 On Mac OS X 10.2 and later, you can do Unicode Normalization by
 specifying the optional argument NORMALIZATION-FORM with a symbol NFD,
 NFKD, NFC, NFKC, HFS+D, or HFS+C.
@@ -4610,6 +4862,7 @@ On successful conversion, return the result string, else return nil.  */)
      Lisp_Object string, source, target, normalization_form;
 {
   Lisp_Object result = Qnil;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   CFStringEncoding src_encoding, tgt_encoding;
   CFStringRef str = NULL;
 
@@ -4620,6 +4873,8 @@ On successful conversion, return the result string, else return nil.  */)
     CHECK_SYMBOL (target);
   CHECK_SYMBOL (normalization_form);
 
+  GCPRO4 (string, source, target, normalization_form);
+
   BLOCK_INPUT;
 
   src_encoding = get_cfstring_encoding_from_lisp (source);
@@ -4660,25 +4915,41 @@ On successful conversion, return the result string, else return nil.  */)
 
   UNBLOCK_INPUT;
 
+  UNGCPRO;
+
   return result;
 }
-#endif /* TARGET_API_MAC_CARBON */
-
 
-DEFUN ("mac-clear-font-name-table", Fmac_clear_font_name_table, Smac_clear_font_name_table, 0, 0, 0,
-       doc: /* Clear the font name table.  */)
-     ()
+DEFUN ("mac-process-hi-command", Fmac_process_hi_command, Smac_process_hi_command, 1, 1, 0,
+       doc: /* Send a HI command whose ID is COMMAND-ID to the command chain.
+COMMAND-ID must be a 4-character string.  Some common command IDs are
+defined in the Carbon Event Manager.  */)
+     (command_id)
+     Lisp_Object command_id;
 {
-  check_mac ();
-  mac_clear_font_name_table ();
+  OSStatus err;
+  HICommand command;
+
+  bzero (&command, sizeof (HICommand));
+  command.commandID = mac_get_code_from_arg (command_id, 0);
+
+  BLOCK_INPUT;
+  err = ProcessHICommand (&command);
+  UNBLOCK_INPUT;
+
+  if (err != noErr)
+    error ("HI command (command ID: '%s') not handled.", SDATA (command_id));
+
   return Qnil;
 }
 
+#endif /* TARGET_API_MAC_CARBON */
+
 
 static Lisp_Object
 mac_get_system_locale ()
 {
-  OSErr err;
+  OSStatus err;
   LangCode lang;
   RegionCode region;
   LocaleRef locale;
@@ -4712,23 +4983,26 @@ extern int noninteractive;
       -> Use `select'.
    2. Sockets are not involved.
       -> Use ReceiveNextEvent.
-   3. [If SELECT_USE_CFSOCKET is defined]
-      Only the window event channel and socket read channels are
+   3. [If SELECT_USE_CFSOCKET is set]
+      Only the window event channel and socket read/write channels are
       involved, and timeout is not too short (greater than
-      SELECT_TIMEOUT_THRESHHOLD_RUNLOOP seconds).
+      SELECT_TIMEOUT_THRESHOLD_RUNLOOP seconds).
       -> Create CFSocket for each socket and add it into the current
-         event RunLoop so that a `ready-to-read' event can be posted
-         to the event queue that is also used for window events.  Then
-         ReceiveNextEvent can wait for both kinds of inputs.
+         event RunLoop so that the current event loop gets quit when
+         the socket becomes ready.  Then CFRunLoopRunInMode can wait
+         for both kinds of inputs.
    4. Otherwise.
       -> Periodically poll the window input channel while repeatedly
          executing `select' with a short timeout
          (SELECT_POLLING_PERIOD_USEC microseconds).  */
 
-#define SELECT_POLLING_PERIOD_USEC 20000
-#ifdef SELECT_USE_CFSOCKET
+#ifndef SELECT_USE_CFSOCKET
+#define SELECT_USE_CFSOCKET 1
+#endif
+
+#define SELECT_POLLING_PERIOD_USEC 100000
+#if SELECT_USE_CFSOCKET
 #define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2
-#define EVENT_CLASS_SOCK 'Sock'
 
 static void
 socket_callback (s, type, address, data, info)
@@ -4738,196 +5012,230 @@ socket_callback (s, type, address, data, info)
      const void *data;
      void *info;
 {
-  EventRef event;
-
-  CreateEvent (NULL, EVENT_CLASS_SOCK, 0, 0, kEventAttributeNone, &event);
-  PostEventToQueue (GetCurrentEventQueue (), event, kEventPriorityStandard);
-  ReleaseEvent (event);
 }
 #endif /* SELECT_USE_CFSOCKET */
 
 static int
-select_and_poll_event (n, rfds, wfds, efds, timeout)
-     int n;
-     SELECT_TYPE *rfds;
-     SELECT_TYPE *wfds;
-     SELECT_TYPE *efds;
-     struct timeval *timeout;
+select_and_poll_event (nfds, rfds, wfds, efds, timeout)
+     int nfds;
+     SELECT_TYPE *rfds, *wfds, *efds;
+     EMACS_TIME *timeout;
 {
-  int r;
-  OSErr err;
+  int timedout_p = 0;
+  int r = 0;
+  EMACS_TIME select_timeout;
+  EventTimeout timeoutval =
+    (timeout
+     ? (EMACS_SECS (*timeout) * kEventDurationSecond
+       + EMACS_USECS (*timeout) * kEventDurationMicrosecond)
+     : kEventDurationForever);
+  SELECT_TYPE orfds, owfds, oefds;
 
-  r = select (n, rfds, wfds, efds, timeout);
-  if (r != -1)
+  if (timeout == NULL)
     {
-      BLOCK_INPUT;
-      err = ReceiveNextEvent (0, NULL, kEventDurationNoWait,
-                             kEventLeaveInQueue, NULL);
-      UNBLOCK_INPUT;
-      if (err == noErr)
+      if (rfds) orfds = *rfds;
+      if (wfds) owfds = *wfds;
+      if (efds) oefds = *efds;
+    }
+
+  /* Try detect_input_pending before CFRunLoopRunInMode in the same
+     BLOCK_INPUT block, in case that some input has already been read
+     asynchronously.  */
+  BLOCK_INPUT;
+  while (1)
+    {
+      if (detect_input_pending ())
+       break;
+
+      EMACS_SET_SECS_USECS (select_timeout, 0, 0);
+      r = select (nfds, rfds, wfds, efds, &select_timeout);
+      if (r != 0)
+       break;
+
+      if (timeoutval == 0.0)
+       timedout_p = 1;
+      else
+       {
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (NULL);
+#endif
+         if (CFRunLoopRunInMode (kCFRunLoopDefaultMode,
+                                 timeoutval >= 0 ? timeoutval : 100000, true)
+             == kCFRunLoopRunTimedOut)
+           timedout_p = 1;
+       }
+
+      if (timeout == NULL && timedout_p)
        {
-         FD_SET (0, rfds);
-         r++;
+         if (rfds) *rfds = orfds;
+         if (wfds) *wfds = owfds;
+         if (efds) *efds = oefds;
        }
+      else
+       break;
     }
-  return r;
-}
+  UNBLOCK_INPUT;
 
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1020
-#undef SELECT_INVALIDATE_CFSOCKET
-#endif
+  if (r != 0)
+    return r;
+  else if (!timedout_p)
+    {
+      /* Pretend that `select' is interrupted by a signal.  */
+      detect_input_pending ();
+      errno = EINTR;
+      return -1;
+    }
+  else
+    return 0;
+}
 
 int
-sys_select (n, rfds, wfds, efds, timeout)
-     int n;
-     SELECT_TYPE *rfds;
-     SELECT_TYPE *wfds;
-     SELECT_TYPE *efds;
-     struct timeval *timeout;
+sys_select (nfds, rfds, wfds, efds, timeout)
+     int nfds;
+     SELECT_TYPE *rfds, *wfds, *efds;
+     EMACS_TIME *timeout;
 {
-  OSErr err;
-  int i, r;
+  int timedout_p = 0;
+  int r;
   EMACS_TIME select_timeout;
+  SELECT_TYPE orfds, owfds, oefds;
 
   if (inhibit_window_system || noninteractive
-      || rfds == NULL || !FD_ISSET (0, rfds))
-    return select (n, rfds, wfds, efds, timeout);
+      || nfds < 1 || rfds == NULL || !FD_ISSET (0, rfds))
+    return select (nfds, rfds, wfds, efds, timeout);
 
   FD_CLR (0, rfds);
+  orfds = *rfds;
 
-  if (wfds == NULL && efds == NULL)
-    {
-      int nsocks = 0;
-      SELECT_TYPE orfds = *rfds;
+  if (wfds)
+    owfds = *wfds;
+  else
+    FD_ZERO (&owfds);
 
-      EventTimeout timeout_sec =
+  if (efds)
+    oefds = *efds;
+  else
+    {
+      EventTimeout timeoutval =
        (timeout
         ? (EMACS_SECS (*timeout) * kEventDurationSecond
            + EMACS_USECS (*timeout) * kEventDurationMicrosecond)
         : kEventDurationForever);
 
-      for (i = 1; i < n; i++)
-       if (FD_ISSET (i, rfds))
-         nsocks++;
-
-      if (nsocks == 0)
+      FD_SET (0, rfds);                /* sentinel */
+      do
        {
-         BLOCK_INPUT;
-         err = ReceiveNextEvent (0, NULL, timeout_sec,
-                                 kEventLeaveInQueue, NULL);
-         UNBLOCK_INPUT;
-         if (err == noErr)
-           {
-             FD_SET (0, rfds);
-             return 1;
-           }
-         else
-           return 0;
+         nfds--;
        }
+      while (!(FD_ISSET (nfds, rfds) || (wfds && FD_ISSET (nfds, wfds))));
+      nfds++;
+      FD_CLR (0, rfds);
+
+      if (nfds == 1)
+       return select_and_poll_event (nfds, rfds, wfds, efds, timeout);
 
-#if USE_CG_DRAWING
-      mac_prepare_for_quickdraw (NULL);
-#endif
       /* Avoid initial overhead of RunLoop setup for the case that
         some input is already available.  */
       EMACS_SET_SECS_USECS (select_timeout, 0, 0);
-      r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout);
-      if (r != 0 || timeout_sec == 0.0)
+      r = select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout);
+      if (r != 0 || timeoutval == 0.0)
        return r;
 
       *rfds = orfds;
+      if (wfds)
+       *wfds = owfds;
 
-#ifdef SELECT_USE_CFSOCKET
-      if (timeout_sec > 0 && timeout_sec <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP)
+#if SELECT_USE_CFSOCKET
+      if (timeoutval > 0 && timeoutval <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP)
        goto poll_periodically;
 
-      {
-       CFRunLoopRef runloop =
-         (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ());
-       EventTypeSpec specs[] = {{EVENT_CLASS_SOCK, 0}};
-#ifdef SELECT_INVALIDATE_CFSOCKET
-       CFSocketRef *shead, *s;
-#else
-       CFRunLoopSourceRef *shead, *s;
-#endif
-
-       BLOCK_INPUT;
-
-#ifdef SELECT_INVALIDATE_CFSOCKET
-       shead = xmalloc (sizeof (CFSocketRef) * nsocks);
-#else
-       shead = xmalloc (sizeof (CFRunLoopSourceRef) * nsocks);
-#endif
-       s = shead;
-       for (i = 1; i < n; i++)
-         if (FD_ISSET (i, rfds))
-           {
-             CFSocketRef socket =
-               CFSocketCreateWithNative (NULL, i, kCFSocketReadCallBack,
-                                         socket_callback, NULL);
-             CFRunLoopSourceRef source =
-               CFSocketCreateRunLoopSource (NULL, socket, 0);
-
-#ifdef SELECT_INVALIDATE_CFSOCKET
-             CFSocketSetSocketFlags (socket, 0);
-#endif
-             CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode);
-#ifdef SELECT_INVALIDATE_CFSOCKET
-             CFRelease (source);
-             *s = socket;
-#else
-             CFRelease (socket);
-             *s = source;
-#endif
-             s++;
-           }
+      /* Try detect_input_pending before CFRunLoopRunInMode in the
+        same BLOCK_INPUT block, in case that some input has already
+        been read asynchronously.  */
+      BLOCK_INPUT;
+      if (!detect_input_pending ())
+       {
+         int minfd, fd;
+         CFRunLoopRef runloop =
+           (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ());
+         static CFMutableDictionaryRef sources;
+
+         if (sources == NULL)
+           sources =
+             CFDictionaryCreateMutable (NULL, 0, NULL,
+                                        &kCFTypeDictionaryValueCallBacks);
+
+         for (minfd = 1; ; minfd++) /* nfds-1 works as a sentinel.  */
+           if (FD_ISSET (minfd, rfds) || (wfds && FD_ISSET (minfd, wfds)))
+             break;
 
-       err = ReceiveNextEvent (0, NULL, timeout_sec, kEventLeaveInQueue, NULL);
+         for (fd = minfd; fd < nfds; fd++)
+           if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds)))
+             {
+               void *key = (void *) fd;
+               CFRunLoopSourceRef source =
+                 (CFRunLoopSourceRef) CFDictionaryGetValue (sources, key);
+
+               if (source == NULL)
+                 {
+                   CFSocketRef socket =
+                     CFSocketCreateWithNative (NULL, fd,
+                                               (kCFSocketReadCallBack
+                                                | kCFSocketConnectCallBack),
+                                               socket_callback, NULL);
+
+                   if (socket == NULL)
+                     continue;
+                   source = CFSocketCreateRunLoopSource (NULL, socket, 0);
+                   CFRelease (socket);
+                   if (source == NULL)
+                     continue;
+                   CFDictionaryAddValue (sources, key, source);
+                   CFRelease (source);
+                 }
+               CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode);
+             }
 
-       do
-         {
-           --s;
-#ifdef SELECT_INVALIDATE_CFSOCKET
-           CFSocketInvalidate (*s);
-#else
-           CFRunLoopRemoveSource (runloop, *s, kCFRunLoopDefaultMode);
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (NULL);
 #endif
-           CFRelease (*s);
-         }
-       while (s != shead);
+         if (CFRunLoopRunInMode (kCFRunLoopDefaultMode,
+                                 timeoutval >= 0 ? timeoutval : 100000, true)
+             == kCFRunLoopRunTimedOut)
+           timedout_p = 1;
 
-       xfree (shead);
-
-       if (err)
-         {
-           FD_ZERO (rfds);
-           r = 0;
-         }
-       else
-         {
-           FlushEventsMatchingListFromQueue (GetCurrentEventQueue (),
-                                             GetEventTypeCount (specs),
-                                             specs);
-           EMACS_SET_SECS_USECS (select_timeout, 0, 0);
-           r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout);
-         }
+         for (fd = minfd; fd < nfds; fd++)
+           if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds)))
+             {
+               void *key = (void *) fd;
+               CFRunLoopSourceRef source =
+                 (CFRunLoopSourceRef) CFDictionaryGetValue (sources, key);
 
-       UNBLOCK_INPUT;
+               CFRunLoopRemoveSource (runloop, source, kCFRunLoopDefaultMode);
+             }
+       }
+      UNBLOCK_INPUT;
 
-       return r;
-      }
+      if (!timedout_p)
+       {
+         EMACS_SET_SECS_USECS (select_timeout, 0, 0);
+         return select_and_poll_event (nfds, rfds, wfds, efds,
+                                       &select_timeout);
+       }
+      else
+       {
+         FD_ZERO (rfds);
+         if (wfds)
+           FD_ZERO (wfds);
+         return 0;
+       }
 #endif /* SELECT_USE_CFSOCKET */
     }
 
  poll_periodically:
   {
     EMACS_TIME end_time, now, remaining_time;
-    SELECT_TYPE orfds = *rfds, owfds, oefds;
 
-    if (wfds)
-      owfds = *wfds;
-    if (efds)
-      oefds = *efds;
     if (timeout)
       {
        remaining_time = *timeout;
@@ -4940,7 +5248,7 @@ sys_select (n, rfds, wfds, efds, timeout)
        EMACS_SET_SECS_USECS (select_timeout, 0, SELECT_POLLING_PERIOD_USEC);
        if (timeout && EMACS_TIME_LT (remaining_time, select_timeout))
          select_timeout = remaining_time;
-       r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout);
+       r = select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout);
        if (r != 0)
          return r;
 
@@ -4958,12 +5266,8 @@ sys_select (n, rfds, wfds, efds, timeout)
       }
     while (!timeout || EMACS_TIME_LT (now, end_time));
 
-    FD_ZERO (rfds);
-    if (wfds)
-      FD_ZERO (wfds);
-    if (efds)
-      FD_ZERO (efds);
-    return 0;
+    EMACS_SET_SECS_USECS (select_timeout, 0, 0);
+    return select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout);
   }
 }
 
@@ -5028,8 +5332,8 @@ init_mac_osx_environment ()
   /* P should have sufficient room for the pathname of the bundle plus
      the subpath in it leading to the respective directories.  Q
      should have three times that much room because EMACSLOADPATH can
-     have the value "<path to lisp dir>:<path to leim dir>:<path to
-     site-lisp dir>".  */
+     have the value "<path to site-lisp dir>:<path to lisp dir>:<path
+     to leim dir>".  */
   p = (char *) alloca (app_bundle_pathname_len + 50);
   q = (char *) alloca (3 * app_bundle_pathname_len + 150);
   if (!getenv ("EMACSLOADPATH"))
@@ -5037,12 +5341,12 @@ init_mac_osx_environment ()
       q[0] = '\0';
 
       strcpy (p, app_bundle_pathname);
-      strcat (p, "/Contents/Resources/lisp");
+      strcat (p, "/Contents/Resources/site-lisp");
       if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
        strcat (q, p);
 
       strcpy (p, app_bundle_pathname);
-      strcat (p, "/Contents/Resources/leim");
+      strcat (p, "/Contents/Resources/lisp");
       if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
        {
          if (q[0] != '\0')
@@ -5051,7 +5355,7 @@ init_mac_osx_environment ()
        }
 
       strcpy (p, app_bundle_pathname);
-      strcat (p, "/Contents/Resources/site-lisp");
+      strcat (p, "/Contents/Resources/leim");
       if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
        {
          if (q[0] != '\0')
@@ -5111,6 +5415,18 @@ init_mac_osx_environment ()
 }
 #endif /* MAC_OSX */
 
+#if TARGET_API_MAC_CARBON
+void
+mac_wakeup_from_rne ()
+{
+#ifndef MAC_OSX
+  if (wakeup_from_rne_enabled_p)
+    /* Post a harmless event so as to wake up from
+       ReceiveNextEvent.  */
+    mac_post_mouse_moved_event ();
+#endif
+}
+#endif
 
 void
 syms_of_mac ()
@@ -5141,12 +5457,22 @@ syms_of_mac ()
   QHFS_plus_C = intern ("HFS+C");      staticpro (&QHFS_plus_C);
 #endif
 
+  {
+    int i;
+
+    for (i = 0; i < sizeof (ae_attr_table) / sizeof (ae_attr_table[0]); i++)
+      {
+       ae_attr_table[i].symbol = intern (ae_attr_table[i].name);
+       staticpro (&ae_attr_table[i].symbol);
+      }
+  }
+
   defsubr (&Smac_coerce_ae_data);
 #if TARGET_API_MAC_CARBON
   defsubr (&Smac_get_preference);
   defsubr (&Smac_code_convert_string);
+  defsubr (&Smac_process_hi_command);
 #endif
-  defsubr (&Smac_clear_font_name_table);
 
   defsubr (&Smac_set_file_creator);
   defsubr (&Smac_set_file_type);