]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
* macterm.c (syms_of_macterm): Provide the feature "mac-carbon" to
[gnu-emacs] / src / macterm.c
index ae1d7389d190032133b0c71b9da3441f5cc8424c..cae4172854e6a3c2683eb7e638a706b7fb890073 100644 (file)
@@ -58,6 +58,10 @@ Boston, MA 02111-1307, USA.  */
 #define max(a, b) ((a) > (b) ? (a) : (b))
 #undef init_process
 #define init_process emacs_init_process
+/* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
+   obtain events from the event queue.  If set to 0, WaitNextEvent is
+   used instead.  */
+#define USE_CARBON_EVENTS 1
 #else /* not MAC_OSX */
 #include <Quickdraw.h>
 #include <ToolUtils.h>
@@ -106,6 +110,15 @@ Boston, MA 02111-1307, USA.  */
 
 #define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))
 
+/* 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)
+
 \f
 /* Fringe bitmaps.  */
 
@@ -353,6 +366,7 @@ extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
 
 extern Lisp_Object x_icon_type P_ ((struct frame *));
 
+extern int inhibit_window_system;
 
 #if __MRC__
 QDGlobals qd;  /* QuickDraw global information structure.  */
@@ -405,7 +419,6 @@ void x_wm_set_icon_pixmap P_ ((struct frame *, int));
 void mac_initialize P_ ((void));
 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
 static int x_compute_min_glyph_bounds P_ ((struct frame *));
-enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
 static void x_draw_phys_cursor_glyph P_ ((struct window *,
                                          struct glyph_row *,
                                          enum draw_glyphs_face));
@@ -430,6 +443,8 @@ static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
 static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
 static void expose_frame P_ ((struct frame *, int, int, int, int));
 static int expose_window_tree P_ ((struct window *, Rect *));
+static void expose_overlaps P_ ((struct window *, struct glyph_row *,
+                                struct glyph_row *));
 static int expose_window P_ ((struct window *, Rect *));
 static void expose_area P_ ((struct window *, struct glyph_row *,
                             Rect *, enum glyph_row_area));
@@ -461,6 +476,8 @@ static void x_produce_stretch_glyph P_ ((struct it *));
 static void activate_scroll_bars (FRAME_PTR);
 static void deactivate_scroll_bars (FRAME_PTR);
 
+static int is_emacs_window (WindowPtr);
+
 extern int image_ascent (struct image *, struct face *);
 void x_set_offset (struct frame *, int, int, int);
 int x_bitmap_icon (struct frame *, Lisp_Object);
@@ -6225,8 +6242,41 @@ x_phys_cursor_in_rect_p (w, r)
 }
 
 
-/* Redraw the part of window W intersection rectagle FR.  Pixel
-   coordinates in FR are frame relative.  Call this function with
+/* Redraw those parts of glyphs rows during expose event handling that
+   overlap other rows.  Redrawing of an exposed line writes over parts
+   of lines overlapping that exposed line; this function fixes that.
+
+   W is the window being exposed.  FIRST_OVERLAPPING_ROW is the first
+   row in W's current matrix that is exposed and overlaps other rows.
+   LAST_OVERLAPPING_ROW is the last such row.  */
+
+static void
+expose_overlaps (w, first_overlapping_row, last_overlapping_row)
+     struct window *w;
+     struct glyph_row *first_overlapping_row;
+     struct glyph_row *last_overlapping_row;
+{
+  struct glyph_row *row;
+  
+  for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
+    if (row->overlapping_p)
+      {
+       xassert (row->enabled_p && !row->mode_line_p);
+         
+       if (row->used[LEFT_MARGIN_AREA])
+         x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
+  
+       if (row->used[TEXT_AREA])
+         x_fix_overlapping_area (w, row, TEXT_AREA);
+  
+       if (row->used[RIGHT_MARGIN_AREA])
+         x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
+      }
+}
+
+
+/* Redraw the part of window W intersection rectangle FR.  Pixel
+   coordinates in FR are frame-relative.  Call this function with
    input blocked.  Value is non-zero if the exposure overwrites
    mouse-face.  */
 
@@ -6266,7 +6316,8 @@ expose_window (w, fr)
       int yb = window_text_bottom_y (w);
       struct glyph_row *row;
       int cursor_cleared_p;
-
+      struct glyph_row *first_overlapping_row, *last_overlapping_row;
+  
       TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
              r.left, r.top, r.right, r.bottom));
 
@@ -6286,7 +6337,8 @@ expose_window (w, fr)
       else
        cursor_cleared_p = 0;
 
-      /* Find the first row intersecting the rectangle R.  */
+      /* Update lines intersecting rectangle R.  */
+      first_overlapping_row = last_overlapping_row = NULL;
       for (row = w->current_matrix->rows;
           row->enabled_p;
           ++row)
@@ -6299,10 +6351,17 @@ expose_window (w, fr)
              || (r.top >= y0 && r.top < y1)
              || (r.bottom > y0 && r.bottom < y1))
            {
+             if (row->overlapping_p)
+               {
+                 if (first_overlapping_row == NULL)
+                   first_overlapping_row = row;
+                 last_overlapping_row = row;
+               }
+             
              if (expose_line (w, row, &r))
                mouse_face_overwritten_p = 1;
            }
-
+             
          if (y1 >= yb)
            break;
        }
@@ -6319,9 +6378,13 @@ expose_window (w, fr)
 
       if (!w->pseudo_window_p)
        {
+         /* Fix the display of overlapping rows.  */
+         if (first_overlapping_row)
+           expose_overlaps (w, first_overlapping_row, last_overlapping_row);
+         
          /* Draw border between windows.  */
          x_draw_vertical_border (w);
-
+      
          /* Turn the cursor on again.  */
          if (cursor_cleared_p)
            x_update_window_cursor (w, 1);
@@ -7005,9 +7068,9 @@ note_mode_line_highlight (w, x, mode_line_p)
 
       if (glyph < end
          && STRINGP (glyph->object)
-         && XSTRING (glyph->object)->intervals
+         && STRING_INTERVALS (glyph->object)
          && glyph->charpos >= 0
-         && glyph->charpos < XSTRING (glyph->object)->size)
+         && glyph->charpos < SCHARS (glyph->object))
        {
          /* If we're on a string with `help-echo' text property,
             arrange for the help to be displayed.  This is done by
@@ -7267,7 +7330,8 @@ note_mouse_highlight (f, x, y)
 
              dpyinfo->mouse_face_face_id
                = face_at_buffer_position (w, pos, 0, 0,
-                                          &ignore, pos + 1, 1);
+                                          &ignore, pos + 1,
+                                          !dpyinfo->mouse_face_hidden);
 
              /* Display it as active.  */
              show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
@@ -7309,7 +7373,8 @@ note_mouse_highlight (f, x, y)
              if (BUFFERP (object))
                dpyinfo->mouse_face_face_id
                  = face_at_buffer_position (w, pos, 0, 0,
-                                            &ignore, pos + 1, 1);
+                                            &ignore, pos + 1,
+                                            !dpyinfo->mouse_face_hidden);
 
              /* Display it as active.  */
              show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
@@ -7328,7 +7393,7 @@ note_mouse_highlight (f, x, y)
              if (NILP (b))
                b = make_number (0);
              if (NILP (e))
-               e = make_number (XSTRING (object)->size - 1);
+               e = make_number (SCHARS (object) - 1);
              fast_find_string_pos (w, XINT (b), object,
                                    &dpyinfo->mouse_face_beg_col,
                                    &dpyinfo->mouse_face_beg_row,
@@ -7388,7 +7453,8 @@ note_mouse_highlight (f, x, y)
                  dpyinfo->mouse_face_window = window;
                  dpyinfo->mouse_face_face_id
                    = face_at_buffer_position (w, pos, 0, 0,
-                                              &ignore, pos + 1, 1);
+                                              &ignore, pos + 1,
+                                              !dpyinfo->mouse_face_hidden);
 
                  /* Display it as active.  */
                  show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
@@ -7426,7 +7492,7 @@ note_mouse_highlight (f, x, y)
            /* Try text properties.  */
            if (STRINGP (object)
                && charpos >= 0
-               && charpos < XSTRING (object)->size)
+               && charpos < SCHARS (object))
              {
                help = Fget_text_property (make_number (charpos),
                                           Qhelp_echo, object);
@@ -8237,9 +8303,12 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
   Point mouse_pos;
   int ignore1, ignore2;
   WindowPtr wp = FrontWindow ();
-  struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;            
+  struct frame *f;
   Lisp_Object frame, tail;
 
+  if (is_emacs_window(wp))
+    f = ((mac_output *) GetWRefCon (wp))->mFP;         
+
   BLOCK_INPUT;
 
   if (! NILP (last_mouse_scroll_bar) && insist == 0)
@@ -9030,7 +9099,7 @@ x_draw_bar_cursor (w, row, width)
        }
 
       if (width < 0)
-       width = f->output_data.mac->cursor_width;
+       width = FRAME_CURSOR_WIDTH (f);
 
       x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
       x_clip_to_row (w, row, gc, 0);
@@ -9232,11 +9301,10 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
   struct frame *f = XFRAME (w->frame);
   int new_cursor_type;
   int new_cursor_width;
+  int active_cursor;
   struct glyph_matrix *current_glyphs;
   struct glyph_row *glyph_row;
   struct glyph *glyph;
-  int cursor_non_selected;
-  int active_cursor = 1;
 
   /* This is pointless on invisible frames, and dangerous on garbaged
      windows and frames; in the latter case, the frame or window may
@@ -9266,65 +9334,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
 
   xassert (interrupt_input_blocked);
 
-  /* Set new_cursor_type to the cursor we want to be displayed.  In a
-     mini-buffer window, we want the cursor only to appear if we are
-     reading input from this window.  For the selected window, we want
-     the cursor type given by the frame parameter.  If explicitly
-     marked off, draw no cursor.  In all other cases, we want a hollow
-     box cursor.  */
-  cursor_non_selected 
-    = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
-                                 w->buffer));
-  new_cursor_width = -1;
-  if (cursor_in_echo_area
-      && FRAME_HAS_MINIBUF_P (f)
-      && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
-    {
-      if (w == XWINDOW (echo_area_window))
-       new_cursor_type = FRAME_DESIRED_CURSOR (f);
-      else
-       {
-         if (cursor_non_selected)
-           new_cursor_type = HOLLOW_BOX_CURSOR;
-         else
-           new_cursor_type = NO_CURSOR;
-         active_cursor = 0;
-       }
-    }
-  else
-    {
-      if (f != FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame
-          || w != XWINDOW (f->selected_window))
-        {
-         active_cursor = 0;
+  /* Set new_cursor_type to the cursor we want to be displayed.  */
+  new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
 
-          if (MINI_WINDOW_P (w) 
-              || !cursor_non_selected
-              || NILP (XBUFFER (w->buffer)->cursor_type))
-            new_cursor_type = NO_CURSOR;
-          else
-            new_cursor_type = HOLLOW_BOX_CURSOR;
-        }
-      else
-        {
-         struct buffer *b = XBUFFER (w->buffer);
-
-         if (EQ (b->cursor_type, Qt))
-            new_cursor_type = FRAME_DESIRED_CURSOR (f);
-         else
-           new_cursor_type = x_specified_cursor_type (b->cursor_type, 
-                                                      &new_cursor_width);
-         if (w->cursor_off_p)
-           {
-             if (new_cursor_type == FILLED_BOX_CURSOR)
-               new_cursor_type = HOLLOW_BOX_CURSOR;
-             else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
-               new_cursor_width = 1;
-             else
-               new_cursor_type = NO_CURSOR;
-           }
-       }
-    }
 
   /* If cursor is currently being shown and we don't want it to be or
      it is in the wrong place, or the cursor type is not what we want,
@@ -9334,7 +9346,7 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
          || w->phys_cursor.x != x
          || w->phys_cursor.y != y
          || new_cursor_type != w->phys_cursor_type
-         || (new_cursor_type == BAR_CURSOR
+         || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
              && new_cursor_width != w->phys_cursor_width)))
     x_erase_phys_cursor (w);
 
@@ -9365,6 +9377,8 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
          x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
          break;
 
+       case HBAR_CURSOR:
+         /* TODO.  For now, just draw bar cursor. */
        case BAR_CURSOR:
          x_draw_bar_cursor (w, glyph_row, new_cursor_width);
          break;
@@ -9469,7 +9483,7 @@ x_bitmap_icon (f, icon)
   if (NILP (icon))
     hicon = LoadIcon (hinst, EMACS_CLASS);
   else if (STRINGP (icon))
-    hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
+    hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
                       LR_DEFAULTSIZE | LR_LOADFROMFILE);
   else if (SYMBOLP (icon))
     {
@@ -9606,7 +9620,7 @@ x_new_fontset (f, fontsetname)
        to do.  */
     return fontset_name (fontset);
 
-  result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
+  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
@@ -10092,108 +10106,21 @@ void
 x_iconify_frame (f)
      struct frame *f;
 {
-#if 0 /* MAC_TODO: really no iconify on Mac */
-  int result;
-  Lisp_Object type;
-
   /* Don't keep the highlight on an invisible frame.  */
-  if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
-    FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
+  if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
+    FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
 
+#if 0
+  /* Review:  Since window is still visible in dock, still allow updates? */
   if (f->async_iconified)
     return;
+#endif
 
   BLOCK_INPUT;
 
-  FRAME_SAMPLE_VISIBILITY (f);
-
-  type = x_icon_type (f);
-  if (!NILP (type))
-    x_bitmap_icon (f, type);
-
-#ifdef USE_X_TOOLKIT
-
-  if (! FRAME_VISIBLE_P (f))
-    {
-      if (! EQ (Vx_no_window_manager, Qt))
-       x_wm_set_window_state (f, IconicState);
-      /* This was XtPopup, but that did nothing for an iconified frame.  */
-      XtMapWidget (f->output_data.x->widget);
-      /* The server won't give us any event to indicate
-        that an invisible frame was changed to an icon,
-        so we have to record it here.  */
-      f->iconified = 1;
-      f->visible = 1;
-      f->async_iconified = 1;
-      f->async_visible = 0;
-      UNBLOCK_INPUT;
-      return;
-    }
-
-  result = XIconifyWindow (FRAME_X_DISPLAY (f),
-                          XtWindow (f->output_data.x->widget),
-                          DefaultScreen (FRAME_X_DISPLAY (f)));
-  UNBLOCK_INPUT;
-
-  if (!result)
-    error ("Can't notify window manager of iconification");
-
-  f->async_iconified = 1;
-  f->async_visible = 0;
-
-
-  BLOCK_INPUT;
-  XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
-#else /* not USE_X_TOOLKIT */
-
-  /* Make sure the X server knows where the window should be positioned,
-     in case the user deiconifies with the window manager.  */
-  if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
-    x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
-
-  /* Since we don't know which revision of X we're running, we'll use both
-     the X11R3 and X11R4 techniques.  I don't know if this is a good idea.  */
-
-  /* X11R4: send a ClientMessage to the window manager using the
-     WM_CHANGE_STATE type.  */
-  {
-    XEvent message;
-
-    message.xclient.window = FRAME_X_WINDOW (f);
-    message.xclient.type = ClientMessage;
-    message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
-    message.xclient.format = 32;
-    message.xclient.data.l[0] = IconicState;
-
-    if (! XSendEvent (FRAME_X_DISPLAY (f),
-                     DefaultRootWindow (FRAME_X_DISPLAY (f)),
-                     False,
-                     SubstructureRedirectMask | SubstructureNotifyMask,
-                     &message))
-      {
-       UNBLOCK_INPUT_RESIGNAL;
-       error ("Can't notify window manager of iconification");
-      }
-  }
-
-  /* X11R3: set the initial_state field of the window manager hints to
-     IconicState.  */
-  x_wm_set_window_state (f, IconicState);
-
-  if (!FRAME_VISIBLE_P (f))
-    {
-      /* If the frame was withdrawn, before, we must map it.  */
-      XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-    }
-
-  f->async_iconified = 1;
-  f->async_visible = 0;
-
-  XFlush (FRAME_X_DISPLAY (f));
+  CollapseWindow (FRAME_MAC_WINDOW (f), true);
+  
   UNBLOCK_INPUT;
-#endif /* not USE_X_TOOLKIT */
-#endif /* MAC_TODO */
 }
 
 \f
@@ -10747,8 +10674,14 @@ init_font_name_table ()
                                                              sc));
              }
            else
-             add_font_name_table_entry (mac_to_x_fontname (name, size, style,
-                                                           sc));
+             {
+               add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                             style, sc));
+               if (smJapanese == sc)
+                 add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                               style,
+                                                               -smJapanese));
+             }
        }
   
       /* Dispose of the iterators.  */
@@ -10833,7 +10766,7 @@ init_font_name_table ()
                            = mac_to_x_fontname (name,
                                                 assc_entry->fontSize,
                                                 assc_entry->fontStyle,
-                                                smRoman);
+                                                -smJapanese);
                        }
                    }
                }
@@ -10854,11 +10787,9 @@ init_font_name_table ()
 
 
 /* Return a list of at most MAXNAMES font specs matching the one in
-   PATTERN.  Note that each '*' in the PATTERN matches exactly one
-   field of the font spec, unlike X in which an '*' in a font spec can
-   match a number of fields.  The result is in the Mac implementation
-   all fonts must be specified by a font spec with all 13 fields
-   (although many of these can be "*'s").  */
+   PATTERN.  Cache matching fonts for patterns in
+   dpyinfo->name_list_element to avoid looking them up again by
+   calling mac_font_pattern_match (slow).  */
 
 Lisp_Object
 x_list_fonts (struct frame *f,
@@ -10867,15 +10798,29 @@ x_list_fonts (struct frame *f,
               int maxnames)
 {
   char *ptnstr;
-  Lisp_Object newlist = Qnil;
+  Lisp_Object newlist = Qnil, tem, key;
   int n_fonts = 0;
   int i;
   struct gcpro gcpro1, gcpro2;
+  struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
 
   if (font_name_table == NULL)  /* Initialize when first used.  */
     init_font_name_table ();
 
-  ptnstr = XSTRING (pattern)->data;
+  if (dpyinfo)
+    {
+      tem = XCDR (dpyinfo->name_list_element);
+      key = Fcons (pattern, make_number (maxnames));
+
+      newlist = Fassoc (key, tem);
+      if (!NILP (newlist))
+       {
+         newlist = Fcdr_safe (newlist);
+         goto label_cached;
+       }
+    }
+
+  ptnstr = SDATA (pattern);
 
   GCPRO2 (pattern, newlist);
 
@@ -10896,6 +10841,14 @@ x_list_fonts (struct frame *f,
 
   UNGCPRO;
 
+  if (dpyinfo)
+    {
+      XSETCDR (dpyinfo->name_list_element,
+              Fcons (Fcons (key, newlist),
+                     XCDR (dpyinfo->name_list_element)));
+    }
+ label_cached:
+  
   return newlist;
 }
 
@@ -11105,7 +11058,7 @@ XLoadQueryFont (Display *dpy, char *fontname)
     if (sscanf (name, 
                "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
                cs) == 1
-       && 0 == strcmp (cs, "mac-roman"))  
+       && 0 == strcmp (cs, "jisx0201.1976-0"))  
       font->mac_scriptcode = smRoman;
   }
   
@@ -11217,9 +11170,9 @@ x_load_font (f, fontname, size)
        for (tail = font_names; CONSP (tail); tail = XCDR (tail))
          if (dpyinfo->font_table[i].name
              && (!strcmp (dpyinfo->font_table[i].name,
-                          XSTRING (XCAR (tail))->data)
+                          SDATA (XCAR (tail)))
                  || !strcmp (dpyinfo->font_table[i].full_name,
-                             XSTRING (XCAR (tail))->data)))
+                             SDATA (XCAR (tail)))))
            return (dpyinfo->font_table + i);
     }
 
@@ -11237,7 +11190,7 @@ x_load_font (f, fontname, size)
        a bug of not finding a font even if the font surely exists and
        is loadable by XLoadQueryFont.  */
     if (size > 0 && !NILP (font_names))
-      fontname = (char *) XSTRING (XCAR (font_names))->data;
+      fontname = (char *) SDATA (XCAR (font_names));
 
     font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
     if (!font)
@@ -11431,7 +11384,7 @@ same_x_server (name1, name2)
      char *name1, *name2;
 {
   int seen_colon = 0;
-  unsigned char *system_name = XSTRING (Vsystem_name)->data;
+  unsigned char *system_name = SDATA (Vsystem_name);
   int system_name_length = strlen (system_name);
   int length_until_period = 0;
 
@@ -11534,9 +11487,26 @@ static long app_sleep_time = WNE_SLEEP_AT_RESUME;
 
 Boolean        terminate_flag = false;
 
-/* true if using command key as meta key */
+/* True if using command key as meta key.  */
 Lisp_Object Vmac_command_key_is_meta;
 
+/* True if the ctrl and meta keys should be reversed.  */
+Lisp_Object Vmac_reverse_ctrl_meta;
+
+#if USE_CARBON_EVENTS
+/* True 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
+   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
+   for processing before Emacs sees it.  */
+Lisp_Object Vmac_pass_control_to_system;
+#endif
+
 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
    to this text encoding */
 int mac_keyboard_text_encoding;
@@ -11551,13 +11521,23 @@ Lisp_Object drag_and_drop_file_list;
 Point saved_menu_event_location;
 
 /* Apple Events */
-static void init_required_apple_events(void);
+static void init_required_apple_events (void);
 static pascal OSErr
-do_ae_open_application(const AppleEvent *, AppleEvent *, long);
+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);
+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);
+
+/* Drag and Drop */
+static OSErr init_mac_drag_n_drop ();
+static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference); 
+
+#if USE_CARBON_EVENTS
+/* Preliminary Support for the OSX Services Menu */
+static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
+static void init_service_handler ();
+#endif
 
 extern void init_emacs_passwd_dir ();
 extern int emacs_main (int, char **, char **);
@@ -11566,6 +11546,104 @@ extern void check_alarm ();
 extern void initialize_applescript();
 extern void terminate_applescript();
 
+static unsigned int 
+#if USE_CARBON_EVENTS
+mac_to_emacs_modifiers (UInt32 mods)
+#else
+mac_to_emacs_modifiers (EventModifiers mods)
+#endif
+{
+  unsigned int result = 0;
+  if (mods & macShiftKey)
+    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;
+  return result;
+}
+
+#if USE_CARBON_EVENTS
+/* Obtains the event modifiers from the event ref and then calls
+   mac_to_emacs_modifiers.  */
+static int 
+mac_event_to_emacs_modifiers (EventRef eventRef) 
+{
+  UInt32 mods = 0;
+  GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
+                   sizeof (UInt32), NULL, &mods);
+  return mac_to_emacs_modifiers (mods);
+}
+
+/* Given an event ref, return the code to use for the mouse button
+   code in the emacs input_event.  */
+static int
+mac_get_mouse_btn (EventRef ref) 
+{
+  EventMouseButton result = kEventMouseButtonPrimary;
+  GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
+                   sizeof (EventMouseButton), NULL, &result);
+  switch (result) 
+    {
+    case kEventMouseButtonPrimary:
+      return 0;
+    case kEventMouseButtonSecondary:
+      return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2; 
+    case kEventMouseButtonTertiary:
+    case 4:  /* 4 is the number for the mouse wheel button */
+      return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1; 
+    default:
+      return 0;
+    }
+}
+
+/* Normally, ConvertEventRefToEventRecord will correctly handle all
+   events.  However the click of the mouse wheel is not converted to a
+   mouseDown or mouseUp event.  This calls ConvertEventRef, but then
+   checks to see if it is a mouse up or down carbon event that has not
+   been converted, and if so, converts it by hand (to be picked up in
+   the XTread_socket loop).  */
+static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) 
+{
+  Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
+  /* Do special case for mouse wheel button.  */
+  if (!result && GetEventClass (eventRef) == kEventClassMouse) 
+    { 
+      UInt32 kind = GetEventKind (eventRef);
+      if (kind == kEventMouseDown && !(eventRec->what == mouseDown)) 
+       {
+         eventRec->what = mouseDown;
+         result=1;
+       }
+      if (kind == kEventMouseUp && !(eventRec->what == mouseUp)) 
+       {
+         eventRec->what = mouseUp;
+         result=1;
+       }
+      if (result) 
+       {
+         /* Need where and when.  */
+         UInt32 mods;
+         GetEventParameter (eventRef, kEventParamMouseLocation,
+                            typeQDPoint, NULL, sizeof (Point),
+                            NULL, &eventRec->where);
+         /* Use two step process because new event modifiers are
+            32-bit and old are 16-bit.  Currently, only loss is
+            NumLock & Fn. */
+         GetEventParameter (eventRef, kEventParamKeyModifiers,
+                            typeUInt32, NULL, sizeof (UInt32),
+                            NULL, &mods);
+         eventRec->modifiers = mods;
+         
+         eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
+       }
+    }
+  return result;
+}
+
+#endif
 
 static void
 do_get_menus (void)
@@ -11770,17 +11848,22 @@ static void
 do_mouse_moved (Point mouse_pos)
 {
   WindowPtr wp = FrontWindow ();
-  struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;            
+  struct frame *f;
 
+  if (is_emacs_window (wp)) 
+    {
+      f = ((mac_output *) GetWRefCon (wp))->mFP;            
+      
 #if TARGET_API_MAC_CARBON
       SetPort (GetWindowPort (wp));
 #else
       SetPort (wp);
 #endif
 
-  GlobalToLocal (&mouse_pos);
-
-  note_mouse_movement (f, &mouse_pos);
+      GlobalToLocal (&mouse_pos);
+      
+      note_mouse_movement (f, &mouse_pos);
+    }
 }
 
 
@@ -11993,6 +12076,13 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   SetPort (save_port);
 }
 
+/* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
+static OSErr
+init_mac_drag_n_drop ()
+{
+  OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
+  return result;
+}
 
 /* Intialize AppleEvent dispatcher table for the required events.  */
 void
@@ -12066,6 +12156,104 @@ init_required_apple_events ()
     abort ();
 }
 
+#if USE_CARBON_EVENTS
+
+void
+init_service_handler ()
+{
+  EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
+                          {kEventClassService, kEventServiceCopy},
+                          {kEventClassService, kEventServicePaste}};
+  InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
+                                 3, specs, NULL, NULL);
+}
+
+/*
+   MAC_TODO: Check to see if this is called by AEProcessDesc...
+ */
+OSStatus
+mac_handle_service_event (EventHandlerCallRef callRef,
+                         EventRef event, void *data)
+{
+  OSStatus err = noErr; 
+  switch (GetEventKind (event))
+    {
+    case kEventServiceGetTypes: 
+      {
+       CFMutableArrayRef copyTypes, pasteTypes;
+       CFStringRef type;
+       Boolean selection = true;
+       /*
+         GetEventParameter(event, kEventParamServicePasteTypes,
+         typeCFMutableArrayRef, NULL,
+         sizeof (CFMutableArrayRef), NULL, &pasteTypes);
+       */
+       GetEventParameter(event, kEventParamServiceCopyTypes,
+                         typeCFMutableArrayRef, NULL,
+                         sizeof (CFMutableArrayRef), NULL, &copyTypes);
+       type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
+       if (type) {
+         CFArrayAppendValue (copyTypes, type);
+         //CFArrayAppendValue (pasteTypes, type);
+         CFRelease (type);
+       }
+      }
+    case kEventServiceCopy:
+      {
+       ScrapRef currentScrap, specificScrap;
+       char * buf = "";
+       Size byteCount = 0;
+
+       GetCurrentScrap (&currentScrap);
+
+       err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
+       if (err == noErr)
+         {
+           void *buffer = xmalloc (byteCount);
+           if (buffer != NULL)
+             {
+               GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
+                                  sizeof (ScrapRef), NULL, &specificScrap);
+             
+               err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
+                                         &byteCount, buffer);
+               if (err == noErr)
+                 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
+                                 kScrapFlavorMaskNone, byteCount, buffer);
+               xfree (buffer);
+             } 
+         }
+       err = noErr;
+      }
+    case kEventServicePaste:
+      {
+       /*
+       // Get the current location
+        Size     byteCount;
+        ScrapRef specificScrap;
+        GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
+                         sizeof(ScrapRef), NULL, &specificScrap);
+        err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
+        if (err == noErr) {
+         void * buffer = xmalloc(byteCount);
+         if (buffer != NULL ) {
+           err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText, 
+                                    &byteCount, buffer);
+           if (err == noErr) {
+             // Actually place in the buffer
+             BLOCK_INPUT;
+             // Get the current "selection" string here
+             UNBLOCK_INPUT;
+           }
+         }
+         xfree(buffer);
+        }
+        */
+      }   
+    }
+  return err;
+}
+#endif
 
 /* Open Application Apple Event */
 static pascal OSErr
@@ -12161,6 +12349,84 @@ descriptor_error_exit:
 }
 
 
+static pascal OSErr
+mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
+                    DragReference theDrag)
+{
+  short items;
+  short index;
+  FlavorFlags theFlags;
+  Point mouse;
+  OSErr result;
+  ItemReference theItem;
+  HFSFlavor data;
+  FSRef fref;
+  Size size = sizeof (HFSFlavor);
+
+  drag_and_drop_file_list = Qnil;
+  GetDragMouse (theDrag, &mouse, 0L);
+  CountDragItems (theDrag, &items);
+  for (index = 1; index <= items; index++) 
+    {
+      /* Only handle file references.  */
+      GetDragItemReferenceNumber (theDrag, index, &theItem);
+      result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
+      if (result == noErr)
+       {
+#ifdef MAC_OSX
+         FSRef frref;
+#else
+         Str255 path_name;
+#endif
+         Str255 unix_path_name;
+         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 (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
+                                     data.fileSpec.parID, data.fileSpec.name) &&
+             mac_to_posix_pathname (path_name, unix_path_name, 255))
+#endif
+            drag_and_drop_file_list = Fcons (build_string (unix_path_name),
+                                            drag_and_drop_file_list);
+       }
+      else
+       return;
+    }
+  /* If there are items in the list, construct an event and post it to
+     the queue like an interrupt using kbd_buffer_store_event.  */
+  if (!NILP (drag_and_drop_file_list)) 
+    {
+      struct input_event event;
+      Lisp_Object frame;
+      struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
+      SetPort (GetWindowPort (window));
+      GlobalToLocal (&mouse);
+
+      event.kind = DRAG_N_DROP_EVENT;
+      event.code = 0;
+      event.modifiers = 0;
+      event.timestamp = TickCount () * (1000 / 60);
+      XSETINT (event.x, mouse.h);
+      XSETINT (event.y, mouse.v);
+      XSETFRAME (frame, f);
+      event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
+      event.arg = Qnil;
+      /* Post to the interrupt queue */
+      kbd_buffer_store_event (&event);
+      /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
+      {
+       ProcessSerialNumber psn;
+       GetCurrentProcess (&psn);
+       SetFrontProcess (&psn);
+      }
+    }
+}
+
+
 /* Print Document Apple Event */
 static pascal OSErr
 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
@@ -12272,7 +12538,7 @@ static unsigned char keycode_to_xkeysym_table[] = {
 /* 0x00 - 0x3f */
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,        0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, '\x0d', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 /* 0x40 */
   0, '\xae' /* kp. */, 0, '\xaa' /* kp* */, 
@@ -12308,7 +12574,12 @@ keycode_to_xkeysym (int keyCode, int *xKeySym)
 int
 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
 {
-  int count = 0;
+  int count = 0; 
+#if USE_CARBON_EVENTS
+  OSStatus rneResult;
+  EventRef eventRef;
+  EventMouseButton mouseBtn;
+#endif
   EventRecord er;
   int the_modifiers;
   EventMask event_mask;
@@ -12354,7 +12625,54 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
   if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
     event_mask -= highLevelEventMask;
 
+#if USE_CARBON_EVENTS
+  rneResult = ReceiveNextEvent (0, NULL, 
+                               expected
+                               ? TicksToEventTime (app_sleep_time)
+                               : 0,
+                               kEventRemoveFromQueue, &eventRef);
+  if (!rneResult)
+    {
+      /* Handle new events */
+      if (!mac_convert_event_ref (eventRef, &er)) 
+       switch (GetEventClass (eventRef)) 
+         {
+         case kEventClassMouse:
+           if (GetEventKind (eventRef) == kEventMouseWheelMoved) 
+             {
+               SInt32 delta;
+               Point point;
+               WindowPtr window_ptr = FrontNonFloatingWindow ();
+               struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
+               GetEventParameter(eventRef, kEventParamMouseWheelDelta,
+                                 typeSInt32, NULL, sizeof (SInt32),
+                                 NULL, &delta);
+               GetEventParameter(eventRef, kEventParamMouseLocation,
+                                 typeQDPoint, NULL, sizeof (Point),
+                                 NULL, &point);
+               bufp->kind = MOUSE_WHEEL_EVENT;
+               bufp->code = delta;
+               bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
+               SetPort (GetWindowPort (window_ptr));
+               GlobalToLocal (&point);
+               XSETINT (bufp->x, point.h);
+               XSETINT (bufp->y, point.v);
+               XSETFRAME (bufp->frame_or_window, mwp->mFP);
+               bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
+               count++;
+             }
+           else             
+             SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+
+           break;
+         default:
+           /* Send the event to the appropriate receiver.  */
+           SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+         }
+      else
+#else
   if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
+#endif /* USE_CARBON_EVENTS */
     switch (er.what)
       {
       case mouseDown:
@@ -12363,6 +12681,17 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
          WindowPtr window_ptr = FrontWindow ();
          SInt16 part_code;
 
+#if USE_CARBON_EVENTS
+         /* This is needed to send mouse events like aqua window buttons
+            to the correct handler.  */
+         if (eventNotHandledErr != SendEventToEventTarget (eventRef, GetEventDispatcherTarget ())) {
+           break;
+         }
+
+         if (!is_emacs_window(window_ptr))
+           break;
+#endif
+
           if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
              && er.what == mouseUp)
             {
@@ -12378,11 +12707,20 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
 
              GlobalToLocal (&mouse_loc);
                  
+#if USE_CARBON_EVENTS
+             bufp->code = mac_get_mouse_btn (eventRef);
+#else
              bufp->code = 0;  /* only one mouse button */
+#endif
               bufp->kind = SCROLL_BAR_CLICK_EVENT;
               bufp->frame_or_window = tracked_scroll_bar->window;
               bufp->part = scroll_bar_handle;
-              bufp->modifiers = up_modifier;
+#if USE_CARBON_EVENTS
+             bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+             bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+              bufp->modifiers |= up_modifier;
              bufp->timestamp = er.when * (1000 / 60);
                /* ticks to milliseconds */
 
@@ -12435,7 +12773,12 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
 #else
                  control_part_code = FindControl (mouse_loc, window_ptr, &ch);
 #endif           
+
+#if USE_CARBON_EVENTS
+                 bufp->code = mac_get_mouse_btn (eventRef);
+#else            
                  bufp->code = 0;  /* only one mouse button */
+#endif
                  XSETINT (bufp->x, mouse_loc.h);
                  XSETINT (bufp->y, mouse_loc.v);
                  bufp->timestamp = er.when * (1000 / 60);
@@ -12475,13 +12818,19 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
                        mouse_tracking_in_progress = mouse_tracking_none;
                    }
                                
+#if USE_CARBON_EVENTS
+                 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+                 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+
                  switch (er.what)
                    {
                    case mouseDown:
-                     bufp->modifiers = down_modifier;
+                     bufp->modifiers |= down_modifier;
                      break;
                    case mouseUp:
-                     bufp->modifiers = up_modifier;
+                     bufp->modifiers |= up_modifier;
                      break;
                    }
                                                                
@@ -12533,6 +12882,9 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
       case updateEvt:
       case osEvt:
       case activateEvt:
+#if USE_CARBON_EVENTS
+       if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
+#endif 
        do_events (&er);
        break;
        
@@ -12542,8 +12894,33 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
          int keycode = (er.message & keyCodeMask) >> 8;
          int xkeysym;
          
+#if USE_CARBON_EVENTS
+         /* When using Carbon Events, we need to pass raw keyboard events
+            to the TSM ourselves.  If TSM handles it, it will pass back
+            noErr, otherwise it will pass back "eventNotHandledErr" and
+            we can process it normally.   */
+         if ((!NILP (Vmac_pass_command_to_system)
+              || !(er.modifiers & cmdKey))
+             && (!NILP (Vmac_pass_control_to_system)
+                 || !(er.modifiers & controlKey)))
+           {
+             OSStatus err;
+             err = SendEventToEventTarget (eventRef,
+                                           GetEventDispatcherTarget ());
+             if (err != eventNotHandledErr)
+               break;
+           }
+#endif
+         
+         if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
+           {
+             SysBeep (1);
+             UNBLOCK_INPUT;
+             return 0;
+           }
+         
          ObscureCursor ();
-
+         
          if (keycode == 0x33)  /* delete key (charCode translated to 0x8) */
            {
              bufp->code = 0x7f;
@@ -12553,105 +12930,96 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
            {
              bufp->code = 0xff00 | xkeysym;
              bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
-           }         
+           }      
          else
            {
-             if (er.modifiers
-                 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
-               {
-                 /* This code comes from Keyboard Resource, Appendix
+             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. */
-                 int new_modifiers = er.modifiers & 0xf600;
-                   /* mask off option and command */
-                 int new_keycode = keycode | new_modifiers;
-                 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
-                 unsigned long some_state = 0;
-                 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
+                    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;
+                 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
                                             &some_state) & 0xff;
-               }
+               }
              else
-               bufp->code = er.message & charCodeMask;
+               bufp->code = er.message & charCodeMask;
              bufp->kind = ASCII_KEYSTROKE_EVENT;
            }
        }
-
-        /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
-           convert non-ASCII characters typed at the Mac keyboard
-           (presumed to be in the Mac Roman encoding) to iso-latin-1
-           encoding before they are passed to Emacs.  This enables the
-           Mac keyboard to be used to enter non-ASCII iso-latin-1
-           characters directly.  */
-        if (mac_keyboard_text_encoding != kTextEncodingMacRoman
+       
+       /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
+          convert non-ASCII characters typed at the Mac keyboard
+          (presumed to be in the Mac Roman encoding) to iso-latin-1
+          encoding before they are passed to Emacs.  This enables the
+          Mac keyboard to be used to enter non-ASCII iso-latin-1
+          characters directly.  */
+       if (mac_keyboard_text_encoding != kTextEncodingMacRoman
            && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
          {
-            static TECObjectRef converter = NULL;
-            OSStatus the_err = noErr;
-            OSStatus convert_status = noErr;
-
-            if (converter ==  NULL)
-              {
-                the_err = TECCreateConverter (&converter,
+           static TECObjectRef converter = NULL;
+           OSStatus the_err = noErr;
+           OSStatus convert_status = noErr;
+           
+           if (converter ==  NULL)
+             {
+               the_err = TECCreateConverter (&converter,
                                              kTextEncodingMacRoman,
                                              mac_keyboard_text_encoding);
-                current_mac_keyboard_text_encoding
+               current_mac_keyboard_text_encoding
                  = mac_keyboard_text_encoding;
-              }
-            else if (mac_keyboard_text_encoding
+             }
+           else if (mac_keyboard_text_encoding
                     != current_mac_keyboard_text_encoding)
-              {
-                /* Free the converter for the current encoding before
-                   creating a new one.  */
-                TECDisposeConverter (converter);
-                the_err = TECCreateConverter (&converter,
+             {
+               /* Free the converter for the current encoding before
+                  creating a new one.  */
+               TECDisposeConverter (converter);
+               the_err = TECCreateConverter (&converter,
                                              kTextEncodingMacRoman,
                                              mac_keyboard_text_encoding);
-                current_mac_keyboard_text_encoding
+               current_mac_keyboard_text_encoding
                  = mac_keyboard_text_encoding;
-              
-              
-            if (the_err == noErr)
-              {
-                unsigned char ch = bufp->code;
-                ByteCount actual_input_length, actual_output_length;
-                unsigned char outch;
-                  
-                convert_status = TECConvertText (converter, &ch, 1,
+             } 
+           
+           if (the_err == noErr)
+             {
+               unsigned char ch = bufp->code;
+               ByteCount actual_input_length, actual_output_length;
+               unsigned char outch;
+               
+               convert_status = TECConvertText (converter, &ch, 1,
                                                 &actual_input_length,
-                                                 &outch, 1,
+                                                &outch, 1,
                                                 &actual_output_length);
-                if (convert_status == noErr
+               if (convert_status == noErr
                    && actual_input_length == 1
                    && actual_output_length == 1)
-                  bufp->code = outch;
-              }
+                 bufp->code = outch;
+             }
          }
-
-       the_modifiers = 0;
-       if (er.modifiers & shiftKey)
-         the_modifiers |= shift_modifier;
-       if (er.modifiers & controlKey)
-         the_modifiers |= ctrl_modifier;
-       /* Use option or command key as meta depending on value of
-          mac-command-key-is-meta.  */
-       if (er.modifiers
-           & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
-         the_modifiers |= meta_modifier;
-       /* If the Mac option key is meta, then make Emacs recognize
-          the Mac command key as alt.  */
-       if (NILP (Vmac_command_key_is_meta) && (er.modifiers & cmdKey))
-         the_modifiers |= alt_modifier;
-
-       bufp->modifiers = the_modifiers;
-                               
+       
+#if USE_CARBON_EVENTS
+       bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+       bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+       
        {
          mac_output *mwp
            = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
          XSETFRAME (bufp->frame_or_window, mwp->mFP);
        }
-
+       
        bufp->timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
 
        count++;
@@ -12666,21 +13034,31 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
            constuct_drag_n_drop in w32term.c.  */
         if (!NILP (drag_and_drop_file_list))
           {
-            struct frame *f;
+            struct frame *f = NULL;
             WindowPtr wp;
             Lisp_Object frame;
 
-            wp = FrontWindow ();
-            if (!wp)
-              f = NULL;
-            else
-              f = ((mac_output *) GetWRefCon (wp))->mFP;            
-            
+            wp = FrontNonFloatingWindow ();
+           
+           if (!wp)
+             {
+               struct frame *f = XFRAME (XCAR (Vframe_list));
+               CollapseWindow (FRAME_MAC_WINDOW (f), false);
+               wp = FrontNonFloatingWindow ();
+             }
+
+            if (wp && is_emacs_window(wp))
+               f = ((mac_output *) GetWRefCon (wp))->mFP;            
+
             bufp->kind = DRAG_N_DROP_EVENT;
             bufp->code = 0;
             bufp->timestamp = er.when * (1000 / 60);
              /* ticks to milliseconds */
-            bufp->modifiers = 0;
+#if USE_CARBON_EVENTS
+           bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+           bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
 
             XSETINT (bufp->x, 0);
             XSETINT (bufp->y, 0);
@@ -12706,10 +13084,13 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
             
             count++;
           }
-        
       default:
        break;
       }
+#if USE_CARBON_EVENTS
+      ReleaseEvent (eventRef);
+    }
+#endif
 
   /* If the focus was just given to an autoraising frame,
      raise it now.  */
@@ -12821,7 +13202,6 @@ NewMacWindow (FRAME_PTR fp)
     if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
       abort ();
   
-
   SetWRefCon (mwp->mWP, (long) mwp);
     /* so that update events can find this mac_output struct */
   mwp->mFP = fp;  /* point back to emacs frame */
@@ -12840,11 +13220,14 @@ NewMacWindow (FRAME_PTR fp)
 }
 
 
-void make_mac_frame (struct frame *f)
+void
+make_mac_frame (struct frame *f)
 {
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
   FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
-  
+
+  FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
   NewMacWindow(f);
 
   f->output_data.mac->cursor_pixel = 0;
@@ -12852,8 +13235,6 @@ void make_mac_frame (struct frame *f)
   f->output_data.mac->mouse_pixel = 0xff00ff;
   f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
 
-  f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
-
   f->output_data.mac->fontset = -1;
   f->output_data.mac->scroll_bar_foreground_pixel = -1;
   f->output_data.mac->scroll_bar_background_pixel = -1;
@@ -12873,7 +13254,8 @@ void make_mac_frame (struct frame *f)
   f->new_height = 0;
 }
 
-void make_mac_terminal_frame (struct frame *f)
+void
+make_mac_terminal_frame (struct frame *f)
 {
   Lisp_Object frame;
 
@@ -12942,7 +13324,7 @@ same_x_server (name1, name2)
      char *name1, *name2;
 {
   int seen_colon = 0;
-  unsigned char *system_name = XSTRING (Vsystem_name)->data;
+  unsigned char *system_name = SDATA (Vsystem_name);
   int system_name_length = strlen (system_name);
   int length_until_period = 0;
 
@@ -13000,11 +13382,11 @@ mac_initialize_display_info ()
   
 #if 0
   dpyinfo->mac_id_name
-    = (char *) xmalloc (XSTRING (Vinvocation_name)->size
-                       + XSTRING (Vsystem_name)->size
+    = (char *) xmalloc (SCHARS (Vinvocation_name)
+                       + SCHARS (Vsystem_name)
                        + 2);
   sprintf (dpyinfo->mac_id_name, "%s@%s",
-          XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
+          SDATA (Vinvocation_name), SDATA (Vsystem_name));
 #else
   dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
   strcpy (dpyinfo->mac_id_name, "Mac Display");
@@ -13055,6 +13437,136 @@ mac_term_init (display_name, xrm_option, resource_name)
   return dpyinfo;
 }
 \f
+#ifdef MAC_OSX
+void
+mac_check_bundle()
+{
+  extern int inhibit_window_system;
+  extern int noninteractive;
+  CFBundleRef appsBundle;
+  pid_t child;
+
+  /* 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 ()
+{
+  ProcessSerialNumber psn;
+  OSErr err;
+  
+  err = GetCurrentProcess (&psn);
+  if (err == noErr)
+    (void) SetFrontProcess (&psn);
+}
+
+/***** Code to handle C-g testing  *****/
+
+/* Contains the Mac modifier formed from quit_char */
+static mac_quit_char_modifiers = 0;
+static 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 |= 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;
+}
+
+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();
+}
+
+static Boolean
+quit_char_comp (EventRef inEvent, void *inCompData)
+{
+  if (GetEventClass(inEvent) != kEventClassKeyboard)
+    return false;
+  if (GetEventKind(inEvent) != kEventRawKeyDown)
+    return false;
+  {
+    UInt32 keyCode;
+    UInt32 keyModifiers;
+    GetEventParameter(inEvent, kEventParamKeyCode, 
+                     typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
+    if (keyCode != mac_quit_char_keycode)
+      return false;
+    GetEventParameter(inEvent, kEventParamKeyModifiers, 
+                     typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
+    if (keyModifiers != mac_quit_char_modifiers)
+      return false;
+  }
+  return true;
+}
+
+void
+mac_check_for_quit_char()
+{
+  EventRef event;
+  /* If windows are not initialized, return immediately (keep it bouncin')*/
+  if (!mac_quit_char_modifiers)
+    return;
+
+  /* Redetermine modifiers because they are based on lisp variables */
+  mac_determine_quit_char_modifiers();
+
+  /* Fill the queue with events */
+  ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
+  event = FindSpecificEventInQueue (GetMainEventQueue(), quit_char_comp, NULL);
+  if (event) 
+    {
+      struct input_event e;
+      struct mac_output *mwp = (mac_output*) GetWRefCon (FrontNonFloatingWindow ());
+      /* Use an input_event to emulate what the interrupt handler does. */
+      e.kind = ASCII_KEYSTROKE_EVENT;
+      e.code = quit_char;
+      e.arg = NULL;
+      e.modifiers = NULL;
+      e.timestamp = EventTimeToTicks(GetEventTime(event))*(1000/60);
+      XSETFRAME(e.frame_or_window, mwp->mFP);
+      /* Remove event from queue to prevent looping. */
+      RemoveEventFromQueue(GetMainEventQueue(), event);
+      ReleaseEvent(event);
+      kbd_buffer_store_event(&e);
+    }
+}
+
+#endif /* MAC_OSX */
+
 /* Set up use of X before we make the first connection.  */
 
 static struct redisplay_interface x_redisplay_interface =
@@ -13157,7 +13669,18 @@ mac_initialize ()
 #if TARGET_API_MAC_CARBON
   init_required_apple_events ();
 
+  init_mac_drag_n_drop ();
+
+#if USE_CARBON_EVENTS
+  init_service_handler ();
+
+  init_quit_char_handler ();
+#endif
+
   DisableMenuCommand (NULL, kHICommandQuit);
+
+  if (!inhibit_window_system)
+    MakeMeTheFrontProcess ();
 #endif
 }
 
@@ -13170,6 +13693,8 @@ syms_of_macterm ()
   x_error_message_string = Qnil;
 #endif
 
+  Fprovide (intern ("mac-carbon"), Qnil);
+
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;
 
@@ -13227,6 +13752,29 @@ to 4.1, set this to nil.  */);
 Otherwise the option key is used.  */);
   Vmac_command_key_is_meta = Qt;
 
+  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;
+
+#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_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
     doc: /* One of the Text Encoding Base constant values defined in the
 Basic Text Constants section of Inside Macintosh - Text Encoding