]> 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 e285480a9e943b315e72fb1f66f15423d26b084e..cae4172854e6a3c2683eb7e638a706b7fb890073 100644 (file)
@@ -419,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));
@@ -444,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));
@@ -6241,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.  */
 
@@ -6282,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));
 
@@ -6302,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)
@@ -6315,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;
        }
@@ -6335,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);
@@ -7283,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);
@@ -7325,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);
@@ -7404,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);
@@ -9049,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);
@@ -9251,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
@@ -9285,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,
@@ -9353,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);
 
@@ -9384,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;
@@ -11595,10 +11590,10 @@ mac_get_mouse_btn (EventRef ref)
     case kEventMouseButtonPrimary:
       return 0;
     case kEventMouseButtonSecondary:
-      return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1
+      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) ? 1 : 2
+      return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1
     default:
       return 0;
     }
@@ -12163,7 +12158,8 @@ init_required_apple_events ()
 
 #if USE_CARBON_EVENTS
 
-void init_service_handler()
+void
+init_service_handler ()
 {
   EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
                           {kEventClassService, kEventServiceCopy},
@@ -12175,8 +12171,9 @@ void init_service_handler()
 /*
    MAC_TODO: Check to see if this is called by AEProcessDesc...
  */
-OSStatus mac_handle_service_event (EventHandlerCallRef callRef,
-                                  EventRef event, void *data)
+OSStatus
+mac_handle_service_event (EventHandlerCallRef callRef,
+                         EventRef event, void *data)
 {
   OSStatus err = noErr; 
   switch (GetEventKind (event))
@@ -12352,8 +12349,9 @@ descriptor_error_exit:
 }
 
 
-static pascal OSErr mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
-                                        DragReference theDrag)
+static pascal OSErr
+mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
+                    DragReference theDrag)
 {
   short items;
   short index;
@@ -12540,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* */, 
@@ -12632,7 +12630,7 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
                                expected
                                ? TicksToEventTime (app_sleep_time)
                                : 0,
-                               true, &eventRef);
+                               kEventRemoveFromQueue, &eventRef);
   if (!rneResult)
     {
       /* Handle new events */
@@ -12663,7 +12661,7 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
                bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
                count++;
              }
-           else
+           else             
              SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
 
            break;
@@ -12913,16 +12911,16 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
                break;
            }
 #endif
-
+         
          if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
            {
              SysBeep (1);
              UNBLOCK_INPUT;
              return 0;
            }
-
+         
          ObscureCursor ();
-
+         
          if (keycode == 0x33)  /* delete key (charCode translated to 0x8) */
            {
              bufp->code = 0x7f;
@@ -12933,100 +12931,83 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
              bufp->code = 0xff00 | xkeysym;
              bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
            }      
-         else if (!NILP (Vmac_reverse_ctrl_meta) && (er.modifiers & controlKey))
-           {
-             /* This is a special case to deal with converting from
-                a control character to non-control character */
-             int new_modifiers = er.modifiers & ~controlKey;
-             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;
-             bufp->kind = ASCII_KEYSTROKE_EVENT;
-           }
          else
            {
-             if (er.modifiers & macMetaKey)
-               {
-                 /* 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;
-               }
-#if USE_CARBON_EVENTS
-             else if (er.modifiers & cmdKey &&
-                      (NILP (Vmac_command_key_is_meta)))
-               {
-                 /* If this is a command key (and we are not overriding it),
-                    send back to the operating system  */
-                 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
-                 break;
                }
-#endif
              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;
+             }
          }
-
+       
 #if USE_CARBON_EVENTS
        bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
@@ -13038,7 +13019,7 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
            = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
          XSETFRAME (bufp->frame_or_window, mwp->mFP);
        }
-
+       
        bufp->timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
 
        count++;
@@ -13058,6 +13039,14 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
             Lisp_Object frame;
 
             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;            
 
@@ -13231,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;
@@ -13243,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;
@@ -13264,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;
 
@@ -13447,7 +13438,38 @@ mac_term_init (display_name, xrm_option, resource_name)
 }
 \f
 #ifdef MAC_OSX
-void MakeMeTheFrontProcess ()
+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;
@@ -13456,6 +13478,93 @@ void MakeMeTheFrontProcess ()
   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.  */
@@ -13564,6 +13673,8 @@ mac_initialize ()
 
 #if USE_CARBON_EVENTS
   init_service_handler ();
+
+  init_quit_char_handler ();
 #endif
 
   DisableMenuCommand (NULL, kHICommandQuit);
@@ -13582,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;