Merged in changes from CVS trunk.
[bpt/emacs.git] / src / macterm.c
index 56c4653..da3dcb1 100644 (file)
@@ -228,6 +228,10 @@ extern int errno;
 
 extern int extra_keyboard_modifiers;
 
+/* The keysyms to use for the various modifiers.  */
+
+static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
+
 static Lisp_Object Qvendor_specific_keysyms;
 
 #if 0
@@ -275,7 +279,7 @@ static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
                                   enum text_cursor_kinds));
 
-static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC));
+static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
 static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
@@ -563,7 +567,7 @@ XCreatePixmap (display, w, width, height, depth)
      Display *display;         /* not used */
      WindowPtr w;
      unsigned int width, height;
-     unsigned int depth;       /* not used */
+     unsigned int depth;
 {
   Pixmap pixmap;
   Rect r;
@@ -639,6 +643,7 @@ XFillRectangle (display, w, gc, x, y, width, height)
 }
 
 
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
 static void
 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
      Display *display;
@@ -662,6 +667,7 @@ mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
 
   SetGWorld (old_port, old_gdh);
 }
+#endif
 
 
 /* Mac replacement for XDrawRectangle: dest is a window.  */
@@ -685,6 +691,7 @@ mac_draw_rectangle (display, w, gc, x, y, width, height)
 }
 
 
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
 /* Mac replacement for XDrawRectangle: dest is a Pixmap.  */
 
 static void
@@ -710,6 +717,7 @@ mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
 
   SetGWorld (old_port, old_gdh);
 }
+#endif
 
 
 static void
@@ -904,24 +912,13 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
      int dest_x, dest_y;
 {
 #if TARGET_API_MAC_CARBON
-  Rect gw_r, src_r, dest_r;
+  Rect src_r;
+  RgnHandle dummy = NewRgn (); /* For avoiding update events.  */
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
-  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
-
-  SetPortWindowPort (w);
-
-  ForeColor (blackColor);
-  BackColor (whiteColor);
-
-  LockPortBits (GetWindowPort (w));
-  {
-    const BitMap *bitmap = GetPortBitMapForCopyBits (GetWindowPort (w));
-    CopyBits (bitmap, bitmap, &src_r, &dest_r, srcCopy, 0);
-  }
-  UnlockPortBits (GetWindowPort (w));
-
-  mac_set_colors (gc);
+  ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
+                   kScrollWindowNoOptions, dummy);
+  DisposeRgn (dummy);
 #else /* not TARGET_API_MAC_CARBON */
   Rect src_r, dest_r;
 
@@ -955,6 +952,7 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
 }
 
 
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
 /* Mac replacement for XCopyArea: dest must be Pixmap.  */
 
 static void
@@ -1033,6 +1031,7 @@ mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
 
   SetGWorld (old_port, old_gdh);
 }
+#endif
 
 
 /* Mac replacement for XChangeGC.  */
@@ -1127,40 +1126,32 @@ x_sync (f)
 }
 
 
-/* Remove calls to XFlush by defining XFlush to an empty replacement.
-   Calls to XFlush should be unnecessary because the X output buffer
-   is flushed automatically as needed by calls to XPending,
-   XNextEvent, or XWindowEvent according to the XFlush man page.
-   XTread_socket calls XPending.  Removing XFlush improves
-   performance.  */
-
-#if TARGET_API_MAC_CARBON
-#define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
-#else
-#define XFlush(DISPLAY)        (void) 0
-#endif
-
 /* Flush display of frame F, or of all frames if F is null.  */
 
-void
+static void
 x_flush (f)
      struct frame *f;
 {
 #if TARGET_API_MAC_CARBON
   BLOCK_INPUT;
-  if (f == NULL)
-    {
-      Lisp_Object rest, frame;
-      FOR_EACH_FRAME (rest, frame)
-       x_flush (XFRAME (frame));
-    }
-  else if (FRAME_MAC_P (f))
-    XFlush (FRAME_MAC_DISPLAY (f));
+  if (f)
+    QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
+  else
+    QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
   UNBLOCK_INPUT;
-#endif /* TARGET_API_MAC_CARBON */
+#endif
 }
 
 
+/* Remove calls to XFlush by defining XFlush to an empty replacement.
+   Calls to XFlush should be unnecessary because the X output buffer
+   is flushed automatically as needed by calls to XPending,
+   XNextEvent, or XWindowEvent according to the XFlush man page.
+   XTread_socket calls XPending.  Removing XFlush improves
+   performance.  */
+
+#define XFlush(DISPLAY)        (void) 0
+
 \f
 /* Return the struct mac_display_info corresponding to DPY.  There's
    only one.  */
@@ -1291,9 +1282,8 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
                                output_cursor.vpos,
                                output_cursor.x, output_cursor.y);
 
-      x_draw_vertical_border (w);
-
-      draw_window_fringes (w);
+      if (draw_window_fringes (w, 1))
+       x_draw_vertical_border (w);
 
       UNBLOCK_INPUT;
     }
@@ -1451,12 +1441,12 @@ x_draw_fringe_bitmap (w, row, p)
       int oldVH = row->visible_height;
       row->visible_height = p->h;
       row->y -= rowY - p->y;
-      x_clip_to_row (w, row, gc);
+      x_clip_to_row (w, row, -1, gc);
       row->y = oldY;
       row->visible_height = oldVH;
     }
   else
-    x_clip_to_row (w, row, gc);
+    x_clip_to_row (w, row, -1, gc);
 
   if (p->bx >= 0 && !p->overlay_p)
     {
@@ -1954,6 +1944,14 @@ x_clear_glyph_string_rect (s, x, y, w, h)
 }
 
 
+/* We prefer not to use XDrawImageString (srcCopy text transfer mode)
+   on Mac OS X because:
+   - Screen is double-buffered.  (In srcCopy mode, a text is drawn
+     into an offscreen graphics world first.  So performance gain
+     cannot be expected.)
+   - It lowers rendering quality.
+   - Some fonts leave garbage on cursor movement.  */
+
 /* Draw the background of glyph_string S.  If S->background_filled_p
    is non-zero don't draw it.  FORCE_P non-zero means draw the
    background even if it wouldn't be drawn normally.  This is used
@@ -1985,10 +1983,12 @@ x_draw_glyph_string_background (s, force_p)
        }
       else
 #endif
+#if 0 /* defined(MAC_OS8)*/
         if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
               || force_p)
+#endif
        {
          x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
                                     s->background_width,
@@ -2041,6 +2041,7 @@ x_draw_glyph_string_foreground (s)
        for (i = 0; i < s->nchars; ++i)
          char1b[i] = s->char2b[i].byte2;
 
+#if 0 /* defined(MAC_OS8) */
       /* Draw text with XDrawString if background has already been
         filled.  Otherwise, use XDrawImageString.  (Note that
         XDrawImageString is usually faster than XDrawString.)  Always
@@ -2048,6 +2049,7 @@ x_draw_glyph_string_foreground (s)
         no chance that characters under a box cursor are invisible.  */
       if (s->for_overlaps_p
          || (s->background_filled_p && s->hl != DRAW_CURSOR))
+#endif
        {
          /* Draw characters with 16-bit or 8-bit functions.  */
          if (s->two_byte_p)
@@ -2057,6 +2059,7 @@ x_draw_glyph_string_foreground (s)
            XDrawString (s->display, s->window, s->gc, x,
                         s->ybase - boff, char1b, s->nchars);
        }
+#if 0 /* defined(MAC_OS8)*/
       else
        {
          if (s->two_byte_p)
@@ -2066,6 +2069,7 @@ x_draw_glyph_string_foreground (s)
            XDrawImageString (s->display, s->window, s->gc, x,
                              s->ybase - boff, char1b, s->nchars);
        }
+#endif
     }
 }
 
@@ -2632,38 +2636,17 @@ x_draw_image_foreground (s)
 
   if (s->img->pixmap)
     {
+      x_set_glyph_string_clipping (s);
+
       if (s->img->mask)
-       {
-         Rect nr;
-         XRectangle clip_rect, image_rect, r;
-
-         get_glyph_string_clip_rect (s, &nr);
-         CONVERT_TO_XRECT (clip_rect, nr);
-         image_rect.x = x;
-         image_rect.y = y;
-         image_rect.width = s->slice.width;
-         image_rect.height = s->slice.height;
-         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
-           mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
-                                    s->window, s->gc,
-                                    s->slice.x + r.x - x, s->slice.y + r.y - y,
-                                    r.width, r.height, r.x, r.y);
-       }
+       mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
+                                s->window, s->gc, s->slice.x, s->slice.y,
+                                s->slice.width, s->slice.height, x, y);
       else
        {
-         Rect nr;
-         XRectangle clip_rect, image_rect, r;
-
-         get_glyph_string_clip_rect (s, &nr);
-         CONVERT_TO_XRECT (clip_rect, nr);
-         image_rect.x = x;
-         image_rect.y = y;
-         image_rect.width = s->slice.width;
-         image_rect.height = s->slice.height;
-         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
-           mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
-                          s->slice.x + r.x - x, s->slice.y + r.y - y,
-                          r.width, r.height, r.x, r.y);
+         mac_copy_area (s->display, s->img->pixmap,
+                        s->window, s->gc, s->slice.x, s->slice.y,
+                        s->slice.width, s->slice.height, x, y);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2742,6 +2725,7 @@ x_draw_image_relief (s)
 }
 
 
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
 /* Draw the foreground of image glyph string S to PIXMAP.  */
 
 static void
@@ -2802,6 +2786,7 @@ x_draw_image_foreground_1 (s, pixmap)
     mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
                                  s->slice.width - 1, s->slice.height - 1);
 }
+#endif
 
 
 /* Draw part of the background of glyph string S.  X, Y, W, and H
@@ -2873,6 +2858,7 @@ x_draw_image_glyph_string (s)
       if (s->slice.y == 0)
        y += box_line_vwidth;
 
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
       if (s->img->mask)
        {
          /* Create a pixmap as large as the glyph string.  Fill it
@@ -2909,12 +2895,14 @@ x_draw_image_glyph_string (s)
            }
        }
       else
+#endif
        x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
 
       s->background_filled_p = 1;
     }
 
   /* Draw the foreground.  */
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
   if (pixmap != 0)
     {
       x_draw_image_foreground_1 (s, pixmap);
@@ -2925,6 +2913,7 @@ x_draw_image_glyph_string (s)
       XFreePixmap (s->display, pixmap);
     }
   else
+#endif
     x_draw_image_foreground (s);
 
   /* If we must draw a relief around the image, do it.  */
@@ -4612,18 +4601,19 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
    mode lines must be clipped to the whole window.  */
 
 static void
-x_clip_to_row (w, row, gc)
+x_clip_to_row (w, row, area, gc)
      struct window *w;
      struct glyph_row *row;
+     int area;
      GC gc;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Rect clip_rect;
-  int window_y, window_width;
+  int window_x, window_y, window_width;
 
-  window_box (w, -1, 0, &window_y, &window_width, 0);
+  window_box (w, area, &window_x, &window_y, &window_width, 0);
 
-  clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
+  clip_rect.left = window_x;
   clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
   clip_rect.top = max (clip_rect.top, window_y);
   clip_rect.right = clip_rect.left + window_width;
@@ -4689,7 +4679,7 @@ x_draw_hollow_cursor (w, row)
   gc = dpyinfo->scratch_cursor_gc;
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
-  x_clip_to_row (w, row, gc);
+  x_clip_to_row (w, row, TEXT_AREA, gc);
   mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
   mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
 }
@@ -4760,7 +4750,7 @@ x_draw_bar_cursor (w, row, width, kind)
       width = min (cursor_glyph->pixel_width, width);
 
       w->phys_cursor_width = width;
-      x_clip_to_row (w, row, gc);
+      x_clip_to_row (w, row, TEXT_AREA, gc);
 
       if (kind == BAR_CURSOR)
        XFillRectangle (dpy, window, gc,
@@ -5050,7 +5040,7 @@ mac_get_window_bounds (f, inner, outer)
   GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
 #else /* not TARGET_API_MAC_CARBON */
   RgnHandle region = NewRgn ();
-    
+
   GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
   *inner = (*region)->rgnBBox;
   GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
@@ -5143,7 +5133,7 @@ x_set_offset (f, xoff, yoff, change_gravity)
   {
     Rect inner, outer, screen_rect, dummy;
     RgnHandle region = NewRgn ();
-    
+
     mac_get_window_bounds (f, &inner, &outer);
     f->x_pixels_diff = inner.left - outer.left;
     f->y_pixels_diff = inner.top - outer.top;
@@ -5318,7 +5308,11 @@ x_raise_frame (f)
      struct frame *f;
 {
   if (f->async_visible)
-    SelectWindow (FRAME_MAC_WINDOW (f));
+    {
+      BLOCK_INPUT;
+      SelectWindow (FRAME_MAC_WINDOW (f));
+      UNBLOCK_INPUT;
+    }
 }
 
 /* Lower frame F.  */
@@ -5327,7 +5321,11 @@ x_lower_frame (f)
      struct frame *f;
 {
   if (f->async_visible)
-    SendBehind (FRAME_MAC_WINDOW (f), nil);
+    {
+      BLOCK_INPUT;
+      SendBehind (FRAME_MAC_WINDOW (f), nil);
+      UNBLOCK_INPUT;
+    }
 }
 
 static void
@@ -5887,7 +5885,14 @@ mac_font_match (char *mf, char *xf)
 static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
 
 static void
-decode_mac_font_name (char *name, int size, short scriptcode)
+decode_mac_font_name (name, size, scriptcode)
+     char *name;
+     int size;
+#if TARGET_API_MAC_CARBON
+     int scriptcode;
+#else
+     short scriptcode;
+#endif
 {
   Lisp_Object coding_system;
   struct coding_system coding;
@@ -5925,7 +5930,15 @@ decode_mac_font_name (char *name, int size, short scriptcode)
 
 
 static char *
-mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
+mac_to_x_fontname (name, size, style, scriptcode, encoding_base)
+     char *name;
+     int size;
+     Style style;
+#if TARGET_API_MAC_CARBON
+     int scriptcode;
+#else
+     short scriptcode;
+#endif
 {
   char foundry[32], family[32], cs[32];
   char xf[256], *result, *p;
@@ -5937,13 +5950,13 @@ mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
 
       switch (scriptcode)
       {
-      case smTradChinese:
+      case smTradChinese:      /* == kTextEncodingMacChineseTrad */
         strcpy(cs, "big5-0");
         break;
-      case smSimpChinese:
+      case smSimpChinese:      /* == kTextEncodingMacChineseSimp */
         strcpy(cs, "gb2312.1980-0");
         break;
-      case smJapanese:
+      case smJapanese:         /* == kTextEncodingMacJapanese */
         strcpy(cs, "jisx0208.1983-sjis");
         break;
       case -smJapanese:
@@ -5955,12 +5968,24 @@ mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
           font is being built.  */
        strcpy(cs, "jisx0201.1976-0");
        break;
-      case smKorean:
+      case smKorean:           /* == kTextEncodingMacKorean */
         strcpy(cs, "ksc5601.1989-0");
         break;
+#if TARGET_API_MAC_CARBON
+      case kTextEncodingMacCyrillic:
+       strcpy(cs, "mac-cyrillic");
+       break;
+      case kTextEncodingMacCentralEurRoman:
+       strcpy(cs, "mac-centraleurroman");
+       break;
+      case kTextEncodingMacSymbol:
+      case kTextEncodingMacDingbats:
+       strcpy(cs, "adobe-fontspecific");
+       break;
+#endif
       default:
-        strcpy(cs, "mac-roman");
-        break;
+       strcpy(cs, "mac-roman");
+       break;
       }
     }
 
@@ -6007,7 +6032,10 @@ x_font_name_to_mac_font_name (char *xf, char *mf)
     coding_system = Qsjis;
   else if (strcmp (cs, "ksc5601.1989-0") == 0)
     coding_system = Qeuc_kr;
-  else if (strcmp (cs, "mac-roman") == 0)
+  else if (strcmp (cs, "mac-roman") == 0
+          || strcmp (cs, "mac-cyrillic") == 0
+          || strcmp (cs, "mac-centraleurroman") == 0
+          || strcmp (cs, "adobe-fontspecific") == 0)
     strcpy (mf, family);
   else
     sprintf (mf, "%s-%s-%s", foundry, family, cs);
@@ -6079,7 +6107,8 @@ init_font_name_table ()
          FMFont font;
          FMFontStyle style;
          FMFontSize size;
-         SInt16 sc;
+         TextEncoding encoding;
+         TextEncodingBase sc;
 
          if (FMGetFontFamilyName (ff, name) != noErr)
            break;
@@ -6087,9 +6116,11 @@ init_font_name_table ()
          if (*name == '.')
            continue;
 
-         sc = FontToScript (ff);
+         if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
+           break;
+         sc = GetTextEncodingBase (encoding);
          decode_mac_font_name (name, sizeof (name), sc);
-
+                                      
          /* Point the instance iterator at the current font family.  */
          if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
            break;
@@ -6244,6 +6275,28 @@ static int xlfd_scalable_fields[] =
     -1
   };
 
+static Lisp_Object
+mac_c_string_match (regexp, string, nonspecial, exact)
+     Lisp_Object regexp;
+     const char *string, *nonspecial;
+     int exact;
+{
+  if (exact)
+    {
+      if (strcmp (string, nonspecial) == 0)
+       return build_string (string);
+    }
+  else if (strstr (string, nonspecial))
+    {
+      Lisp_Object str = build_string (string);
+
+      if (fast_string_match (regexp, str) >= 0)
+       return str;
+    }
+
+  return Qnil;
+}
+
 static Lisp_Object
 mac_do_list_fonts (pattern, maxnames)
      char *pattern;
@@ -6255,6 +6308,8 @@ mac_do_list_fonts (pattern, maxnames)
   char scaled[256];
   char *ptr;
   int scl_val[XLFD_SCL_LAST], *field, *val;
+  char *longest_start, *cur_start, *nonspecial;
+  int longest_len, cur_len, exact;
 
   for (i = 0; i < XLFD_SCL_LAST; i++)
     scl_val[i] = -1;
@@ -6312,34 +6367,66 @@ mac_do_list_fonts (pattern, maxnames)
   ptr = regex;
   *ptr++ = '^';
 
-  /* Turn pattern into a regexp and do a regexp match.  */
+  longest_start = cur_start = ptr;
+  longest_len = cur_len = 0;
+  exact = 1;
+
+  /* Turn pattern into a regexp and do a regexp match.  Also find the
+     longest substring containing no special characters.  */
   for (; *pattern; pattern++)
     {
-      if (*pattern == '?')
-        *ptr++ = '.';
-      else if (*pattern == '*')
-        {
-          *ptr++ = '.';
-          *ptr++ = '*';
-        }
+      if (*pattern == '?' || *pattern == '*')
+       {
+         if (cur_len > longest_len)
+           {
+             longest_start = cur_start;
+             longest_len = cur_len;
+           }
+         cur_len = 0;
+         exact = 0;
+
+         if (*pattern == '?')
+           *ptr++ = '.';
+         else /* if (*pattern == '*') */
+           {
+             *ptr++ = '.';
+             *ptr++ = '*';
+           }
+       }
       else
-        *ptr++ = tolower (*pattern);
+       {
+         if (cur_len == 0)
+           cur_start = ptr;
+         cur_len++;
+
+         *ptr++ = tolower (*pattern);
+       }
     }
+
+  if (cur_len > longest_len)
+    {
+      longest_start = cur_start;
+      longest_len = cur_len;
+    }
+
   *ptr = '$';
   *(ptr + 1) = '\0';
 
+  nonspecial = xmalloc (longest_len + 1);
+  strncpy (nonspecial, longest_start, longest_len);
+  nonspecial[longest_len] = '\0';
+
   pattern_regex = build_string (regex);
 
   for (i = 0; i < font_name_count; i++)
     {
-      fontname = build_string (font_name_table[i]);
-      if (fast_string_match (pattern_regex, fontname) >= 0)
+      fontname = mac_c_string_match (pattern_regex, font_name_table[i],
+                                    nonspecial, exact);
+      if (!NILP (fontname))
        {
          font_list = Fcons (fontname, font_list);
-
-          n_fonts++;
-          if (maxnames > 0 && n_fonts >= maxnames)
-            break;
+         if (exact || maxnames > 0 && ++n_fonts >= maxnames)
+           break;
        }
       else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
               && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
@@ -6353,17 +6440,19 @@ mac_do_list_fonts (pattern, maxnames)
                   scl_val[XLFD_SCL_POINT_SIZE],
                   scl_val[XLFD_SCL_AVGWIDTH],
                   ptr + sizeof ("-0-0-75-75-m-0-") - 1);
-         fontname = build_string (scaled);
-         if (fast_string_match (pattern_regex, fontname) >= 0)
+         fontname = mac_c_string_match (pattern_regex, scaled,
+                                        nonspecial, exact);
+         if (!NILP (fontname))
            {
              font_list = Fcons (fontname, font_list);
-
-             n_fonts++;
-             if (maxnames > 0 && n_fonts >= maxnames)
+             if (exact || maxnames > 0 && ++n_fonts >= maxnames)
                break;
            }
        }
     }
+
+  xfree (nonspecial);
+
   return font_list;
 }
 
@@ -6981,6 +7070,9 @@ Lisp_Object Qreverse;
 /* True if using command key as meta key.  */
 Lisp_Object Vmac_command_key_is_meta;
 
+/* Modifier associated with the option key, or nil for normal behavior. */
+Lisp_Object Vmac_option_modifier;
+
 /* True if the ctrl and meta keys should be reversed.  */
 Lisp_Object Vmac_reverse_ctrl_meta;
 
@@ -7062,6 +7154,12 @@ mac_to_emacs_modifiers (EventModifiers mods)
     result |= meta_modifier;
   if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
     result |= alt_modifier;
+  if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
+      Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
+      if (!NILP(val))
+          result |= XUINT(val);
+  }
+
   return result;
 }
 
@@ -8114,7 +8212,7 @@ XTread_socket (sd, expected, hold_quit)
        switch (GetEventClass (eventRef))
          {
          case kEventClassWindow:
-           if (GetEventKind (eventRef) == kEventWindowBoundsChanged) 
+           if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
              {
                WindowPtr window_ptr;
                GetEventParameter(eventRef, kEventParamDirectObject,
@@ -8431,7 +8529,7 @@ XTread_socket (sd, expected, hold_quit)
 
            if (!is_emacs_window (window_ptr))
              break;
-           
+
            f = mac_window_to_frame (window_ptr);
 
            if ((er.modifiers & activeFlag) != 0)
@@ -8542,7 +8640,18 @@ XTread_socket (sd, expected, hold_quit)
                    unsigned long some_state = 0;
                    inev.code = KeyTranslate (kchr_ptr, new_keycode,
                                              &some_state) & 0xff;
-                 }
+                 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
+            {
+                /* When using the option key as an emacs modifier, convert
+                   the pressed key code back to one without the Mac option
+                   modifier applied. */
+                int new_modifiers = er.modifiers & ~optionKey;
+                int new_keycode = keycode | new_modifiers;
+                Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+                unsigned long some_state = 0;
+                inev.code = KeyTranslate (kchr_ptr, new_keycode,
+                                          &some_state) & 0xff;
+            }
                else
                  inev.code = er.message & charCodeMask;
                inev.kind = ASCII_KEYSTROKE_EVENT;
@@ -8587,17 +8696,30 @@ XTread_socket (sd, expected, hold_quit)
                {
                  unsigned char ch = inev.code;
                  ByteCount actual_input_length, actual_output_length;
-                 unsigned char outch;
-
-                 convert_status = TECConvertText (converter, &ch, 1,
-                                                  &actual_input_length,
-                                                  &outch, 1,
-                                                  &actual_output_length);
-                 if (convert_status == noErr
-                     && actual_input_length == 1
-                     && actual_output_length == 1)
-                   inev.code = outch;
-               }
+                 unsigned char outbuf[32];
+                 
+                  convert_status = TECConvertText (converter, &ch, 1,
+                                                   &actual_input_length,
+                                                  outbuf, 1,
+                                                   &actual_output_length);
+                  if (convert_status == noErr
+                      && actual_input_length == 1
+                      && actual_output_length == 1)
+                   inev.code = *outbuf;
+                 
+                 /* Reset internal states of the converter object.
+                   If it fails, create another one. */
+                 convert_status = TECFlushText (converter, outbuf,
+                                                sizeof (outbuf),
+                                               &actual_output_length);
+                 if (convert_status != noErr)
+                   {
+                     TECDisposeConverter (converter);
+                     TECCreateConverter (&converter,
+                                         kTextEncodingMacRoman,
+                                         mac_keyboard_text_encoding);
+                   }
+                }
            }
 
 #if USE_CARBON_EVENTS
@@ -8758,6 +8880,7 @@ make_mac_frame (FRAME_PTR fp)
 
   mwp = fp->output_data.mac;
 
+  BLOCK_INPUT;
   if (making_terminal_window)
     {
       if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
@@ -8785,9 +8908,8 @@ make_mac_frame (FRAME_PTR fp)
     /* so that update events can find this mac_output struct */
   mwp->mFP = fp;  /* point back to emacs frame */
 
-  SetPortWindowPort (mwp->mWP);
-
   SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
+  UNBLOCK_INPUT;
 }
 
 
@@ -9116,7 +9238,7 @@ static struct redisplay_interface x_redisplay_interface =
   x_update_window_end,
   x_cursor_to,
   x_flush,
-  x_flush,
+  0, /* flush_display_optional */
   x_clear_window_mouse_face,
   x_get_glyph_overhangs,
   x_fix_overlapping_area,
@@ -9211,6 +9333,7 @@ mac_initialize ()
   signal (SIGPIPE, x_connection_signal);
 #endif
 
+  BLOCK_INPUT;
   mac_initialize_display_info ();
 
 #if TARGET_API_MAC_CARBON
@@ -9229,6 +9352,7 @@ mac_initialize ()
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
 #endif
+  UNBLOCK_INPUT;
 }
 
 
@@ -9240,6 +9364,14 @@ syms_of_macterm ()
   x_error_message_string = Qnil;
 #endif
 
+  Qmodifier_value = intern ("modifier-value");
+  Qalt = intern ("alt");
+  Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
+  Qhyper = intern ("hyper");
+  Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
+  Qsuper = intern ("super");
+  Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
+
   Fprovide (intern ("mac-carbon"), Qnil);
 
   staticpro (&Qreverse);
@@ -9296,6 +9428,12 @@ to 4.1, set this to nil.  */);
 Otherwise the option key is used.  */);
   Vmac_command_key_is_meta = Qt;
 
+  DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
+    doc: /* Modifier to use for the Mac alt/option key.  The value can
+be alt, hyper, or super for the respective modifier.  If the value is
+nil then the key will act as the normal Mac option modifier.  */);
+  Vmac_option_modifier = Qnil;
+
   DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
     doc: /* Non-nil means that the control and meta keys are reversed.  This is
            useful for non-standard keyboard layouts.  */);