]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
Merge from emacs--devo--0
[gnu-emacs] / src / macterm.c
index 535d433bb37d902c3efe811716a19cda2dd845e4..549e1e7977b3a66ed6e6fbbc35874bb5547c1e0e 100644 (file)
@@ -84,6 +84,8 @@ Boston, MA 02110-1301, USA.  */
 #include "intervals.h"
 #include "atimer.h"
 #include "keymap.h"
+#include "character.h"
+#include "ccl.h"
 
 \f
 
@@ -2169,7 +2171,8 @@ XTreset_terminal_modes ()
 /* Function prototypes of this page.  */
 
 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
-static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
+static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, 
+                               struct charset *, int *));
 
 
 static void
@@ -2313,13 +2316,13 @@ mac_per_char_metric (font, char2b, font_type)
    the two-byte form of C.  Encoding is returned in *CHAR2B.  */
 
 static int
-mac_encode_char (c, char2b, font_info, two_byte_p)
+mac_encode_char (c, char2b, font_info, charset, two_byte_p)
      int c;
      XChar2b *char2b;
      struct font_info *font_info;
+     struct charset *charset;
      int *two_byte_p;
 {
-  int charset = CHAR_CHARSET (c);
   XFontStruct *font = font_info->font;
 
   /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
@@ -2333,31 +2336,31 @@ mac_encode_char (c, char2b, font_info, two_byte_p)
       check_ccl_update (ccl);
       if (CHARSET_DIMENSION (charset) == 1)
        {
-         ccl->reg[0] = charset;
-         ccl->reg[1] = char2b->byte2;
+         ccl->reg[0] = CHARSET_ID (charset);
+         ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
          ccl->reg[2] = -1;
        }
       else
        {
-         ccl->reg[0] = charset;
-         ccl->reg[1] = char2b->byte1;
-         ccl->reg[2] = char2b->byte2;
+         ccl->reg[0] = CHARSET_ID (charset);
+         ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
+         ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
        }
 
-      ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
+      ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
 
       /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
       if (font->max_byte1 == 0)        /* 1-byte font */
-       char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
+       STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
       else
-       char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
+       STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
     }
-  else if (font_info->encoding[charset])
+  else if (font_info->encoding_type)
     {
       /* Fixed encoding scheme.  See fontset.h for the meaning of the
         encoding numbers.  */
-      int enc = font_info->encoding[charset];
+      unsigned char enc = font_info->encoding_type;
 
       if ((enc == 1 || enc == 2)
          && CHARSET_DIMENSION (charset) == 2)
@@ -2367,13 +2370,12 @@ mac_encode_char (c, char2b, font_info, two_byte_p)
        char2b->byte2 |= 0x80;
 
       if (enc == 4)
-        {
-          int sjis1, sjis2;
+       {
+         int code = (char2b->byte1 << 8) | char2b->byte2;
 
-          ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
-          char2b->byte1 = sjis1;
-          char2b->byte2 = sjis2;
-        }
+         JIS_TO_SJIS (code);
+         STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
+       }
     }
 
   if (two_byte_p)
@@ -2492,9 +2494,9 @@ x_set_mouse_face_gc (s)
     face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
 
   if (s->first_glyph->type == CHAR_GLYPH)
-    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
   else
-    face_id = FACE_FOR_CHAR (s->f, face, 0);
+    face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
@@ -3529,19 +3531,28 @@ x_draw_stretch_glyph_string (s)
     {
       /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
         as wide as the stretch glyph.  */
-      int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
+      int width, background_width = s->background_width;
+      int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+      if (x < left_x)
+       {
+         background_width -= left_x - x;
+         x = left_x;
+       }
+      width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
 
       /* Draw cursor.  */
-      x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
+      x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
 
       /* Clear rest using the GC of the original non-cursor face.  */
-      if (width < s->background_width)
+      if (width < background_width)
        {
-         int x = s->x + width, y = s->y;
-         int w = s->background_width - width, h = s->height;
+         int y = s->y;
+         int w = background_width - width, h = s->height;
          Rect r;
          GC gc;
 
+         x += width;
          if (s->row->mouse_face_p
              && cursor_in_mouse_face_p (s->w))
            {
@@ -3568,8 +3579,18 @@ x_draw_stretch_glyph_string (s)
        }
     }
   else if (!s->background_filled_p)
-    x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
-                                s->height);
+    {
+      int background_width = s->background_width;
+      int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+      if (x < left_x)
+       {
+         background_width -= left_x - x;
+         x = left_x;
+       }
+      if (background_width > 0)
+       x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
+    }
 
   s->background_filled_p = 1;
 }
@@ -4097,6 +4118,11 @@ x_new_focus_frame (dpyinfo, frame)
        pending_autoraise_frame = dpyinfo->x_focus_frame;
       else
        pending_autoraise_frame = 0;
+
+#if USE_MAC_FONT_PANEL
+      if (frame)
+       mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
+#endif
     }
 
   x_frame_rehighlight (dpyinfo);
@@ -5391,8 +5417,7 @@ x_draw_hollow_cursor (w, row)
     return;
 
   /* Compute frame-relative coordinates for phys cursor.  */
-  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
+  get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
   wd = w->phys_cursor_width;
 
   /* The foreground of cursor_gc is typically the same as the normal
@@ -5662,11 +5687,16 @@ x_new_font (f, fontname)
      register char *fontname;
 {
   struct font_info *fontp
-    = FS_LOAD_FONT (f, 0, fontname, -1);
+    = FS_LOAD_FONT (f, fontname);
 
   if (!fontp)
     return Qnil;
 
+  if (FRAME_FONT (f) == (XFontStruct *) (fontp->font))
+    /* This font is already set in frame F.  There's nothing more to
+       do.  */
+    return build_string (fontp->full_name);
+
   FRAME_FONT (f) = (XFontStruct *) (fontp->font);
   FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
   FRAME_FONTSET (f) = -1;
@@ -5709,38 +5739,50 @@ x_new_font (f, fontname)
 
   return build_string (fontp->full_name);
 }
+\f
+/* Give frame F the fontset named FONTSETNAME as its default fontset,
+   and return the full name of that fontset.  FONTSETNAME may be a
+   wildcard pattern; in that case, we choose some fontset that fits
+   the pattern.  FONTSETNAME may be a font name for ASCII characters;
+   in that case, we create a fontset from that font name.
 
-/* Give frame F the fontset named FONTSETNAME as its default font, and
-   return the full name of that fontset.  FONTSETNAME may be a wildcard
-   pattern; in that case, we choose some fontset that fits the pattern.
-   The return value shows which fontset we chose.  */
+   The return value shows which fontset we chose.
+   If FONTSETNAME specifies the default fontset, return Qt.
+   If an ASCII font in the specified fontset can't be loaded, return
+   Qnil.  */
 
 Lisp_Object
 x_new_fontset (f, fontsetname)
      struct frame *f;
-     char *fontsetname;
+     Lisp_Object fontsetname;
 {
-  int fontset = fs_query_fontset (build_string (fontsetname), 0);
+  int fontset = fs_query_fontset (fontsetname, 0);
   Lisp_Object result;
 
-  if (fontset < 0)
-    return Qnil;
-
-  if (FRAME_FONTSET (f) == fontset)
+  if (fontset > 0 && FRAME_FONTSET(f) == fontset)
     /* This fontset is already set in frame F.  There's nothing more
        to do.  */
     return fontset_name (fontset);
+  else if (fontset == 0)
+    /* The default fontset can't be the default font.   */
+    return Qt;
 
-  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
+  if (fontset > 0)
+    result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
+  else
+    result = x_new_font (f, SDATA (fontsetname));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
     return Qnil;
 
+  if (fontset < 0)
+    fontset = new_fontset_from_font_name (result);
+
   /* Since x_new_font doesn't update any fontset information, do it now.  */
   FRAME_FONTSET (f) = fontset;
 
-  return build_string (fontsetname);
+  return fontset_name (fontset);
 }
 
 \f
@@ -6111,6 +6153,7 @@ mac_handle_visibility_change (f)
          EVENT_INIT (buf);
          buf.kind = DEICONIFY_EVENT;
          XSETFRAME (buf.frame_or_window, f);
+         buf.arg = Qnil;
          kbd_buffer_store_event (&buf);
        }
       else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
@@ -6124,6 +6167,7 @@ mac_handle_visibility_change (f)
        EVENT_INIT (buf);
        buf.kind = ICONIFY_EVENT;
        XSETFRAME (buf.frame_or_window, f);
+       buf.arg = Qnil;
        kbd_buffer_store_event (&buf);
       }
 
@@ -6343,7 +6387,12 @@ x_free_frame_resources (f)
   f->output_data.mac = NULL;
 
   if (f == dpyinfo->x_focus_frame)
-    dpyinfo->x_focus_frame = 0;
+    {
+      dpyinfo->x_focus_frame = 0;
+#if USE_MAC_FONT_PANEL
+      mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
+#endif
+    }
   if (f == dpyinfo->x_focus_event_frame)
     dpyinfo->x_focus_event_frame = 0;
   if (f == dpyinfo->x_highlight_frame)
@@ -6867,6 +6916,8 @@ static Lisp_Object fm_font_family_alist;
 #if USE_ATSUI
 /* Hash table linking font family names to ATSU font IDs.  */
 static Lisp_Object atsu_font_id_hash;
+static Lisp_Object Vmac_atsu_font_table;
+extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
 #endif
 
 /* Alist linking character set strings to Mac text encoding and Emacs
@@ -6927,12 +6978,12 @@ decode_mac_font_name (name, size, coding_system)
          coding.src_multibyte = 0;
          coding.dst_multibyte = 1;
          coding.mode |= CODING_MODE_LAST_BLOCK;
-         coding.composing = COMPOSITION_DISABLED;
-         buf = (char *) alloca (size);
+         coding.dst_bytes = size;
+         coding.destination = (unsigned char *) alloca (coding.dst_bytes);
 
-         decode_coding (&coding, name, buf, strlen (name), size - 1);
-         bcopy (buf, name, coding.produced);
-         name[coding.produced] = '\0';
+         decode_coding_c_string (&coding, name, strlen (name), Qnil);
+         bcopy (coding.destination, name, min (coding.produced, size));
+         name[min (coding.produced, size)] = '\0';
        }
     }
 
@@ -7162,8 +7213,21 @@ init_font_name_table ()
                                    NULL, NULL);
            if (err == noErr)
              {
+               FMFontFamily ff;
+               FMFontStyle style = normal;
+
                decode_mac_font_name (name, name_len + 1, Qnil);
                family = make_unibyte_string (name, name_len);
+               FMGetFontFamilyInstanceFromFont (font_ids[i], &ff, &style);
+               Fputhash (make_unibyte_string ((char *)(font_ids + i),
+                                              sizeof (ATSUFontID)),
+                         Fcons (QCfamily,
+                                list5 (family,
+                                       QCweight,
+                                       style & bold ? Qbold : Qnormal,
+                                       QCslant,
+                                       style & italic ? Qitalic : Qnormal)),
+                         Vmac_atsu_font_table);
                if (*name != '.'
                    && hash_lookup (h, family, &hash_code) < 0)
                  {
@@ -7709,6 +7773,7 @@ XLoadQueryFont (Display *dpy, char *fontname)
       ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector,
                                             kDecomposeDiacriticsSelector};
       Lisp_Object font_id_cons;
+      FMFontStyle style;
 
       font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
                               atsu_font_id_hash, Qnil);
@@ -7727,7 +7792,11 @@ XLoadQueryFont (Display *dpy, char *fontname)
        return NULL;
       err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
                               tags, sizes, values);
-      fontnum = -1;
+      if (err != noErr)
+       return NULL;
+      err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
+      if (err != noErr)
+       fontnum = -1;
       scriptcode = kTextEncodingMacUnicode;
     }
   else
@@ -7787,22 +7856,20 @@ XLoadQueryFont (Display *dpy, char *fontname)
       pcm_init (font->bounds.rows[0], 0x100);
 
 #if USE_CG_TEXT_DRAWING
-      {
-       FMFontFamily font_family;
-       FMFontStyle style;
-       ATSFontRef ats_font;
+      if (fontnum != -1)
+       {
+         FMFontStyle style;
+         ATSFontRef ats_font;
 
-       err = FMGetFontFamilyInstanceFromFont (font_id, &font_family, &style);
-       if (err == noErr)
-         err = FMGetFontFromFontFamilyInstance (font_family, fontface,
+         err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
                                                 &font_id, &style);
-       /* Use CG text drawing if italic/bold is not synthesized.  */
-       if (err == noErr && style == fontface)
-         {
-           ats_font = FMGetATSFontRefFromFont (font_id);
-           font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
-         }
-      }
+         /* Use CG text drawing if italic/bold is not synthesized.  */
+         if (err == noErr && style == fontface)
+           {
+             ats_font = FMGetATSFontRefFromFont (font_id);
+             font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
+           }
+       }
 
       if (font->cg_font)
        {
@@ -8132,6 +8199,7 @@ x_load_font (f, fontname, size)
     bzero (fontp, sizeof (*fontp));
     fontp->font = font;
     fontp->font_idx = i;
+    fontp->charset = -1;       /* fs_load_font sets it.  */
     fontp->name = (char *) xmalloc (strlen (fontname) + 1);
     bcopy (fontname, fontp->name, strlen (fontname) + 1);
 
@@ -8177,19 +8245,20 @@ x_load_font (f, fontname, size)
        fontp->height = max_height;
     }
 
+    /* MAC_TODO: The script encoding is irrelevant in unicode? */
     /* The slot `encoding' specifies how to map a character
        code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
        the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
        (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
        2:0xA020..0xFF7F).  For the moment, we don't know which charset
-       uses this font.  So, we set information in fontp->encoding[1]
+       uses this font.  So, we set information in fontp->encoding_type
        which is never used by any charset.  If mapping can't be
        decided, set FONT_ENCODING_NOT_DECIDED.  */
     if (font->mac_scriptcode == smJapanese)
-      fontp->encoding[1] = 4;
+      fontp->encoding_type = 4;
     else
       {
-        fontp->encoding[1]
+        fontp->encoding_type
            = (font->max_byte1 == 0
              /* 1-byte font */
              ? (font->min_char_or_byte2 < 0x80
@@ -8291,6 +8360,78 @@ x_find_ccl_program (fontp)
     }
 }
 
+#if USE_MAC_FONT_PANEL
+/* Whether Font Panel has been shown before.  The first call to font
+   panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
+   slow.  This variable is used for deferring such a call as much as
+   possible.  */
+static int font_panel_shown_p = 0;
+
+int
+mac_font_panel_visible_p ()
+{
+  return font_panel_shown_p && FPIsFontPanelVisible ();
+}
+
+OSStatus
+mac_show_hide_font_panel ()
+{
+  font_panel_shown_p = 1;
+
+  return FPShowHideFontPanel ();
+}
+
+OSStatus
+mac_set_font_info_for_selection (f, face_id, c)
+     struct frame *f;
+     int face_id, c;
+{
+  OSStatus err;
+  EventTargetRef target = NULL;
+  XFontStruct *font = NULL;
+
+  if (!mac_font_panel_visible_p ())
+    return noErr;
+
+  if (f)
+    {
+      target = GetWindowEventTarget (FRAME_MAC_WINDOW (f));
+
+      if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0))
+       {
+         struct face *face;
+
+         face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
+         face = FACE_FROM_ID (f, face_id);
+         font = face->font;
+       }
+    }
+
+  if (font == NULL)
+    err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target);
+  else
+    {
+      if (font->mac_fontnum != -1)
+       {
+         FontSelectionQDStyle qd_style;
+
+         qd_style.version = kFontSelectionQDStyleVersionZero;
+         qd_style.instance.fontFamily = font->mac_fontnum;
+         qd_style.instance.fontStyle = font->mac_fontface;
+         qd_style.size = font->mac_fontsize;
+         qd_style.hasColor = false;
+
+         err = SetFontInfoForSelection (kFontSelectionQDType,
+                                        1, &qd_style, target);
+       }
+      else
+       err = SetFontInfoForSelection (kFontSelectionATSUIType,
+                                      1, &font->mac_style, target);
+    }
+
+  return err;
+}
+#endif
 
 \f
 /* The Mac Event loop code */
@@ -8378,6 +8519,21 @@ Point saved_menu_event_location;
 /* Apple Events */
 #if USE_CARBON_EVENTS
 static Lisp_Object Qhicommand;
+#ifdef MAC_OSX
+extern Lisp_Object Qwindow;
+static Lisp_Object Qtoolbar_switch_mode;
+#endif
+#if USE_MAC_FONT_PANEL
+extern Lisp_Object Qfont;
+static Lisp_Object Qpanel_closed, Qselection;
+#endif
+#if USE_MAC_TSM
+static TSMDocumentID tsm_document_id;
+static Lisp_Object Qtext_input;
+static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
+static Lisp_Object Vmac_ts_active_input_overlay;
+extern Lisp_Object Qbefore_string;
+#endif
 #endif
 extern int mac_ready_for_apple_events;
 extern Lisp_Object Qundefined;
@@ -8394,7 +8550,7 @@ void remove_drag_handler P_ ((WindowRef));
 #if USE_CARBON_EVENTS
 #ifdef MAC_OSX
 extern void init_service_handler ();
-static Lisp_Object Qservices, Qpaste, Qperform;
+static Lisp_Object Qservice, Qpaste, Qperform;
 #endif
 /* Window Event Handler */
 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
@@ -8729,13 +8885,17 @@ is_emacs_window (WindowPtr win)
 static void
 do_app_resume ()
 {
-  /* Window-activate events will do the job. */
+#if USE_MAC_TSM
+  ActivateTSMDocument (tsm_document_id);
+#endif
 }
 
 static void
 do_app_suspend ()
 {
-  /* Window-deactivate events will do the job. */
+#if USE_MAC_TSM
+  DeactivateTSMDocument (tsm_document_id);
+#endif
 }
 
 
@@ -8966,6 +9126,45 @@ mac_store_apple_event (class, id, desc)
 }
 
 #if TARGET_API_MAC_CARBON
+static OSStatus
+mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
+                                   event, num_params, names, types)
+     AEEventClass class;
+     AEEventID id;
+     Lisp_Object class_key, id_key;
+     EventRef event;
+     UInt32 num_params;
+     EventParamName *names;
+     EventParamType *types;
+{
+  OSStatus err = eventNotHandledErr;
+  Lisp_Object binding;
+
+  mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
+  if (!NILP (binding) && !EQ (binding, Qundefined))
+    {
+      if (INTEGERP (binding))
+       err = XINT (binding);
+      else
+       {
+         AppleEvent apple_event;
+         err = create_apple_event_from_event_ref (event, num_params,
+                                                  names, types,
+                                                  &apple_event);
+         if (err == noErr)
+           {
+             mac_store_apple_event (class_key, id_key, &apple_event);
+             AEDisposeDesc (&apple_event);
+             /* Post a harmless event so as to wake up from
+                ReceiveNextEvent.  */
+             mac_post_mouse_moved_event ();
+           }
+       }
+    }
+
+  return err;
+}
+
 void
 mac_store_drag_event (window, mouse_pos, modifiers, desc)
      WindowRef window;
@@ -8997,7 +9196,11 @@ mac_handle_command_event (next_handler, event, data)
 {
   OSStatus result, err;
   HICommand command;
-  Lisp_Object class_key, id_key, binding;
+  static EventParamName names[] = {kEventParamDirectObject,
+                                  kEventParamKeyModifiers};
+  static EventParamType types[] = {typeHICommand,
+                                  typeUInt32};
+  int num_params = sizeof (names) / sizeof (names[0]);
 
   result = CallNextEventHandler (next_handler, event);
   if (result != eventNotHandledErr)
@@ -9011,32 +9214,10 @@ mac_handle_command_event (next_handler, event, data)
 
   /* A HICommand event is mapped to an Apple event whose event class
      symbol is `hicommand' and event ID is its command ID.  */
-  class_key = Qhicommand;
-  mac_find_apple_event_spec (0, command.commandID,
-                            &class_key, &id_key, &binding);
-  if (!NILP (binding) && !EQ (binding, Qundefined))
-    {
-      if (INTEGERP (binding))
-       return XINT (binding);
-      else
-       {
-         AppleEvent apple_event;
-         static EventParamName names[] = {kEventParamDirectObject,
-                                          kEventParamKeyModifiers};
-         static EventParamType types[] = {typeHICommand,
-                                          typeUInt32};
-         err = create_apple_event_from_event_ref (event, 2, names, types,
-                                                  &apple_event);
-         if (err == noErr)
-           {
-             mac_store_apple_event (class_key, id_key, &apple_event);
-             AEDisposeDesc (&apple_event);
-             return noErr;
-           }
-       }
-    }
-
-  return eventNotHandledErr;
+  err = mac_store_event_ref_as_apple_event (0, command.commandID,
+                                           Qhicommand, Qnil,
+                                           event, num_params, names, types);
+  return err == noErr ? noErr : eventNotHandledErr;
 }
 
 static OSErr
@@ -9139,6 +9320,45 @@ mac_handle_window_event (next_handler, event, data)
       return noErr;
 
       break;
+
+#ifdef MAC_OSX
+    case kEventWindowToolbarSwitchMode:
+      result = CallNextEventHandler (next_handler, event);
+      {
+       static EventParamName names[] = {kEventParamDirectObject,
+                                        kEventParamWindowMouseLocation,
+                                        kEventParamKeyModifiers,
+                                        kEventParamMouseButton,
+                                        kEventParamClickCount,
+                                        kEventParamMouseChord};
+       static EventParamType types[] = {typeWindowRef,
+                                        typeQDPoint,
+                                        typeUInt32,
+                                        typeMouseButton,
+                                        typeUInt32,
+                                        typeUInt32};
+       int num_params = sizeof (names) / sizeof (names[0]);
+
+       err = mac_store_event_ref_as_apple_event (0, 0,
+                                                 Qwindow,
+                                                 Qtoolbar_switch_mode,
+                                                 event, num_params,
+                                                 names, types);
+      }
+      return err == noErr ? noErr : result;
+#endif
+
+#if USE_MAC_TSM
+    case kEventWindowFocusAcquired:
+      result = CallNextEventHandler (next_handler, event);
+      err = ActivateTSMDocument (tsm_document_id);
+      return err == noErr ? noErr : result;
+
+    case kEventWindowFocusRelinquish:
+      result = CallNextEventHandler (next_handler, event);
+      err = DeactivateTSMDocument (tsm_document_id);
+      return err == noErr ? noErr : result;
+#endif
     }
 
   return eventNotHandledErr;
@@ -9213,33 +9433,219 @@ mac_handle_mouse_event (next_handler, event, data)
   return eventNotHandledErr;
 }
 
-#ifdef MAC_OSX
-OSErr
-mac_store_services_event (event)
+#if USE_MAC_FONT_PANEL
+static pascal OSStatus
+mac_handle_font_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
      EventRef event;
+     void *data;
 {
-  OSErr err;
-  AppleEvent apple_event;
+  OSStatus result, err;
   Lisp_Object id_key;
+  int num_params;
+  EventParamName *names;
+  EventParamType *types;
+  static EventParamName names_sel[] = {kEventParamATSUFontID,
+                                      kEventParamATSUFontSize,
+                                      kEventParamFMFontFamily,
+                                      kEventParamFMFontSize,
+                                      kEventParamFontColor};
+  static EventParamType types_sel[] = {typeATSUFontID,
+                                      typeATSUSize,
+                                      typeFMFontFamily,
+                                      typeFMFontSize,
+                                      typeFontColor};
+
+  result = CallNextEventHandler (next_handler, event);
+  if (result != eventNotHandledErr)
+    return result;
 
   switch (GetEventKind (event))
     {
-    case kEventServicePaste:
-      id_key = Qpaste;
-      err = create_apple_event_from_event_ref (event, 0, NULL, NULL,
-                                              &apple_event);
+    case kEventFontPanelClosed:
+      id_key = Qpanel_closed;
+      num_params = 0;
+      names = NULL;
+      types = NULL;
       break;
 
-    case kEventServicePerform:
+    case kEventFontSelection:
+      id_key = Qselection;
+      num_params = sizeof (names_sel) / sizeof (names_sel[0]);
+      names = names_sel;
+      types = types_sel;
+      break;
+    }
+
+  err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
+                                           event, num_params,
+                                           names, types);
+
+  return err == noErr ? noErr : eventNotHandledErr;
+}
+#endif
+
+#if USE_MAC_TSM
+static pascal OSStatus
+mac_handle_text_input_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  OSStatus result, err = noErr;
+  Lisp_Object id_key = Qnil;
+  int num_params;
+  EventParamName *names;
+  EventParamType *types;
+  static UInt32 seqno_uaia = 0;
+  static EventParamName names_uaia[] =
+    {kEventParamTextInputSendComponentInstance,
+     kEventParamTextInputSendRefCon,
+     kEventParamTextInputSendSLRec,
+     kEventParamTextInputSendFixLen,
+     kEventParamTextInputSendText,
+     kEventParamTextInputSendUpdateRng,
+     kEventParamTextInputSendHiliteRng,
+     kEventParamTextInputSendClauseRng,
+     kEventParamTextInputSendPinRng,
+     kEventParamTextInputSendTextServiceEncoding,
+     kEventParamTextInputSendTextServiceMacEncoding,
+     EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
+  static EventParamType types_uaia[] =
+    {typeComponentInstance,
+     typeLongInteger,
+     typeIntlWritingCode,
+     typeLongInteger,
+     typeUnicodeText,
+     typeTextRangeArray,
+     typeTextRangeArray,
+     typeOffsetArray,
+     typeTextRange,
+     typeUInt32,
+     typeUInt32,
+     typeUInt32};
+  static EventParamName names_ufke[] =
+    {kEventParamTextInputSendComponentInstance,
+     kEventParamTextInputSendRefCon,
+     kEventParamTextInputSendSLRec,
+     kEventParamTextInputSendText};
+  static EventParamType types_ufke[] =
+    {typeComponentInstance,
+     typeLongInteger,
+     typeIntlWritingCode,
+     typeUnicodeText};
+
+  result = CallNextEventHandler (next_handler, event);
+
+  switch (GetEventKind (event))
+    {
+    case kEventTextInputUpdateActiveInputArea:
+      id_key = Qupdate_active_input_area;
+      num_params = sizeof (names_uaia) / sizeof (names_uaia[0]);
+      names = names_uaia;
+      types = types_uaia;
+      SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
+                        typeUInt32, sizeof (UInt32), &seqno_uaia);
+      seqno_uaia++;
+      break;
+
+    case kEventTextInputUnicodeForKeyEvent:
       {
-       static EventParamName names[] = {kEventParamServiceMessageName,
-                                        kEventParamServiceUserData};
-       static EventParamType types[] = {typeCFStringRef,
-                                        typeCFStringRef};
-
-       id_key = Qperform;
-       err = create_apple_event_from_event_ref (event, 2, names, types,
-                                                &apple_event);
+       EventRef kbd_event;
+       UInt32 actual_size, modifiers, mapped_modifiers;
+       UniChar code;
+
+       err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent,
+                                typeEventRef, NULL, sizeof (EventRef), NULL,
+                                &kbd_event);
+       if (err == noErr)
+         err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
+                                  typeUInt32, NULL,
+                                  sizeof (UInt32), NULL, &modifiers);
+       if (err == noErr)
+         {
+           mapped_modifiers =
+             (NILP (Vmac_control_modifier) ? 0 : controlKey)
+             | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+             | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
+#ifdef MAC_OSX
+           mapped_modifiers |=
+             (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
+#endif
+           if (modifiers & mapped_modifiers)
+             /* There're mapped modifier keys.  Process it in
+                XTread_socket.  */
+             return eventNotHandledErr;
+         }
+       if (err == noErr)
+         err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
+                                  typeUnicodeText, NULL, 0, &actual_size,
+                                  NULL);
+       if (err == noErr)
+         {
+           if (actual_size == sizeof (UniChar))
+             err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
+                                      typeUnicodeText, NULL,
+                                      sizeof (UniChar), NULL, &code);
+           if (err == noErr && code < 0x80)
+             {
+               /* ASCII character.  Process it in XTread_socket.  */
+               if (read_socket_inev && code >= 0x20 && code <= 0x7e)
+                 {
+                   struct frame *f = mac_focus_frame (&one_mac_display_info);
+
+                   read_socket_inev->kind = ASCII_KEYSTROKE_EVENT;
+                   read_socket_inev->code = code;
+                   read_socket_inev->modifiers =
+                     (extra_keyboard_modifiers
+                      & (meta_modifier | alt_modifier
+                         | hyper_modifier | super_modifier));
+                   XSETFRAME (read_socket_inev->frame_or_window, f);
+                 }
+               return eventNotHandledErr;
+             }
+         }
+      }
+      /* 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:
+      {
+       struct frame *f;
+       struct window *w;
+       Point p;
+
+       if (!OVERLAYP (Vmac_ts_active_input_overlay))
+         return eventNotHandledErr;
+
+       /* 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)))
+         {
+           /* 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);
+         }
+
+       p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
+              + WINDOW_LEFT_FRINGE_WIDTH (w));
+       p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
+              + FONT_BASE (FRAME_FONT (f)));
+       SetPortWindowPort (FRAME_MAC_WINDOW (f));
+       LocalToGlobal (&p);
+       err = SetEventParameter (event, kEventParamTextInputReplyPoint,
+                                typeQDPoint, sizeof (typeQDPoint), &p);
       }
       break;
 
@@ -9247,12 +9653,54 @@ mac_store_services_event (event)
       abort ();
     }
 
-  if (err == noErr)
+  if (!NILP (id_key))
+    err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
+                                             event, num_params,
+                                             names, types);
+
+  return err == noErr ? noErr : result;
+}
+#endif
+
+#ifdef MAC_OSX
+OSStatus
+mac_store_service_event (event)
+     EventRef event;
+{
+  OSStatus err;
+  Lisp_Object id_key;
+  int num_params;
+  EventParamName *names;
+  EventParamType *types;
+  static EventParamName names_pfm[] = {kEventParamServiceMessageName,
+                                      kEventParamServiceUserData};
+  static EventParamType types_pfm[] = {typeCFStringRef,
+                                      typeCFStringRef};
+
+  switch (GetEventKind (event))
     {
-      mac_store_apple_event (Qservices, id_key, &apple_event);
-      AEDisposeDesc (&apple_event);
+    case kEventServicePaste:
+      id_key = Qpaste;
+      num_params = 0;
+      names = NULL;
+      types = NULL;
+      break;
+
+    case kEventServicePerform:
+      id_key = Qperform;
+      num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
+      names = names_pfm;
+      types = types_pfm;
+      break;
+
+    default:
+      abort ();
     }
 
+  err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
+                                           event, num_params,
+                                           names, types);
+
   return err;
 }
 #endif /* MAC_OSX */
@@ -9271,15 +9719,44 @@ install_window_handler (window)
      {kEventClassWindow, kEventWindowShown},
      {kEventClassWindow, kEventWindowHidden},
      {kEventClassWindow, kEventWindowExpanded},
-     {kEventClassWindow, kEventWindowCollapsed}};
+     {kEventClassWindow, kEventWindowCollapsed},
+#ifdef MAC_OSX
+     {kEventClassWindow, kEventWindowToolbarSwitchMode},
+#endif
+#if USE_MAC_TSM
+     {kEventClassWindow, kEventWindowFocusAcquired},
+     {kEventClassWindow, kEventWindowFocusRelinquish},
+#endif
+  };
   EventTypeSpec specs_mouse[] = {{kEventClassMouse, kEventMouseWheelMoved}};
   static EventHandlerUPP handle_window_eventUPP = NULL;
   static EventHandlerUPP handle_mouse_eventUPP = NULL;
+#if USE_MAC_FONT_PANEL
+  EventTypeSpec specs_font[] = {{kEventClassFont, kEventFontPanelClosed},
+                               {kEventClassFont, kEventFontSelection}};
+  static EventHandlerUPP handle_font_eventUPP = NULL;
+#endif
+#if USE_MAC_TSM
+  EventTypeSpec specs_text_input[] =
+    {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
+     {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
+     {kEventClassTextInput, kEventTextInputOffsetToPos}};
+  static EventHandlerUPP handle_text_input_eventUPP = NULL;
+#endif
 
   if (handle_window_eventUPP == NULL)
     handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
   if (handle_mouse_eventUPP == NULL)
     handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
+#if USE_MAC_FONT_PANEL
+  if (handle_font_eventUPP == NULL)
+    handle_font_eventUPP = NewEventHandlerUPP (mac_handle_font_event);
+#endif
+#if USE_MAC_TSM
+  if (handle_text_input_eventUPP == NULL)
+    handle_text_input_eventUPP =
+      NewEventHandlerUPP (mac_handle_text_input_event);
+#endif
   err = InstallWindowEventHandler (window, handle_window_eventUPP,
                                   GetEventTypeCount (specs_window),
                                   specs_window, NULL, NULL);
@@ -9287,6 +9764,18 @@ install_window_handler (window)
     err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
                                     GetEventTypeCount (specs_mouse),
                                     specs_mouse, NULL, NULL);
+#if USE_MAC_FONT_PANEL
+  if (err == noErr)
+    err = InstallWindowEventHandler (window, handle_font_eventUPP,
+                                    GetEventTypeCount (specs_font),
+                                    specs_font, NULL, NULL);
+#endif
+#if USE_MAC_TSM
+  if (err == noErr)
+    err = InstallWindowEventHandler (window, handle_text_input_eventUPP,
+                                    GetEventTypeCount (specs_text_input),
+                                    specs_text_input, window, NULL);
+#endif
 #endif
   if (err == noErr)
     err = install_drag_handler (window);
@@ -9412,7 +9901,7 @@ static unsigned char keycode_to_xkeysym_table[] = {
 
   /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
   /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
-  /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
+  /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
   /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
 
   /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
@@ -9429,7 +9918,13 @@ keycode_to_xkeysym (int keyCode, int *xKeySym)
   return *xKeySym != 0;
 }
 
-static unsigned char fn_keycode_to_xkeysym_table[] = {
+#ifdef MAC_OSX
+/* Table for translating Mac keycode with the laptop `fn' key to that
+   without it.  Destination symbols in comments are keys on US
+   keyboard, and they may not be the same on other types of keyboards.
+   If the destination is identical to the source (f1 ... f12), it
+   doesn't map `fn' key to a modifier.  */
+static unsigned char fn_keycode_to_keycode_table[] = {
   /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -9439,113 +9934,27 @@ static unsigned char fn_keycode_to_xkeysym_table[] = {
   /*0x38*/ 0, 0, 0, 0,
   /*0x3C*/ 0, 0, 0, 0,
 
-  /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
-  /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
-  /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
-  /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
+  /*0x40*/ 0, 0x2f /*kp-. -> '.'*/, 0, 0x23 /*kp-* -> 'p'*/,
+  /*0x44*/ 0, 0x2c /*kp-+ -> '/'*/, 0, 0x16 /*clear -> '6'*/,
+  /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
+  /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-- -> ';'*/, 0,
 
-  /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
-  /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
-  /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
-  /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
+  /*0x50*/ 0, 0x1b /*kp-= -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
+  /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
+  /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
+  /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
 
-  /*0x60*/ 0, 0, 0, 0,
-  /*0x64*/ 0, 0, 0, 0,
+  /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
+  /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
   /*0x68*/ 0, 0, 0, 0,
-  /*0x6C*/ 0, 0, 0, 0,
+  /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
 
-  /*0x70*/ 0, 0, 0, 0,
-  /*0x74*/ 0, 0, 0, 0,
-  /*0x78*/ 0, 0, 0, 0,
+  /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
+  /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
+  /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
   /*0x7C*/ 0, 0, 0, 0
 };
-static int
-convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
-{
-#ifdef MAC_OSX
-  /* Use the special map to translate keys when function modifier is
-     to be caught. KeyTranslate can't be used in that case.
-     We can't detect the function key using the input_event.modifiers,
-     because this uses the high word of an UInt32. Therefore,
-     we'll just read it out of the original eventRef.
-  */
-
-
-  /* TODO / known issues
-
-  - Fn-Shift-j is regonized as Fn-j and not Fn-J.
-  The above table always translates to lower characters. We need to use
-  the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
-
-  - The table is meant for English language keyboards, and it will work
-  for many others with the exception of key combinations like Fn-ö on
-  a German keyboard, which is currently mapped to Fn-;.
-  How to solve this without keeping separate tables for all keyboards
-  around? KeyTranslate isn't of much help here, as it only takes a 16-bit
-  value for keycode with the modifiers in he high byte, i.e. no room for the
-  Fn modifier. That's why we need the table.
-
-  */
-  OSStatus err;
-  UInt32 mods = 0;
-  if (!NILP(Vmac_function_modifier))
-    {
-      err = GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
-                              NULL, sizeof (UInt32), NULL, &mods);
-      if (err != noErr && mods & kEventKeyModifierFnMask)
-       {  *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
-
-         return (*newCode != 0);
-       }
-    }
-#endif
-  return false;
-}
-
-static int
-backtranslate_modified_keycode(int mods, int keycode, int def)
-{
-  EventModifiers mapped_modifiers =
-    (NILP (Vmac_control_modifier) ? 0 : controlKey)
-    | (NILP (Vmac_option_modifier) ? 0 : optionKey)
-    | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
-
-  if (mods & mapped_modifiers)
-    {
-      /* This code comes from Keyboard Resource,
-        Appendix C of IM - Text.  This is necessary
-        since shift is ignored in KCHR table
-        translation when option or command is pressed.
-        It also does not translate correctly
-        control-shift chars like C-% so mask off shift
-        here also.
-
-        Not done for combinations with the option key (alt)
-        unless it is to be caught by Emacs:  this is
-        to preserve key combinations translated by the OS
-        such as Alt-3.
-      */
-      /* Mask off modifier keys that are mapped to some Emacs
-        modifiers.  */
-      int new_modifiers = mods & ~mapped_modifiers;
-      /* set high byte of keycode to modifier high byte*/
-      int new_keycode = keycode | new_modifiers;
-      Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
-      unsigned long some_state = 0;
-      return (int) KeyTranslate (kchr_ptr, new_keycode,
-                                &some_state) & 0xff;
-      /* TO DO: Recognize two separate resulting characters, "for
-        example, when the user presses Option-E followed by N, you
-        can map this through the KeyTranslate function using the
-        U.S. 'KCHR' resource to produce Â´n, which KeyTranslate
-        returns as two characters in the bytes labeled Character code
-        1 and Character code 2." (from Carbon API doc) */
-
-    }
-  else
-    return def;
-}
-
+#endif /* MAC_OSX */
 
 #if !USE_CARBON_EVENTS
 static RgnHandle mouse_region = NULL;
@@ -9619,6 +10028,44 @@ mac_post_mouse_moved_event ()
 
   return err;
 }
+
+static void
+mac_set_unicode_keystroke_event (code, buf)
+     UniChar code;
+     struct input_event *buf;
+{
+  int charset_id, c1, c2;
+
+  if (code < 0x80)
+    {
+      buf->kind = ASCII_KEYSTROKE_EVENT;
+      buf->code = code;
+    }
+  else if (code < 0x100)
+    {
+      if (code < 0xA0)
+       charset_id = CHARSET_8_BIT_CONTROL;
+      else
+       charset_id = charset_latin_iso8859_1;
+      buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+      buf->code = MAKE_CHAR (charset_id, code, 0);
+    }
+  else
+    {
+      if (code < 0x2500)
+       charset_id = charset_mule_unicode_0100_24ff,
+         code -= 0x100;
+      else if (code < 0x33FF)
+       charset_id = charset_mule_unicode_2500_33ff,
+         code -= 0x2500;
+      else if (code >= 0xE000)
+       charset_id = charset_mule_unicode_e000_ffff,
+         code -= 0xE000;
+      c1 = (code / 96) + 32, c2 = (code % 96) + 32;
+      buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+      buf->code = MAKE_CHAR (charset_id, c1, c2);
+    }
+}
 #endif
 
 /* Emacs calls this whenever it wants to read an input event from the
@@ -9668,10 +10115,6 @@ XTread_socket (sd, expected, hold_quit)
       struct frame *f;
       unsigned long timestamp;
 
-      /* It is necessary to set this (additional) argument slot of an
-        event to nil because keyboard.c protects incompletely
-        processed event from being garbage collected by placing them
-        in the kbd_buffer_gcpro vector.  */
       EVENT_INIT (inev);
       inev.kind = NO_EVENT;
       inev.arg = Qnil;
@@ -9748,7 +10191,13 @@ XTread_socket (sd, expected, hold_quit)
                break;
 
              case inContent:
-               if (window_ptr != FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo)))
+               if (
+#if TARGET_API_MAC_CARBON
+                   FrontNonFloatingWindow ()
+#else
+                   FrontWindow ()
+#endif
+                   != window_ptr)
                  SelectWindow (window_ptr);
                else
                  {
@@ -10127,10 +10576,29 @@ XTread_socket (sd, expected, hold_quit)
          break;
 
        case keyDown:
+       case keyUp:
        case autoKey:
          {
            int keycode = (er.message & keyCodeMask) >> 8;
            int xkeysym;
+           static SInt16 last_key_script = -1;
+           SInt16 current_key_script;
+           UInt32 modifiers = er.modifiers, mapped_modifiers;
+
+           mapped_modifiers =
+             (NILP (Vmac_control_modifier) ? 0 : controlKey)
+             | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+             | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
+
+#if USE_CARBON_EVENTS && defined (MAC_OSX)
+           mapped_modifiers |=
+             (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
+
+           GetEventParameter (eventRef, kEventParamKeyModifiers,
+                              typeUInt32, NULL,
+                              sizeof (UInt32), NULL, &modifiers);
+#endif
+           mapped_modifiers &= modifiers;
 
 #if USE_CARBON_EVENTS && defined (MAC_OSX)
            /* When using Carbon Events, we need to pass raw keyboard
@@ -10138,45 +10606,21 @@ XTread_socket (sd, expected, hold_quit)
               will pass back noErr, otherwise it will pass back
               "eventNotHandledErr" and we can process it
               normally.  */
-           if ((mac_pass_command_to_system
-                || !(er.modifiers & cmdKey))
-               && (mac_pass_control_to_system
-                   || !(er.modifiers & controlKey))
-               && (NILP (Vmac_option_modifier)
-                   || !(er.modifiers & optionKey)))
-             if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
-                 != eventNotHandledErr)
-               break;
-#endif
-
-#if 0
-           if (dpyinfo->x_focus_frame == NULL)
+           if (!(mapped_modifiers
+                 & ~(mac_pass_command_to_system ? cmdKey : 0)
+                 & ~(mac_pass_control_to_system ? controlKey : 0)))
              {
-               /* Beep if keyboard input occurs when all the frames
-                  are invisible.  */
-               SysBeep (1);
-               break;
+               OSStatus err;
+
+               read_socket_inev = &inev;
+               err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
+               read_socket_inev = NULL;
+               if (err != eventNotHandledErr)
+                 break;
              }
 #endif
-
-           {
-             static SInt16 last_key_script = -1;
-             SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
-
-             if (last_key_script != current_key_script)
-               {
-                 struct input_event event;
-
-                 EVENT_INIT (event);
-                 event.kind = LANGUAGE_CHANGE_EVENT;
-                 event.arg = Qnil;
-                 event.code = current_key_script;
-                 event.timestamp = timestamp;
-                 kbd_buffer_store_event (&event);
-                 count++;
-               }
-             last_key_script = current_key_script;
-           }
+           if (er.what == keyUp)
+             break;
 
            ObscureCursor ();
 
@@ -10189,51 +10633,163 @@ XTread_socket (sd, expected, hold_quit)
                dpyinfo->mouse_face_hidden = 1;
              }
 
-           /* translate the keycode back to determine the original key */
-           /* Convert key code if function key is pressed.
-              Otherwise, if non-ASCII-event, take care of that
-              without re-translating the key code. */
-#if USE_CARBON_EVENTS
-           if (convert_fn_keycode (eventRef, keycode, &xkeysym))
+           current_key_script = GetScriptManagerVariable (smKeyScript);
+           if (last_key_script != current_key_script)
              {
-               inev.code = xkeysym;
-               /* this doesn't work - tried to add shift modifiers */
-                 inev.code =
-                   backtranslate_modified_keycode(er.modifiers & (~0x2200),
-                                                  xkeysym | 0x80,  xkeysym);
-               inev.kind = ASCII_KEYSTROKE_EVENT;
+               struct input_event event;
+
+               EVENT_INIT (event);
+               event.kind = LANGUAGE_CHANGE_EVENT;
+               event.arg = Qnil;
+               event.code = current_key_script;
+               event.timestamp = timestamp;
+               kbd_buffer_store_event (&event);
+               count++;
+               last_key_script = current_key_script;
              }
-           else
+
+#if USE_MAC_TSM
+           if (inev.kind != NO_EVENT)
+             break;
 #endif
-             if (keycode_to_xkeysym (keycode, &xkeysym))
-               {
-                 inev.code = 0xff00 | xkeysym;
-                 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
-               }
-             else
-               {
-                 inev.code =
-                   backtranslate_modified_keycode(er.modifiers, keycode,
-                                                  er.message & charCodeMask);
-                 inev.kind = ASCII_KEYSTROKE_EVENT;
-               }
-         }
 
-#if USE_CARBON_EVENTS
-         inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
-#else
-         inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+#ifdef MAC_OSX
+           if (mapped_modifiers & kEventKeyModifierFnMask
+               && keycode <= 0x7f
+               && fn_keycode_to_keycode_table[keycode])
+             keycode = fn_keycode_to_keycode_table[keycode];
+#endif
+           if (keycode_to_xkeysym (keycode, &xkeysym))
+             {
+               inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+               inev.code = 0xff00 | xkeysym;
+#ifdef MAC_OSX
+               if (modifiers & kEventKeyModifierFnMask
+                   && keycode <= 0x7f
+                   && fn_keycode_to_keycode_table[keycode] == keycode)
+                 modifiers &= ~kEventKeyModifierFnMask;
+#endif
+             }
+           else if (mapped_modifiers)
+             {
+               /* translate the keycode back to determine the
+                  original key */
+#ifdef MAC_OSX
+               static SInt16 last_key_layout_id = 0;
+               static Handle uchr_handle = (Handle)-1;
+               SInt16 current_key_layout_id =
+                 GetScriptVariable (current_key_script, smScriptKeys);
+
+               if (uchr_handle == (Handle)-1
+                   || last_key_layout_id != current_key_layout_id)
+                 {
+                   uchr_handle = GetResource ('uchr', current_key_layout_id);
+                   last_key_layout_id = current_key_layout_id;
+                 }
+
+               if (uchr_handle)
+                 {
+                   OSStatus status;
+                   UInt16 key_action = er.what - keyDown;
+                   UInt32 modifier_key_state =
+                     (modifiers & ~mapped_modifiers) >> 8;
+                   UInt32 keyboard_type = LMGetKbdType ();
+                   SInt32 dead_key_state = 0;
+                   UniChar code;
+                   UniCharCount actual_length;
+
+                   status = UCKeyTranslate ((UCKeyboardLayout *)*uchr_handle,
+                                            keycode, key_action,
+                                            modifier_key_state,
+                                            keyboard_type,
+                                            kUCKeyTranslateNoDeadKeysMask,
+                                            &dead_key_state,
+                                            1, &actual_length, &code);
+                   if (status == noErr && actual_length == 1)
+                     mac_set_unicode_keystroke_event (code, &inev);
+                 }
+#endif /* MAC_OSX */
+
+               if (inev.kind == NO_EVENT)
+                 {
+                   /* This code comes from Keyboard Resource,
+                      Appendix C of IM - Text.  This is necessary
+                      since shift is ignored in KCHR table
+                      translation when option or command is pressed.
+                      It also does not translate correctly
+                      control-shift chars like C-% so mask off shift
+                      here also.  */
+                   /* Mask off modifier keys that are mapped to some
+                      Emacs modifiers.  */
+                   int new_modifiers = er.modifiers & ~mapped_modifiers;
+                   /* set high byte of keycode to modifier high byte*/
+                   int new_keycode = keycode | new_modifiers;
+                   Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+                   unsigned long some_state = 0;
+                   UInt32 new_char_code;
+
+                   new_char_code = KeyTranslate (kchr_ptr, new_keycode,
+                                                 &some_state);
+                   if (new_char_code == 0)
+                     /* Seems like a dead key.  Append up-stroke.  */
+                     new_char_code = KeyTranslate (kchr_ptr,
+                                                   new_keycode | 0x80,
+                                                   &some_state);
+                   if (new_char_code)
+                     {
+                       inev.kind = ASCII_KEYSTROKE_EVENT;
+                       inev.code = new_char_code & 0xff;
+                     }
+                 }
+             }
+
+           if (inev.kind == NO_EVENT)
+             {
+               inev.kind = ASCII_KEYSTROKE_EVENT;
+               inev.code = er.message & charCodeMask;
+             }
+
+           inev.modifiers = mac_to_emacs_modifiers (modifiers);
+           inev.modifiers |= (extra_keyboard_modifiers
+                              & (meta_modifier | alt_modifier
+                                 | hyper_modifier | super_modifier));
+           XSETFRAME (inev.frame_or_window, f);
+
+#if TARGET_API_MAC_CARBON
+           if (inev.kind == ASCII_KEYSTROKE_EVENT
+               && inev.code >= 0x80 && inev.modifiers)
+             {
+               OSStatus err;
+               TextEncoding encoding = kTextEncodingMacRoman;
+               TextToUnicodeInfo ttu_info;
+
+               UpgradeScriptInfoToTextEncoding (current_key_script,
+                                                kTextLanguageDontCare,
+                                                kTextRegionDontCare,
+                                                NULL, &encoding);
+               err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
+               if (err == noErr)
+                 {
+                   UniChar code;
+                   Str255 pstr;
+                   ByteCount unicode_len;
+
+                   pstr[0] = 1;
+                   pstr[1] = inev.code;
+                   err = ConvertFromPStringToUnicode (ttu_info, pstr,
+                                                      sizeof (UniChar),
+                                                      &unicode_len, &code);
+                   if (err == noErr && unicode_len == sizeof (UniChar))
+                     mac_set_unicode_keystroke_event (code, &inev);
+                   DisposeTextToUnicodeInfo (&ttu_info);
+                 }
+             }
 #endif
-         inev.modifiers |= (extra_keyboard_modifiers
-                            & (meta_modifier | alt_modifier
-                               | hyper_modifier | super_modifier));
-         XSETFRAME (inev.frame_or_window, f);
+         }
          break;
 
        case kHighLevelEvent:
-         read_socket_inev = &inev;
          AEProcessAppleEvent (&er);
-         read_socket_inev = NULL;
          break;
 
        default:
@@ -10705,6 +11261,16 @@ init_menu_bar ()
 #endif
 }
 
+#if USE_MAC_TSM
+static void
+init_tsm ()
+{
+  static InterfaceTypeList types = {kUnicodeDocument};
+
+  NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
+                 &tsm_document_id, 0);
+}
+#endif
 
 /* Set up use of X before we make the first connection.  */
 
@@ -10799,6 +11365,10 @@ mac_initialize ()
   init_command_handler ();
 
   init_menu_bar ();
+
+#if USE_MAC_TSM
+  init_tsm ();
+#endif
 #endif /* USE_CARBON_EVENTS */
 
 #ifdef MAC_OSX
@@ -10844,10 +11414,24 @@ syms_of_macterm ()
 #if USE_CARBON_EVENTS
   Qhicommand   = intern ("hicommand");    staticpro (&Qhicommand);
 #ifdef MAC_OSX
-  Qservices    = intern ("services");    staticpro (&Qservices);
+  Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
+  staticpro (&Qtoolbar_switch_mode);
+#if USE_MAC_FONT_PANEL
+  Qpanel_closed = intern ("panel-closed");  staticpro (&Qpanel_closed);
+  Qselection    = intern ("selection");     staticpro (&Qselection);
+#endif
+
+  Qservice     = intern ("service");     staticpro (&Qservice);
   Qpaste       = intern ("paste");       staticpro (&Qpaste);
   Qperform     = intern ("perform");     staticpro (&Qperform);
 #endif
+#if USE_MAC_TSM
+  Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
+  Qupdate_active_input_area = intern ("update-active-input-area");
+  staticpro (&Qupdate_active_input_area);
+  Qunicode_for_key_event = intern ("unicode-for-key-event");
+  staticpro (&Qunicode_for_key_event);
+#endif
 #endif
 
 #ifdef MAC_OSX
@@ -10884,7 +11468,7 @@ NOTE: Not supported on Mac yet.  */);
   x_use_underline_position_properties = 0;
 
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
-              doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
+    doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
 #ifdef USE_TOOLKIT_SCROLL_BARS
   Vx_toolkit_scroll_bars = Qt;
 #else
@@ -10938,23 +11522,23 @@ mouse-3 and the command-key will register for mouse-2.  */);
 
 #if USE_CARBON_EVENTS
   DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
-   doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
+    doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
 Otherwise, the right click will be treated as mouse-2 and the wheel
 button will be mouse-3.  */);
   mac_wheel_button_is_mouse_2 = 1;
 
   DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
-   doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox.  */);
+    doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox.  */);
   mac_pass_command_to_system = 1;
 
   DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
-   doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox.  */);
+    doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox.  */);
   mac_pass_control_to_system = 1;
 
 #endif
 
   DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
-   doc: /* *If non-nil, allow anti-aliasing.
+    doc: /* *If non-nil, allow anti-aliasing.
 The text will be rendered using Core Graphics text rendering which
 may anti-alias the text.  */);
 #if USE_CG_DRAWING
@@ -10967,7 +11551,7 @@ may anti-alias the text.  */);
      creating the terminal frame on Mac OS 9 before loading
      term/mac-win.elc.  */
   DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
-               doc: /* Alist of Emacs character sets vs text encodings and coding systems.
+    doc: /* Alist of Emacs character sets vs text encodings and coding systems.
 Each entry should be of the form:
 
    (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
@@ -10978,6 +11562,23 @@ CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING.  */);
   Vmac_charset_info_alist =
     Fcons (list3 (build_string ("mac-roman"),
                  make_number (smRoman), Qnil), Qnil);
+
+#if USE_ATSUI
+  DEFVAR_LISP ("mac-atsu-font-table", &Vmac_atsu_font_table,
+    doc: /* Hash table of ATSU font IDs vs plist of attributes and values.
+Each font ID is represented as a four-byte string in native byte
+order.  */);
+  Vmac_atsu_font_table =
+    make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
+                    make_float (DEFAULT_REHASH_SIZE),
+                    make_float (DEFAULT_REHASH_THRESHOLD),
+                    Qnil, Qnil, Qnil);
+#endif
+#if USE_MAC_TSM
+  DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
+    doc: /* Overlay used to display Mac TSM active input area.  */);
+  Vmac_ts_active_input_overlay = Qnil;
+#endif
 }
 
 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b