]> code.delx.au - gnu-emacs/blobdiff - src/mac.c
*** empty log message ***
[gnu-emacs] / src / mac.c
index f3d65604f5b458b00a24b7beda5d10cb5411445d..cce1b858cb3a43d6958951e0f614697fa6fdf077 100644 (file)
--- a/src/mac.c
+++ b/src/mac.c
@@ -24,12 +24,17 @@ Boston, MA 02111-1307, USA.  */
 
 #include <stdio.h>
 #include <errno.h>
+#include <time.h>
 #include <utime.h>
 #include <dirent.h>
+#include <sys/types.h>
 #include <sys/stat.h>
 #include <string.h>
 #include <pwd.h>
+#include <grp.h>
 #include <sys/param.h>
+#include <stdlib.h>
+#include <fcntl.h>
 #if __MWERKS__
 #include <unistd.h>
 #endif
@@ -42,6 +47,8 @@ Boston, MA 02111-1307, USA.  */
 #undef realloc
 #undef init_process
 #include <Carbon/Carbon.h>
+#undef mktime
+#define mktime emacs_mktime
 #undef free
 #define free unexec_free
 #undef malloc
@@ -68,6 +75,7 @@ Boston, MA 02111-1307, USA.  */
 #include "process.h"
 #include "sysselect.h"
 #include "systime.h"
+#include "blockinput.h"
 
 Lisp_Object QCLIPBOARD;
 
@@ -89,7 +97,7 @@ string_cat_and_replace (char *s1, const char *s2, int n, char a, char b)
   int l2 = strlen (s2);
   char *p = s1 + l1;
   int i;
-  
+
   strncat (s1, s2, n);
   for (i = 0; i < l2; i++)
     {
@@ -102,27 +110,27 @@ string_cat_and_replace (char *s1, const char *s2, int n, char a, char b)
 
 /* Convert a Mac pathname to Posix form.  A Mac full pathname is one
    that does not begin with a ':' and contains at least one ':'. A Mac
-   full pathname causes an '/' to be prepended to the Posix pathname.
+   full pathname causes a '/' to be prepended to the Posix pathname.
    The algorithm for the rest of the pathname is as follows:
      For each segment between two ':',
        if it is non-null, copy as is and then add a '/' at the end,
        otherwise, insert a "../" into the Posix pathname.
    Returns 1 if successful; 0 if fails.  */
-   
+
 int
 mac_to_posix_pathname (const char *mfn, char *ufn, int ufnbuflen)
 {
   const char *p, *q, *pe;
-       
+
   strcpy (ufn, "");
-       
+
   if (*mfn == '\0')
     return 1;
-       
+
   p = strchr (mfn, ':');
   if (p != 0 && p != mfn)  /* full pathname */
     strcat (ufn, "/");
-               
+
   p = mfn;
   if (*p == ':')
     p++;
@@ -157,7 +165,7 @@ mac_to_posix_pathname (const char *mfn, char *ufn, int ufnbuflen)
          p = pe;
        }
     }
-       
+
   return 1;
 }
 
@@ -167,20 +175,20 @@ extern char *get_temp_dir_name ();
 
 /* Convert a Posix pathname to Mac form.  Approximately reverse of the
    above in algorithm.  */
-   
+
 int
 posix_to_mac_pathname (const char *ufn, char *mfn, int mfnbuflen)
 {
   const char *p, *q, *pe;
   char expanded_pathname[MAXPATHLEN+1];
-       
+
   strcpy (mfn, "");
-       
+
   if (*ufn == '\0')
     return 1;
 
   p = ufn;
-  
+
   /* Check for and handle volume names.  Last comparison: strangely
      somewhere "/.emacs" is passed.  A temporary fix for now.  */
   if (*p == '/' && strchr (p+1, '/') == NULL && strcmp (p, "/.emacs") != 0)
@@ -214,10 +222,10 @@ posix_to_mac_pathname (const char *ufn, char *mfn, int mfnbuflen)
       strcat (expanded_pathname, p);
       p = expanded_pathname;
         /* now p points to the pathname with emacs dir prefix */
-    }    
+    }
   else if (*p != '/')  /* relative pathname */
     strcat (mfn, ":");
-               
+
   if (*p == '/')
     p++;
 
@@ -250,10 +258,26 @@ posix_to_mac_pathname (const char *ufn, char *mfn, int mfnbuflen)
          p = pe;
        }
     }
-       
+
   return 1;
 }
 
+#if TARGET_API_MAC_CARBON
+CFStringRef
+cfstring_create_with_utf8_cstring (c_str)
+     const char *c_str;
+{
+  CFStringRef str;
+
+  str = CFStringCreateWithCString (NULL, c_str, kCFStringEncodingUTF8);
+  if (str == NULL)
+    /* Failed to interpret as UTF 8.  Fall back on Mac Roman.  */
+    str = CFStringCreateWithCString (NULL, c_str, kCFStringEncodingMacRoman);
+
+  return str;
+}
+#endif
+
 #ifndef MAC_OSX
 
 /* The following functions with "sys_" prefix are stubs to Unix
@@ -309,7 +333,7 @@ stat_noalias (const char *path, struct stat *buf)
   cipb.hFileInfo.ioDirID = 0;
   cipb.hFileInfo.ioFDirIndex = 0;
     /* set to 0 to get information about specific dir or file */
-  
+
   errno = PBGetCatInfo (&cipb, false);
   if (errno == -43) /* -43: fnfErr defined in Errors.h */
     errno = ENOENT;
@@ -319,7 +343,7 @@ stat_noalias (const char *path, struct stat *buf)
   if (cipb.hFileInfo.ioFlAttrib & 0x10)  /* bit 4 = 1 for directories */
     {
       buf->st_mode = S_IFDIR | S_IREAD | S_IEXEC;
-      
+
       if (!(cipb.hFileInfo.ioFlAttrib & 0x1))
        buf->st_mode |= S_IWRITE;  /* bit 1 = 1 for locked files/directories */
       buf->st_ino = cipb.dirInfo.ioDrDirID;
@@ -375,7 +399,7 @@ lstat (const char *path, struct stat *buf)
 
   if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
     return -1;
-  
+
   return stat_noalias (true_pathname, buf);
 }
 
@@ -384,16 +408,16 @@ int
 stat (const char *path, struct stat *sb)
 {
   int result;
-  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];  
+  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
   int len;
-  
+
   if ((result = stat_noalias (path, sb)) >= 0 &&
       ! (sb->st_mode & S_IFLNK))
     return result;
 
   if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
     return -1;
-  
+
   len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
   if (len > -1)
     {
@@ -435,10 +459,10 @@ mkdir (const char *dirname, int mode)
 
   HFileParam hfpb;
   char true_pathname[MAXPATHLEN+1], mac_pathname[MAXPATHLEN+1];
-  
+
   if (find_true_pathname (dirname, true_pathname, MAXPATHLEN+1) == -1)
     return -1;
-       
+
   if (posix_to_mac_pathname (true_pathname, mac_pathname, MAXPATHLEN+1) == 0)
     return -1;
 
@@ -446,7 +470,7 @@ mkdir (const char *dirname, int mode)
   hfpb.ioNamePtr = mac_pathname;
   hfpb.ioVRefNum = 0;  /* ignored unless name is invalid */
   hfpb.ioDirID = 0;  /* parent is the root */
-  
+
   errno = PBDirCreate ((HParmBlkPtr) &hfpb, false);
     /* just return the Mac OSErr code for now */
   return errno == noErr ? 0 : -1;
@@ -458,7 +482,7 @@ sys_rmdir (const char *dirname)
 {
   HFileParam hfpb;
   char mac_pathname[MAXPATHLEN+1];
-       
+
   if (posix_to_mac_pathname (dirname, mac_pathname, MAXPATHLEN+1) == 0)
     return -1;
 
@@ -466,7 +490,7 @@ sys_rmdir (const char *dirname)
   hfpb.ioNamePtr = mac_pathname;
   hfpb.ioVRefNum = 0;  /* ignored unless name is invalid */
   hfpb.ioDirID = 0;  /* parent is the root */
-  
+
   errno = PBHDelete ((HParmBlkPtr) &hfpb, false);
   return errno == noErr ? 0 : -1;
 }
@@ -485,14 +509,14 @@ execvp (const char *path, ...)
 int
 utime (const char *path, const struct utimbuf *times)
 {
-  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];  
+  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
   int len;
   char mac_pathname[MAXPATHLEN+1];
   CInfoPBRec cipb;
-  
+
   if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
     return -1;
-  
+
   len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
   if (len > -1)
     fully_resolved_name[len] = '\0';
@@ -506,9 +530,9 @@ utime (const char *path, const struct utimbuf *times)
   cipb.hFileInfo.ioNamePtr = mac_pathname;
   cipb.hFileInfo.ioVRefNum = 0;
   cipb.hFileInfo.ioDirID = 0;
-  cipb.hFileInfo.ioFDirIndex = 0; 
+  cipb.hFileInfo.ioFDirIndex = 0;
     /* set to 0 to get information about specific dir or file */
-  
+
   errno = PBGetCatInfo (&cipb, false);
   if (errno != noErr)
     return -1;
@@ -547,14 +571,14 @@ utime (const char *path, const struct utimbuf *times)
 int
 access (const char *path, int mode)
 {
-  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];  
+  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
   int len;
   char mac_pathname[MAXPATHLEN+1];
   CInfoPBRec cipb;
-  
+
   if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
     return -1;
-  
+
   len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
   if (len > -1)
     fully_resolved_name[len] = '\0';
@@ -570,7 +594,7 @@ access (const char *path, int mode)
   cipb.hFileInfo.ioDirID = 0;
   cipb.hFileInfo.ioFDirIndex = 0;
     /* set to 0 to get information about specific dir or file */
-  
+
   errno = PBGetCatInfo (&cipb, false);
   if (errno != noErr)
     return -1;
@@ -603,16 +627,16 @@ access (const char *path, int mode)
 int
 sys_open (const char *path, int oflag)
 {
-  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];  
+  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
   int len;
   char mac_pathname[MAXPATHLEN+1];
-       
+
   if (strcmp (path, "/dev/null") == 0)
     return DEV_NULL_FD;  /* some bogus fd to be ignored in write */
-  
+
   if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
     return -1;
-  
+
   len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
   if (len > -1)
     fully_resolved_name[len] = '\0';
@@ -640,10 +664,10 @@ sys_open (const char *path, int oflag)
 int
 sys_creat (const char *path, mode_t mode)
 {
-  char true_pathname[MAXPATHLEN+1];  
+  char true_pathname[MAXPATHLEN+1];
   int len;
   char mac_pathname[MAXPATHLEN+1];
-       
+
   if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
     return -1;
 
@@ -666,13 +690,13 @@ sys_creat (const char *path, mode_t mode)
 int
 sys_unlink (const char *path)
 {
-  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];  
+  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
   int len;
   char mac_pathname[MAXPATHLEN+1];
-       
+
   if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
     return -1;
-  
+
   len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
   if (len > -1)
     fully_resolved_name[len] = '\0';
@@ -721,13 +745,13 @@ int
 sys_rename (const char * old_name, const char * new_name)
 {
   char true_old_pathname[MAXPATHLEN+1], true_new_pathname[MAXPATHLEN+1];
-  char fully_resolved_old_name[MAXPATHLEN+1];  
+  char fully_resolved_old_name[MAXPATHLEN+1];
   int len;
   char mac_old_name[MAXPATHLEN+1], mac_new_name[MAXPATHLEN+1];
-       
+
   if (find_true_pathname (old_name, true_old_pathname, MAXPATHLEN+1) == -1)
     return -1;
-  
+
   len = readlink (true_old_pathname, fully_resolved_old_name, MAXPATHLEN);
   if (len > -1)
     fully_resolved_old_name[len] = '\0';
@@ -736,7 +760,7 @@ sys_rename (const char * old_name, const char * new_name)
 
   if (find_true_pathname (new_name, true_new_pathname, MAXPATHLEN+1) == -1)
     return -1;
-       
+
   if (strcmp (fully_resolved_old_name, true_new_pathname) == 0)
     return 0;
 
@@ -744,7 +768,7 @@ sys_rename (const char * old_name, const char * new_name)
                             mac_old_name,
                             MAXPATHLEN+1))
     return -1;
-               
+
   if (!posix_to_mac_pathname(true_new_pathname, mac_new_name, MAXPATHLEN+1))
     return -1;
 
@@ -752,7 +776,7 @@ sys_rename (const char * old_name, const char * new_name)
      file in Unix.  CW version fails in these situation.  So we add a
      call to unlink here.  */
   (void) unlink (mac_new_name);
-  
+
   return rename (mac_old_name, mac_new_name);
 }
 
@@ -762,13 +786,13 @@ extern FILE *fopen (const char *name, const char *mode);
 FILE *
 sys_fopen (const char *name, const char *mode)
 {
-  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];  
+  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
   int len;
   char mac_pathname[MAXPATHLEN+1];
-       
+
   if (find_true_pathname (name, true_pathname, MAXPATHLEN+1) == -1)
     return 0;
-  
+
   len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
   if (len > -1)
     fully_resolved_name[len] = '\0';
@@ -821,6 +845,8 @@ check_alarm ()
 }
 
 
+extern Boolean mac_wait_next_event (EventRecord *, UInt32, Boolean);
+
 int
 select (n,  rfds, wfds, efds, timeout)
   int n;
@@ -829,49 +855,24 @@ select (n,  rfds, wfds, efds, timeout)
   SELECT_TYPE *efds;
   struct timeval *timeout;
 {
-#ifdef TARGET_API_MAC_CARBON
+#if TARGET_API_MAC_CARBON
   return 1;
 #else /* not TARGET_API_MAC_CARBON */
-  EMACS_TIME end_time, now;
   EventRecord e;
+  UInt32 sleep_time = EMACS_SECS (*timeout) * 60 +
+    ((EMACS_USECS (*timeout) * 60) / 1000000);
 
   /* Can only handle wait for keyboard input.  */
   if (n > 1 || wfds || efds)
     return -1;
 
-  EMACS_GET_TIME (end_time);
-  EMACS_ADD_TIME (end_time, end_time, *timeout);
-  
-  do
-    {
-      /* 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 (FD_ISSET (0, rfds) && EventAvail (everyEvent, &e))
-        return 1;
-
-      /* Also check movement of the mouse.  */
-      {
-        Point mouse_pos;
-        static Point old_mouse_pos = {-1, -1};
-        
-        GetMouse (&mouse_pos);
-        if (!EqualPt (mouse_pos, old_mouse_pos))
-          {
-            old_mouse_pos = mouse_pos;
-            return 1;
-          }
-      }
-      
-      WaitNextEvent (0, &e, 1UL, NULL);        /* Accept no event; wait 1
-                                          tic. by T.I. */
-      
-      EMACS_GET_TIME (now);
-      EMACS_SUB_TIME (now, end_time, now);
-    }
-  while (!EMACS_TIME_NEG_P (now));
+  /* 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 (FD_ISSET (0, rfds) && mac_wait_next_event (&e, sleep_time, false))
+    return 1;
 
   return 0;
 #endif /* not TARGET_API_MAC_CARBON */
@@ -885,18 +886,18 @@ pause ()
 {
   EventRecord e;
   unsigned long tick;
-  
+
   if (!target_ticks)  /* no alarm pending */
     return -1;
 
   if ((tick = TickCount ()) < target_ticks)
     WaitNextEvent (0, &e, target_ticks - tick, NULL); /* Accept no event;
                                                         just wait. by T.I. */
-  
+
   target_ticks = 0;
   if (alarm_signal_func)
     (*alarm_signal_func)(SIGALRM);
-  
+
   return 0;
 }
 
@@ -905,9 +906,9 @@ int
 alarm (int seconds)
 {
   long remaining = target_ticks ? (TickCount () - target_ticks) / 60 : 0;
-       
+
   target_ticks = seconds ? TickCount () + 60 * seconds : 0;
-       
+
   return (remaining < 0) ? 0 : (unsigned int) remaining;
 }
 
@@ -930,9 +931,9 @@ sys_signal (int signal_num, __signal_func_ptr signal_func)
   else
     {
 #ifdef __MRC__
-      __sigfun old_signal_func;                
+      __sigfun old_signal_func;
 #elif __MWERKS__
-      __signal_func_ptr old_signal_func;               
+      __signal_func_ptr old_signal_func;
 #else
       You lose!!!
 #endif
@@ -977,7 +978,7 @@ gettimeofday (tp)
 
   /* Get time since boot */
   Microseconds (&uw_microseconds);
-  
+
   /* Convert to time since midnight*/
   w_microseconds.hi = uw_microseconds.hi;
   w_microseconds.lo = uw_microseconds.lo;
@@ -1017,7 +1018,7 @@ struct tm *
 sys_gmtime (const time_t *timer)
 {
   time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
-  
+
   return gmtime (&unix_time);
 }
 
@@ -1032,7 +1033,7 @@ sys_localtime (const time_t *timer)
 #else
   time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
 #endif
-  
+
   return localtime (&unix_time);
 }
 
@@ -1047,7 +1048,7 @@ sys_ctime (const time_t *timer)
 #else
   time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
 #endif
-  
+
   return ctime (&unix_time);
 }
 
@@ -1065,7 +1066,7 @@ sys_time (time_t *timer)
 
   if (timer)
     *timer = mac_time;
-    
+
   return mac_time;
 }
 
@@ -1128,23 +1129,23 @@ mktemp (char *template)
 {
   int len, k;
   static seqnum = 0;
-  
+
   len = strlen (template);
   k = len - 1;
   while (k >= 0 && template[k] == 'X')
     k--;
-  
+
   k++;  /* make k index of first 'X' */
-  
+
   if (k < len)
     {
       /* Zero filled, number of digits equal to the number of X's.  */
       sprintf (&template[k], "%0*d", len-k, seqnum++);
-  
+
       return template;
     }
   else
-    return 0;  
+    return 0;
 }
 
 
@@ -1155,12 +1156,19 @@ mktemp (char *template)
 static char my_passwd_name[PASSWD_FIELD_SIZE];
 static char my_passwd_dir[MAXPATHLEN+1];
 
-static struct passwd my_passwd = 
+static struct passwd my_passwd =
 {
   my_passwd_name,
   my_passwd_dir,
 };
 
+static struct group my_group =
+{
+  /* There are no groups on the mac, so we just return "root" as the
+     group name.  */
+  "root",
+};
+
 
 /* Initialized by main () in macterm.c to pathname of emacs directory.  */
 
@@ -1199,7 +1207,7 @@ init_emacs_passwd_dir ()
            }
        }
     }
-  
+
   if (!found)
     {
       /* Setting to "/" probably won't work but set it to something
@@ -1210,7 +1218,7 @@ init_emacs_passwd_dir ()
 }
 
 
-static struct passwd emacs_passwd = 
+static struct passwd emacs_passwd =
 {
   "emacs",
   emacs_passwd_dir,
@@ -1246,15 +1254,22 @@ struct passwd *
 getpwuid (uid_t uid)
 {
   if (!my_passwd_inited)
-    {  
+    {
       init_my_passwd ();
       my_passwd_inited = 1;
     }
-  
+
   return &my_passwd;
 }
 
 
+struct group *
+getgrgid (gid_t gid)
+{
+  return &my_group;
+}
+
+
 struct passwd *
 getpwnam (const char *name)
 {
@@ -1262,11 +1277,11 @@ getpwnam (const char *name)
        return &emacs_passwd;
 
   if (!my_passwd_inited)
-    {  
+    {
       init_my_passwd ();
       my_passwd_inited = 1;
     }
-  
+
   return &my_passwd;
 }
 
@@ -1308,7 +1323,7 @@ int
 sigblock (int mask)
 {
   return 0;
-} 
+}
 
 
 void
@@ -1390,7 +1405,7 @@ path_from_vol_dir_name (char *path, int man_path_len, short vol_ref_num,
       err = PBGetCatInfo (&cipb, false);
       if (err != noErr)
         return 0;
-      
+
       p2cstr (dir_name);
       if (strlen (dir_name) + strlen (path) + 1 >= man_path_len)
         return 0;
@@ -1402,7 +1417,7 @@ path_from_vol_dir_name (char *path, int man_path_len, short vol_ref_num,
     }
   while (cipb.dirInfo.ioDrDirID != fsRtDirID);
     /* stop when we see the volume's root directory */
-  
+
   return 1;  /* success */
 }
 
@@ -1466,7 +1481,7 @@ find_true_pathname (const char *path, char *buf, int bufsiz)
     return -1;
 
   buf[0] = '\0';
-  
+
   p = path;
   if (*p == '/')
     q = strchr (p + 1, '/');
@@ -1490,10 +1505,10 @@ find_true_pathname (const char *path, char *buf, int bufsiz)
       p = q + 1;
       q = strchr(p, '/');
     }
-  
+
   if (len + strlen (p) + 1 >= bufsiz)
     return -1;
-  
+
   strcat (buf, p);
   return len + strlen (p);
 }
@@ -1541,7 +1556,7 @@ int
 dup2 (int oldd, int newd)
 {
   int fd, ret;
-  
+
   close (newd);
 
   fd = dup (oldd);
@@ -1652,7 +1667,7 @@ get_temp_dir_name ()
   CInfoPBRec cpb;
   char unix_dir_name[MAXPATHLEN+1];
   DIR *dir;
-  
+
   /* Cache directory name with pointer temp_dir_name.
      Look for it only the first time.  */
   if (!temp_dir_name)
@@ -1661,18 +1676,18 @@ get_temp_dir_name ()
                        &vol_ref_num, &dir_id);
       if (err != noErr)
        return NULL;
-      
+
       if (!path_from_vol_dir_name (full_path, 255, vol_ref_num, dir_id, "\p"))
         return NULL;
 
       if (strlen (full_path) + 6 <= MAXPATHLEN)
        strcat (full_path, "Emacs:");
-      else 
+      else
        return NULL;
 
       if (!mac_to_posix_pathname (full_path, unix_dir_name, MAXPATHLEN+1))
        return NULL;
-    
+
       dir = opendir (unix_dir_name);  /* check whether temp directory exists */
       if (dir)
        closedir (dir);
@@ -1691,7 +1706,7 @@ get_temp_dir_name ()
 /* Allocate and construct an array of pointers to strings from a list
    of strings stored in a 'STR#' resource.  The returned pointer array
    is stored in the style of argv and environ: if the 'STR#' resource
-   contains numString strings, an pointer array with numString+1
+   contains numString strings, a pointer array with numString+1
    elements is returned in which the last entry contains a null
    pointer.  The pointer to the pointer array is passed by pointer in
    parameter t.  The resource ID of the 'STR#' resource is passed in
@@ -1745,19 +1760,19 @@ get_path_to_system_folder ()
   CInfoPBRec cpb;
   static char system_folder_unix_name[MAXPATHLEN+1];
   DIR *dir;
-  
+
   err = FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder,
                    &vol_ref_num, &dir_id);
   if (err != noErr)
     return NULL;
-      
+
   if (!path_from_vol_dir_name (full_path, 255, vol_ref_num, dir_id, "\p"))
     return NULL;
 
   if (!mac_to_posix_pathname (full_path, system_folder_unix_name,
                              MAXPATHLEN+1))
     return NULL;
-    
+
   return system_folder_unix_name;
 }
 
@@ -1772,7 +1787,7 @@ void
 init_environ ()
 {
   int i;
-  
+
   get_string_list (&environ, ENVIRON_STRING_LIST_ID);
 
   i = 0;
@@ -1916,7 +1931,7 @@ mystrchr (char *s, char c)
 
 char *
 mystrtok (char *s)
-{      
+{
   while (*s)
     s++;
 
@@ -1958,7 +1973,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
      const char *workdir;
      const char *infn, *outfn, *errfn;
 {
-#ifdef TARGET_API_MAC_CARBON
+#if TARGET_API_MAC_CARBON
   return -1;
 #else /* not TARGET_API_MAC_CARBON */
   char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1];
@@ -1972,7 +1987,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
   RgnHandle cursor_region_handle;
   TargetID targ;
   unsigned long ref_con, len;
-       
+
   if (posix_to_mac_pathname (workdir, macworkdir, MAXPATHLEN+1) == 0)
     return -1;
   if (posix_to_mac_pathname (infn, macinfn, MAXPATHLEN+1) == 0)
@@ -1981,7 +1996,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
     return -1;
   if (posix_to_mac_pathname (errfn, macerrfn, MAXPATHLEN+1) == 0)
     return -1;
-  
+
   paramlen = strlen (macworkdir) + strlen (macinfn) + strlen (macoutfn)
              + strlen (macerrfn) + 4;  /* count nulls at end of strings */
 
@@ -2000,14 +2015,14 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
       && argc == 3 && strcmp (argv[1], "-c") == 0)
     {
       char *command, *t, tempmacpathname[MAXPATHLEN+1];
-    
+
       /* The arguments for the command in argv[2] are separated by
         spaces.  Count them and put the count in newargc.  */
       command = (char *) alloca (strlen (argv[2])+2);
       strcpy (command, argv[2]);
       if (command[strlen (command) - 1] != ' ')
        strcat (command, " ");
-    
+
       t = command;
       newargc = 0;
       t = mystrchr (t, ' ');
@@ -2016,9 +2031,9 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
          newargc++;
          t = mystrchr (t+1, ' ');
        }
-    
+
       newargv = (char **) alloca (sizeof (char *) * newargc);
-    
+
       t = command;
       for (j = 0; j < newargc; j++)
        {
@@ -2028,7 +2043,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
          t = mystrtok (t);
          paramlen += strlen (newargv[j]) + 1;
        }
-    
+
       if (strncmp (newargv[0], "~emacs/", 7) == 0)
        {
          if (posix_to_mac_pathname (newargv[0], tempmacpathname, MAXPATHLEN+1)
@@ -2043,7 +2058,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
          strcat (t, newargv[0]);
 #endif /* 0 */
          Lisp_Object path;
-         openp (Vexec_path, build_string (newargv[0]), EXEC_SUFFIXES, &path,
+         openp (Vexec_path, build_string (newargv[0]), Vexec_suffixes, &path,
                 make_number (X_OK));
 
          if (NILP (path))
@@ -2055,12 +2070,12 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
       strcpy (macappname, tempmacpathname);
     }
   else
-    {      
+    {
       if (posix_to_mac_pathname (argv[0], macappname, MAXPATHLEN+1) == 0)
        return -1;
 
       newargv = (char **) alloca (sizeof (char *) * argc);
-      newargc = argc;  
+      newargc = argc;
       for (j = 1; j < argc; j++)
        {
          if (strncmp (argv[j], "~emacs/", 7) == 0)
@@ -2090,7 +2105,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
                }
            }
          else
-           newargv[j] = argv[j];  
+           newargv[j] = argv[j];
          paramlen += strlen (newargv[j]) + 1;
        }
     }
@@ -2111,24 +2126,24 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
     /* null terminate strings sent so it's possible to use strcpy over there */
   strcpy (p, macinfn);
   p += strlen (macinfn);
-  *p++ = '\0';  
+  *p++ = '\0';
   strcpy (p, macoutfn);
   p += strlen (macoutfn);
-  *p++ = '\0';  
+  *p++ = '\0';
   strcpy (p, macerrfn);
   p += strlen (macerrfn);
-  *p++ = '\0';  
+  *p++ = '\0';
   for (j = 1; j < newargc; j++)
     {
       strcpy (p, newargv[j]);
       p += strlen (newargv[j]);
-      *p++ = '\0';  
+      *p++ = '\0';
     }
-  
+
   c2pstr (macappname);
-  
+
   iErr = FSMakeFSSpec (0, 0, macappname, &spec);
-  
+
   if (iErr != noErr)
     {
       free (param);
@@ -2169,7 +2184,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
     }
 
   cursor_region_handle = NewRgn ();
-       
+
   /* Wait for the subprocess to finish, when it will send us a ERPY
      high level event.  */
   while (1)
@@ -2177,7 +2192,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
                       cursor_region_handle)
        && reply_event.message == kEmacsSubprocessReply)
       break;
-  
+
   /* The return code is sent through the refCon */
   iErr = AcceptHighLevelEvent (&targ, &ref_con, NULL, &len);
   if (iErr != noErr)
@@ -2186,7 +2201,7 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
       free (param);
       return -1;
     }
-  
+
   DisposeHandle ((Handle) cursor_region_handle);
   free (param);
 
@@ -2198,16 +2213,16 @@ run_mac_command (argv, workdir, infn, outfn, errfn)
 DIR *
 opendir (const char *dirname)
 {
-  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];  
+  char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
   char mac_pathname[MAXPATHLEN+1], vol_name[MAXPATHLEN+1];
   DIR *dirp;
   CInfoPBRec cipb;
   HVolumeParam vpb;
   int len, vol_name_len;
-       
+
   if (find_true_pathname (dirname, true_pathname, MAXPATHLEN+1) == -1)
     return 0;
-  
+
   len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
   if (len > -1)
     fully_resolved_name[len] = '\0';
@@ -2235,7 +2250,7 @@ opendir (const char *dirname)
   len = strlen (mac_pathname);
   if (mac_pathname[len - 1] != ':' && len < MAXPATHLEN)
     strcat (mac_pathname, ":");
-  
+
   /* Extract volume name */
   vol_name_len = strchr (mac_pathname, ':') - mac_pathname;
   strncpy (vol_name, mac_pathname, vol_name_len);
@@ -2249,7 +2264,7 @@ opendir (const char *dirname)
   cipb.hFileInfo.ioDirID = 0;
   cipb.hFileInfo.ioFDirIndex = 0;
     /* set to 0 to get information about specific dir or file */
-  
+
   errno = PBGetCatInfo (&cipb, false);
   if (errno != noErr)
     {
@@ -2277,7 +2292,7 @@ opendir (const char *dirname)
     }
 
   dirp->vol_ref_num = vpb.ioVRefNum;
-  
+
   return dirp;
 }
 
@@ -2310,14 +2325,14 @@ readdir (DIR *dp)
       hpblock.volumeParam.ioNamePtr = s_name;
       hpblock.volumeParam.ioVRefNum = 0;
       hpblock.volumeParam.ioVolIndex = dp->current_index;
-                
+
       errno = PBHGetVInfo (&hpblock, false);
       if (errno != noErr)
        {
          errno = ENOENT;
          return 0;
        }
-                        
+
       p2cstr (s_name);
       strcat (s_name, "/");  /* need "/" for stat to work correctly */
 
@@ -2325,7 +2340,7 @@ readdir (DIR *dp)
 
       s_dirent.d_ino = hpblock.volumeParam.ioVRefNum;
       s_dirent.d_name = s_name;
-  
+
       return &s_dirent;
     }
   else
@@ -2341,25 +2356,25 @@ readdir (DIR *dp)
          cipb.hFileInfo.ioDirID = dp->dir_id;
            /* directory ID found by opendir */
          cipb.hFileInfo.ioFDirIndex = dp->current_index;
-         
+
          errno = PBGetCatInfo (&cipb, false);
          if (errno != noErr)
            {
              errno = ENOENT;
              return 0;
            }
-         
-         /* insist on an visibile entry */
+
+         /* insist on a visible entry */
          if (cipb.hFileInfo.ioFlAttrib & 0x10)  /* directory? */
            done = !(cipb.dirInfo.ioDrUsrWds.frFlags & fInvisible);
          else
            done = !(cipb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible);
-         
+
          dp->current_index++;
        }
 
       p2cstr (s_name);
-      
+
       p = s_name;
       while (*p)
         {
@@ -2371,7 +2386,7 @@ readdir (DIR *dp)
       s_dirent.d_ino = cipb.dirInfo.ioDrDirID;
         /* value unimportant: non-zero for valid file */
       s_dirent.d_name = s_name;
-  
+
       return &s_dirent;
     }
 }
@@ -2402,7 +2417,7 @@ initialize_applescript ()
 {
   AEDesc null_desc;
   OSAError osaerror;
-  
+
   /* if open fails, as_scripting_component is set to NULL.  Its
      subsequent use in OSA calls will fail with badComponentInstance
      error.  */
@@ -2528,8 +2543,10 @@ component.  */)
   long status;
 
   CHECK_STRING (script);
-  
+
+  BLOCK_INPUT;
   status = do_applescript (SDATA (script), &result);
+  UNBLOCK_INPUT;
   if (status)
     {
       if (!result)
@@ -2565,7 +2582,7 @@ DEFUN ("mac-file-name-to-posix", Fmac_file_name_to_posix,
   char posix_filename[MAXPATHLEN+1];
 
   CHECK_STRING (mac_filename);
-  
+
   if (mac_to_posix_pathname (SDATA (mac_filename), posix_filename,
                           MAXPATHLEN))
     return build_string (posix_filename);
@@ -2583,7 +2600,7 @@ DEFUN ("posix-file-name-to-mac", Fposix_file_name_to_mac,
   char mac_filename[MAXPATHLEN+1];
 
   CHECK_STRING (posix_filename);
-  
+
   if (posix_to_mac_pathname (SDATA (posix_filename), mac_filename,
                           MAXPATHLEN))
     return build_string (mac_filename);
@@ -2599,28 +2616,25 @@ DEFUN ("mac-paste-function", Fmac_paste_function, Smac_paste_function, 0, 0, 0,
      ()
 {
 #if TARGET_API_MAC_CARBON
+  OSStatus err;
   ScrapRef scrap;
   ScrapFlavorFlags sff;
   Size s;
   int i;
   char *data;
 
-  if (GetCurrentScrap (&scrap) != noErr)
-    return Qnil;
-
-  if (GetScrapFlavorFlags (scrap, kScrapFlavorTypeText, &sff) != noErr)
-    return Qnil;
-
-  if (GetScrapFlavorSize (scrap, kScrapFlavorTypeText, &s) != noErr)
+  BLOCK_INPUT;
+  err = GetCurrentScrap (&scrap);
+  if (err == noErr)
+    err = GetScrapFlavorFlags (scrap, kScrapFlavorTypeText, &sff);
+  if (err == noErr)
+    err = GetScrapFlavorSize (scrap, kScrapFlavorTypeText, &s);
+  if (err == noErr && (data = (char*) alloca (s)))
+    err = GetScrapFlavorData (scrap, kScrapFlavorTypeText, &s, data);
+  UNBLOCK_INPUT;
+  if (err != noErr || s == 0)
     return Qnil;
 
-  if ((data = (char*) alloca (s)) == NULL)
-    return Qnil;
-
-  if (GetScrapFlavorData (scrap, kScrapFlavorTypeText, &s, data) != noErr
-      || s == 0)
-    return Qnil;
-  
   /* Emacs expects clipboard contents have Unix-style eol's */
   for (i = 0; i < s; i++)
     if (data[i] == '\r')
@@ -2648,7 +2662,7 @@ DEFUN ("mac-paste-function", Fmac_paste_function, Smac_paste_function, 0, 0, 0,
   value = make_string (*my_handle, rc);
 
   HUnlock (my_handle);
-  
+
   DisposeHandle (my_handle);
 
   return value;
@@ -2669,12 +2683,12 @@ DEFUN ("mac-cut-function", Fmac_cut_function, Smac_cut_function, 1, 2, 0,
   /* fixme: ignore the push flag for now */
 
   CHECK_STRING (value);
-  
+
   len = SCHARS (value);
   buf = (char *) alloca (len+1);
   bcopy (SDATA (value), buf, len);
   buf[len] = '\0';
-  
+
   /* convert to Mac-style eol's before sending to clipboard */
   for (i = 0; i < len; i++)
     if (buf[i] == '\n')
@@ -2683,19 +2697,28 @@ DEFUN ("mac-cut-function", Fmac_cut_function, Smac_cut_function, 1, 2, 0,
 #if TARGET_API_MAC_CARBON
   {
     ScrapRef scrap;
+
+    BLOCK_INPUT;
     ClearCurrentScrap ();
     if (GetCurrentScrap (&scrap) != noErr)
-      error ("cannot get current scrap");
+      {
+       UNBLOCK_INPUT;
+       error ("cannot get current scrap");
+      }
 
     if (PutScrapFlavor (scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone, len,
                        buf) != noErr)
-      error ("cannot put to scrap");
+      {
+       UNBLOCK_INPUT;
+       error ("cannot put to scrap");
+      }
+    UNBLOCK_INPUT;
   }
 #else /* not TARGET_API_MAC_CARBON */
   ZeroScrap ();
   PutScrap (len, 'TEXT', buf);
 #endif /* not TARGET_API_MAC_CARBON */
-  
+
   return Qnil;
 }
 
@@ -2724,9 +2747,11 @@ and t is the same as `SECONDARY'.  */)
       ScrapRef scrap;
       ScrapFlavorFlags sff;
 
+      BLOCK_INPUT;
       if (GetCurrentScrap (&scrap) == noErr)
         if (GetScrapFlavorFlags (scrap, kScrapFlavorTypeText, &sff) == noErr)
           val = Qt;
+      UNBLOCK_INPUT;
 #else /* not TARGET_API_MAC_CARBON */
       Handle my_handle;
       long rc, scrap_offset;
@@ -2745,20 +2770,434 @@ and t is the same as `SECONDARY'.  */)
   return Qnil;
 }
 
+extern void mac_clear_font_name_table P_ ((void));
+
+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.  */)
+  ()
+{
+  check_mac ();
+  mac_clear_font_name_table ();
+  return Qnil;
+}
+
+#ifdef MAC_OSX
+#undef select
+
+extern int inhibit_window_system;
+extern int noninteractive;
+
+/* Unlike in X11, window events in Carbon do not come from sockets.
+   So we cannot simply use `select' to monitor two kinds of inputs:
+   window events and process outputs.  We emulate such functionality
+   by regarding fd 0 as the window event channel and simultaneously
+   monitoring both kinds of input channels.  It is implemented by
+   dividing into some cases:
+   1. The window event channel is not involved.
+      -> 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
+      involved, and timeout is not too short (greater than
+      SELECT_TIMEOUT_THRESHHOLD_RUNLOOP seconds).
+      -> Create CFSocket for each socket and add it into the current
+         event RunLoop so that an `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.
+   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
+#define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2
+#define EVENT_CLASS_SOCK 'Sock'
+
+static void
+socket_callback (s, type, address, data, info)
+     CFSocketRef s;
+     CFSocketCallBackType type;
+     CFDataRef address;
+     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;
+{
+  int r;
+  OSErr err;
+
+  r = select (n, rfds, wfds, efds, timeout);
+  if (r != -1)
+    {
+      BLOCK_INPUT;
+      err = ReceiveNextEvent (0, NULL, kEventDurationNoWait,
+                             kEventLeaveInQueue, NULL);
+      UNBLOCK_INPUT;
+      if (err == noErr)
+       {
+         FD_SET (0, rfds);
+         r++;
+       }
+    }
+  return r;
+}
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1020
+#undef SELECT_INVALIDATE_CFSOCKET
+#endif
+
+int
+sys_select (n, rfds, wfds, efds, timeout)
+     int n;
+     SELECT_TYPE *rfds;
+     SELECT_TYPE *wfds;
+     SELECT_TYPE *efds;
+     struct timeval *timeout;
+{
+  OSErr err;
+  int i, r;
+  EMACS_TIME select_timeout;
+
+  if (inhibit_window_system || noninteractive
+      || rfds == NULL || !FD_ISSET (0, rfds))
+    return select (n, rfds, wfds, efds, timeout);
+
+  FD_CLR (0, rfds);
+
+  if (wfds == NULL && efds == NULL)
+    {
+      int nsocks = 0;
+      SELECT_TYPE orfds = *rfds;
+
+      EventTimeout timeout_sec =
+       (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)
+       {
+         BLOCK_INPUT;
+         err = ReceiveNextEvent (0, NULL, timeout_sec,
+                                 kEventLeaveInQueue, NULL);
+         UNBLOCK_INPUT;
+         if (err == noErr)
+           {
+             FD_SET (0, rfds);
+             return 1;
+           }
+         else
+           return 0;
+       }
+
+      /* 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)
+       return r;
+
+      *rfds = orfds;
+
+#ifdef SELECT_USE_CFSOCKET
+      if (timeout_sec > 0 && timeout_sec <= 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++;
+           }
+
+       err = ReceiveNextEvent (0, NULL, timeout_sec, kEventLeaveInQueue, NULL);
+
+       do
+         {
+           --s;
+#ifdef SELECT_INVALIDATE_CFSOCKET
+           CFSocketInvalidate (*s);
+#else
+           CFRunLoopRemoveSource (runloop, *s, kCFRunLoopDefaultMode);
+#endif
+           CFRelease (*s);
+         }
+       while (s != shead);
+
+       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);
+         }
+
+       UNBLOCK_INPUT;
+
+       return r;
+      }
+#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;
+       EMACS_GET_TIME (now);
+       EMACS_ADD_TIME (end_time, now, remaining_time);
+      }
+
+    do
+      {
+       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);
+       if (r != 0)
+         return r;
+
+       *rfds = orfds;
+       if (wfds)
+         *wfds = owfds;
+       if (efds)
+         *efds = oefds;
+
+       if (timeout)
+         {
+           EMACS_GET_TIME (now);
+           EMACS_SUB_TIME (remaining_time, end_time, now);
+         }
+      }
+    while (!timeout || EMACS_TIME_LT (now, end_time));
+
+    FD_ZERO (rfds);
+    if (wfds)
+      FD_ZERO (wfds);
+    if (efds)
+      FD_ZERO (efds);
+    return 0;
+  }
+}
+
+/* Set up environment variables so that Emacs can correctly find its
+   support files when packaged as an application bundle.  Directories
+   placed in /usr/local/share/emacs/<emacs-version>/, /usr/local/bin,
+   and /usr/local/libexec/emacs/<emacs-version>/<system-configuration>
+   by `make install' by default can instead be placed in
+   .../Emacs.app/Contents/Resources/ and
+   .../Emacs.app/Contents/MacOS/.  Each of these environment variables
+   is changed only if it is not already set.  Presumably if the user
+   sets an environment variable, he will want to use files in his path
+   instead of ones in the application bundle.  */
+void
+init_mac_osx_environment ()
+{
+  CFBundleRef bundle;
+  CFURLRef bundleURL;
+  CFStringRef cf_app_bundle_pathname;
+  int app_bundle_pathname_len;
+  char *app_bundle_pathname;
+  char *p, *q;
+  struct stat st;
+
+  /* Fetch the pathname of the application bundle as a C string into
+     app_bundle_pathname.  */
+
+  bundle = CFBundleGetMainBundle ();
+  if (!bundle)
+    return;
+
+  bundleURL = CFBundleCopyBundleURL (bundle);
+  if (!bundleURL)
+    return;
+
+  cf_app_bundle_pathname = CFURLCopyFileSystemPath (bundleURL,
+                                                   kCFURLPOSIXPathStyle);
+  app_bundle_pathname_len = CFStringGetLength (cf_app_bundle_pathname);
+  app_bundle_pathname = (char *) alloca (app_bundle_pathname_len + 1);
+
+  if (!CFStringGetCString (cf_app_bundle_pathname,
+                          app_bundle_pathname,
+                          app_bundle_pathname_len + 1,
+                          kCFStringEncodingISOLatin1))
+    {
+      CFRelease (cf_app_bundle_pathname);
+      return;
+    }
+
+  CFRelease (cf_app_bundle_pathname);
+
+  /* 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>".  */
+  p = (char *) alloca (app_bundle_pathname_len + 50);
+  q = (char *) alloca (3 * app_bundle_pathname_len + 150);
+  if (!getenv ("EMACSLOADPATH"))
+    {
+      q[0] = '\0';
+
+      strcpy (p, app_bundle_pathname);
+      strcat (p, "/Contents/Resources/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");
+      if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
+       {
+         if (q[0] != '\0')
+           strcat (q, ":");
+         strcat (q, p);
+       }
+
+      strcpy (p, app_bundle_pathname);
+      strcat (p, "/Contents/Resources/site-lisp");
+      if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
+       {
+         if (q[0] != '\0')
+           strcat (q, ":");
+         strcat (q, p);
+       }
+
+      if (q[0] != '\0')
+       setenv ("EMACSLOADPATH", q, 1);
+    }
+
+  if (!getenv ("EMACSPATH"))
+    {
+      q[0] = '\0';
+
+      strcpy (p, app_bundle_pathname);
+      strcat (p, "/Contents/MacOS/libexec");
+      if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
+       strcat (q, p);
+
+      strcpy (p, app_bundle_pathname);
+      strcat (p, "/Contents/MacOS/bin");
+      if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
+       {
+         if (q[0] != '\0')
+           strcat (q, ":");
+         strcat (q, p);
+       }
+
+      if (q[0] != '\0')
+       setenv ("EMACSPATH", q, 1);
+    }
+
+  if (!getenv ("EMACSDATA"))
+    {
+      strcpy (p, app_bundle_pathname);
+      strcat (p, "/Contents/Resources/etc");
+      if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
+       setenv ("EMACSDATA", p, 1);
+    }
+
+  if (!getenv ("EMACSDOC"))
+    {
+      strcpy (p, app_bundle_pathname);
+      strcat (p, "/Contents/Resources/etc");
+      if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
+       setenv ("EMACSDOC", p, 1);
+    }
+
+  if (!getenv ("INFOPATH"))
+    {
+      strcpy (p, app_bundle_pathname);
+      strcat (p, "/Contents/Resources/info");
+      if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
+       setenv ("INFOPATH", p, 1);
+    }
+}
+#endif /* MAC_OSX */
 
 void
 syms_of_mac ()
 {
   QCLIPBOARD = intern ("CLIPBOARD");
   staticpro (&QCLIPBOARD);
-  
+
   defsubr (&Smac_paste_function);
   defsubr (&Smac_cut_function);
-#if 0
   defsubr (&Sx_selection_exists_p);
-#endif /* 0 */
+  defsubr (&Smac_clear_font_name_table);
 
   defsubr (&Sdo_applescript);
   defsubr (&Smac_file_name_to_posix);
   defsubr (&Sposix_file_name_to_mac);
 }
+
+/* arch-tag: 29d30c1f-0c6b-4f88-8a6d-0558d7f9dbff
+   (do not change this comment) */