]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
Merge from emacs--devo--0
[gnu-emacs] / src / macterm.c
index bdeedfb9ab67a0d7315b4b4abbdbe82156f8c280..5643372845b5c976515161544dbd8d199c4123d2 100644 (file)
@@ -6,7 +6,7 @@ This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -226,14 +226,14 @@ void x_raise_frame P_ ((struct frame *));
 void x_set_window_size P_ ((struct frame *, int, int, int));
 void x_wm_set_window_state P_ ((struct frame *, int));
 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
-void mac_initialize P_ ((void));
+static 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 *));
 static void x_update_end P_ ((struct frame *));
 static void XTframe_up_to_date P_ ((struct frame *));
-static void XTset_terminal_modes P_ ((void));
-static void XTreset_terminal_modes P_ ((void));
-static void x_clear_frame P_ ((void));
+static void XTset_terminal_modes P_ ((struct terminal *));
+static void XTreset_terminal_modes P_ ((struct terminal *));
+static void x_clear_frame P_ ((struct frame *));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
@@ -261,6 +261,8 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
 static int is_emacs_window P_ ((WindowRef));
 static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
 static void XSetFont P_ ((Display *, GC, XFontStruct *));
+static struct terminal *mac_create_terminal P_ ((struct mac_display_info *dpyinfo));
+
 
 #define GC_FORE_COLOR(gc)      (&(gc)->fore_color)
 #define GC_BACK_COLOR(gc)      (&(gc)->back_color)
@@ -2194,6 +2196,81 @@ x_draw_fringe_bitmap (w, row, p)
   Display *display = FRAME_MAC_DISPLAY (f);
   struct face *face = p->face;
   int rowY;
+  int overlay_p = p->overlay_p;
+
+#ifdef MAC_OSX
+  if (!overlay_p)
+    {
+      int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
+
+#if 0  /* MAC_TODO: stipple */
+      /* In case the same realized face is used for fringes and
+        for something displayed in the text (e.g. face `region' on
+        mono-displays, the fill style may have been changed to
+        FillSolid in x_draw_glyph_string_background.  */
+      if (face->stipple)
+       XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
+      else
+       XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
+#endif
+
+      /* If the fringe is adjacent to the left (right) scroll bar of a
+        leftmost (rightmost, respectively) window, then extend its
+        background to the gap between the fringe and the bar.  */
+      if ((WINDOW_LEFTMOST_P (w)
+          && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+         || (WINDOW_RIGHTMOST_P (w)
+             && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
+       {
+         int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
+
+         if (sb_width > 0)
+           {
+             int left = WINDOW_SCROLL_BAR_AREA_X (w);
+             int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
+                          * FRAME_COLUMN_WIDTH (f));
+
+             if (bx < 0
+                 && (left + width == p->x
+                     || p->x + p->wd == left))
+               {
+                 /* Bitmap fills the fringe and we need background
+                    extension.  */
+                 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+
+                 bx = p->x;
+                 nx = p->wd;
+                 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+                                                       row->y));
+                 ny = row->visible_height;
+               }
+
+             if (bx >= 0)
+               {
+                 if (left + width == bx)
+                   {
+                     bx = left + sb_width;
+                     nx += width - sb_width;
+                   }
+                 else if (bx + nx == left)
+                   nx += width - sb_width;
+               }
+           }
+       }
+
+      if (bx >= 0)
+       {
+         mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
+         /* The fringe background has already been filled.  */
+         overlay_p = 1;
+       }
+
+#if 0  /* MAC_TODO: stipple */
+      if (!face->stipple)
+       XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
+#endif
+    }
+#endif /* MAC_OSX */
 
   /* Must clip because of partially visible lines.  */
   rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
@@ -2212,6 +2289,7 @@ x_draw_fringe_bitmap (w, row, p)
   else
     x_clip_to_row (w, row, -1, face->gc);
 
+#ifndef MAC_OSX
   if (p->bx >= 0 && !p->overlay_p)
     {
 #if 0  /* MAC_TODO: stipple */
@@ -2232,6 +2310,7 @@ x_draw_fringe_bitmap (w, row, p)
        XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
 #endif
     }
+#endif /* !MAC_OSX */
 
   if (p->which
 #if USE_CG_DRAWING
@@ -2249,10 +2328,10 @@ x_draw_fringe_bitmap (w, row, p)
                       : face->foreground));
 #if USE_CG_DRAWING
       mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
-                        p->wd, p->h, p->x, p->y, p->overlay_p);
+                        p->wd, p->h, p->x, p->y, overlay_p);
 #else
       mac_draw_bitmap (f, face->gc, p->x, p->y,
-                      p->wd, p->h, p->bits + p->dh, p->overlay_p);
+                      p->wd, p->h, p->bits + p->dh, overlay_p);
 #endif
       XSetForeground (display, face->gc, gcv.foreground);
     }
@@ -2312,7 +2391,7 @@ mac_destroy_fringe_bitmap (which)
    rarely happens).  */
 
 static void
-XTset_terminal_modes ()
+XTset_terminal_modes (struct terminal *t)
 {
 }
 
@@ -2320,7 +2399,7 @@ XTset_terminal_modes ()
    the windows go away, and suspending requires no action.  */
 
 static void
-XTreset_terminal_modes ()
+XTreset_terminal_modes (struct terminal *t)
 {
 }
 
@@ -3963,15 +4042,8 @@ x_delete_glyphs (n)
    frame.  Otherwise clear the selected frame.  */
 
 static void
-x_clear_frame ()
+x_clear_frame (struct frame *f)
 {
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
   /* Clearing the frame will erase any cursor, so mark them all as no
      longer visible.  */
   mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
@@ -4505,7 +4577,7 @@ note_mouse_movement (frame, pos)
       clear_mouse_face (dpyinfo);
       dpyinfo->mouse_face_mouse_frame = 0;
       if (!dpyinfo->grabbed)
-       rif->define_frame_cursor (frame,
+       FRAME_RIF (frame)->define_frame_cursor (frame,
                                  frame->output_data.mac->nontext_cursor);
     }
 
@@ -4995,6 +5067,9 @@ x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
   XSETINT (bar->start, 0);
   XSETINT (bar->end, 0);
   bar->dragging = Qnil;
+#ifdef MAC_OSX
+  bar->fringe_extended_p = Qnil;
+#endif
 #ifdef USE_TOOLKIT_SCROLL_BARS
   bar->track_top = Qnil;
   bar->track_height = Qnil;
@@ -5127,6 +5202,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   struct scroll_bar *bar;
   int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
   int window_y, window_height;
+#ifdef MAC_OSX
+  int fringe_extended_p;
+#endif
 
   /* Get window dimensions.  */
   window_box (w, -1, 0, &window_y, 0, &window_height);
@@ -5146,9 +5224,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
   /* Compute the left edge of the scroll bar.  */
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left;
+    sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
   else
-    sb_left = left + width - sb_width;
+    sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
 
   /* Adjustments according to Inside Macintosh to make it look nice */
   disp_top = top;
@@ -5169,11 +5247,29 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
     sb_left++;
 #endif
 
+#ifdef MAC_OSX
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+    fringe_extended_p = (WINDOW_LEFTMOST_P (w)
+                        && WINDOW_LEFT_FRINGE_WIDTH (w)
+                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                            || WINDOW_LEFT_MARGIN_COLS (w) == 0));
+  else
+    fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
+                        && WINDOW_RIGHT_FRINGE_WIDTH (w)
+                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                            || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
+#endif
+
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
     {
       BLOCK_INPUT;
-      mac_clear_area (f, left, top, width, height);
+#ifdef MAC_OSX
+      if (fringe_extended_p)
+       mac_clear_area (f, sb_left, top, sb_width, height);
+      else
+#endif
+       mac_clear_area (f, left, top, width, height);
       UNBLOCK_INPUT;
       bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
                                 disp_height);
@@ -5193,11 +5289,20 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
       if (!(XINT (bar->left) == sb_left
            && XINT (bar->top) == top
            && XINT (bar->width) == sb_width
-           && XINT (bar->height) == height))
+           && XINT (bar->height) == height
+#ifdef MAC_OSX
+           && !NILP (bar->fringe_extended_p) == fringe_extended_p
+#endif
+           ))
        {
          /* Since toolkit scroll bars are smaller than the space reserved
             for them on the frame, we have to clear "under" them.  */
-         mac_clear_area (f, left, top, width, height);
+#ifdef MAC_OSX
+         if (fringe_extended_p)
+           mac_clear_area (f, sb_left, top, sb_width, height);
+         else
+#endif
+           mac_clear_area (f, left, top, width, height);
 
 #if USE_CG_DRAWING
          mac_prepare_for_quickdraw (f);
@@ -5226,6 +5331,10 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
       UNBLOCK_INPUT;
     }
 
+#ifdef MAC_OSX
+  bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
+#endif
+
 #ifdef USE_TOOLKIT_SCROLL_BARS
   if (NILP (bar->track_top))
     {
@@ -5587,6 +5696,539 @@ x_scroll_bar_clear (f)
   XTjudge_scroll_bars (f);
 }
 
+\f
+/***********************************************************************
+                              Tool-bars
+ ***********************************************************************/
+#if USE_MAC_TOOLBAR
+
+/* In identifiers such as function/variable names, Emacs tool bar is
+   referred to as `tool_bar', and Carbon HIToolbar as `toolbar'.  */
+
+#define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
+#define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
+
+#define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
+#define TOOLBAR_ITEM_COMMAND_ID_P(id)                  \
+  (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
+#define TOOLBAR_ITEM_COMMAND_ID_VALUE(id)      \
+  ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
+#define TOOLBAR_ITEM_MAKE_COMMAND_ID(value)    \
+  ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
+
+static int mac_event_to_emacs_modifiers P_ ((EventRef));
+static void mac_handle_origin_change P_ ((struct frame *));
+static OSStatus mac_handle_toolbar_command_event P_ ((EventHandlerCallRef,
+                                                     EventRef, void *));
+
+static void
+mac_move_window_with_gravity (f, win_gravity, left, top)
+     struct frame *f;
+     int win_gravity;
+     short left, top;
+{
+  Rect inner, outer;
+
+  mac_get_window_bounds (f, &inner, &outer);
+
+  switch (win_gravity)
+    {
+    case NorthWestGravity:
+    case WestGravity:
+    case SouthWestGravity:
+      left += inner.left - outer.left;
+      break;
+
+    case NorthGravity:
+    case CenterGravity:
+    case SouthGravity:
+      left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
+      break;
+
+    case NorthEastGravity:
+    case EastGravity:
+    case SouthEastGravity:
+      left += inner.right - outer.right;
+      break;
+    }
+
+  switch (win_gravity)
+    {
+    case NorthWestGravity:
+    case NorthGravity:
+    case NorthEastGravity:
+      top += inner.top - outer.top;
+      break;
+
+    case WestGravity:
+    case CenterGravity:
+    case EastGravity:
+      top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
+      break;
+
+    case SouthWestGravity:
+    case SouthGravity:
+    case SouthEastGravity:
+      top += inner.bottom - outer.bottom;
+      break;
+    }
+
+  MoveWindow (FRAME_MAC_WINDOW (f), left, top, false);
+}
+
+static void
+mac_get_window_origin_with_gravity (f, win_gravity, left, top)
+     struct frame *f;
+     int win_gravity;
+     short *left, *top;
+{
+  Rect inner, outer;
+
+  mac_get_window_bounds (f, &inner, &outer);
+
+  switch (win_gravity)
+    {
+    case NorthWestGravity:
+    case WestGravity:
+    case SouthWestGravity:
+      *left = outer.left;
+      break;
+
+    case NorthGravity:
+    case CenterGravity:
+    case SouthGravity:
+      *left = outer.left + ((outer.right - outer.left)
+                           - (inner.right - inner.left)) / 2;
+      break;
+
+    case NorthEastGravity:
+    case EastGravity:
+    case SouthEastGravity:
+      *left = outer.right - (inner.right - inner.left);
+      break;
+    }
+
+  switch (win_gravity)
+    {
+    case NorthWestGravity:
+    case NorthGravity:
+    case NorthEastGravity:
+      *top = outer.top;
+      break;
+
+    case WestGravity:
+    case CenterGravity:
+    case EastGravity:
+      *top = outer.top + ((outer.bottom - outer.top)
+                         - (inner.bottom - inner.top)) / 2;
+      break;
+
+    case SouthWestGravity:
+    case SouthGravity:
+    case SouthEastGravity:
+      *top = outer.bottom - (inner.bottom - inner.top);
+      break;
+    }
+}
+
+static OSStatus
+mac_handle_toolbar_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  OSStatus err, result = eventNotHandledErr;
+
+  switch (GetEventKind (event))
+    {
+    case kEventToolbarGetDefaultIdentifiers:
+      result = noErr;
+      break;
+
+    case kEventToolbarGetAllowedIdentifiers:
+      {
+       CFMutableArrayRef array;
+
+       GetEventParameter (event, kEventParamMutableArray,
+                          typeCFMutableArrayRef, NULL,
+                          sizeof (CFMutableArrayRef), NULL, &array);
+       CFArrayAppendValue (array, TOOLBAR_ICON_ITEM_IDENTIFIER);
+       result = noErr;
+      }
+      break;
+
+    case kEventToolbarCreateItemWithIdentifier:
+      {
+       CFStringRef identifier;
+       HIToolbarItemRef item = NULL;
+
+       GetEventParameter (event, kEventParamToolbarItemIdentifier,
+                          typeCFStringRef, NULL,
+                          sizeof (CFStringRef), NULL, &identifier);
+
+       if (CFStringCompare (identifier, TOOLBAR_ICON_ITEM_IDENTIFIER, 0)
+           == kCFCompareEqualTo)
+         HIToolbarItemCreate (identifier,
+                              kHIToolbarItemAllowDuplicates
+                              | kHIToolbarItemCantBeRemoved, &item);
+
+       if (item)
+         {
+           SetEventParameter (event, kEventParamToolbarItem,
+                              typeHIToolbarItemRef,
+                              sizeof (HIToolbarItemRef), &item);
+           result = noErr;
+         }
+      }
+      break;
+
+    default:
+      abort ();
+    }
+
+  return result;
+}
+
+static CGImageRef
+mac_image_spec_to_cg_image (f, image)
+     struct frame *f;
+     Lisp_Object image;
+{
+  if (!valid_image_p (image))
+    return NULL;
+  else
+    {
+      int img_id = lookup_image (f, image);
+      struct image *img = IMAGE_FROM_ID (f, img_id);
+
+      prepare_image_for_display (f, img);
+
+      return img->data.ptr_val;
+    }
+}
+
+/* Create a tool bar for frame F.  */
+
+static OSStatus
+mac_create_frame_tool_bar (f)
+     FRAME_PTR f;
+{
+  OSStatus err;
+  HIToolbarRef toolbar;
+
+  err = HIToolbarCreate (TOOLBAR_IDENTIFIER, kHIToolbarNoAttributes,
+                        &toolbar);
+  if (err == noErr)
+    {
+      static const EventTypeSpec specs[] =
+       {{kEventClassToolbar, kEventToolbarGetDefaultIdentifiers},
+        {kEventClassToolbar, kEventToolbarGetAllowedIdentifiers},
+        {kEventClassToolbar, kEventToolbarCreateItemWithIdentifier}};
+
+      err = InstallEventHandler (HIObjectGetEventTarget (toolbar),
+                                mac_handle_toolbar_event,
+                                GetEventTypeCount (specs), specs,
+                                f, NULL);
+    }
+
+  if (err == noErr)
+    err = HIToolbarSetDisplayMode (toolbar, kHIToolbarDisplayModeIconOnly);
+  if (err == noErr)
+    {
+      static const EventTypeSpec specs[] =
+       {{kEventClassCommand, kEventCommandProcess}};
+
+      err = InstallWindowEventHandler (FRAME_MAC_WINDOW (f),
+                                      mac_handle_toolbar_command_event,
+                                      GetEventTypeCount (specs),
+                                      specs, f, NULL);
+    }
+  if (err == noErr)
+    err = SetWindowToolbar (FRAME_MAC_WINDOW (f), toolbar);
+
+  if (toolbar)
+    CFRelease (toolbar);
+
+  return err;
+}
+
+/* Update the tool bar for frame F.  Add new buttons and remove old.  */
+
+void
+update_frame_tool_bar (f)
+     FRAME_PTR f;
+{
+  HIToolbarRef toolbar = NULL;
+  short left, top;
+  CFArrayRef old_items = NULL;
+  CFIndex old_count;
+  int i, pos, win_gravity = f->output_data.mac->toolbar_win_gravity;
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+  BLOCK_INPUT;
+
+  GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
+  if (toolbar == NULL)
+    {
+      mac_create_frame_tool_bar (f);
+      GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
+      if (toolbar == NULL)
+       goto out;
+      if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
+       mac_get_window_origin_with_gravity (f, win_gravity, &left, &top);
+    }
+
+  HIToolbarCopyItems (toolbar, &old_items);
+  if (old_items == NULL)
+    goto out;
+
+  old_count = CFArrayGetCount (old_items);
+  pos = 0;
+  for (i = 0; i < f->n_tool_bar_items; ++i)
+    {
+#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
+
+      int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
+      int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
+      int idx;
+      Lisp_Object image;
+      CGImageRef cg_image;
+      CFStringRef label;
+      HIToolbarItemRef item;
+
+      /* If image is a vector, choose the image according to the
+        button state.  */
+      image = PROP (TOOL_BAR_ITEM_IMAGES);
+      if (VECTORP (image))
+       {
+         if (enabled_p)
+           idx = (selected_p
+                  ? TOOL_BAR_IMAGE_ENABLED_SELECTED
+                  : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
+         else
+           idx = (selected_p
+                  ? TOOL_BAR_IMAGE_DISABLED_SELECTED
+                  : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
+
+         xassert (ASIZE (image) >= idx);
+         image = AREF (image, idx);
+       }
+      else
+       idx = -1;
+
+      cg_image = mac_image_spec_to_cg_image (f, image);
+      /* Ignore invalid image specifications.  */
+      if (cg_image == NULL)
+       continue;
+
+      label = cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION));
+      if (label == NULL)
+       label = CFSTR ("");
+
+      if (pos < old_count)
+       {
+         CGImageRef old_cg_image = NULL;
+         CFStringRef old_label = NULL;
+         Boolean old_enabled_p;
+
+         item = (HIToolbarItemRef) CFArrayGetValueAtIndex (old_items, pos);
+
+         HIToolbarItemCopyImage (item, &old_cg_image);
+         if (cg_image != old_cg_image)
+           HIToolbarItemSetImage (item, cg_image);
+         CGImageRelease (old_cg_image);
+
+         HIToolbarItemCopyLabel (item, &old_label);
+         if (CFStringCompare (label, old_label, 0) != kCFCompareEqualTo)
+           HIToolbarItemSetLabel (item, label);
+         CFRelease (old_label);
+
+         old_enabled_p = HIToolbarItemIsEnabled (item);
+         if ((enabled_p || idx >= 0) != old_enabled_p)
+           HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
+       }
+      else
+       {
+         item = NULL;
+         HIToolbarCreateItemWithIdentifier (toolbar,
+                                            TOOLBAR_ICON_ITEM_IDENTIFIER,
+                                            NULL, &item);
+         if (item)
+           {
+             HIToolbarItemSetImage (item, cg_image);
+             HIToolbarItemSetLabel (item, label);
+             HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
+             HIToolbarAppendItem (toolbar, item);
+             CFRelease (item);
+           }
+       }
+
+      CFRelease (label);
+      if (item)
+       {
+         HIToolbarItemSetCommandID (item, TOOLBAR_ITEM_MAKE_COMMAND_ID (i));
+         pos++;
+       }
+    }
+
+  CFRelease (old_items);
+
+  while (pos < old_count)
+    HIToolbarRemoveItemAtIndex (toolbar, --old_count);
+
+  ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), true,
+                        !win_gravity && f == mac_focus_frame (dpyinfo));
+  /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
+     toolbar visibility change.  */
+  mac_handle_origin_change (f);
+  if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
+    {
+      mac_move_window_with_gravity (f, win_gravity, left, top);
+      /* If the title bar is completely outside the screen, adjust the
+        position. */
+      ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
+                              kWindowConstrainMoveRegardlessOfFit
+                              | kWindowConstrainAllowPartial, NULL, NULL);
+      f->output_data.mac->toolbar_win_gravity = 0;
+    }
+
+ out:
+  UNBLOCK_INPUT;
+}
+
+/* Hide the tool bar on frame F.  Unlike the counterpart on GTK+, it
+   doesn't deallocate the resources.  */
+
+void
+free_frame_tool_bar (f)
+     FRAME_PTR f;
+{
+  if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f)))
+    {
+      struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+      BLOCK_INPUT;
+      ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), false,
+                            f == mac_focus_frame (dpyinfo));
+      /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
+        on toolbar visibility change.  */
+      mac_handle_origin_change (f);
+      UNBLOCK_INPUT;
+    }
+}
+
+static void
+mac_tool_bar_note_mouse_movement (f, event)
+     struct frame *f;
+     EventRef event;
+{
+  OSStatus err;
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+  int mouse_down_p;
+  HIViewRef item_view;
+  UInt32 command_id;
+
+  mouse_down_p = (dpyinfo->grabbed
+                 && f == last_mouse_frame
+                 && FRAME_LIVE_P (f));
+  if (mouse_down_p)
+    return;
+
+  err = HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f)),
+                                   event, &item_view);
+  /* This doesn't work on Mac OS X 10.2.  On Mac OS X 10.3 and 10.4, a
+     toolbar item view seems to have the same command ID with that of
+     the toolbar item.  */
+  if (err == noErr)
+    err = GetControlCommandID (item_view, &command_id);
+  if (err == noErr && TOOLBAR_ITEM_COMMAND_ID_P (command_id))
+    {
+      int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id);
+
+      if (i < f->n_tool_bar_items)
+       {
+         HIRect bounds;
+         HIViewRef content_view;
+
+         err = HIViewGetBounds (item_view, &bounds);
+         if (err == noErr)
+           err = HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f)),
+                                 kHIViewWindowContentID, &content_view);
+         if (err == noErr)
+           err = HIViewConvertRect (&bounds, item_view, content_view);
+         if (err == noErr)
+           SetRect (&last_mouse_glyph,
+                    CGRectGetMinX (bounds), CGRectGetMinY (bounds),
+                    CGRectGetMaxX (bounds), CGRectGetMaxY (bounds));
+
+         help_echo_object = help_echo_window = Qnil;
+         help_echo_pos = -1;
+         help_echo_string = PROP (TOOL_BAR_ITEM_HELP);
+         if (NILP (help_echo_string))
+           help_echo_string = PROP (TOOL_BAR_ITEM_CAPTION);
+       }
+    }
+}
+
+static OSStatus
+mac_handle_toolbar_command_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  OSStatus err, result = eventNotHandledErr;
+  struct frame *f = (struct frame *) data;
+  HICommand command;
+
+  err = GetEventParameter (event, kEventParamDirectObject,
+                          typeHICommand, NULL,
+                          sizeof (HICommand), NULL, &command);
+  if (err != noErr)
+    return result;
+
+  switch (GetEventKind (event))
+    {
+    case kEventCommandProcess:
+      if (!TOOLBAR_ITEM_COMMAND_ID_P (command.commandID))
+       result = CallNextEventHandler (next_handler, event);
+      else
+       {
+         int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command.commandID);
+
+         if (i < f->n_tool_bar_items
+             && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)))
+           {
+             Lisp_Object frame;
+             struct input_event buf;
+
+             EVENT_INIT (buf);
+
+             XSETFRAME (frame, f);
+             buf.kind = TOOL_BAR_EVENT;
+             buf.frame_or_window = frame;
+             buf.arg = frame;
+             kbd_buffer_store_event (&buf);
+
+             buf.kind = TOOL_BAR_EVENT;
+             buf.frame_or_window = frame;
+             buf.arg = PROP (TOOL_BAR_ITEM_KEY);
+             buf.modifiers = mac_event_to_emacs_modifiers (event);
+             kbd_buffer_store_event (&buf);
+
+             result = noErr;
+           }
+       }
+      break;
+
+    default:
+      abort ();
+    }
+#undef PROP
+
+  return result;
+}
+#endif /* USE_MAC_TOOLBAR */
+
 \f
 /***********************************************************************
                             Text Cursor
@@ -10080,6 +10722,13 @@ mac_handle_window_event (next_handler, event, data)
                                kWindowCascadeOnParentWindowScreen
 #endif
                                );
+#if USE_MAC_TOOLBAR
+             /* This is a workaround.  RepositionWindow fails to put
+                a window at the cascading position when its parent
+                window has a Carbon HIToolbar.  */
+             if (f->top_pos == sf->top_pos && f->left_pos == sf->left_pos)
+               MoveWindowStructure (wp,  f->left_pos + 10, f->top_pos + 32);
+#endif
            }
          result = noErr;
        }
@@ -10362,8 +11011,7 @@ mac_handle_keyboard_event (next_handler, event, data)
       if (err != noErr)
        break;
 
-      do_keystroke ((GetEventKind (event) == kEventRawKeyDown
-                    ? keyDown : autoKey),
+      do_keystroke ((event_kind == kEventRawKeyDown ? keyDown : autoKey),
                    char_code, key_code, modifiers,
                    ((unsigned long)
                     (GetEventTime (event) / kEventDurationMillisecond)),
@@ -10511,7 +11159,7 @@ mac_handle_text_input_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
-  OSStatus result, err = noErr;
+  OSStatus err, result;
   Lisp_Object id_key = Qnil;
   int num_params;
   const EventParamName *names;
@@ -10572,6 +11220,7 @@ mac_handle_text_input_event (next_handler, event, data)
       SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
                         typeUInt32, sizeof (UInt32), &seqno_uaia);
       seqno_uaia++;
+      result = noErr;
       break;
 
     case kEventTextInputUnicodeForKeyEvent:
@@ -10589,7 +11238,7 @@ mac_handle_text_input_event (next_handler, event, data)
        if (err == noErr && mac_mapped_modifiers (modifiers))
          /* There're mapped modifier keys.  Process it in
             do_keystroke.  */
-         return eventNotHandledErr;
+         break;
        if (err == noErr)
          err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
                                   typeUnicodeText, NULL, 0, &actual_size,
@@ -10628,16 +11277,20 @@ mac_handle_text_input_event (next_handler, event, data)
                        XSETFRAME (read_socket_inev->frame_or_window, f);
                      }
                  }
-               return eventNotHandledErr;
+               break;
              }
          }
+       if (err == noErr)
+         {
+           /* Non-ASCII keystrokes without mapped modifiers are
+              processed at the Lisp level.  */
+           id_key = Qunicode_for_key_event;
+           num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
+           names = names_ufke;
+           types = types_ufke;
+           result = noErr;
+         }
       }
-      /* Non-ASCII keystrokes without mapped modifiers are processed
-        at the Lisp level.  */
-      id_key = Qunicode_for_key_event;
-      num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
-      names = names_ufke;
-      types = types_ufke;
       break;
 
     case kEventTextInputOffsetToPos:
@@ -10647,22 +11300,24 @@ mac_handle_text_input_event (next_handler, event, data)
        Point p;
 
        if (!OVERLAYP (Vmac_ts_active_input_overlay))
-         return eventNotHandledErr;
+         break;
 
        /* Strictly speaking, this is not always correct because
           previous events may change some states about display.  */
-       if (NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
+       if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
+         {
+           /* Active input area is displayed around the current point.  */
+           f = SELECTED_FRAME ();
+           w = XWINDOW (f->selected_window);
+         }
+       else if (WINDOWP (echo_area_window))
          {
            /* Active input area is displayed in the echo area.  */
            w = XWINDOW (echo_area_window);
            f = WINDOW_XFRAME (w);
          }
        else
-         {
-           /* Active input area is displayed around the current point.  */
-           f = SELECTED_FRAME ();
-           w = XWINDOW (f->selected_window);
-         }
+         break;
 
        p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
               + WINDOW_LEFT_FRINGE_WIDTH (w)
@@ -10672,6 +11327,8 @@ mac_handle_text_input_event (next_handler, event, data)
               + f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f));
        err = SetEventParameter (event, kEventParamTextInputReplyPoint,
                                 typeQDPoint, sizeof (typeQDPoint), &p);
+       if (err == noErr)
+         result = noErr;
       }
       break;
 
@@ -10683,9 +11340,6 @@ mac_handle_text_input_event (next_handler, event, data)
     err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
                                              event, num_params,
                                              names, types);
-  if (err == noErr)
-    result = noErr;
-
   return result;
 }
 #endif
@@ -11417,6 +12071,21 @@ XTread_socket (sd, expected, hold_quit)
                  do_zoom_window (window_ptr, part_code);
                break;
 
+#if USE_MAC_TOOLBAR
+             case inStructure:
+               {
+                 OSStatus err;
+                 HIViewRef ch;
+
+                 err = HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr),
+                                                   eventRef, &ch);
+                 /* This doesn't work on Mac OS X 10.2.  */
+                 if (err == noErr)
+                   HIViewClick (ch, eventRef);
+               }
+               break;
+#endif /* USE_MAC_TOOLBAR */
+
              default:
                break;
              }
@@ -11501,6 +12170,10 @@ XTread_socket (sd, expected, hold_quit)
                        }
                      if (!note_mouse_movement (f, &mouse_pos))
                        help_echo_string = previous_help_echo_string;
+#if USE_MAC_TOOLBAR
+                     else
+                       mac_tool_bar_note_mouse_movement (f, eventRef);
+#endif
                    }
                }
 
@@ -11840,6 +12513,7 @@ mac_term_init (display_name, xrm_option, resource_name)
      char *resource_name;
 {
   struct mac_display_info *dpyinfo;
+  struct terminal *terminal;
 
   BLOCK_INPUT;
 
@@ -11855,6 +12529,13 @@ mac_term_init (display_name, xrm_option, resource_name)
   dpyinfo = &one_mac_display_info;
   bzero (dpyinfo, sizeof (*dpyinfo));
 
+  terminal = mac_create_terminal (dpyinfo);
+
+  /* Set the name of the terminal. */
+  terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
+  strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
+  terminal->name[SBYTES (display_name)] = 0;
+
 #ifdef MAC_OSX
   dpyinfo->mac_id_name
     = (char *) xmalloc (SCHARS (Vinvocation_name)
@@ -12056,44 +12737,71 @@ static struct redisplay_interface x_redisplay_interface =
   mac_shift_glyphs_for_insert
 };
 
-void
+static struct terminal *
+mac_create_terminal (struct mac_display_info *dpyinfo)
+{
+  struct terminal *terminal;
+  
+  terminal = create_terminal ();
+
+  terminal->type = output_mac;
+  terminal->display_info.mac = dpyinfo;
+  dpyinfo->terminal = terminal;
+
+  terminal->clear_frame_hook = x_clear_frame;
+  terminal->ins_del_lines_hook = x_ins_del_lines;
+  terminal->delete_glyphs_hook = x_delete_glyphs;
+  terminal->ring_bell_hook = XTring_bell;
+  terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
+  terminal->set_terminal_modes_hook = XTset_terminal_modes;
+  terminal->update_begin_hook = x_update_begin;
+  terminal->update_end_hook = x_update_end;
+  terminal->set_terminal_window_hook = XTset_terminal_window;
+  terminal->read_socket_hook = XTread_socket;
+  terminal->frame_up_to_date_hook = XTframe_up_to_date;
+  terminal->mouse_position_hook = XTmouse_position;
+  terminal->frame_rehighlight_hook = XTframe_rehighlight;
+  terminal->frame_raise_lower_hook = XTframe_raise_lower;
+  /* terminal->fullscreen_hook = XTfullscreen_hook; */
+  terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
+  terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
+  terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
+  terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
+  terminal->delete_frame_hook = x_destroy_window;
+  /* terminal->delete_terminal_hook = x_delete_terminal; */
+
+  terminal->rif = &x_redisplay_interface;
+#if 0
+  TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
+  TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
+  TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
+  TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
+  TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
+                                                         scrolls off the
+                                                         bottom */
+#else
+  terminal->scroll_region_ok = 1;    /* We'll scroll partial frames. */
+  terminal->char_ins_del_ok = 1;
+  terminal->line_ins_del_ok = 1;         /* We'll just blt 'em. */
+  terminal->fast_clear_end_of_line = 1;  /* X does this well. */
+  terminal->memory_below_frame = 0;   /* We don't remember what scrolls
+                                        off the bottom. */
+
+#endif
+  return terminal;
+}
+
+static void
 mac_initialize ()
 {
-  rif = &x_redisplay_interface;
-
-  clear_frame_hook = x_clear_frame;
-  ins_del_lines_hook = x_ins_del_lines;
-  delete_glyphs_hook = x_delete_glyphs;
-  ring_bell_hook = XTring_bell;
-  reset_terminal_modes_hook = XTreset_terminal_modes;
-  set_terminal_modes_hook = XTset_terminal_modes;
-  update_begin_hook = x_update_begin;
-  update_end_hook = x_update_end;
-  set_terminal_window_hook = XTset_terminal_window;
-  read_socket_hook = XTread_socket;
-  frame_up_to_date_hook = XTframe_up_to_date;
-  mouse_position_hook = XTmouse_position;
-  frame_rehighlight_hook = XTframe_rehighlight;
-  frame_raise_lower_hook = XTframe_raise_lower;
-
-  set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
-  condemn_scroll_bars_hook = XTcondemn_scroll_bars;
-  redeem_scroll_bar_hook = XTredeem_scroll_bar;
-  judge_scroll_bars_hook = XTjudge_scroll_bars;
-
-  scroll_region_ok = 1;         /* we'll scroll partial frames */
-  char_ins_del_ok = 1;
-  line_ins_del_ok = 1;          /* we'll just blt 'em */
-  fast_clear_end_of_line = 1;   /* X does this well */
-  memory_below_frame = 0;       /* we don't remember what scrolls
-                                  off the bottom */
+
   baud_rate = 19200;
 
   last_tool_bar_item = -1;
   any_help_event_p = 0;
 
   /* Try to use interrupt input; if we can't, then start polling.  */
-  Fset_input_mode (Qt, Qnil, Qt, Qnil);
+  Fset_input_interrupt_mode (Qt);
 
   BLOCK_INPUT;
 
@@ -12130,6 +12838,7 @@ mac_initialize ()
 #endif
 
   UNBLOCK_INPUT;
+
 }