]> code.delx.au - gnu-emacs/blobdiff - src/macfns.c
* process.c (wait_reading_process_output): Check for window
[gnu-emacs] / src / macfns.c
index 617167dfc467295010ee8aecd9717b47684f105b..19947cadae466b3552f36f8ae93e32d24ebf4beb 100644 (file)
@@ -1,12 +1,12 @@
 /* Graphical user interface functions for Mac OS.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006 Free Software Foundation, Inc.
+                 2005, 2006, 2007, 2008 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,
@@ -51,6 +51,14 @@ Boston, MA 02110-1301, USA.  */
 
 extern void free_frame_menubar ();
 
+#if TARGET_API_MAC_CARBON
+
+/* Carbon version info */
+
+static Lisp_Object Vmac_carbon_version_string;
+
+#endif /* TARGET_API_MAC_CARBON */
+
 /* Non-zero means we're allowed to display an hourglass cursor.  */
 
 int display_hourglass_p;
@@ -210,15 +218,6 @@ void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
-                                     Lisp_Object));
-void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
-                                     Lisp_Object));
-static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
-                                                            Lisp_Object,
-                                                            Lisp_Object,
-                                                            char *, char *,
-                                                            int));
 
 extern void mac_get_window_bounds P_ ((struct frame *, Rect *, Rect *));
 
@@ -252,7 +251,7 @@ typedef struct colormap_t
   char *name;
 } colormap_t;
 
-colormap_t mac_color_map[] =
+static const colormap_t mac_color_map[] =
 {
   { RGB_TO_ULONG(255, 250, 250), "snow" },
   { RGB_TO_ULONG(248, 248, 255), "ghost white" },
@@ -1010,7 +1009,7 @@ colormap_t mac_color_map[] =
 
 Lisp_Object
 mac_color_map_lookup (colorname)
-     char *colorname;
+     const char *colorname;
 {
   Lisp_Object ret = Qnil;
   int i;
@@ -1033,7 +1032,7 @@ Lisp_Object
 x_to_mac_color (colorname)
      char * colorname;
 {
-  register Lisp_Object tail, ret = Qnil;
+  register Lisp_Object ret = Qnil;
 
   BLOCK_INPUT;
 
@@ -1100,7 +1099,7 @@ x_to_mac_color (colorname)
       char *color;
       unsigned long colorval;
       int i, pos;
-      pos = 0;
+      pos = 16;
 
       colorval = 0;
       color = colorname + 4;
@@ -1136,7 +1135,7 @@ x_to_mac_color (colorname)
          if (value == ULONG_MAX)
            break;
          colorval |= (value << pos);
-         pos += 0x8;
+         pos -= 0x8;
          if (i == 2)
            {
              if (*end != '\0')
@@ -1155,7 +1154,7 @@ x_to_mac_color (colorname)
       char *color;
       unsigned long colorval;
       int i, pos;
-      pos = 0;
+      pos = 16;
 
       colorval = 0;
       color = colorname + 5;
@@ -1177,7 +1176,7 @@ x_to_mac_color (colorname)
          if (val == 0x100)
            val = 0xFF;
          colorval |= (val << pos);
-         pos += 0x8;
+         pos -= 0x8;
          if (i == 2)
            {
              if (*end != '\0')
@@ -1368,7 +1367,6 @@ x_set_mouse_color (f, arg, oldval)
      Lisp_Object arg, oldval;
 {
   struct x_output *x = f->output_data.x;
-  Display *dpy = FRAME_MAC_DISPLAY (f);
   Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
   Cursor hourglass_cursor, horizontal_drag_cursor;
   unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
@@ -1602,7 +1600,7 @@ x_set_icon_name (f, arg, oldval)
       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
        return;
     }
-  else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
+  else if (!NILP (arg) || NILP (oldval))
     return;
 
   f->icon_name = arg;
@@ -1857,15 +1855,7 @@ x_implicitly_set_name (f, arg, oldval)
 }
 \f
 /* Change the title of frame F to NAME.
-   If NAME is nil, use the frame name as the title.
-
-   If EXPLICIT is non-zero, that indicates that lisp code is setting the
-       name; if NAME is a string, set F's name to NAME and set
-       F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
-
-   If EXPLICIT is zero, that indicates that Emacs redisplay code is
-       suggesting a new name, which lisp code should override; if
-       F->explicit_name is set, ignore the new name; otherwise, set it.  */
+   If NAME is nil, use the frame name as the title.  */
 
 void
 x_set_title (f, name, old_name)
@@ -1897,7 +1887,7 @@ x_set_scroll_bar_default_width (f)
   int wid = FRAME_COLUMN_WIDTH (f);
 
 #ifdef MAC_OSX
-  FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 16;  /* Aqua scroll bars.  */
+  FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = MAC_AQUA_VERTICAL_SCROLL_BAR_WIDTH;
   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
                                      wid - 1) / wid;
 #else /* not MAC_OSX */
@@ -1911,6 +1901,147 @@ x_set_scroll_bar_default_width (f)
 #endif /* not MAC_OSX */
 }
 
+static void
+mac_set_font (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  x_set_font (f, arg, oldval);
+#if USE_MAC_FONT_PANEL
+  {
+    Lisp_Object focus_frame = x_get_focus_frame (f);
+
+    if ((NILP (focus_frame) && f == SELECTED_FRAME ())
+       || XFRAME (focus_frame) == f)
+      {
+       BLOCK_INPUT;
+       mac_set_font_info_for_selection (f, DEFAULT_FACE_ID, 0);
+       UNBLOCK_INPUT;
+      }
+  }
+#endif
+}
+
+#if TARGET_API_MAC_CARBON
+static void
+mac_update_proxy_icon (f)
+     struct frame *f;
+{
+  OSStatus err;
+  Lisp_Object file_name =
+    XBUFFER (XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer)->filename;
+  Window w = FRAME_MAC_WINDOW (f);
+  AliasHandle alias = NULL;
+
+  BLOCK_INPUT;
+
+  err = GetWindowProxyAlias (w, &alias);
+  if (err == errWindowDoesNotHaveProxy && !STRINGP (file_name))
+    goto out;
+
+  if (STRINGP (file_name))
+    {
+      AEDesc desc;
+#ifdef MAC_OSX
+      FSRef fref, fref_proxy;
+#else
+      FSSpec fss, fss_proxy;
+#endif
+      Boolean changed;
+      Lisp_Object encoded_file_name = ENCODE_FILE (file_name);
+
+#ifdef MAC_OSX
+      err = AECoercePtr (TYPE_FILE_NAME, SDATA (encoded_file_name),
+                        SBYTES (encoded_file_name), typeFSRef, &desc);
+#else
+      SetPortWindowPort (w);
+      err = AECoercePtr (TYPE_FILE_NAME, SDATA (encoded_file_name),
+                        SBYTES (encoded_file_name), typeFSS, &desc);
+#endif
+      if (err == noErr)
+       {
+#ifdef MAC_OSX
+         err = AEGetDescData (&desc, &fref, sizeof (FSRef));
+#else
+         err = AEGetDescData (&desc, &fss, sizeof (FSSpec));
+#endif
+         AEDisposeDesc (&desc);
+       }
+      if (err == noErr)
+       {
+         if (alias)
+           {
+             /* (FS)ResolveAlias never sets `changed' to true if
+                `alias' is minimal.  */
+#ifdef MAC_OSX
+             err = FSResolveAlias (NULL, alias, &fref_proxy, &changed);
+             if (err == noErr)
+               err = FSCompareFSRefs (&fref, &fref_proxy);
+#else
+             err = ResolveAlias (NULL, alias, &fss_proxy, &changed);
+             if (err == noErr)
+               err = !(fss.vRefNum == fss_proxy.vRefNum
+                       && fss.parID == fss_proxy.parID
+                       && EqualString (fss.name, fss_proxy.name,
+                                       false, true));
+#endif
+           }
+         if (err != noErr || alias == NULL)
+           {
+             if (alias)
+               DisposeHandle ((Handle) alias);
+#ifdef MAC_OSX
+             err = FSNewAliasMinimal (&fref, &alias);
+#else
+             err = NewAliasMinimal (&fss, &alias);
+#endif
+             changed = true;
+           }
+       }
+      if (err == noErr)
+       if (changed)
+         err = SetWindowProxyAlias (w, alias);
+    }
+
+  if (alias)
+    DisposeHandle ((Handle) alias);
+
+  if (err != noErr || !STRINGP (file_name))
+    RemoveWindowProxy (w);
+
+ out:
+  UNBLOCK_INPUT;
+}
+#endif
+
+void
+mac_update_title_bar (f, save_match_data)
+     struct frame *f;
+     int save_match_data;
+{
+#if TARGET_API_MAC_CARBON
+  struct window *w;
+  int modified_p;
+
+  if (!FRAME_MAC_P (f))
+    return;
+
+  w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+  modified_p = (BUF_SAVE_MODIFF (XBUFFER (w->buffer))
+               < BUF_MODIFF (XBUFFER (w->buffer)));
+  if (windows_or_buffers_changed
+      /* Minibuffer modification status shown in the close button is
+        confusing.  */
+      || (!MINI_WINDOW_P (w)
+         && (modified_p != !NILP (w->last_had_star))))
+    {
+      SetWindowModified (FRAME_MAC_WINDOW (f),
+                        !MINI_WINDOW_P (w) && modified_p);
+      mac_update_proxy_icon (f);
+    }
+#endif
+}
+
 \f
 /* Subroutines of creating a frame.  */
 
@@ -2111,8 +2242,10 @@ mac_window (f)
 #if TARGET_API_MAC_CARBON
   CreateNewWindow (kDocumentWindowClass,
                   kWindowStandardDocumentAttributes
-                  /* | kWindowToolbarButtonAttribute */,
-                  &r, &FRAME_MAC_WINDOW (f));
+#ifdef MAC_OSX
+                  | kWindowToolbarButtonAttribute
+#endif
+                  , &r, &FRAME_MAC_WINDOW (f));
   if (FRAME_MAC_WINDOW (f))
     {
       SetWRefCon (FRAME_MAC_WINDOW (f), (long) f->output_data.mac);
@@ -2355,7 +2488,7 @@ unwind_create_frame (frame)
 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
        1, 1, 0,
        doc: /* Make a new window, which is called a "frame" in Emacs terms.
-Returns an Emacs frame object.
+Return an Emacs frame object.
 ALIST is an alist of frame parameters.
 If the parameters specify that the frame should not have a minibuffer,
 and do not specify a specific minibuffer window to use,
@@ -2378,7 +2511,6 @@ This function is an internal primitive--use `make-frame' instead.  */)
   struct mac_display_info *dpyinfo = NULL;
   Lisp_Object parent;
   struct kboard *kb;
-  static int x_frame_count = 2;  /* begins at 2 because terminal frame is F1 */
 
   check_mac ();
 
@@ -2442,7 +2574,6 @@ This function is an internal primitive--use `make-frame' instead.  */)
   f->output_data.mac = (struct mac_output *) xmalloc (sizeof (struct mac_output));
   bzero (f->output_data.mac, sizeof (struct mac_output));
   FRAME_FONTSET (f) = -1;
-  record_unwind_protect (unwind_create_frame, frame);
 
   f->icon_name
     = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
@@ -2450,6 +2581,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
     f->icon_name = Qnil;
 
 /*   FRAME_MAC_DISPLAY_INFO (f) = dpyinfo; */
+
+  /* With FRAME_MAC_DISPLAY_INFO set up, this unwind-protect is safe.  */
+  record_unwind_protect (unwind_create_frame, frame);
 #if GLYPH_DEBUG
   image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
   dpyinfo_refcount = dpyinfo->reference_count;
@@ -2522,8 +2656,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
       error ("Cannot find any usable font");
     UNBLOCK_INPUT;
 
-    x_default_parameter (f, parms, Qfont, font,
-                        "font", "Font", RES_TYPE_STRING);
+    x_set_frame_parameters (f, Fcons (Fcons (Qfont, font), Qnil));
   }
 
   x_default_parameter (f, parms, Qborder_width, make_number (0),
@@ -2704,27 +2837,45 @@ FRAME nil means use the selected frame.  */)
      (frame)
      Lisp_Object frame;
 {
+  OSErr err;
+  ProcessSerialNumber front_psn;
+  static const ProcessSerialNumber current_psn = {0, kCurrentProcess};
+  Boolean front_p;
   struct frame *f = check_x_frame (frame);
-  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
 
-  if (dpyinfo->x_focus_frame != f)
-    {
-      BLOCK_INPUT;
+  BLOCK_INPUT;
+  /* Move the current process to the foreground if it is not.  Don't
+     call SetFrontProcess if the current process is already running in
+     the foreground so as not to change the z-order of windows.  */
+  err = GetFrontProcess (&front_psn);
+  if (err == noErr)
+    err = SameProcess (&front_psn, &current_psn, &front_p);
+  if (err == noErr)
+    if (!front_p)
+      {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+       if (FrontNonFloatingWindow () == FRAME_MAC_WINDOW (f))
+         SetFrontProcessWithOptions (&current_psn,
+                                     kSetFrontProcessFrontWindowOnly);
+       else
+#endif
+         SetFrontProcess (&current_psn);
+      }
+
 #ifdef MAC_OSX
-      ActivateWindow (ActiveNonFloatingWindow (), false);
-      ActivateWindow (FRAME_MAC_WINDOW (f), true);
+  ActivateWindow (ActiveNonFloatingWindow (), false);
+  ActivateWindow (FRAME_MAC_WINDOW (f), true);
 #else
 #if !TARGET_API_MAC_CARBON
-      /* SelectWindow (Non-Carbon) does not issue deactivate events if
-        the possibly inactive window that is to be selected is
-        already the frontmost one.  */
-      SendBehind (FRAME_MAC_WINDOW (f), NULL);
+  /* SelectWindow (Non-Carbon) does not issue deactivate events if the
+     possibly inactive window that is to be selected is already the
+     frontmost one.  */
+  SendBehind (FRAME_MAC_WINDOW (f), NULL);
 #endif
-      /* This brings the window to the front.  */
-      SelectWindow (FRAME_MAC_WINDOW (f));
+  /* This brings the window to the front.  */
+  SelectWindow (FRAME_MAC_WINDOW (f));
 #endif
-      UNBLOCK_INPUT;
-    }
+  UNBLOCK_INPUT;
 
   return Qnil;
 }
@@ -2757,14 +2908,9 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
   CHECK_STRING (color);
 
   if (mac_defined_color (f, SDATA (color), &foo, 0))
-    {
-      Lisp_Object rgb[3];
-
-      rgb[0] = make_number (foo.red);
-      rgb[1] = make_number (foo.green);
-      rgb[2] = make_number (foo.blue);
-      return Flist (3, rgb);
-    }
+    return list3 (make_number (foo.red),
+                 make_number (foo.green),
+                 make_number (foo.blue));
   else
     return Qnil;
 }
@@ -2802,7 +2948,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 
 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
        0, 1, 0,
-       doc: /* Returns the width in pixels of DISPLAY.
+       doc: /* Return the width in pixels of DISPLAY.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
 If omitted or nil, that stands for the selected frame's display.  */)
@@ -2816,7 +2962,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 
 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
        Sx_display_pixel_height, 0, 1, 0,
-       doc: /* Returns the height in pixels of DISPLAY.
+       doc: /* Return the height in pixels of DISPLAY.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
 If omitted or nil, that stands for the selected frame's display.  */)
@@ -2830,7 +2976,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 
 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
        0, 1, 0,
-       doc: /* Returns the number of bitplanes of DISPLAY.
+       doc: /* Return the number of bitplanes of DISPLAY.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
 If omitted or nil, that stands for the selected frame's display.  */)
@@ -2844,7 +2990,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 
 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
        0, 1, 0,
-       doc: /* Returns the number of color cells of DISPLAY.
+       doc: /* Return the number of color cells of DISPLAY.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
 If omitted or nil, that stands for the selected frame's display.  */)
@@ -2860,7 +3006,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
        Sx_server_max_request_size,
        0, 1, 0,
-       doc: /* Returns the maximum request size of the server of DISPLAY.
+       doc: /* Return the maximum request size of the server of DISPLAY.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
 If omitted or nil, that stands for the selected frame's display.  */)
@@ -2873,18 +3019,18 @@ If omitted or nil, that stands for the selected frame's display.  */)
 }
 
 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
-       doc: /* Returns the "vendor ID" string of the Mac OS system (Apple).
+       doc: /* Return the "vendor ID" string of the Mac OS system (Apple).
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
 If omitted or nil, that stands for the selected frame's display.  */)
      (display)
      Lisp_Object display;
 {
-  return build_string ("Apple Computers");
+  return build_string ("Apple Inc.");
 }
 
 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
-       doc: /* Returns the version numbers of the Mac OS system.
+       doc: /* Return the version numbers of the Mac OS system.
 The value is a list of three integers: the major and minor
 version numbers, and the vendor-specific release
 number.  See also the function `x-server-vendor'.
@@ -2901,23 +3047,25 @@ If omitted or nil, that stands for the selected frame's display.  */)
   BLOCK_INPUT;
   err = Gestalt (gestaltSystemVersion, &response);
   if (err == noErr)
-    if (response >= 0x00001040)
-      {
-       err = Gestalt ('sys1', &major); /* gestaltSystemVersionMajor */
-       if (err == noErr)
-         err = Gestalt ('sys2', &minor); /* gestaltSystemVersionMinor */
-       if (err == noErr)
-         err = Gestalt ('sys3', &bugfix); /* gestaltSystemVersionBugFix */
-      }
-    else
-      {
-       bugfix = response & 0xf;
-       response >>= 4;
-       minor = response & 0xf;
-       response >>= 4;
-       /* convert BCD to int */
-       major = response - (response >> 4) * 6;
-      }
+    {
+      if (response >= 0x00001040)
+       {
+         err = Gestalt (gestaltSystemVersionMajor, &major);
+         if (err == noErr)
+           err = Gestalt (gestaltSystemVersionMinor, &minor);
+         if (err == noErr)
+           err = Gestalt (gestaltSystemVersionBugFix, &bugfix);
+       }
+      else
+       {
+         bugfix = response & 0xf;
+         response >>= 4;
+         minor = response & 0xf;
+         response >>= 4;
+         /* convert BCD to int */
+         major = response - (response >> 4) * 6;
+       }
+    }
   UNBLOCK_INPUT;
 
   if (err != noErr)
@@ -2948,11 +3096,33 @@ If omitted or nil, that stands for the selected frame's display.  */)
      (display)
      Lisp_Object display;
 {
-  /* MAC_TODO: this is an approximation, and only of the main display */
-
   struct mac_display_info *dpyinfo = check_x_display_info (display);
+  float mm_per_pixel;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  if (CGDisplayScreenSize != NULL)
+#endif
+    {
+      CGSize size;
 
-  return make_number ((int) (dpyinfo->height * 25.4 / dpyinfo->resy));
+      BLOCK_INPUT;
+      size = CGDisplayScreenSize (kCGDirectMainDisplay);
+      mm_per_pixel = size.height / CGDisplayPixelsHigh (kCGDirectMainDisplay);
+      UNBLOCK_INPUT;
+    }
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  else
+#endif
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030  */
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+    {
+      /* This is an approximation.  */
+      mm_per_pixel = 25.4f / dpyinfo->resy;
+    }
+#endif
+
+  return make_number ((int) (dpyinfo->height * mm_per_pixel + 0.5f));
 }
 
 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
@@ -2963,16 +3133,38 @@ If omitted or nil, that stands for the selected frame's display.  */)
      (display)
      Lisp_Object display;
 {
-  /* MAC_TODO: this is an approximation, and only of the main display */
-
   struct mac_display_info *dpyinfo = check_x_display_info (display);
+  float mm_per_pixel;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  if (CGDisplayScreenSize != NULL)
+#endif
+    {
+      CGSize size;
 
-  return make_number ((int) (dpyinfo->width * 25.4 / dpyinfo->resx));
+      BLOCK_INPUT;
+      size = CGDisplayScreenSize (kCGDirectMainDisplay);
+      mm_per_pixel = size.width / CGDisplayPixelsWide (kCGDirectMainDisplay);
+      UNBLOCK_INPUT;
+    }
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  else
+#endif
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030  */
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+    {
+      /* This is an approximation.  */
+      mm_per_pixel = 25.4f / dpyinfo->resx;
+    }
+#endif
+
+  return make_number ((int) (dpyinfo->width * mm_per_pixel + 0.5f));
 }
 
 DEFUN ("x-display-backing-store", Fx_display_backing_store,
        Sx_display_backing_store, 0, 1, 0,
-       doc: /* Returns an indication of whether DISPLAY does backing store.
+       doc: /* Return an indication of whether DISPLAY does backing store.
 The value may be `always', `when-mapped', or `not-useful'.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
@@ -2985,7 +3177,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 
 DEFUN ("x-display-visual-class", Fx_display_visual_class,
        Sx_display_visual_class, 0, 1, 0,
-       doc: /* Returns the visual class of DISPLAY.
+       doc: /* Return the visual class of DISPLAY.
 The value is one of the symbols `static-gray', `gray-scale',
 `static-color', `pseudo-color', `true-color', or `direct-color'.
 
@@ -3016,7 +3208,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 
 DEFUN ("x-display-save-under", Fx_display_save_under,
        Sx_display_save_under, 0, 1, 0,
-       doc: /* Returns t if DISPLAY supports the save-under feature.
+       doc: /* Return t if DISPLAY supports the save-under feature.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
 If omitted or nil, that stands for the selected frame's display.  */)
@@ -3201,6 +3393,14 @@ DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
   return Qnil;
 }
 
+/* x_sync is a no-op on Mac.  */
+
+void
+x_sync (f)
+     FRAME_PTR f;
+{
+}
+
 \f
 /***********************************************************************
                            Window properties
@@ -3453,6 +3653,9 @@ show_hourglass (timer)
          if (FRAME_LIVE_P (f) && FRAME_MAC_P (f)
              && FRAME_MAC_WINDOW (f) != tip_window)
            {
+#if USE_CG_DRAWING
+             mac_prepare_for_quickdraw (f);
+#endif
              if (!f->output_data.mac->hourglass_control)
                {
                  Window w = FRAME_MAC_WINDOW (f);
@@ -3497,7 +3700,12 @@ hide_hourglass ()
          if (FRAME_MAC_P (f)
              /* Watch out for newly created frames.  */
              && f->output_data.mac->hourglass_control)
-           HideControl (f->output_data.mac->hourglass_control);
+           {
+#if USE_CG_DRAWING
+             mac_prepare_for_quickdraw (f);
+#endif
+             HideControl (f->output_data.mac->hourglass_control);
+           }
        }
 
       hourglass_shown_p = 0;
@@ -3582,6 +3790,7 @@ x_create_tip_frame (dpyinfo, parms, text)
 
   check_mac ();
 
+  parms = Fcopy_alist (parms);
 
 #ifdef MULTI_KBOARD
   kb = dpyinfo->kboard;
@@ -3900,6 +4109,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
        doc: /* Show STRING in a "tooltip" window on frame FRAME.
 A tooltip window is a small window displaying a string.
 
+This is an internal function; Lisp code should call `tooltip-show'.
+
 FRAME nil or omitted means use the selected frame.
 
 PARMS is an optional list of frame parameters which can be used to
@@ -4172,14 +4383,14 @@ If ONLY-DIR-P is non-nil, the user can only select directories.  */)
      (prompt, dir, default_filename, mustmatch, only_dir_p)
      Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
 {
-  struct frame *f = SELECTED_FRAME ();
   Lisp_Object file = Qnil;
   int count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
   char filename[MAXPATHLEN];
-  int default_filter_index = 1; /* 1: All Files, 2: Directories only  */
   static NavEventUPP mac_nav_event_callbackUPP = NULL;
 
+  check_mac ();
+
   GCPRO6 (prompt, dir, default_filename, mustmatch, file, only_dir_p);
   CHECK_STRING (prompt);
   CHECK_STRING (dir);
@@ -4302,7 +4513,7 @@ If ONLY-DIR-P is non-nil, the user can only select directories.  */)
                      filename[len++] = '/';
                    CFStringGetCString(reply.saveFileName, filename+len,
                                       sizeof (filename) - len,
-#if MAC_OSX
+#ifdef MAC_OSX
                                       kCFStringEncodingUTF8
 #else
                                       CFStringGetSystemEncoding ()
@@ -4348,6 +4559,77 @@ mac_nav_event_callback (selector, parms, data)
 {
 }
 #endif
+\f
+/***********************************************************************
+                               Fonts
+ ***********************************************************************/
+
+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;
+}
+
+#if USE_MAC_FONT_PANEL
+DEFUN ("mac-set-font-panel-visible-p", Fmac_set_font_panel_visible_p,
+       Smac_set_font_panel_visible_p, 1, 1, 0,
+  doc: /* Make the font panel visible if and only if FLAG is non-nil.
+This is for internal use only.  Use `mac-font-panel-mode' instead.  */)
+     (flag)
+     Lisp_Object flag;
+{
+  OSStatus err = noErr;
+
+  check_mac ();
+
+  BLOCK_INPUT;
+  if (NILP (flag) != !mac_font_panel_visible_p ())
+    {
+      err = mac_show_hide_font_panel ();
+      if (err == noErr && !NILP (flag))
+       {
+         Lisp_Object focus_frame = x_get_focus_frame (SELECTED_FRAME ());
+         struct frame *f = (NILP (focus_frame) ? SELECTED_FRAME ()
+                            : XFRAME (focus_frame));
+
+         mac_set_font_info_for_selection (f, DEFAULT_FACE_ID, 0);
+       }
+    }
+  UNBLOCK_INPUT;
+
+  if (err != noErr)
+    error ("Cannot change visibility of the font panel");
+  return Qnil;
+}
+#endif
+
+#if USE_ATSUI
+extern Lisp_Object mac_atsu_font_face_attributes P_ ((ATSUFontID));
+
+DEFUN ("mac-atsu-font-face-attributes", Fmac_atsu_font_face_attributes,
+       Smac_atsu_font_face_attributes, 1, 1, 0,
+  doc: /* Return plist of face attributes and values for ATSU font ID.
+ID is specified by either an integer or a float.  */)
+     (id)
+     Lisp_Object id;
+{
+  ATSUFontID font_id;
+  Lisp_Object result;
+
+  check_mac ();
+  CHECK_NUMBER_OR_FLOAT (id);
+  font_id = INTEGERP (id) ? XINT (id) : XFLOAT_DATA (id);
+  BLOCK_INPUT;
+  result = mac_atsu_font_face_attributes (font_id);
+  UNBLOCK_INPUT;
+  return result;
+}
+#endif
+
 \f
 /***********************************************************************
                            Initialization
@@ -4365,7 +4647,7 @@ frame_parm_handler mac_frame_parm_handlers[] =
   x_set_border_width,
   x_set_cursor_color,
   x_set_cursor_type,
-  x_set_font,
+  mac_set_font,
   x_set_foreground_color,
   x_set_icon_name,
   0, /* MAC_TODO: x_set_icon_type, */
@@ -4501,6 +4783,22 @@ such a font.  This is especially effective for such large fonts as
 Chinese, Japanese, and Korean.  */);
   Vx_pixel_size_width_font_regexp = Qnil;
 
+#if TARGET_API_MAC_CARBON
+  DEFVAR_LISP ("mac-carbon-version-string", &Vmac_carbon_version_string,
+    doc: /* Version info for Carbon API.  */);
+  {
+    OSErr err;
+    UInt32 response;
+    char carbon_version[16] = "Unknown";
+
+    err = Gestalt (gestaltCarbonVersion, &response);
+    if (err == noErr)
+      sprintf (carbon_version, "%u.%u.%u",
+              (response >> 8) & 0xf, (response >> 4) & 0xf, response & 0xf);
+    Vmac_carbon_version_string = build_string (carbon_version);
+  }
+#endif /* TARGET_API_MAC_CARBON */
+
   /* X window properties.  */
   defsubr (&Sx_change_window_property);
   defsubr (&Sx_delete_window_property);
@@ -4541,7 +4839,7 @@ Chinese, Japanese, and Korean.  */);
   load_font_func = x_load_font;
   find_ccl_program_func = x_find_ccl_program;
   query_font_func = x_query_font;
-  set_frame_fontset_func = x_set_font;
+  set_frame_fontset_func = mac_set_font;
   check_window_system_func = check_mac;
 
   hourglass_atimer = NULL;
@@ -4559,6 +4857,13 @@ Chinese, Japanese, and Korean.  */);
 
 #if TARGET_API_MAC_CARBON
   defsubr (&Sx_file_dialog);
+#endif
+  defsubr (&Smac_clear_font_name_table);
+#if USE_MAC_FONT_PANEL
+  defsubr (&Smac_set_font_panel_visible_p);
+#endif
+#if USE_ATSUI
+  defsubr (&Smac_atsu_font_face_attributes);
 #endif
 }