diff src/macterm.c @ 90261:7beb78bc1f8e

Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-97 Merge from emacs--cvs-trunk--0 Patches applied: * emacs--cvs-trunk--0 (patch 616-696) - Add lisp/mh-e/.arch-inventory - Update from CVS - Merge from gnus--rel--5.10 - Update from CVS: lisp/smerge-mode.el: Add 'tools' to file keywords. - lisp/gnus/ChangeLog: Remove duplicate entry * gnus--rel--5.10 (patch 147-181) - Update from CVS - Merge from emacs--cvs-trunk--0 - Update from CVS: lisp/mml.el (mml-preview): Doc fix. - Update from CVS: texi/message.texi: Fix default values. - Update from CVS: texi/gnus.texi (RSS): Addition.
author Miles Bader <miles@gnu.org>
date Mon, 16 Jan 2006 08:37:27 +0000
parents 0ca0d9181b5e d88b44855af3
children c5406394f567
line wrap: on
line diff
--- a/src/macterm.c	Mon Jan 16 06:59:21 2006 +0000
+++ b/src/macterm.c	Mon Jan 16 08:37:27 2006 +0000
@@ -68,7 +68,6 @@
 #include <errno.h>
 #include <setjmp.h>
 #include <sys/stat.h>
-#include <sys/param.h>
 
 #include "charset.h"
 #include "coding.h"
@@ -89,22 +88,15 @@
 #include "character.h"
 #include "ccl.h"
 
-/* Set of macros that handle mapping of Mac modifier keys to emacs.  */
-#define macCtrlKey     (NILP (Vmac_reverse_ctrl_meta) ? controlKey :	\
-			(NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
-#define macShiftKey    (shiftKey)
-#define macMetaKey     (NILP (Vmac_reverse_ctrl_meta) ?			\
-			(NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
-			: controlKey)
-#define macAltKey      (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
 
 
 /* Non-nil means Emacs uses toolkit scroll bars.  */
 
 Lisp_Object Vx_toolkit_scroll_bars;
 
-/* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text.  */
-Lisp_Object Vmac_use_core_graphics;
+/* If non-zero, the text will be rendered using Core Graphics text
+   rendering which may anti-alias the text.  */
+int mac_use_core_graphics;
 
 
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
@@ -115,6 +107,10 @@
 /* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
 static Lisp_Object last_window;
 
+/* Non-zero means make use of UNDERLINE_POSITION font properties.
+   (Not yet supported.)  */
+int x_use_underline_position_properties;
+
 /* This is a chain of structures for all the X displays currently in
    use.  */
 
@@ -167,6 +163,7 @@
 /* Where the mouse was last time we reported a mouse event.  */
 
 static Rect last_mouse_glyph;
+static FRAME_PTR last_mouse_glyph_frame;
 
 /* The scroll bar in which the last X motion event occurred.
 
@@ -208,7 +205,7 @@
 
 /* The keysyms to use for the various modifiers.  */
 
-static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
+static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
 
 extern int inhibit_window_system;
 
@@ -263,7 +260,7 @@
 					    unsigned long *));
 
 static int is_emacs_window P_ ((WindowPtr));
-
+static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
 static void XSetFont P_ ((Display *, GC, XFontStruct *));
 
 /* Defined in macmenu.h.  */
@@ -630,7 +627,8 @@
       ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
       static ATSLineLayoutOptions line_layout =
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-	kATSLineDisableAllLayoutOperations  | kATSLineUseDeviceMetrics
+	kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
+	| kATSLineUseQDRendering
 #else
 	kATSLineIsDisplayOnly | kATSLineFractDisable
 #endif
@@ -695,7 +693,7 @@
 {
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
   UInt32 textFlags, savedFlags;
-  if (!NILP(Vmac_use_core_graphics)) {
+  if (mac_use_core_graphics) {
     textFlags = kQDUseCGTextRendering;
     savedFlags = SwapQDTextFlags(textFlags);
   }
@@ -718,10 +716,10 @@
 #ifndef WORDS_BIG_ENDIAN
       {
 	int i;
-	Unichar *text = (Unichar *)buf;
+	UniChar *text = (UniChar *)buf;
 
 	for (i = 0; i < nchars; i++)
-	  text[i] = buf[2*i] << 8 | buf[2*i+1];
+	  text[i] = EndianU16_BtoN (text[i]);
       }
 #endif
       err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
@@ -731,7 +729,7 @@
       if (err == noErr)
 	{
 #ifdef MAC_OSX
-	  if (NILP (Vmac_use_core_graphics))
+	  if (!mac_use_core_graphics)
 	    {
 #endif
 	      mac_begin_clip (GC_CLIP_REGION (gc));
@@ -775,11 +773,18 @@
 		ATSUDrawText (text_layout,
 			      kATSUFromTextBeginning, kATSUToTextEnd,
 			      Long2Fix (x), Long2Fix (port_height - y));
+	      CGContextSynchronize (context);
+	      QDEndCGContext (port, &context);
+#if 0
+	      /* This doesn't work on Mac OS X 10.1.  */
 	      ATSUClearLayoutControls (text_layout,
 				       sizeof (tags) / sizeof (tags[0]),
 				       tags);
-	      CGContextSynchronize (context);
-	      QDEndCGContext (port, &context);
+#else
+	      ATSUSetLayoutControls (text_layout,
+				     sizeof (tags) / sizeof (tags[0]),
+				     tags, sizes, values);
+#endif
 	    }
 #endif
 	}
@@ -803,7 +808,7 @@
   if (mode != srcOr)
     RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-  if (!NILP(Vmac_use_core_graphics))
+  if (mac_use_core_graphics)
     SwapQDTextFlags(savedFlags);
 #endif
 }
@@ -865,6 +870,244 @@
 }
 
 
+/* Mac replacement for XQueryTextExtents, but takes a character.  If
+   STYLE is NULL, measurement is done by QuickDraw Text routines for
+   the font of the current graphics port.  If CG_GLYPH is not NULL,
+   *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained.  */
+
+static OSErr
+mac_query_char_extents (style, c,
+			font_ascent_return, font_descent_return,
+			overall_return, cg_glyph)
+#if USE_ATSUI
+     ATSUStyle style;
+#else
+     void *style;
+#endif
+     int c;
+     int *font_ascent_return, *font_descent_return;
+     XCharStruct *overall_return;
+#if USE_CG_TEXT_DRAWING
+     CGGlyph *cg_glyph;
+#else
+     void *cg_glyph;
+#endif
+{
+  OSErr err = noErr;
+  int width;
+  Rect char_bounds;
+
+#if USE_ATSUI
+  if (style)
+    {
+      ATSUTextLayout text_layout;
+      UniChar ch = c;
+
+      err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
+      if (err == noErr)
+	{
+	  ATSTrapezoid glyph_bounds;
+
+	  err = ATSUGetGlyphBounds (text_layout, 0, 0,
+				    kATSUFromTextBeginning, kATSUToTextEnd,
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+				    kATSUseFractionalOrigins,
+#else
+				    kATSUseDeviceOrigins,
+#endif
+				    1, &glyph_bounds, NULL);
+	  if (err == noErr)
+	    {
+	      xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
+		       == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
+
+	      width = Fix2Long (glyph_bounds.upperRight.x
+				- glyph_bounds.upperLeft.x);
+	      if (font_ascent_return)
+		*font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
+	      if (font_descent_return)
+		*font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
+	    }
+	}
+      if (err == noErr && overall_return)
+	{
+	  err = ATSUMeasureTextImage (text_layout,
+				      kATSUFromTextBeginning, kATSUToTextEnd,
+				      0, 0, &char_bounds);
+	  if (err == noErr)
+	    STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
+#if USE_CG_TEXT_DRAWING
+	  if (err == noErr && cg_glyph)
+	    {
+	      OSErr err1;
+	      ATSUGlyphInfoArray glyph_info_array;
+	      ByteCount count = sizeof (ATSUGlyphInfoArray);
+
+	      err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
+					   kATSUToTextEnd, NULL, NULL, NULL);
+	      if (err1 == noErr)
+		err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
+					 kATSUToTextEnd, &count,
+					 &glyph_info_array);
+	      if (err1 == noErr)
+		{
+		  xassert (glyph_info_array.glyphs[0].glyphID);
+		  *cg_glyph = glyph_info_array.glyphs[0].glyphID;
+		}
+	      else
+		*cg_glyph = 0;
+	    }
+#endif
+	}
+    }
+  else
+#endif
+    {
+      if (font_ascent_return || font_descent_return)
+	{
+	  FontInfo font_info;
+
+	  GetFontInfo (&font_info);
+	  if (font_ascent_return)
+	    *font_ascent_return = font_info.ascent;
+	  if (font_descent_return)
+	    *font_descent_return = font_info.descent;
+	}
+      if (overall_return)
+	{
+	  char ch = c;
+
+	  width = CharWidth (ch);
+	  QDTextBounds (1, &ch, &char_bounds);
+	  STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
+	}
+    }
+
+  return err;
+}
+
+
+/* Mac replacement for XTextExtents16.  Only sets horizontal metrics.  */
+
+static int
+mac_text_extents_16 (font_struct, string, nchars, overall_return)
+     XFontStruct *font_struct;
+     XChar2b *string;
+     int nchars;
+     XCharStruct *overall_return;
+{
+  int i;
+  short width = 0, lbearing = 0, rbearing = 0;
+  XCharStruct *pcm;
+
+  for (i = 0; i < nchars; i++)
+    {
+      pcm = mac_per_char_metric (font_struct, string, 0);
+      if (pcm == NULL)
+	width += FONT_WIDTH (font_struct);
+      else
+	{
+	  lbearing = min (lbearing, width + pcm->lbearing);
+	  rbearing = max (rbearing, width + pcm->rbearing);
+	  width += pcm->width;
+	}
+      string++;
+    }
+
+  overall_return->lbearing = lbearing;
+  overall_return->rbearing = rbearing;
+  overall_return->width = width;
+
+  /* What's the meaning of the return value of XTextExtents16?  */
+}
+
+
+#if USE_CG_TEXT_DRAWING
+static int cg_text_anti_aliasing_threshold = 8;
+
+static void
+init_cg_text_anti_aliasing_threshold ()
+{
+  Lisp_Object val =
+    Fmac_get_preference (build_string ("AppleAntiAliasingThreshold"),
+			 Qnil, Qnil, Qnil);
+
+  if (INTEGERP (val))
+    cg_text_anti_aliasing_threshold = XINT (val);
+}
+
+static int
+mac_draw_string_cg (f, gc, x, y, buf, nchars)
+     struct frame *f;
+     GC gc;
+     int x, y;
+     XChar2b *buf;
+     int nchars;
+{
+  CGrafPtr port;
+  float port_height, gx, gy;
+  int i;
+  CGContextRef context;
+  CGGlyph *glyphs;
+  CGSize *advances;
+
+  if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
+    return 0;
+
+  port = GetWindowPort (FRAME_MAC_WINDOW (f));
+  port_height = FRAME_PIXEL_HEIGHT (f);
+  gx = x;
+  gy = port_height - y;
+  glyphs = (CGGlyph *)buf;
+  advances = xmalloc (sizeof (CGSize) * nchars);
+  for (i = 0; i < nchars; i++)
+    {
+      XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
+
+      advances[i].width = pcm->width;
+      advances[i].height = 0;
+      glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
+      buf++;
+    }
+
+  QDBeginCGContext (port, &context);
+  if (gc->n_clip_rects)
+    {
+      CGContextTranslateCTM (context, 0, port_height);
+      CGContextScaleCTM (context, 1, -1);
+      CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+      CGContextScaleCTM (context, 1, -1);
+      CGContextTranslateCTM (context, 0, -port_height);
+    }
+  CGContextSetRGBFillColor (context,
+			    RED_FROM_ULONG (gc->xgcv.foreground) / 255.0,
+			    GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0,
+			    BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0,
+			    1.0);
+  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);
+#else
+  for (i = 0; i < nchars; i++)
+    {
+      CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
+      gx += advances[i].width;
+    }
+#endif
+  CGContextSynchronize (context);
+  QDEndCGContext (port, &context);
+
+  xfree (advances);
+
+  return 1;
+}
+#endif
+
+
 /* Mac replacement for XCopyArea: dest must be window.  */
 
 static void
@@ -1636,59 +1879,32 @@
 #if USE_ATSUI
   if (font->mac_style)
     {
-      if (char2b->byte1 >= font->min_byte1
-	  && char2b->byte1 <= font->max_byte1
-	  && char2b->byte2 >= font->min_char_or_byte2
-	  && char2b->byte2 <= font->max_char_or_byte2)
+      XCharStructRow **row = font->bounds.rows + char2b->byte1;
+
+      if (*row == NULL)
 	{
-	  pcm = (font->per_char
-		 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
-		    * (char2b->byte1 - font->min_byte1))
-		 + (char2b->byte2 - font->min_char_or_byte2));
+	  *row = xmalloc (sizeof (XCharStructRow));
+	  if (*row)
+	    bzero (*row, sizeof (XCharStructRow));
 	}
-
-      if (pcm && !pcm->valid_p)
+      if (*row)
 	{
-	  OSErr err;
-	  ATSUTextLayout text_layout;
-	  UniChar c;
-	  int char_width;
-	  ATSTrapezoid glyph_bounds;
-	  Rect char_bounds;
-
-	  c = (char2b->byte1 << 8) + char2b->byte2;
-	  BLOCK_INPUT;
-	  err = atsu_get_text_layout_with_text_ptr (&c, 1,
-						    font->mac_style,
-						    &text_layout);
-	  if (err == noErr)
-	    err = ATSUMeasureTextImage (text_layout,
-					kATSUFromTextBeginning, kATSUToTextEnd,
-					0, 0, &char_bounds);
-
-	  if (err == noErr)
-	    err = ATSUGetGlyphBounds (text_layout, 0, 0,
-				      kATSUFromTextBeginning, kATSUToTextEnd,
-				      kATSUseFractionalOrigins, 1,
-				      &glyph_bounds, NULL);
-	  UNBLOCK_INPUT;
-	  if (err != noErr)
-	    pcm = NULL;
-	  else
+	  pcm = (*row)->per_char + char2b->byte2;
+	  if (!XCHARSTRUCTROW_CHAR_VALID_P (*row, char2b->byte2))
 	    {
-	      xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
-		       == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
-
-	      char_width = Fix2Long (glyph_bounds.upperRight.x
-				     - glyph_bounds.upperLeft.x);
-	      STORE_XCHARSTRUCT (*pcm, char_width, char_bounds);
+	      BLOCK_INPUT;
+	      mac_query_char_extents (font->mac_style,
+				      (char2b->byte1 << 8) + char2b->byte2,
+				      NULL, NULL, pcm, NULL);
+	      UNBLOCK_INPUT;
+	      XCHARSTRUCTROW_SET_CHAR_VALID (*row, char2b->byte2);
 	    }
 	}
     }
   else
     {
 #endif
-  if (font->per_char != NULL)
+  if (font->bounds.per_char != NULL)
     {
       if (font->min_byte1 == 0 && font->max_byte1 == 0)
 	{
@@ -1701,7 +1917,8 @@
 	  if (char2b->byte1 == 0
 	      && char2b->byte2 >= font->min_char_or_byte2
 	      && char2b->byte2 <= font->max_char_or_byte2)
-	    pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
+	    pcm = font->bounds.per_char
+	      + (char2b->byte2 - font->min_char_or_byte2);
 	}
       else
 	{
@@ -1723,7 +1940,7 @@
 	      && char2b->byte2 >= font->min_char_or_byte2
 	      && char2b->byte2 <= font->max_char_or_byte2)
 	    {
-	      pcm = (font->per_char
+	      pcm = (font->bounds.per_char
 		     + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
 			* (char2b->byte1 - font->min_byte1))
 		     + (char2b->byte2 - font->min_char_or_byte2));
@@ -2064,67 +2281,32 @@
 {
   if (s->cmp == NULL
       && s->first_glyph->type == CHAR_GLYPH)
-    {
-      Rect r;
-      MacFontStruct *font = s->font;
-
+    if (!s->two_byte_p
 #if USE_ATSUI
-      if (font->mac_style)
-	{
-	  OSErr err;
-	  ATSUTextLayout text_layout;
-	  UniChar *buf;
-	  int i;
-
-	  SetRect (&r, 0, 0, 0, 0);
-	  buf = xmalloc (sizeof (UniChar) * s->nchars);
-	  if (buf)
-	    {
-	      for (i = 0; i < s->nchars; i++)
-		buf[i] = (s->char2b[i].byte1 << 8) + s->char2b[i].byte2;
-
-	      err = atsu_get_text_layout_with_text_ptr (buf, s->nchars,
-							font->mac_style,
-							&text_layout);
-	      if (err == noErr)
-		err = ATSUMeasureTextImage (text_layout,
-					    kATSUFromTextBeginning,
-					    kATSUToTextEnd,
-					    0, 0, &r);
-	      xfree (buf);
-	    }
-	}
-      else
-	{
-#endif
-      TextFont (font->mac_fontnum);
-      TextSize (font->mac_fontsize);
-      TextFace (font->mac_fontface);
-
-      if (s->two_byte_p)
+	|| s->font->mac_style
+#endif
+	)
+      {
+	XCharStruct cs;
+
+	mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
+	s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
+	s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
+      }
+    else
+      {
+	Rect r;
+	MacFontStruct *font = s->font;
+
+	TextFont (font->mac_fontnum);
+	TextSize (font->mac_fontsize);
+	TextFace (font->mac_fontface);
+
 	QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
-      else
-	{
-	  int i;
-	  char *buf = xmalloc (s->nchars);
-
-	  if (buf == NULL)
-	    SetRect (&r, 0, 0, 0, 0);
-	  else
-	    {
-	      for (i = 0; i < s->nchars; ++i)
-		buf[i] = s->char2b[i].byte2;
-	      QDTextBounds (s->nchars, buf, &r);
-	      xfree (buf);
-	    }
-	}
-#if USE_ATSUI
-        }
-#endif
-
-      s->right_overhang = r.right > s->width ? r.right - s->width : 0;
-      s->left_overhang = r.left < 0 ? -r.left : 0;
-    }
+
+	s->right_overhang = r.right > s->width ? r.right - s->width : 0;
+	s->left_overhang = r.left < 0 ? -r.left : 0;
+      }
 }
 
 
@@ -2255,6 +2437,13 @@
 	      || GC_FONT (s->gc)->mac_style
 #endif
 	      )
+#if USE_CG_TEXT_DRAWING
+	    if (!s->two_byte_p
+		&& mac_draw_string_cg (s->f, s->gc, x, s->ybase - boff,
+				       s->char2b, s->nchars))
+	      ;
+	    else
+#endif
 	    mac_draw_string_16 (s->f, s->gc, x,	s->ybase - boff,
 				s->char2b, s->nchars);
 	  else
@@ -3912,13 +4101,15 @@
       return 1;
     }
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  if (!PtInRect (*pos, &last_mouse_glyph))
+  if (frame != last_mouse_glyph_frame
+      || !PtInRect (*pos, &last_mouse_glyph))
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, pos->h, pos->v);
       /* Remember which glyph we're now on.  */
       remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
+      last_mouse_glyph_frame = frame;
       return 1;
     }
 
@@ -4023,6 +4214,7 @@
 	  GetMouse (&mouse_pos);
 	  remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
 				&last_mouse_glyph);
+	  last_mouse_glyph_frame = f1;
 
 	  *bar_window = Qnil;
 	  *part = 0;
@@ -6591,7 +6783,7 @@
 
   sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
 	   style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
-	   size, size * 10, size ? 75 : 0, size ? 75 : 0, size * 10, charset);
+	   size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
 
   result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
   sprintf (result, "-%s-%s-%s", foundry, family, xf);
@@ -6717,6 +6909,9 @@
   text_encoding_info_alist = create_text_encoding_info_alist ();
 
 #if USE_ATSUI
+#if USE_CG_TEXT_DRAWING
+  init_cg_text_anti_aliasing_threshold ();
+#endif
   if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
 			   text_encoding_info_alist)))
     {
@@ -7080,7 +7275,7 @@
 	    continue;
 	  memcpy (scaled, font_name_table[i], former_len);
 	  sprintf (scaled + former_len,
-		   "-%d-%d-75-75-m-%d-%s",
+		   "-%d-%d-72-72-m-%d-%s",
 		   scl_val[XLFD_SCL_PIXEL_SIZE],
 		   scl_val[XLFD_SCL_POINT_SIZE],
 		   scl_val[XLFD_SCL_AVGWIDTH],
@@ -7286,12 +7481,13 @@
 static MacFontStruct *
 XLoadQueryFont (Display *dpy, char *fontname)
 {
-  int i, size, char_width;
+  int size;
   char *name;
   Str255 family;
   Str31 charset;
   SInt16 fontnum;
 #if USE_ATSUI
+  static ATSUFontID font_id;
   ATSUStyle mac_style = NULL;
 #endif
   Style fontface;
@@ -7302,6 +7498,7 @@
   short scriptcode;
 #endif
   MacFontStruct *font;
+  XCharStruct *space_bounds = NULL, *pcm;
 
   if (is_fully_specified_xlfd (fontname))
     name = fontname;
@@ -7326,13 +7523,14 @@
 				 kATSUQDBoldfaceTag, kATSUQDItalicTag};
       ByteCount sizes[] = {sizeof (ATSUFontID), sizeof (Fixed),
 			   sizeof (Boolean), sizeof (Boolean)};
-      static ATSUFontID font_id;
       static Fixed size_fixed;
       static Boolean bold_p, italic_p;
       ATSUAttributeValuePtr values[] = {&font_id, &size_fixed,
 					&bold_p, &italic_p};
-      ATSUFontFeatureType types[] = {kAllTypographicFeaturesType};
-      ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector};
+      ATSUFontFeatureType types[] = {kAllTypographicFeaturesType,
+				     kDiacriticsType};
+      ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector,
+					     kDecomposeDiacriticsSelector};
       Lisp_Object font_id_cons;
 
       font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
@@ -7380,6 +7578,10 @@
   font->mac_scriptcode = scriptcode;
 #if USE_ATSUI
   font->mac_style = mac_style;
+#if USE_CG_TEXT_DRAWING
+  font->cg_font = NULL;
+  font->cg_glyphs = NULL;
+#endif
 #endif
 
   /* Apple Japanese (SJIS) font is listed as both
@@ -7395,83 +7597,103 @@
   if (font->mac_style)
     {
       OSErr err;
-      ATSUTextLayout text_layout;
-      UniChar c = 0x20;
-      Rect char_bounds, min_bounds, max_bounds;
-      int min_width, max_width;
-      ATSTrapezoid glyph_bounds;
-
-      font->per_char = xmalloc (sizeof (XCharStruct) * 0x10000);
-      if (font->per_char == NULL)
+      UniChar c;
+
+      font->min_byte1 = 0;
+      font->max_byte1 = 0xff;
+      font->min_char_or_byte2 = 0;
+      font->max_char_or_byte2 = 0xff;
+
+      font->bounds.rows = xmalloc (sizeof (XCharStructRow *) * 0x100);
+      if (font->bounds.rows == NULL)
+	{
+	  mac_unload_font (&one_mac_display_info, font);
+	  return NULL;
+	}
+      bzero (font->bounds.rows, sizeof (XCharStructRow *) * 0x100);
+      font->bounds.rows[0] = xmalloc (sizeof (XCharStructRow));
+      if (font->bounds.rows[0] == NULL)
 	{
 	  mac_unload_font (&one_mac_display_info, font);
 	  return NULL;
 	}
-      bzero (font->per_char, sizeof (XCharStruct) * 0x10000);
-
-      err = atsu_get_text_layout_with_text_ptr (&c, 1,
-						font->mac_style,
-						&text_layout);
+      bzero (font->bounds.rows[0], sizeof (XCharStructRow));
+
+#if USE_CG_TEXT_DRAWING
+      {
+	FMFontFamily font_family;
+	FMFontStyle style;
+	ATSFontRef ats_font;
+
+	err = FMGetFontFamilyInstanceFromFont (font_id, &font_family, &style);
+	if (err == noErr)
+	  err = FMGetFontFromFontFamilyInstance (font_family, fontface,
+						 &font_id, &style);
+	/* Use CG text drawing if italic/bold is not synthesized.  */
+	if (err == noErr && style == fontface)
+	  {
+	    ats_font = FMGetATSFontRefFromFont (font_id);
+	    font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
+	  }
+      }
+
+      if (font->cg_font)
+	font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
+      if (font->cg_glyphs)
+	bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
+#endif
+      space_bounds = font->bounds.rows[0]->per_char + 0x20;
+      err = mac_query_char_extents (font->mac_style, 0x20,
+				    &font->ascent, &font->descent,
+				    space_bounds,
+#if USE_CG_TEXT_DRAWING
+				    (font->cg_glyphs ? font->cg_glyphs + 0x20
+				     : NULL)
+#else
+				    NULL
+#endif
+				    );
       if (err != noErr)
 	{
 	  mac_unload_font (&one_mac_display_info, font);
 	  return NULL;
 	}
-
-      for (c = 0x20; c <= 0x7e; c++)
+      XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], 0x20);
+
+      pcm = font->bounds.rows[0]->per_char;
+      for (c = 0x21; c <= 0xff; c++)
 	{
-	  err = ATSUClearLayoutCache (text_layout, kATSUFromTextBeginning);
-	  if (err == noErr)
-	    err = ATSUMeasureTextImage (text_layout,
-					kATSUFromTextBeginning, kATSUToTextEnd,
-					0, 0, &char_bounds);
-	  if (err == noErr)
-	    err = ATSUGetGlyphBounds (text_layout, 0, 0,
-				      kATSUFromTextBeginning, kATSUToTextEnd,
-				      kATSUseFractionalOrigins, 1,
-				      &glyph_bounds, NULL);
-	  if (err == noErr)
+	  if (c == 0xad)
+	    /* Soft hyphen is not supported in ATSUI.  */
+	    continue;
+	  else if (c == 0x7f)
 	    {
-	      xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
-		       == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
-
-	      char_width = Fix2Long (glyph_bounds.upperRight.x
-				     - glyph_bounds.upperLeft.x);
-	      STORE_XCHARSTRUCT (font->per_char[c],
-				 char_width, char_bounds);
-	      if (c == 0x20)
-		{
-		  min_width = max_width = char_width;
-		  min_bounds = max_bounds = char_bounds;
-		  font->ascent = -Fix2Long (glyph_bounds.upperLeft.y);
-		  font->descent = Fix2Long (glyph_bounds.lowerLeft.y);
-		}
-	      else
-		{
-		  if (char_width > 0)
-		    {
-		      min_width = min (min_width, char_width);
-		      max_width = max (max_width, char_width);
-		    }
-		  if (!EmptyRect (&char_bounds))
-		    {
-		      SetRect (&min_bounds,
-			       max (min_bounds.left, char_bounds.left),
-			       max (min_bounds.top, char_bounds.top),
-			       min (min_bounds.right, char_bounds.right),
-			       min (min_bounds.bottom, char_bounds.bottom));
-		      UnionRect (&max_bounds, &char_bounds, &max_bounds);
-		    }
-		}
+	      c = 0x9f;
+	      continue;
 	    }
+
+	  mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c,
+#if USE_CG_TEXT_DRAWING
+				  (font->cg_glyphs ? font->cg_glyphs + c
+				   : NULL)
+#else
+				    NULL
+#endif
+				  );
+	  XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], c);
+
+#if USE_CG_TEXT_DRAWING
+	  if (font->cg_glyphs && font->cg_glyphs[c] == 0)
+	    {
+	      /* Don't use CG text drawing if font substitution occurs in
+		 ASCII or Latin-1 characters.  */
+	      CGFontRelease (font->cg_font);
+	      font->cg_font = NULL;
+	      xfree (font->cg_glyphs);
+	      font->cg_glyphs = NULL;
+	    }
+#endif
 	}
-      STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
-      STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
-
-      font->min_byte1 = 0;
-      font->max_byte1 = 0xff;
-      font->min_char_or_byte2 = 0;
-      font->max_char_or_byte2 = 0xff;
     }
   else
 #endif
@@ -7510,6 +7732,8 @@
 
       if (is_two_byte_font)
 	{
+	  int char_width;
+
 	  font->min_byte1 = 0xa1;
 	  font->max_byte1 = 0xfe;
 	  font->min_char_or_byte2 = 0xa1;
@@ -7538,21 +7762,8 @@
 	      char_width = StringWidth("\p\xa1\xa1");
 	      break;
 	    }
-	}
-      else
-	{
-	  font->min_byte1 = font->max_byte1 = 0;
-	  font->min_char_or_byte2 = 0x20;
-	  font->max_char_or_byte2 = 0xff;
-
-	  /* Do this instead of use the_fontinfo.widMax, which
-	     incorrectly returns 15 for 12-point Monaco! */
-	  char_width = CharWidth ('m');
-	}
-
-      if (is_two_byte_font)
-	{
-	  font->per_char = NULL;
+
+	  font->bounds.per_char = NULL;
 
 	  if (fontface & italic)
 	    font->max_bounds.rbearing = char_width + 1;
@@ -7567,49 +7778,28 @@
 	}
       else
 	{
-	  int c, min_width, max_width;
-	  Rect char_bounds, min_bounds, max_bounds;
-	  char ch;
-
-	  font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
-	  bzero (font->per_char, sizeof (XCharStruct) * (0xff - 0x20 + 1));
-
-	  min_width = max_width = char_width;
-	  SetRect (&min_bounds, -32767, -32767, 32767, 32767);
-	  SetRect (&max_bounds, 0, 0, 0, 0);
-	  for (c = 0x20; c <= 0xff; c++)
+	  int c;
+
+	  font->min_byte1 = font->max_byte1 = 0;
+	  font->min_char_or_byte2 = 0x20;
+	  font->max_char_or_byte2 = 0xff;
+
+	  font->bounds.per_char =
+	    xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
+	  if (font->bounds.per_char == NULL)
 	    {
-	      ch = c;
-	      char_width = CharWidth (ch);
-	      QDTextBounds (1, &ch, &char_bounds);
-	      STORE_XCHARSTRUCT (font->per_char[c - 0x20],
-				 char_width, char_bounds);
-	      /* Some Japanese fonts (in SJIS encoding) return 0 as
-		 the character width of 0x7f.  */
-	      if (char_width > 0)
-		{
-		  min_width = min (min_width, char_width);
-		  max_width = max (max_width, char_width);
-		}
-	      if (!EmptyRect (&char_bounds))
-		{
-		  SetRect (&min_bounds,
-			   max (min_bounds.left, char_bounds.left),
-			   max (min_bounds.top, char_bounds.top),
-			   min (min_bounds.right, char_bounds.right),
-			   min (min_bounds.bottom, char_bounds.bottom));
-		  UnionRect (&max_bounds, &char_bounds, &max_bounds);
-		}
+	      mac_unload_font (&one_mac_display_info, font);
+	      return NULL;
 	    }
-	  STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
-	  STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
-	  if (min_width == max_width
-	      && max_bounds.left >= 0 && max_bounds.right <= max_width)
-	    {
-	      /* Fixed width and no overhangs.  */
-	      xfree (font->per_char);
-	      font->per_char = NULL;
-	    }
+	  bzero (font->bounds.per_char,
+		 sizeof (XCharStruct) * (0xff - 0x20 + 1));
+
+	  space_bounds = font->bounds.per_char;
+	  mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent,
+				  space_bounds, NULL);
+
+	  for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
+	    mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
 	}
 
       /* Restore previous font number, size and face.  */
@@ -7618,6 +7808,55 @@
       TextFace (old_fontface);
     }
 
+  if (space_bounds)
+    {
+      int c;
+
+      font->min_bounds = font->max_bounds = *space_bounds;
+      for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
+	if (pcm->width > 0)
+	  {
+	    font->min_bounds.lbearing = min (font->min_bounds.lbearing,
+					     pcm->lbearing);
+	    font->min_bounds.rbearing = min (font->min_bounds.rbearing,
+					     pcm->rbearing);
+	    font->min_bounds.width    = min (font->min_bounds.width,
+					     pcm->width);
+	    font->min_bounds.ascent   = min (font->min_bounds.ascent,
+					     pcm->ascent);
+
+	    font->max_bounds.lbearing = max (font->max_bounds.lbearing,
+					     pcm->lbearing);
+	    font->max_bounds.rbearing = max (font->max_bounds.rbearing,
+					     pcm->rbearing);
+	    font->max_bounds.width    = max (font->max_bounds.width,
+					     pcm->width);
+	    font->max_bounds.ascent   = max (font->max_bounds.ascent,
+					     pcm->ascent);
+	  }
+      if (
+#if USE_ATSUI
+	  font->mac_style == NULL &&
+#endif
+	  font->max_bounds.width == font->min_bounds.width
+	  && font->min_bounds.lbearing >= 0
+	  && font->max_bounds.rbearing <= font->max_bounds.width)
+	{
+	  /* Fixed width and no overhangs.  */
+	  xfree (font->bounds.per_char);
+	  font->bounds.per_char = NULL;
+	}
+    }
+
+#if !defined (MAC_OS8) || USE_ATSUI
+  /* AppKit and WebKit do some adjustment to the heights of Courier,
+     Helvetica, and Times.  This only works on the environments where
+     the XDrawImageString counterpart is never used.  */
+  if (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
+      || strcmp (family, "times") == 0)
+    font->ascent += (font->ascent + font->descent) * .15 + 0.5;
+#endif
+
   return font;
 }
 
@@ -7628,11 +7867,26 @@
      XFontStruct *font;
 {
   xfree (font->full_name);
-  if (font->per_char)
-    xfree (font->per_char);
 #if USE_ATSUI
   if (font->mac_style)
-    ATSUDisposeStyle (font->mac_style);
+    {
+      int i;
+
+      for (i = font->min_byte1; i <= font->max_byte1; i++)
+	if (font->bounds.rows[i])
+	  xfree (font->bounds.rows[i]);
+      xfree (font->bounds.rows);
+      ATSUDisposeStyle (font->mac_style);
+    }
+  else
+#endif
+    if (font->bounds.per_char)
+      xfree (font->bounds.per_char);
+#if USE_CG_TEXT_DRAWING
+  if (font->cg_font)
+    CGFontRelease (font->cg_font);
+  if (font->cg_glyphs)
+    xfree (font->cg_glyphs);
 #endif
   xfree (font);
 }
@@ -7922,31 +8176,35 @@
 /* Contains the string "reverse", which is a constant for mouse button emu.*/
 Lisp_Object Qreverse;
 
-/* True if using command key as meta key.  */
-Lisp_Object Vmac_command_key_is_meta;
-
-/* Modifier associated with the option key, or nil for normal behavior. */
+
+/* Modifier associated with the control key, or nil to ignore. */
+Lisp_Object Vmac_control_modifier;
+
+/* Modifier associated with the option key, or nil to ignore. */
 Lisp_Object Vmac_option_modifier;
 
-/* True if the ctrl and meta keys should be reversed.  */
-Lisp_Object Vmac_reverse_ctrl_meta;
+/* Modifier associated with the command key, or nil to ignore. */
+Lisp_Object Vmac_command_modifier;
+
+/* Modifier associated with the function key, or nil to ignore. */
+Lisp_Object Vmac_function_modifier;
 
 /* True if the option and command modifiers should be used to emulate
    a three button mouse */
 Lisp_Object Vmac_emulate_three_button_mouse;
 
 #if USE_CARBON_EVENTS
-/* True if the mouse wheel button (i.e. button 4) should map to
+/* Non-zero if the mouse wheel button (i.e. button 4) should map to
    mouse-2, instead of mouse-3.  */
-Lisp_Object Vmac_wheel_button_is_mouse_2;
-
-/* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
+int mac_wheel_button_is_mouse_2;
+
+/* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
    for processing before Emacs sees it.  */
-Lisp_Object Vmac_pass_command_to_system;
-
-/* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
+int mac_pass_command_to_system;
+
+/* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
    for processing before Emacs sees it.  */
-Lisp_Object Vmac_pass_control_to_system;
+int mac_pass_control_to_system;
 #endif
 
 /* Points to the variable `inev' in the function XTread_socket.  It is
@@ -7954,20 +8212,19 @@
    Carbon/Apple event handlers.  */
 static struct input_event *read_socket_inev = NULL;
 
-/* Set in term/mac-win.el to indicate that event loop can now generate
-   drag and drop events.  */
-Lisp_Object Qmac_ready_for_drag_n_drop;
-
 Point saved_menu_event_location;
 
 /* Apple Events */
-static void init_required_apple_events (void);
-static pascal OSErr
-do_ae_open_application (const AppleEvent *, AppleEvent *, long);
-static pascal OSErr
-do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
+#if USE_CARBON_EVENTS
+static Lisp_Object Qhicommand;
+#endif
+extern int mac_ready_for_apple_events;
+extern Lisp_Object Qundefined;
+extern void init_apple_event_handler P_ ((void));
+extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
+					   Lisp_Object *, Lisp_Object *,
+					   Lisp_Object *));
+extern OSErr init_coercion_handler P_ ((void));
 
 #if TARGET_API_MAC_CARBON
 /* Drag and Drop */
@@ -7977,11 +8234,10 @@
 static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL;
 #endif
 
-static Lisp_Object Qapplication, Qabout;
 #if USE_CARBON_EVENTS
 #ifdef MAC_OSX
 extern void init_service_handler ();
-static Lisp_Object Qpreferences, Qservices, Qpaste, Qperform;
+static Lisp_Object Qservices, Qpaste, Qperform;
 #endif
 /* Window Event Handler */
 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
@@ -8003,19 +8259,41 @@
 #endif
 {
   unsigned int result = 0;
-  if (mods & macShiftKey)
+  if (mods & shiftKey)
     result |= shift_modifier;
-  if (mods & macCtrlKey)
-    result |= ctrl_modifier;
-  if (mods & macMetaKey)
-    result |= meta_modifier;
-  if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
-    result |= alt_modifier;
+
+  /* Deactivated to simplify configuration:
+     if Vmac_option_modifier is non-NIL, we fully process the Option
+     key. Otherwise, we only process it if an additional Ctrl or Command
+     is pressed. That way the system may convert the character to a
+     composed one.
+     if ((mods & optionKey) &&
+      (( !NILP(Vmac_option_modifier) ||
+      ((mods & cmdKey) || (mods & controlKey))))) */
+
   if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
-      Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
-      if (!NILP(val))
-          result |= XUINT(val);
+    Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
+  }
+  if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
+    Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
   }
+  if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
+    Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
+  }
+
+#ifdef MAC_OSX
+  if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
+    Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
+  }
+#endif
 
   return result;
 }
@@ -8037,7 +8315,7 @@
 #if USE_CARBON_EVENTS
 /* Obtains the event modifiers from the event ref and then calls
    mac_to_emacs_modifiers.  */
-static int
+static UInt32
 mac_event_to_emacs_modifiers (EventRef eventRef)
 {
   UInt32 mods = 0;
@@ -8071,10 +8349,10 @@
 	return mac_get_emulated_btn(mods);
       }
     case kEventMouseButtonSecondary:
-      return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
+      return mac_wheel_button_is_mouse_2 ? 2 : 1;
     case kEventMouseButtonTertiary:
     case 4:  /* 4 is the number for the mouse wheel button */
-      return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
+      return mac_wheel_button_is_mouse_2 ? 1 : 2;
     default:
       return 0;
     }
@@ -8502,179 +8780,49 @@
   x_real_positions (f, &f->left_pos, &f->top_pos);
 }
 
-/* Intialize AppleEvent dispatcher table for the required events.  */
-void
-init_required_apple_events ()
-{
-  OSErr err;
-  long result;
-
-  /* Make sure we have apple events before starting.  */
-  err = Gestalt (gestaltAppleEventsAttr, &result);
-  if (err != noErr)
-    abort ();
-
-  if (!(result & (1 << gestaltAppleEventsPresent)))
-    abort ();
-
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
-			      NewAEEventHandlerUPP
-			      ((AEEventHandlerProcPtr) do_ae_open_application),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
-			      NewAEEventHandlerProc
-			      ((AEEventHandlerProcPtr) do_ae_open_application),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
-
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
-                              NewAEEventHandlerUPP
-			      ((AEEventHandlerProcPtr) do_ae_open_documents),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
-                              NewAEEventHandlerProc
-			      ((AEEventHandlerProcPtr) do_ae_open_documents),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
-
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
-                              NewAEEventHandlerUPP
-			      ((AEEventHandlerProcPtr) do_ae_print_documents),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
-                              NewAEEventHandlerProc
-			      ((AEEventHandlerProcPtr) do_ae_print_documents),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
-
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
-                              NewAEEventHandlerUPP
-			      ((AEEventHandlerProcPtr) do_ae_quit_application),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
-                              NewAEEventHandlerProc
-			      ((AEEventHandlerProcPtr) do_ae_quit_application),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
-}
-
-void
-mac_store_application_menu_event (event)
-#if USE_CARBON_EVENTS
-     EventRef event;
-#else
-     UInt32 event;
-#endif
-{
+OSErr
+mac_store_apple_event (class, id, desc)
+     Lisp_Object class, id;
+     const AEDesc *desc;
+{
+  OSErr err = noErr;
   struct input_event buf;
-  Lisp_Object frame, entry;
-
-  EVENT_INIT (buf);
-
-  XSETFRAME (frame, mac_focus_frame (&one_mac_display_info));
-  buf.kind = MENU_BAR_EVENT;
-  buf.frame_or_window = frame;
-  buf.arg = frame;
-  kbd_buffer_store_event (&buf);
-
-  buf.arg = Qapplication;
-  kbd_buffer_store_event (&buf);
-
-#if USE_CARBON_EVENTS
-  switch (GetEventClass (event))
-    {
-#ifdef MAC_OSX
-    case kEventClassService:
-      buf.arg = Qservices;
+  AEDesc *desc_copy;
+
+  desc_copy = xmalloc (sizeof (AEDesc));
+  if (desc_copy == NULL)
+    err = memFullErr;
+  else
+    err = AEDuplicateDesc (desc, desc_copy);
+  if (err == noErr)
+    {
+      EVENT_INIT (buf);
+
+      buf.kind = MAC_APPLE_EVENT;
+      buf.x = class;
+      buf.y = id;
+      buf.code = (int)desc_copy;
+      XSETFRAME (buf.frame_or_window,
+		 mac_focus_frame (&one_mac_display_info));
+      buf.arg = Qnil;
       kbd_buffer_store_event (&buf);
-      switch (GetEventKind (event))
-	{
-	case kEventServicePaste:
-	  entry = Qpaste;
-	  break;
-
-	case kEventServicePerform:
-	  {
-	    OSErr err;
-	    CFStringRef message;
-
-	    err = GetEventParameter (event, kEventParamServiceMessageName,
-				     typeCFStringRef, NULL,
-				     sizeof (CFStringRef), NULL, &message);
-	    buf.arg = Qperform;
-	    kbd_buffer_store_event (&buf);
-	    if (err == noErr && message)
-	      entry = intern (SDATA (cfstring_to_lisp (message)));
-	    else
-	      entry = Qnil;
-	  }
-	  break;
-
-	default:
-	  abort ();
-	}
-      break;
-#endif	/* MAC_OSX */
-    case kEventClassCommand:
-      {
-	HICommand command;
-
-	GetEventParameter(event, kEventParamDirectObject, typeHICommand,
-			  NULL, sizeof (HICommand), NULL, &command);
-	switch (command.commandID)
-	  {
-	  case kHICommandAbout:
-	    entry = Qabout;
-	    break;
-#ifdef MAC_OSX
-	  case kHICommandPreferences:
-	    entry = Qpreferences;
-	    break;
-#endif /* MAC_OSX */
-	  case kHICommandQuit:
-	    entry = Qquit;
-	    break;
-	  default:
-	    abort ();
-	  }
-      }
-      break;
-
-    default:
-      abort ();
-    }
-#else  /* USE_CARBON_EVENTS */
-  switch (event)
-    {
-    case kHICommandAbout:
-      entry = Qabout;
-      break;
-    case kHICommandQuit:
-      entry = Qquit;
-      break;
-    default:
-      abort ();
-    }
-#endif
-
-  buf.arg = entry;
-  kbd_buffer_store_event (&buf);
+    }
+
+  return err;
+}
+
+Lisp_Object
+mac_make_lispy_event_code (code)
+     int code;
+{
+  AEDesc *desc = (AEDesc *)code;
+  Lisp_Object obj;
+
+  obj = mac_aedesc_to_lisp (desc);
+  AEDisposeDesc (desc);
+  xfree (desc);
+
+  return obj;
 }
 
 #if USE_CARBON_EVENTS
@@ -8684,28 +8832,47 @@
      EventRef event;
      void *data;
 {
+  OSStatus result;
+  OSErr err;
   HICommand command;
-  OSErr result;
-
-  GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL,
-		    sizeof (HICommand), NULL, &command);
-
-  switch (command.commandID)
-    {
-    case kHICommandAbout:
-#ifdef MAC_OSX
-    case kHICommandPreferences:
-#endif	/* MAC_OSX */
-      result = CallNextEventHandler (next_handler, event);
-      if (result != eventNotHandledErr)
-	return result;
-
-      mac_store_application_menu_event (event);
-      return noErr;
-
-    default:
-      break;
-    }
+  Lisp_Object class_key, id_key, binding;
+
+  result = CallNextEventHandler (next_handler, event);
+  if (result != eventNotHandledErr)
+    return result;
+
+  GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL,
+		     sizeof (HICommand), NULL, &command);
+
+  if (command.commandID == 0)
+    return eventNotHandledErr;
+
+  /* A HICommand event is mapped to an Apple event whose event class
+     symbol is `hicommand' and event ID is its command ID.  */
+  class_key = Qhicommand;
+  mac_find_apple_event_spec (0, command.commandID,
+			     &class_key, &id_key, &binding);
+  if (!NILP (binding) && !EQ (binding, Qundefined))
+    if (INTEGERP (binding))
+      return XINT (binding);
+    else
+      {
+	AppleEvent apple_event;
+	UInt32 modifiers;
+	static EventParamName names[] = {kEventParamDirectObject,
+					 kEventParamKeyModifiers};
+	static EventParamType types[] = {typeHICommand,
+					 typeUInt32};
+	err = create_apple_event_from_event_ref (event, 2, names, types,
+						 &apple_event);
+	if (err == noErr)
+	  {
+	    err = mac_store_apple_event (class_key, id_key, &apple_event);
+	    AEDisposeDesc (&apple_event);
+	  }
+	if (err == noErr)
+	  return noErr;
+      }
 
   return eventNotHandledErr;
 }
@@ -8867,6 +9034,50 @@
 
   return eventNotHandledErr;
 }
+
+#ifdef MAC_OSX
+OSErr
+mac_store_services_event (event)
+     EventRef event;
+{
+  OSErr err;
+  AppleEvent apple_event;
+  Lisp_Object id_key;
+
+  switch (GetEventKind (event))
+    {
+    case kEventServicePaste:
+      id_key = Qpaste;
+      err = create_apple_event_from_event_ref (event, 0, NULL, NULL,
+					       &apple_event);
+      break;
+
+    case kEventServicePerform:
+      {
+	static EventParamName names[] = {kEventParamServiceMessageName,
+					 kEventParamServiceUserData};
+	static EventParamType types[] = {typeCFStringRef,
+					 typeCFStringRef};
+
+	id_key = Qperform;
+	err = create_apple_event_from_event_ref (event, 2, names, types,
+						 &apple_event);
+      }
+      break;
+
+    default:
+      abort ();
+    }
+
+  if (err == noErr)
+    {
+      err = mac_store_apple_event (Qservices, id_key, &apple_event);
+      AEDisposeDesc (&apple_event);
+    }
+
+  return err;
+}
+#endif	/* MAC_OSX */
 #endif	/* USE_CARBON_EVENTS */
 
 
@@ -8925,159 +9136,6 @@
 #endif
 }
 
-/* Open Application Apple Event */
-static pascal OSErr
-do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
-{
-  return noErr;
-}
-
-
-/* Called when we receive an AppleEvent with an ID of
-   "kAEOpenDocuments".  This routine gets the direct parameter,
-   extracts the FSSpecs in it, and puts their names on a list.  */
-#pragma options align=mac68k
-typedef struct SelectionRange {
-  short unused1; // 0 (not used)
-  short lineNum; // line to select (<0 to specify range)
-  long startRange; // start of selection range (if line < 0)
-  long endRange; // end of selection range (if line < 0)
-  long unused2; // 0 (not used)
-  long theDate; // modification date/time
-} SelectionRange;
-#pragma options align=reset
-
-static pascal OSErr
-do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
-{
-  OSErr err, err2;
-  AEDesc the_desc;
-  AEKeyword keyword;
-  DescType actual_type;
-  Size actual_size;
-  SelectionRange position;
-  Lisp_Object file_list = Qnil;
-
-  xassert (read_socket_inev);
-
-  err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
-  if (err != noErr)
-    goto descriptor_error_exit;
-
-  err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
-  if (err == noErr)
-    file_list = Fcons (list3 (make_number (position.lineNum + 1),
-			      make_number (position.startRange + 1),
-			      make_number (position.endRange + 1)),
-		       file_list);
-
-  /* Check to see that we got all of the required parameters from the
-     event descriptor.  For an 'odoc' event this should just be the
-     file list.  */
-  err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
-			  &actual_type, (Ptr) &keyword,
-                          sizeof (keyword), &actual_size);
-  /* No error means that we found some unused parameters.
-     errAEDescNotFound means that there are no more parameters.  If we
-     get an error code other than that, flag it.  */
-  if ((err == noErr) || (err != errAEDescNotFound))
-    {
-      err = errAEEventNotHandled;
-      goto error_exit;
-    }
-  err = noErr;
-
-  /* Got all the parameters we need.  Now, go through the direct
-     object list and parse it up.  */
-  {
-    long num_files_to_open;
-
-    err = AECountItems (&the_desc, &num_files_to_open);
-    if (err == noErr)
-      {
-        int i;
-
-        /* AE file list is one based so just use that for indexing here.  */
-        for (i = 1; i <= num_files_to_open; i++)
-	  {
-	    char unix_path_name[MAXPATHLEN];
-#ifdef MAC_OSX
-	    FSRef fref;
-
-	    err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
-			       &actual_type, &fref, sizeof (FSRef),
-			       &actual_size);
-	    if (err != noErr || actual_type != typeFSRef)
-	      continue;
-
-	    if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
-		== noErr)
-#else
-	    FSSpec fs;
-
-	    err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
-			      (Ptr) &fs, sizeof (fs), &actual_size);
-	    if (err != noErr) continue;
-
-	    if (fsspec_to_posix_pathname (&fs, unix_path_name,
-					  sizeof (unix_path_name) - 1) == noErr)
-#endif
-	      /* x-dnd functions expect undecoded filenames.  */
-	      file_list = Fcons (make_unibyte_string (unix_path_name,
-						      strlen (unix_path_name)),
-				 file_list);
-	  }
-      }
-
-    /* Build a DRAG_N_DROP_EVENT type event as is done in
-       constuct_drag_n_drop in w32term.c.  */
-    if (!NILP (file_list))
-      {
-	struct frame *f = mac_focus_frame (&one_mac_display_info);
-	WindowPtr wp;
-	Lisp_Object frame;
-
-	read_socket_inev->kind = DRAG_N_DROP_EVENT;
-	read_socket_inev->code = 0;
-	read_socket_inev->modifiers = 0;
-
-	XSETINT (read_socket_inev->x, 0);
-	XSETINT (read_socket_inev->y, 0);
-
-	XSETFRAME (frame, f);
-	read_socket_inev->frame_or_window = Fcons (frame, file_list);
-
-#if 0
-	/* Regardless of whether Emacs was suspended or in the
-	   foreground, ask it to redraw its entire screen.  Otherwise
-	   parts of the screen can be left in an inconsistent
-	   state.  */
-	wp = FRAME_MAC_WINDOW (f);
-	if (wp)
-#if TARGET_API_MAC_CARBON
-	  {
-	    Rect r;
-
-	    GetWindowPortBounds (wp, &r);
-	    InvalWindowRect (wp, &r);
-	  }
-#else /* not TARGET_API_MAC_CARBON */
-	InvalRect (&(wp->portRect));
-#endif /* not TARGET_API_MAC_CARBON */
-#endif
-      }
-  }
-
-error_exit:
-  /* Nuke the coerced file list in any case */
-  err2 = AEDisposeDesc(&the_desc);
-
-descriptor_error_exit:
-  /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
-  return err;
-}
-
-
 #if TARGET_API_MAC_CARBON
 static pascal OSErr
 mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
@@ -9173,25 +9231,25 @@
       result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
       if (result == noErr)
 	{
-#ifdef MAC_OSX
-	  FSRef fref;
-#endif
-	  char unix_path_name[MAXPATHLEN];
-
-	  GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
-#ifdef MAC_OSX
-	  /* Use Carbon routines, otherwise it converts the file name
-	     to /Macintosh HD/..., which is not correct. */
-	  FSpMakeFSRef (&data.fileSpec, &fref);
-	  if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
-#else
-	  if (fsspec_to_posix_pathname (&data.fileSpec, unix_path_name,
-					sizeof (unix_path_name) - 1) == noErr)
-#endif
-	    /* x-dnd functions expect undecoded filenames.  */
-            file_list = Fcons (make_unibyte_string (unix_path_name,
-						    strlen (unix_path_name)),
-			       file_list);
+	  OSErr err;
+	  AEDesc desc;
+
+	  err = GetFlavorData (theDrag, theItem, flavorTypeHFS,
+			       &data, &size, 0L);
+	  if (err == noErr)
+	    err = AECoercePtr (typeFSS, &data.fileSpec, sizeof (FSSpec),
+			       TYPE_FILE_NAME, &desc);
+	  if (err == noErr)
+	    {
+	      Lisp_Object file;
+
+	      /* x-dnd functions expect undecoded filenames.  */
+	      file = make_uninit_string (AEGetDescDataSize (&desc));
+	      err = AEGetDescData (&desc, SDATA (file), SBYTES (file));
+	      if (err == noErr)
+		file_list = Fcons (file, file_list);
+	      AEDisposeDesc (&desc);
+	    }
 	}
     }
   /* If there are items in the list, construct an event and post it to
@@ -9213,8 +9271,8 @@
       XSETINT (event.x, mouse.h);
       XSETINT (event.y, mouse.v);
       XSETFRAME (frame, f);
-      event.frame_or_window = Fcons (frame, file_list);
-      event.arg = Qnil;
+      event.frame_or_window = frame;
+      event.arg = file_list;
       /* Post to the interrupt queue */
       kbd_buffer_store_event (&event);
       /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
@@ -9232,44 +9290,6 @@
 #endif
 
 
-/* Print Document Apple Event */
-static pascal OSErr
-do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
-{
-  return errAEEventNotHandled;
-}
-
-
-static pascal OSErr
-do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
-{
-#if USE_CARBON_EVENTS
-  OSErr err;
-  EventRef event = NULL;
-  static const HICommand quit_command = {kEventAttributeNone, kHICommandQuit};
-
-  err = CreateEvent (NULL, kEventClassCommand, kEventCommandProcess, 0,
-		     kEventAttributeUserEvent, &event);
-  if (err == noErr)
-    err = SetEventParameter (event, kEventParamDirectObject, typeHICommand,
-			     sizeof (HICommand), &quit_command);
-  if (err == noErr)
-    mac_store_application_menu_event (event);
-  if (event)
-    ReleaseEvent (event);
-
-  if (err == noErr)
-    return noErr;
-  else
-    return errAEEventNotHandled;
-#else
-  mac_store_application_menu_event (kHICommandQuit);
-
-  return noErr;
-#endif
-}
-
-
 #if __profile__
 void
 profiler_exit_proc ()
@@ -9321,9 +9341,11 @@
 
   init_environ ();
 
+  init_coercion_handler ();
+
   initialize_applescript ();
 
-  init_required_apple_events ();
+  init_apple_event_handler ();
 
   {
     char **argv;
@@ -9387,6 +9409,7 @@
   /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
 };
 
+
 static int
 keycode_to_xkeysym (int keyCode, int *xKeySym)
 {
@@ -9394,6 +9417,124 @@
   return *xKeySym != 0;
 }
 
+static unsigned char fn_keycode_to_xkeysym_table[] = {
+  /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+  /*0x30*/ 0, 0, 0, 0,
+  /*0x34*/ 0, 0, 0, 0,
+  /*0x38*/ 0, 0, 0, 0,
+  /*0x3C*/ 0, 0, 0, 0,
+
+  /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
+  /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
+  /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
+  /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
+
+  /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
+  /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
+  /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
+  /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
+
+  /*0x60*/ 0, 0, 0, 0,
+  /*0x64*/ 0, 0, 0, 0,
+  /*0x68*/ 0, 0, 0, 0,
+  /*0x6C*/ 0, 0, 0, 0,
+
+  /*0x70*/ 0, 0, 0, 0,
+  /*0x74*/ 0, 0, 0, 0,
+  /*0x78*/ 0, 0, 0, 0,
+  /*0x7C*/ 0, 0, 0, 0
+};
+static int
+convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
+{
+#ifdef MAC_OSX
+  /* Use the special map to translate keys when function modifier is
+     to be caught. KeyTranslate can't be used in that case.
+     We can't detect the function key using the input_event.modifiers,
+     because this uses the high word of an UInt32. Therefore,
+     we'll just read it out of the original eventRef.
+  */
+
+
+  /* TODO / known issues
+
+  - Fn-Shift-j is regonized as Fn-j and not Fn-J.
+  The above table always translates to lower characters. We need to use
+  the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
+
+  - The table is meant for English language keyboards, and it will work
+  for many others with the exception of key combinations like Fn-ö on
+  a German keyboard, which is currently mapped to Fn-;.
+  How to solve this without keeping separate tables for all keyboards
+  around? KeyTranslate isn't of much help here, as it only takes a 16-bit
+  value for keycode with the modifiers in he high byte, i.e. no room for the
+  Fn modifier. That's why we need the table.
+
+  */
+
+  UInt32 mods = 0;
+  if (!NILP(Vmac_function_modifier))
+    {
+      GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
+			 sizeof (UInt32), NULL, &mods);
+      if (mods & kEventKeyModifierFnMask)
+	{  *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
+
+	  return (*newCode != 0);
+	}
+    }
+#endif
+  return false;
+}
+
+static int
+backtranslate_modified_keycode(int mods, int keycode, int def)
+{
+  EventModifiers mapped_modifiers =
+    (NILP (Vmac_control_modifier) ? 0 : controlKey)
+    | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+    | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
+
+  if (mods & mapped_modifiers)
+    {
+      /* This code comes from Keyboard Resource,
+	 Appendix C of IM - Text.  This is necessary
+	 since shift is ignored in KCHR table
+	 translation when option or command is pressed.
+	 It also does not translate correctly
+	 control-shift chars like C-% so mask off shift
+	 here also.
+
+	 Not done for combinations with the option key (alt)
+	 unless it is to be caught by Emacs:  this is
+	 to preserve key combinations translated by the OS
+	 such as Alt-3.
+      */
+      /* Mask off modifier keys that are mapped to some Emacs
+	 modifiers.  */
+      int new_modifiers = mods & ~mapped_modifiers;
+      /* set high byte of keycode to modifier high byte*/
+      int new_keycode = keycode | new_modifiers;
+      Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+      unsigned long some_state = 0;
+      return (int) KeyTranslate (kchr_ptr, new_keycode,
+				 &some_state) & 0xff;
+      /* TO DO: Recognize two separate resulting characters, "for
+	 example, when the user presses Option-E followed by N, you
+	 can map this through the KeyTranslate function using the
+	 U.S. 'KCHR' resource to produce ´n, which KeyTranslate
+	 returns as two characters in the bytes labeled Character code
+	 1 and Character code 2." (from Carbon API doc) */
+
+    }
+  else
+    return def;
+}
+
+
 #if !USE_CARBON_EVENTS
 static RgnHandle mouse_region = NULL;
 
@@ -9411,7 +9552,7 @@
     mouse_region = NewRgn ();
 
   event_mask = everyEvent;
-  if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
+  if (!mac_ready_for_apple_events)
     event_mask -= highLevelEventMask;
 
   current_tick = TickCount ();
@@ -9522,6 +9663,7 @@
 		!= eventNotHandledErr)
 	      break;
 #endif
+	    last_mouse_glyph_frame = 0;
 
 	    if (dpyinfo->grabbed && last_mouse_frame
 		&& FRAME_LIVE_P (last_mouse_frame))
@@ -9933,12 +10075,11 @@
 	       will pass back noErr, otherwise it will pass back
 	       "eventNotHandledErr" and we can process it
 	       normally.  */
-	    if ((!NILP (Vmac_pass_command_to_system)
+	    if ((mac_pass_command_to_system
 		 || !(er.modifiers & cmdKey))
-		&& (!NILP (Vmac_pass_control_to_system)
+		&& (mac_pass_control_to_system
 		    || !(er.modifiers & controlKey))
-		&& (!NILP (Vmac_command_key_is_meta)
-		    && NILP (Vmac_option_modifier)
+		&& (NILP (Vmac_option_modifier)
 		    || !(er.modifiers & optionKey)))
 	      if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
 		  != eventNotHandledErr)
@@ -9982,49 +10123,34 @@
 		dpyinfo->mouse_face_hidden = 1;
 	      }
 
-	    if (keycode_to_xkeysym (keycode, &xkeysym))
+	    /* translate the keycode back to determine the original key */
+	    /* Convert key code if function key is pressed.
+	       Otherwise, if non-ASCII-event, take care of that
+	       without re-translating the key code. */
+#if USE_CARBON_EVENTS
+	    if (convert_fn_keycode (eventRef, keycode, &xkeysym))
 	      {
-		inev.code = 0xff00 | xkeysym;
-		inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+		inev.code = xkeysym;
+		/* this doesn't work - tried to add shift modifiers */
+		  inev.code =
+		    backtranslate_modified_keycode(er.modifiers & (~0x2200),
+						   xkeysym | 0x80,  xkeysym);
+		inev.kind = ASCII_KEYSTROKE_EVENT;
 	      }
 	    else
-	      {
-		if (er.modifiers & (controlKey |
-				    (NILP (Vmac_command_key_is_meta) ? optionKey
-				     : cmdKey)))
-		  {
-		    /* This code comes from Keyboard Resource,
-		       Appendix C of IM - Text.  This is necessary
-		       since shift is ignored in KCHR table
-		       translation when option or command is pressed.
-		       It also does not translate correctly
-		       control-shift chars like C-% so mask off shift
-		       here also */
-		    int new_modifiers = er.modifiers & 0xe600;
-		    /* mask off option and command */
-		    int new_keycode = keycode | new_modifiers;
-		    Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
-		    unsigned long some_state = 0;
-		    inev.code = KeyTranslate (kchr_ptr, new_keycode,
-					      &some_state) & 0xff;
-		  }
-		else if (!NILP (Vmac_option_modifier)
-			 && (er.modifiers & optionKey))
-		  {
-		    /* When using the option key as an emacs modifier,
-		       convert the pressed key code back to one
-		       without the Mac option modifier applied. */
-		    int new_modifiers = er.modifiers & ~optionKey;
-		    int new_keycode = keycode | new_modifiers;
-		    Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
-		    unsigned long some_state = 0;
-		    inev.code = KeyTranslate (kchr_ptr, new_keycode,
-					      &some_state) & 0xff;
-		  }
-		else
-		  inev.code = er.message & charCodeMask;
-		inev.kind = ASCII_KEYSTROKE_EVENT;
-	      }
+#endif
+	      if (keycode_to_xkeysym (keycode, &xkeysym))
+		{
+		  inev.code = 0xff00 | xkeysym;
+		  inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+		}
+	      else
+		{
+		  inev.code =
+		    backtranslate_modified_keycode(er.modifiers, keycode,
+						   er.message & charCodeMask);
+		  inev.kind = ASCII_KEYSTROKE_EVENT;
+		}
 	  }
 
 #if USE_CARBON_EVENTS
@@ -10251,8 +10377,8 @@
   main_device_handle = LMGetMainDevice();
 
   dpyinfo->reference_count = 0;
-  dpyinfo->resx = 75.0;
-  dpyinfo->resy = 75.0;
+  dpyinfo->resx = 72.0;
+  dpyinfo->resy = 72.0;
   dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
 #ifdef MAC_OSX
   /* HasDepth returns true if it is possible to have a 32 bit display,
@@ -10464,10 +10590,9 @@
 
   /* Map modifiers */
   mac_quit_char_modifiers = 0;
-  if (qc_modifiers & ctrl_modifier)  mac_quit_char_modifiers |= macCtrlKey;
-  if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
-  if (qc_modifiers & meta_modifier)  mac_quit_char_modifiers |= macMetaKey;
-  if (qc_modifiers & alt_modifier)   mac_quit_char_modifiers |= macAltKey;
+  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
@@ -10592,7 +10717,6 @@
   BLOCK_INPUT;
 
 #if TARGET_API_MAC_CARBON
-  init_required_apple_events ();
 
 #if USE_CARBON_EVENTS
 #ifdef MAC_OSX
@@ -10607,6 +10731,10 @@
 #endif	/* USE_CARBON_EVENTS */
 
 #ifdef MAC_OSX
+  init_coercion_handler ();
+
+  init_apple_event_handler ();
+
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
 #endif
@@ -10623,23 +10751,28 @@
   x_error_message_string = Qnil;
 #endif
 
+  Qcontrol = intern ("control");	staticpro (&Qcontrol);
+  Qmeta    = intern ("meta");		staticpro (&Qmeta);
+  Qalt     = intern ("alt");		staticpro (&Qalt);
+  Qhyper   = intern ("hyper");		staticpro (&Qhyper);
+  Qsuper   = intern ("super");		staticpro (&Qsuper);
   Qmodifier_value = intern ("modifier-value");
-  Qalt = intern ("alt");
-  Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
-  Qhyper = intern ("hyper");
-  Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
-  Qsuper = intern ("super");
-  Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
-
-  Qapplication = intern ("application");  staticpro (&Qapplication);
-  Qabout       = intern ("about");	  staticpro (&Qabout);
-
-#if USE_CARBON_EVENTS && defined (MAC_OSX)
-  Qpreferences = intern ("preferences");  staticpro (&Qpreferences);
+  staticpro (&Qmodifier_value);
+
+  Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
+  Fput (Qmeta,    Qmodifier_value, make_number (meta_modifier));
+  Fput (Qalt,     Qmodifier_value, make_number (alt_modifier));
+  Fput (Qhyper,   Qmodifier_value, make_number (hyper_modifier));
+  Fput (Qsuper,   Qmodifier_value, make_number (super_modifier));
+
+#if USE_CARBON_EVENTS
+  Qhicommand   = intern ("hicommand");    staticpro (&Qhicommand);
+#ifdef MAC_OSX
   Qservices    = intern ("services");	  staticpro (&Qservices);
   Qpaste       = intern ("paste");	  staticpro (&Qpaste);
   Qperform     = intern ("perform");	  staticpro (&Qperform);
 #endif
+#endif
 
 #ifdef MAC_OSX
   Fprovide (intern ("mac-carbon"), Qnil);
@@ -10648,9 +10781,6 @@
   staticpro (&Qreverse);
   Qreverse = intern ("reverse");
 
-  staticpro (&Qmac_ready_for_drag_n_drop);
-  Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
-
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;
 
@@ -10665,6 +10795,18 @@
   atsu_font_id_hash = Qnil;
 #endif
 
+  /* We don't yet support this, but defining this here avoids whining
+     from cus-start.el and other places, like "M-x set-variable".  */
+  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
+UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
+to 4.1, set this to nil.
+
+NOTE: Not supported on Mac yet.  */);
+  x_use_underline_position_properties = 0;
+
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
 	       doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
 #ifdef USE_TOOLKIT_SCROLL_BARS
@@ -10676,70 +10818,83 @@
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 
-  DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
-    doc: /* Non-nil means that the command key is used as the Emacs meta key.
-Otherwise the option key is used.  */);
-  Vmac_command_key_is_meta = Qt;
+/* Variables to configure modifier key assignment.  */
+
+  DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
+    doc: /* *Modifier key assumed when the Mac control key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  The default is `control'.  */);
+  Vmac_control_modifier = Qcontrol;
 
   DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
-    doc: /* Modifier to use for the Mac alt/option key.  The value can
-be alt, hyper, or super for the respective modifier.  If the value is
-nil then the key will act as the normal Mac option modifier.  */);
+    doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  If the value is nil then the key will act as the
+normal Mac control modifier, and the option key can be used to compose
+characters depending on the chosen Mac keyboard setting.  */);
   Vmac_option_modifier = Qnil;
 
-  DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
-    doc: /* Non-nil means that the control and meta keys are reversed.  This is
-useful for non-standard keyboard layouts.  */);
-  Vmac_reverse_ctrl_meta = Qnil;
+  DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
+    doc: /* *Modifier key assumed when the Mac command key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  The default is `meta'.  */);
+  Vmac_command_modifier = Qmeta;
+
+  DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
+    doc: /* *Modifier key assumed when the Mac function key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  Note that remapping the function key may lead to
+unexpected results for some keys on non-US/GB keyboards.  */);
+  Vmac_function_modifier = Qnil;
 
   DEFVAR_LISP ("mac-emulate-three-button-mouse",
 	       &Vmac_emulate_three_button_mouse,
-    doc: /* 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.
-'reverse means that the option-key will register for mouse-3
-and the command-key will register for mouse-2.  nil means that
-no emulation should be done and the modifiers should be placed
-on the mouse-1 event. */);
+    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.
+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.
+The symbol `reverse' means that the option-key will register for
+mouse-3 and the command-key will register for mouse-2.  */);
   Vmac_emulate_three_button_mouse = Qnil;
 
 #if USE_CARBON_EVENTS
-  DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
-   doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
-the right click will be mouse-3.
-Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
-  Vmac_wheel_button_is_mouse_2 = Qt;
-
-  DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
-   doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
-Toolbox for processing before Emacs sees it.  */);
-  Vmac_pass_command_to_system = Qt;
-
-  DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
-   doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
-Toolbox for processing before Emacs sees it.  */);
-  Vmac_pass_control_to_system = Qt;
-
-#endif
-
-  DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics,
-   doc: /* If non-nil, allow anti-aliasing.
+  DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
+   doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
+Otherwise, the right click will be treated as mouse-2 and the wheel
+button will be mouse-3.  */);
+  mac_wheel_button_is_mouse_2 = 1;
+
+  DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
+   doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox.  */);
+  mac_pass_command_to_system = 1;
+
+  DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
+   doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox.  */);
+  mac_pass_control_to_system = 1;
+
+#endif
+
+  DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
+   doc: /* *If non-nil, allow anti-aliasing.
 The text will be rendered using Core Graphics text rendering which
 may anti-alias the text.  */);
-  Vmac_use_core_graphics = Qnil;
+  mac_use_core_graphics = 0;
 
   /* Register an entry for `mac-roman' so that it can be used when
      creating the terminal frame on Mac OS 9 before loading
      term/mac-win.elc.  */
   DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
-               doc: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
+               doc: /* Alist of Emacs character sets vs text encodings and coding systems.
 Each entry should be of the form:
 
    (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
 
 where CHARSET-NAME is a string used in font names to identify the
-charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
-is a coding system corresponding to TEXT-ENCODING.  */);
+charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
+CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING.  */);
   Vmac_charset_info_alist =
     Fcons (list3 (build_string ("mac-roman"),
 		  make_number (smRoman), Qnil), Qnil);