]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
(try_window): Revert previous change.
[gnu-emacs] / src / macterm.c
index 97a87cd3d3aa70ce366e05f1593c963d48beecdb..ff94a67d3f1eb58b4a236ce68f405e93d2272e9e 100644 (file)
@@ -1,6 +1,6 @@
 /* Implementation of GUI terminal 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.
 
@@ -270,16 +270,63 @@ static void XSetFont P_ ((Display *, GC, XFontStruct *));
 #define GC_BACK_COLOR(gc)      (&(gc)->back_color)
 #define GC_FONT(gc)            ((gc)->xgcv.font)
 #define FRAME_NORMAL_GC(f)     ((f)->output_data.mac->normal_gc)
-#define CG_SET_FILL_COLOR(context, color)                      \
+
+#define CG_SET_FILL_COLOR(context, color)                              \
   CGContextSetRGBFillColor (context,                                   \
                            RED_FROM_ULONG (color) / 255.0f,            \
                            GREEN_FROM_ULONG (color) / 255.0f,          \
                            BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
-#define CG_SET_STROKE_COLOR(context, color)            \
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  do {                                                                \
+    if (CGColorGetTypeID != NULL)                                     \
+      CGContextSetFillColorWithColor (context, cg_color);             \
+    else                                                              \
+      CG_SET_FILL_COLOR (context, color);                             \
+  } while (0)
+#else
+#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  CGContextSetFillColorWithColor (context, cg_color)
+#endif
+#else
+#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  CG_SET_FILL_COLOR (context, color)
+#endif
+#define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc)              \
+  CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground,        \
+                                       (gc)->cg_fore_color)
+#define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc)              \
+  CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background,        \
+                                       (gc)->cg_back_color)
+
+
+#define CG_SET_STROKE_COLOR(context, color)                            \
   CGContextSetRGBStrokeColor (context,                                 \
                              RED_FROM_ULONG (color) / 255.0f,          \
                              GREEN_FROM_ULONG (color) / 255.0f,        \
                              BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  do {                                                                \
+    if (CGColorGetTypeID != NULL)                                     \
+      CGContextSetStrokeColorWithColor (context, cg_color);           \
+    else                                                              \
+      CG_SET_STROKE_COLOR (context, color);                           \
+  } while (0)
+#else
+#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  CGContextSetStrokeColorWithColor (context, cg_color)
+#endif
+#else
+#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  CG_SET_STROKE_COLOR (context, color)
+#endif
+#define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
+  CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
+                                         (gc)->cg_fore_color)
+
 #if USE_CG_DRAWING
 #define FRAME_CG_CONTEXT(f)    ((f)->output_data.mac->cg_context)
 
@@ -288,6 +335,29 @@ static void XSetFont P_ ((Display *, GC, XFontStruct *));
 static int max_fringe_bmp = 0;
 static CGImageRef *fringe_bmp = 0;
 
+static CGColorSpaceRef mac_cg_color_space_rgb;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+static CGColorRef mac_cg_color_black;
+#endif
+
+static void
+init_cg_color ()
+{
+  mac_cg_color_space_rgb = CGColorSpaceCreateDeviceRGB ();
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  /* Don't check the availability of CGColorCreate; this symbol is
+     defined even in Mac OS X 10.1.  */
+  if (CGColorGetTypeID != NULL)
+#endif
+    {
+      float rgba[] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+      mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba);
+    }
+#endif
+}
+
 static CGContextRef
 mac_begin_cg_clip (f, gc)
      struct frame *f;
@@ -401,7 +471,7 @@ mac_draw_line (f, gc, x1, y1, x2, y2)
     gy1 += 0.5f, gy2 += 0.5f;
 
   context = mac_begin_cg_clip (f, gc);
-  CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+  CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
   CGContextBeginPath (context);
   CGContextMoveToPoint (context, gx1, gy1);
   CGContextAddLineToPoint (context, gx2, gy2);
@@ -435,8 +505,10 @@ mac_draw_line (f, gc, x1, y1, x2, y2)
 #endif
 }
 
+/* Mac version of XDrawLine (to Pixmap).  */
+
 void
-mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
+XDrawLine (display, p, gc, x1, y1, x2, y2)
      Display *display;
      Pixmap p;
      GC gc;
@@ -485,7 +557,7 @@ mac_erase_rectangle (f, gc, x, y, width, height)
   CGContextRef context;
 
   context = mac_begin_cg_clip (f, gc);
-  CG_SET_FILL_COLOR (context, gc->xgcv.background);
+  CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
   CGContextFillRect (context, CGRectMake (x, y, width, height));
   mac_end_cg_clip (f);
 #else
@@ -527,7 +599,7 @@ mac_clear_window (f)
   GC gc = FRAME_NORMAL_GC (f);
 
   context = mac_begin_cg_clip (f, NULL);
-  CG_SET_FILL_COLOR (context, gc->xgcv.background);
+  CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
   CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
                                          FRAME_PIXEL_HEIGHT (f)));
   mac_end_cg_clip (f);
@@ -570,14 +642,14 @@ mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
   context = mac_begin_cg_clip (f, gc);
   if (!overlay_p)
     {
-      CG_SET_FILL_COLOR (context, gc->xgcv.background);
+      CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
       CGContextFillRect (context, dest_rect);
     }
   CGContextClipToRect (context, dest_rect);
   CGContextScaleCTM (context, 1, -1);
   CGContextTranslateCTM (context, 0, -port_height);
   if (CGImageIsMask (image))
-    CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+    CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
   CGContextDrawImage (context,
                      CGRectMake (dest_x - src_x,
                                  port_height - (dest_y - src_y
@@ -764,7 +836,7 @@ mac_fill_rectangle (f, gc, x, y, width, height)
   CGContextRef context;
 
   context = mac_begin_cg_clip (f, gc);
-  CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
   CGContextFillRect (context, CGRectMake (x, y, width, height));
   mac_end_cg_clip (f);
 #else
@@ -795,7 +867,7 @@ mac_draw_rectangle (f, gc, x, y, width, height)
   CGContextRef context;
 
   context = mac_begin_cg_clip (f, gc);
-  CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+  CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
   CGContextStrokeRect (context,
                       CGRectMake (x + 0.5f, y + 0.5f, width, height));
   mac_end_cg_clip (f);
@@ -982,7 +1054,7 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
 #endif
              if (bg_width)
                {
-                 CG_SET_FILL_COLOR (context, gc->xgcv.background);
+                 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
                  CGContextFillRect
                    (context,
                     CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
@@ -993,7 +1065,7 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
 #if !USE_CG_DRAWING
            }
 #endif
-         CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+         CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
          err = ATSUSetLayoutControls (text_layout,
                                       sizeof (tags) / sizeof (tags[0]),
                                       tags, sizes, values);
@@ -1154,7 +1226,8 @@ mac_query_char_extents (style, c,
       UniChar ch = c;
 
       err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
-      if (err == noErr)
+      if (err == noErr
+         && (font_ascent_return || font_descent_return || overall_return))
        {
          ATSTrapezoid glyph_bounds;
 
@@ -1343,7 +1416,7 @@ mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
 #endif
       if (bg_width)
        {
-         CG_SET_FILL_COLOR (context, gc->xgcv.background);
+         CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
          CGContextFillRect
            (context,
             CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
@@ -1354,26 +1427,37 @@ mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
 #if !USE_CG_DRAWING
     }
 #endif
-  CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
   CGContextSetFont (context, GC_FONT (gc)->cg_font);
   CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
   if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
     CGContextSetShouldAntialias (context, false);
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
-  CGContextSetTextPosition (context, gx, gy);
-  CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
-  if (overstrike_p)
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  if (CGContextShowGlyphsWithAdvances != NULL)
+#endif
     {
-      CGContextSetTextPosition (context, gx + 1.0f, gy);
+      CGContextSetTextPosition (context, gx, gy);
       CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
+      if (overstrike_p)
+       {
+         CGContextSetTextPosition (context, gx + 1.0f, gy);
+         CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
+       }
     }
-#else
-  for (i = 0; i < nchars; i++)
+#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
     {
-      CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
-      if (overstrike_p)
-       CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
-      gx += advances[i].width;
+      for (i = 0; i < nchars; i++)
+       {
+         CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
+         if (overstrike_p)
+           CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
+         gx += advances[i].width;
+       }
     }
 #endif
 #if USE_CG_DRAWING
@@ -1546,15 +1630,25 @@ XChangeGC (display, gc, mask, xgcv)
 /* Mac replacement for XCreateGC.  */
 
 GC
-XCreateGC (display, window, mask, xgcv)
+XCreateGC (display, d, mask, xgcv)
      Display *display;
-     Window window;
+     void *d;
      unsigned long mask;
      XGCValues *xgcv;
 {
   GC gc = xmalloc (sizeof (*gc));
 
   bzero (gc, sizeof (*gc));
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  if (CGColorGetTypeID != NULL)
+#endif
+    {
+      gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
+      CGColorRetain (gc->cg_fore_color);
+      CGColorRetain (gc->cg_back_color);
+    }
+#endif
   XChangeGC (display, gc, mask, xgcv);
 
   return gc;
@@ -1570,6 +1664,15 @@ XFreeGC (display, gc)
 {
   if (gc->clip_region)
     DisposeRgn (gc->clip_region);
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  if (CGColorGetTypeID != NULL)
+#endif
+    {
+      CGColorRelease (gc->cg_fore_color);
+      CGColorRelease (gc->cg_back_color);
+    }
+#endif
   xfree (gc);
 }
 
@@ -1606,6 +1709,29 @@ XSetForeground (display, gc, color)
       gc->fore_color.red = RED16_FROM_ULONG (color);
       gc->fore_color.green = GREEN16_FROM_ULONG (color);
       gc->fore_color.blue = BLUE16_FROM_ULONG (color);
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+      if (CGColorGetTypeID != NULL)
+#endif
+       {
+         CGColorRelease (gc->cg_fore_color);
+         if (color == 0)
+           {
+             gc->cg_fore_color = mac_cg_color_black;
+             CGColorRetain (gc->cg_fore_color);
+           }
+         else
+           {
+             float rgba[4];
+
+             rgba[0] = gc->fore_color.red / 65535.0f;
+             rgba[1] = gc->fore_color.green / 65535.0f;
+             rgba[2] = gc->fore_color.blue / 65535.0f;
+             rgba[3] = 1.0f;
+             gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
+           }
+       }
+#endif
     }
 }
 
@@ -1624,6 +1750,29 @@ XSetBackground (display, gc, color)
       gc->back_color.red = RED16_FROM_ULONG (color);
       gc->back_color.green = GREEN16_FROM_ULONG (color);
       gc->back_color.blue = BLUE16_FROM_ULONG (color);
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+      if (CGColorGetTypeID != NULL)
+#endif
+       {
+         CGColorRelease (gc->cg_back_color);
+         if (color == 0)
+           {
+             gc->cg_back_color = mac_cg_color_black;
+             CGColorRetain (gc->cg_back_color);
+           }
+         else
+           {
+             float rgba[4];
+
+             rgba[0] = gc->back_color.red / 65535.0f;
+             rgba[1] = gc->back_color.green / 65535.0f;
+             rgba[2] = gc->back_color.blue / 65535.0f;
+             rgba[3] = 1.0f;
+             gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
+           }
+       }
+#endif
     }
 }
 
@@ -6423,6 +6572,9 @@ x_free_frame_resources (f)
   if (wp != tip_window)
     remove_window_handler (wp);
 
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   DisposeWindow (wp);
   if (wp == tip_window)
     /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
@@ -6976,7 +7128,6 @@ static Lisp_Object fm_font_family_alist;
 static Lisp_Object atsu_font_id_hash;
 /* Alist linking Font Manager style to face attributes.  */
 static Lisp_Object fm_style_face_attributes_alist;
-static Lisp_Object Vmac_atsu_font_table;
 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
 #endif
 
@@ -7213,6 +7364,73 @@ add_mac_font_name (name, size, style, charset)
 }
 
 #if USE_ATSUI
+static FMFontStyle
+fm_get_style_from_font (font)
+     FMFont font;
+{
+  OSStatus err;
+  FMFontStyle style = normal;
+  ByteCount len;
+  UInt16 mac_style;
+  FMFontFamily font_family;
+#define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
+
+  /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
+     some font (e.g., Optima) even if it is `bold'.  */
+  err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
+                       sizeof (mac_style), &mac_style, &len);
+  if (err == noErr
+      && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
+    style = EndianU16_BtoN (mac_style);
+  else
+    FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
+
+  return style;
+}
+
+static ATSUFontID
+atsu_find_font_from_family_name (family)
+     const char *family;
+{
+  struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
+  unsigned hash_code;
+  int i;
+  Lisp_Object rest, best;
+  FMFontStyle min_style, style;
+
+  i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
+                  &hash_code);
+  if (i < 0)
+    return kATSUInvalidFontID;
+
+  rest = HASH_VALUE (h, i);
+  if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
+    return cons_to_long (rest);
+
+  rest = Fnreverse (rest);
+  best = XCAR (rest);
+  rest = XCDR (rest);
+  if (!NILP (rest)
+      && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
+    do
+      {
+       style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
+       if (style < min_style)
+         {
+           best = XCAR (rest);
+           if (style == normal)
+             break;
+           else
+             min_style = style;
+         }
+       rest = XCDR (rest);
+      }
+    while (!NILP (rest));
+
+  HASH_VALUE (h, i) = best;
+  return cons_to_long (best);
+}
+
 static Lisp_Object
 fm_style_to_face_attributes (fm_style)
      FMFontStyle fm_style;
@@ -7233,6 +7451,44 @@ fm_style_to_face_attributes (fm_style)
 
   return tem;
 }
+
+static Lisp_Object
+atsu_find_font_family_name (font_id)
+     ATSUFontID font_id;
+{
+  OSStatus err;
+  ByteCount len;
+  Lisp_Object family = Qnil;
+
+  err = ATSUFindFontName (font_id, kFontFamilyName,
+                         kFontMacintoshPlatform, kFontNoScript,
+                         kFontNoLanguage, 0, NULL, &len, NULL);
+  if (err == noErr)
+    {
+      family = make_uninit_string (len);
+      err = ATSUFindFontName (font_id, kFontFamilyName,
+                             kFontMacintoshPlatform, kFontNoScript,
+                             kFontNoLanguage, len, SDATA (family),
+                             NULL, NULL);
+    }
+  if (err == noErr)
+    decode_mac_font_name (SDATA (family), len + 1, Qnil);
+
+  return family;
+}
+
+Lisp_Object
+mac_atsu_font_face_attributes (font_id)
+     ATSUFontID font_id;
+{
+  Lisp_Object family, style_attrs;
+
+  family = atsu_find_font_family_name (font_id);
+  if (NILP (family))
+    return Qnil;
+  style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
+  return Fcons (QCfamily, Fcons (family, style_attrs));
+}
 #endif
 
 /* Sets up the table font_name_table to contain the list of all fonts
@@ -7264,9 +7520,8 @@ init_font_name_table ()
       unsigned hash_code;
       ItemCount nfonts, i;
       ATSUFontID *font_ids = NULL;
-      Ptr name;
-      ByteCount name_len;
-      Lisp_Object family;
+      Lisp_Object prev_family = Qnil;
+      int j;
 
       atsu_font_id_hash =
        make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
@@ -7284,41 +7539,25 @@ init_font_name_table ()
       if (err == noErr)
        for (i = 0; i < nfonts; i++)
          {
-           err = ATSUFindFontName (font_ids[i], kFontFamilyName,
-                                   kFontMacintoshPlatform, kFontNoScript,
-                                   kFontNoLanguage, 0, NULL, &name_len, NULL);
-           if (err != noErr)
+           Lisp_Object family;
+
+           family = atsu_find_font_family_name (font_ids[i]);
+           if (NILP (family) || SREF (family, 0) == '.')
              continue;
-           name = xmalloc (name_len + 1);
-           name[name_len] = '\0';
-           err = ATSUFindFontName (font_ids[i], kFontFamilyName,
-                                   kFontMacintoshPlatform, kFontNoScript,
-                                   kFontNoLanguage, name_len, name,
-                                   NULL, NULL);
-           if (err == noErr)
+           if (!NILP (Fequal (prev_family, family)))
+             family = prev_family;
+           else
+             j = hash_lookup (h, family, &hash_code);
+           if (j < 0)
              {
-               FMFontFamily ff;
-               FMFontStyle style = normal;
-
-               decode_mac_font_name (name, name_len + 1, Qnil);
-               family = make_unibyte_string (name, name_len);
-               FMGetFontFamilyInstanceFromFont (font_ids[i], &ff, &style);
-               Fputhash ((font_ids[i] > MOST_POSITIVE_FIXNUM
-                          ? make_float (font_ids[i])
-                          : make_number (font_ids[i])),
-                         Fcons (QCfamily,
-                                Fcons (family,
-                                       fm_style_to_face_attributes (style))),
-                         Vmac_atsu_font_table);
-               if (*name != '.'
-                   && hash_lookup (h, family, &hash_code) < 0)
-                 {
-                   add_mac_font_name (name, 0, normal, "iso10646-1");
-                   hash_put (h, family, long_to_cons (font_ids[i]),
-                             hash_code);
-                 }
+               add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
+               j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
+                                               Qnil), hash_code);
              }
-           xfree (name);
+           else if (EQ (prev_family, family))
+             HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
+                                        HASH_VALUE (h, j));
+           prev_family = family;
          }
       if (font_ids)
        xfree (font_ids);
@@ -7862,14 +8101,11 @@ mac_load_query_font (f, fontname)
        {kAllTypographicFeaturesType, kDiacriticsType};
       static const ATSUFontFeatureSelector selectors[] =
        {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
-      Lisp_Object font_id_cons;
       FMFontStyle style;
 
-      font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
-                              atsu_font_id_hash, Qnil);
-      if (NILP (font_id_cons))
-       return NULL;
-      font_id = cons_to_long (font_id_cons);
+      font_id = atsu_find_font_from_family_name (family);
+      if (font_id == kATSUInvalidFontID)
+       return;
       size_fixed = Long2Fix (size);
       bold_p = (fontface & bold) != 0;
       italic_p = (fontface & italic) != 0;
@@ -7993,11 +8229,19 @@ mac_load_query_font (f, fontname)
            continue;
          else if (c == 0x7f)
            {
-             c = 0x9f;
-             continue;
+#if USE_CG_TEXT_DRAWING
+             if (font->cg_glyphs)
+               {
+                 c = 0x9f;
+                 pcm = NULL;
+                 continue;
+               }
+#endif
+             break;
            }
 
-         mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c,
+         mac_query_char_extents (font->mac_style, c, NULL, NULL,
+                                 pcm ? pcm + c : NULL,
 #if USE_CG_TEXT_DRAWING
                                  (font->cg_glyphs ? font->cg_glyphs + c
                                   : NULL)
@@ -8015,6 +8259,8 @@ mac_load_query_font (f, fontname)
              font->cg_font = NULL;
              xfree (font->cg_glyphs);
              font->cg_glyphs = NULL;
+             if (pcm == NULL)
+               break;
            }
 #endif
        }
@@ -8022,6 +8268,7 @@ mac_load_query_font (f, fontname)
   else
 #endif
     {
+      OSStatus err;
       FontInfo the_fontinfo;
       int is_two_byte_font;
 
@@ -8104,8 +8351,13 @@ mac_load_query_font (f, fontname)
                 sizeof (XCharStruct) * (0xff - 0x20 + 1));
 
          space_bounds = font->bounds.per_char;
-         mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent,
-                                 space_bounds, NULL);
+         err = mac_query_char_extents (NULL, 0x20, &font->ascent,
+                                       &font->descent, space_bounds, NULL);
+         if (err != noErr || space_bounds->width <= 0)
+           {
+             mac_unload_font (&one_mac_display_info, font);
+             return NULL;
+           }
 
          for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
            mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
@@ -8626,14 +8878,18 @@ extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
 extern OSErr init_coercion_handler P_ ((void));
 
 /* Drag and Drop */
-OSErr install_drag_handler P_ ((WindowRef));
-void remove_drag_handler P_ ((WindowRef));
+extern OSErr install_drag_handler P_ ((WindowRef));
+extern void remove_drag_handler P_ ((WindowRef));
+
+/* Showing help echo string during menu tracking  */
+extern OSStatus install_menu_target_item_handler P_ ((WindowPtr));
 
 #if USE_CARBON_EVENTS
 #ifdef MAC_OSX
 extern void init_service_handler ();
 static Lisp_Object Qservice, Qpaste, Qperform;
 #endif
+
 /* Window Event Handler */
 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
                                                EventRef, void *);
@@ -8721,7 +8977,7 @@ static const unsigned char fn_keycode_to_keycode_table[] = {
 };
 #endif /* MAC_OSX */
 
-static unsigned int
+static int
 #if USE_CARBON_EVENTS
 mac_to_emacs_modifiers (UInt32 mods)
 #else
@@ -8768,6 +9024,23 @@ mac_to_emacs_modifiers (EventModifiers mods)
   return result;
 }
 
+static UInt32
+mac_mapped_modifiers (modifiers)
+     UInt32 modifiers;
+{
+  UInt32 mapped_modifiers_all =
+    (NILP (Vmac_control_modifier) ? 0 : controlKey)
+    | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+    | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
+
+#ifdef MAC_OSX
+  mapped_modifiers_all |=
+    (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
+#endif
+
+  return mapped_modifiers_all & modifiers;
+}
+
 static int
 mac_get_emulated_btn ( UInt32 modifiers )
 {
@@ -8782,10 +9055,42 @@ mac_get_emulated_btn ( UInt32 modifiers )
   return result;
 }
 
+#if TARGET_API_MAC_CARBON
+/***** Code to handle C-g testing  *****/
+extern int quit_char;
+extern int make_ctrl_char P_ ((int));
+
+int
+mac_quit_char_key_p (modifiers, key_code)
+     UInt32 modifiers, key_code;
+{
+  UInt32 char_code;
+  unsigned long some_state = 0;
+  Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+  int c, emacs_modifiers;
+
+  /* Mask off modifier keys that are mapped to some Emacs modifiers.  */
+  key_code |= (modifiers & ~(mac_mapped_modifiers (modifiers)));
+  char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
+  if (char_code & ~0xff)
+    return 0;
+
+  emacs_modifiers = mac_to_emacs_modifiers (modifiers);
+  if (emacs_modifiers & ctrl_modifier)
+    c = make_ctrl_char (char_code);
+
+  c |= (emacs_modifiers
+       & (meta_modifier | alt_modifier
+          | hyper_modifier | super_modifier));
+
+  return c == quit_char;
+}
+#endif
+
 #if USE_CARBON_EVENTS
 /* Obtains the event modifiers from the event ref and then calls
    mac_to_emacs_modifiers.  */
-static UInt32
+static int
 mac_event_to_emacs_modifiers (EventRef eventRef)
 {
   UInt32 mods = 0;
@@ -9010,6 +9315,9 @@ do_window_update (WindowPtr win)
          GetPortVisibleRegion (GetWindowPort (win), region);
          GetRegionBounds (region, &r);
          expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
+#endif
          UpdateControls (win, region);
          DisposeRgn (region);
 #else
@@ -9354,9 +9662,7 @@ mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
            {
              mac_store_apple_event (class_key, id_key, &apple_event);
              AEDisposeDesc (&apple_event);
-             /* Post a harmless event so as to wake up from
-                ReceiveNextEvent.  */
-             mac_post_mouse_moved_event ();
+             mac_wakeup_from_rne ();
            }
        }
     }
@@ -9823,21 +10129,10 @@ mac_handle_text_input_event (next_handler, event, data)
          err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
                                   typeUInt32, NULL,
                                   sizeof (UInt32), NULL, &modifiers);
-       if (err == noErr)
-         {
-           mapped_modifiers =
-             (NILP (Vmac_control_modifier) ? 0 : controlKey)
-             | (NILP (Vmac_option_modifier) ? 0 : optionKey)
-             | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
-#ifdef MAC_OSX
-           mapped_modifiers |=
-             (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
-#endif
-           if (modifiers & mapped_modifiers)
-             /* There're mapped modifier keys.  Process it in
-                XTread_socket.  */
-             return eventNotHandledErr;
-         }
+       if (err == noErr && mac_mapped_modifiers (modifiers))
+         /* There're mapped modifier keys.  Process it in
+            XTread_socket.  */
+         return eventNotHandledErr;
        if (err == noErr)
          err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
                                   typeUnicodeText, NULL, 0, &actual_size,
@@ -10058,6 +10353,8 @@ install_window_handler (window)
 #endif
   if (err == noErr)
     err = install_drag_handler (window);
+  if (err == noErr)
+    err = install_menu_target_item_handler (window);
 
   return err;
 }
@@ -10105,7 +10402,7 @@ main (void)
 
 #if __MWERKS__
   /* set creator and type for files created by MSL */
-  _fcreator = 'EMAx';
+  _fcreator = MAC_EMACS_CREATOR_CODE;
   _ftype = 'TEXT';
 #endif
 
@@ -10393,7 +10690,9 @@ XTread_socket (sd, expected, hold_quit)
 #else
                    FrontWindow ()
 #endif
-                   != window_ptr)
+                   != window_ptr
+                   || (mac_window_to_frame (window_ptr)
+                       != dpyinfo->x_focus_frame))
                  SelectWindow (window_ptr);
                else
                  {
@@ -10784,20 +11083,12 @@ XTread_socket (sd, expected, hold_quit)
            SInt16 current_key_script;
            UInt32 modifiers = er.modifiers, mapped_modifiers;
 
-           mapped_modifiers =
-             (NILP (Vmac_control_modifier) ? 0 : controlKey)
-             | (NILP (Vmac_option_modifier) ? 0 : optionKey)
-             | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
-
 #if USE_CARBON_EVENTS && defined (MAC_OSX)
-           mapped_modifiers |=
-             (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
-
            GetEventParameter (eventRef, kEventParamKeyModifiers,
                               typeUInt32, NULL,
                               sizeof (UInt32), NULL, &modifiers);
 #endif
-           mapped_modifiers &= modifiers;
+           mapped_modifiers = mac_mapped_modifiers (modifiers);
 
 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
            /* When using Carbon Events, we need to pass raw keyboard
@@ -11350,35 +11641,6 @@ x_delete_display (dpyinfo)
 
 \f
 #ifdef MAC_OSX
-void
-mac_check_bundle()
-{
-  extern int inhibit_window_system;
-  extern int noninteractive;
-  CFBundleRef appsBundle;
-
-  /* No need to test if already -nw*/
-  if (inhibit_window_system || noninteractive)
-    return;
-
-  appsBundle = CFBundleGetMainBundle();
-  if (appsBundle != NULL)
-    {
-      CFStringRef cfBI = CFSTR("CFBundleIdentifier");
-      CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
-      /* We found the bundle identifier, now we know we are valid. */
-      if (res != NULL)
-       {
-         CFRelease(res);
-         return;
-       }
-    }
-  /* MAC_TODO:  Have this start the bundled executable */
-
-  /* For now, prevent the fatal error by bringing it up in the terminal */
-  inhibit_window_system = 1;
-}
-
 void
 MakeMeTheFrontProcess ()
 {
@@ -11389,37 +11651,6 @@ MakeMeTheFrontProcess ()
   if (err == noErr)
     (void) SetFrontProcess (&psn);
 }
-
-/***** Code to handle C-g testing  *****/
-
-/* Contains the Mac modifier formed from quit_char */
-int mac_quit_char_modifiers = 0;
-int mac_quit_char_keycode;
-extern int quit_char;
-
-static void
-mac_determine_quit_char_modifiers()
-{
-  /* Todo: Determine modifiers from quit_char. */
-  UInt32 qc_modifiers = ctrl_modifier;
-
-  /* Map modifiers */
-  mac_quit_char_modifiers = 0;
-  if (qc_modifiers & ctrl_modifier)  mac_quit_char_modifiers |= controlKey;
-  if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey;
-  if (qc_modifiers & alt_modifier)   mac_quit_char_modifiers |= optionKey;
-}
-
-static void
-init_quit_char_handler ()
-{
-  /* TODO: Let this support keys other the 'g' */
-  mac_quit_char_keycode = 5;
-  /* Look at <architecture/adb_kb_map.h> for details */
-  /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
-
-  mac_determine_quit_char_modifiers();
-}
 #endif /* MAC_OSX */
 
 static void
@@ -11555,8 +11786,6 @@ mac_initialize ()
 #if USE_CARBON_EVENTS
 #ifdef MAC_OSX
   init_service_handler ();
-
-  init_quit_char_handler ();
 #endif /* MAC_OSX */
 
   init_command_handler ();
@@ -11579,6 +11808,8 @@ mac_initialize ()
 #endif
 
 #if USE_CG_DRAWING
+  init_cg_color ();
+
   mac_init_fringe ();
 #endif
 
@@ -11665,7 +11896,7 @@ syms_of_macterm ()
   DEFVAR_BOOL ("x-use-underline-position-properties",
               &x_use_underline_position_properties,
      doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
-nil means ignore them.  If you encounter fonts with bogus
+A value of nil means ignore them.  If you encounter fonts with bogus
 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
 to 4.1, set this to nil.
 
@@ -11675,9 +11906,9 @@ NOTE: Not supported on Mac yet.  */);
   DEFVAR_BOOL ("x-underline-at-descent-line",
               &x_underline_at_descent_line,
      doc: /* *Non-nil means to draw the underline at the same place as the descent line.
-nil means to draw the underline according to the value of the variable
-`x-use-underline-position-properties', which is usually at the baseline
-level.  The default value is nil.  */);
+A value of nil means to draw the underline according to the value of the
+variable `x-use-underline-position-properties', which is usually at the
+baseline level.  The default value is nil.  */);
   x_underline_at_descent_line = 0;
 
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
@@ -11724,8 +11955,8 @@ unexpected results for some keys on non-US/GB keyboards.  */);
               &Vmac_emulate_three_button_mouse,
     doc: /* *Specify a way of three button mouse emulation.
 The value can be nil, t, or the symbol `reverse'.
-nil means that no emulation should be done and the modifiers should be
-placed on the mouse-1 event.
+A value of nil means that no emulation should be done and the modifiers
+should be placed on the mouse-1 event.
 t means that when the option-key is held down while pressing the mouse
 button, the click will register as mouse-2 and while the command-key
 is held down, the click will register as mouse-3.
@@ -11776,15 +12007,6 @@ CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING.  */);
     Fcons (list3 (build_string ("mac-roman"),
                  make_number (smRoman), Qnil), Qnil);
 
-#if USE_ATSUI
-  DEFVAR_LISP ("mac-atsu-font-table", &Vmac_atsu_font_table,
-    doc: /* Hash table of ATSU font IDs vs plist of attributes and values.  */);
-  Vmac_atsu_font_table =
-    make_hash_table (Qeql, make_number (DEFAULT_HASH_SIZE),
-                    make_float (DEFAULT_REHASH_SIZE),
-                    make_float (DEFAULT_REHASH_THRESHOLD),
-                    Qnil, Qnil, Qnil);
-#endif
 #if USE_MAC_TSM
   DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
     doc: /* Overlay used to display Mac TSM active input area.  */);