(font_idx_temp): Extern it.
[bpt/emacs.git] / src / xterm.c
index 4716185..67335d4 100644 (file)
@@ -268,7 +268,7 @@ static void do_line_dance ();
 static int XTcursor_to ();
 static int XTclear_end_of_line ();
 static int x_io_error_quitter ();
-void x_catch_errors ();
+int x_catch_errors ();
 void x_uncatch_errors ();
 \f
 #if 0
@@ -550,7 +550,7 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
   Window window = FRAME_X_WINDOW (f);
   int orig_left = left;
   int gidx = 0;
-  int pixel_width;
+  int i;
 
   while (n > 0)
     {
@@ -607,7 +607,7 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
              || (cmpcharp == NULL && FAST_GLYPH_FACE (g) != cf))
            break;
 
-         if (c2)
+         if (c2 > 0)
            cp->byte1 = c1, cp->byte2 = c2;
          else
            cp->byte1 = 0, cp->byte2 = c1;
@@ -619,11 +619,6 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
 
       /* LEN gets the length of the run.  */
       len = cp - buf;
-      /* PIXEL_WIDTH get the pixcel width of the run.  */
-      pixel_width
-       = (FONT_WIDTH (f->output_data.x->font)
-          * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset)));
-
       /* Now output this run of chars, with the font and pixel values
         determined by the face code CF.  */
       {
@@ -631,10 +626,19 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
        XFontStruct *font = NULL;
        GC gc;
        int stippled = 0;
+       int line_height = f->output_data.x->line_height;
+       /* Pixel width of each glyph in this run.  */
+       int glyph_width
+         = (FONT_WIDTH (f->output_data.x->font)
+            * (cmpcharp ? cmpcharp->width : CHARSET_WIDTH (charset)));
+       /* Overall pixel width of this run.  */
+       int run_width
+         = (FONT_WIDTH (f->output_data.x->font)
+            * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset)));
        /* A flag to tell if we have already filled background.  We
           fill background in advance in the following cases:
           1) A face has stipple.
-          2) A height of font is different from that of the current line.
+          2) A height of font is shorter than LINE_HEIGHT.
           3) Drawing a composite character.
           4) Font has non-zero _MULE_BASELINE_OFFSET property.
           After filling background, we draw glyphs by XDrawString16.  */
@@ -644,6 +648,8 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
        /* The property value of `_MULE_RELATIVE_COMPOSE' and
            `_MULE_DEFAULT_ASCENT'.  */
        int relative_compose = 0, default_ascent = 0;
+       /* 1 if we find no font or a font of inappropriate size.  */
+       int require_clipping;
 
        /* HL = 3 means use a mouse face previously chosen.  */
        if (hl == 3)
@@ -676,6 +682,8 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
              stippled = 1;
          }
 
+#define FACE_DEFAULT (~0)
+
        /* Setting appropriate font and gc for this charset.  */
        if (charset != CHARSET_ASCII)
          {
@@ -691,12 +699,17 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
            font = (XFontStruct *) (fontp->font);
            gc = FACE_NON_ASCII_GC (face);
            XSetFont (FRAME_X_DISPLAY (f), gc, font->fid);
-           if (font->max_byte1 != 0)
-             baseline = (f->output_data.x->line_height
-                         + font->ascent - font->descent) / 2;
-           else
-             baseline = (f->output_data.x->font_baseline
-                         - fontp->baseline_offset);
+           baseline
+             = (font->max_byte1 != 0
+                ? (line_height + font->ascent - font->descent) / 2
+                : f->output_data.x->font_baseline - fontp->baseline_offset);
+           if (FONT_HEIGHT (font) <= line_height
+               && (font->ascent > baseline
+                   || font->descent > line_height - baseline))
+             /* Adjust baseline for this font to show the whole
+                 glyphs in a line.  */
+             baseline = line_height - font->descent;
+             
            if (cmpcharp && cmpcharp->cmp_rule == NULL)
              {
                relative_compose = fontp->relative_compose;
@@ -741,26 +754,38 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
          }
        else
          {
-           font = FACE_FONT (face);
-           baseline = FONT_BASE (font);
          font_not_found:
-           gc   = FACE_GC   (face);
+           if (charset == CHARSET_ASCII || charset == charset_latin_iso8859_1)
+             {
+               font = FACE_FONT (face);
+               if (font == (XFontStruct *) FACE_DEFAULT)
+                 font = f->output_data.x->font;
+               baseline = FONT_BASE (font);
+               if (charset == charset_latin_iso8859_1)
+                 {
+                   if (font->max_char_or_byte2 < 0x80)
+                     /* This font can't display Latin1 characters.  */
+                     font = NULL;
+                   else
+                     {
+                       for (cp = buf; cp < buf + len; cp++)
+                         cp->byte2 |= 0x80;
+                     }
+                 }
+             }
+           gc = FACE_GC (face);
          }
 
-#define FACE_DEFAULT (~0)
-
        /* Now override that if the cursor's on this character.  */
        if (hl == 2)
          {
            /* The cursor overrides stippling.  */
            stippled = 0;
 
-           if (!cmpcharp
-               && (!font
-                   || font == (XFontStruct *) FACE_DEFAULT
-                   || font == f->output_data.x->font)
+           if (font == f->output_data.x->font
                && face->background == f->output_data.x->background_pixel
-               && face->foreground == f->output_data.x->foreground_pixel)
+               && face->foreground == f->output_data.x->foreground_pixel
+               && !cmpcharp)
              {
                gc = f->output_data.x->cursor_gc;
              }
@@ -810,32 +835,49 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
              }
          }
 
-       if (font == (XFontStruct *) FACE_DEFAULT)
-         font = f->output_data.x->font;
+       if (font)
+         require_clipping = (!NILP (Vclip_large_size_font)
+                             && (font->ascent > baseline
+                                 || font->descent > line_height - baseline
+                                 || (!cmpcharp
+                                     && FONT_WIDTH (font) > glyph_width)));
 
        if (font && (just_foreground || (cmpcharp && gidx > 0)))
          background_filled = 1;
-       else if (!font
-                || stippled
-                || f->output_data.x->line_height != FONT_HEIGHT (font)
-                || cmpcharp
-                || baseline != f->output_data.x->font_baseline)
+       else if (stippled)
          {
-           if (!stippled)
-             /* This is to fill a rectangle with background color.  */
-             XSetStipple (FRAME_X_DISPLAY (f), gc,
-                          FRAME_X_DISPLAY_INFO (f)->null_pixel);
            /* Turn stipple on.  */
            XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled);
 
            /* Draw stipple or background color on background.  */
            XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
-                           left, top, pixel_width,
-                           f->output_data.x->line_height);
+                           left, top, run_width, line_height);
 
            /* Turn stipple off.  */
            XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid);
 
+           background_filled = 1;
+         }
+       else if (!font
+                || FONT_HEIGHT (font) < line_height
+                || FONT_WIDTH (font) < glyph_width
+                || cmpcharp)
+         {
+           /* Fill a area for the current run in background pixle of GC.  */
+           XGCValues xgcv;
+           unsigned long mask = GCForeground | GCBackground;
+           unsigned long fore, back;
+
+           /* The current code at first set foreground to background,
+             fill the area, then recover the original foreground.
+             Aren't there any smarter ways?  */
+
+           XGetGCValues (FRAME_X_DISPLAY (f), gc, mask, &xgcv);
+           XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
+           XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
+                           left, top, run_width, line_height);
+           XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
+
            background_filled = 1;
            if (cmpcharp)
              /* To assure not to fill background while drawing
@@ -847,10 +889,48 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
 
        if (font)
          {
-           if (cmpcharp)
+           if (require_clipping)
+             {
+               Region region;  /* Region used for setting clip mask to GC.  */
+               XPoint x[4];    /* Data used for creating REGION.  */
+
+               x[0].x = x[3].x = left, x[1].x = x[2].x = left + glyph_width;
+               x[0].y = x[1].y = top,  x[2].y = x[3].y = top + line_height;
+               region = XPolygonRegion (x, 4, EvenOddRule);
+               XSetRegion (FRAME_X_DISPLAY (f), gc, region);
+               XDestroyRegion (region);
+             }
+
+           if (!cmpcharp)
+             {
+               if (require_clipping || FONT_WIDTH (font) != glyph_width)
+                 for (i = 0; i < len; i++)
+                   {
+                     if (require_clipping && i > 0) 
+                       XSetClipOrigin (FRAME_X_DISPLAY (f), gc,
+                                       glyph_width * i, 0);
+                     if (background_filled)
+                       XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
+                                      left + glyph_width * i,
+                                      top + baseline, buf + i, 1);
+                     else
+                       XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc,
+                                           left + glyph_width * i,
+                                           top + baseline, buf + i, 1);
+                   }
+               else
+                 {
+                   if (background_filled)
+                     XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
+                                    left, top + baseline, buf, len);
+                   else
+                     XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc,
+                                         left, top + baseline, buf, len);
+                 }
+             }
+           else
              {
                XCharStruct *pcm; /* Pointer to per char metric info.  */
-               int i;
 
                if ((cmpcharp->cmp_rule || relative_compose)
                    && gidx == 0)
@@ -939,22 +1019,8 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
                                   buf + i, 1);
                  }
              }
-           else if (background_filled)
-             XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
-                            left, top + baseline, buf, len);
-           else
-             XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc,
-                                 left, top + baseline, buf, len);
-
-           /* Clear the rest of the line's height.  */
-           if (f->output_data.x->line_height > FONT_HEIGHT (font))
-             XClearArea (FRAME_X_DISPLAY (f), window, left,
-                         top + FONT_HEIGHT (font),
-                         FONT_WIDTH (font) * len,
-                         /* This is how many pixels of height
-                            we have to clear.  */
-                         f->output_data.x->line_height - FONT_HEIGHT (font),
-                         False);
+           if (require_clipping)
+             XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
 
 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
         which often is not up to date yet.  */
@@ -969,31 +1035,33 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
              }
 #endif
          }
-       else
+       if (!font)
          {
-           /* There's no appropriate font for this glyph.  Just show
-               rectangles.  */
+           /* Show rectangles to indicate that we found no font.  */
+           int limit = cmpcharp ? 1 : len;
 
-           if (cmpcharp)
-             XDrawRectangle
-               (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                left, top + 1,
-                pixel_width - 2, f->output_data.x->line_height - 3);
-           else
+           for (i = 0; i < limit; i++)
+             XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                             left + glyph_width * i, top,
+                             glyph_width - 1, line_height - 1);
+         }
+       else if (require_clipping && !NILP (Vhighlight_wrong_size_font))
+         {
+           /* Show ??? to indicate that we found a font of
+               inappropriate size.  */
+           int limit = cmpcharp ? 1 : len;
+
+           for (i = 0; i < limit; i++)
              {
-               int left_offset;
-               int left_skip_step = (FONT_WIDTH (f->output_data.x->font)
-                                     * CHARSET_WIDTH (charset));
-
-               for (left_offset = 0; left_offset < pixel_width;
-                    left_offset += left_skip_step)
-                 XDrawRectangle
-                   (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                    left + left_offset, top + 1,
-                    left_skip_step - 2, f->output_data.x->line_height - 3);
+               XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                          left + glyph_width * i, top + line_height - 1,
+                          left + glyph_width * i + 1, top + line_height - 1);
+               XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                          left + glyph_width * i, top + line_height - 3,
+                          left + glyph_width * i, top + line_height - 1);
              }
          }
-       
+
        /* We should probably check for XA_UNDERLINE_POSITION and
           XA_UNDERLINE_THICKNESS properties on the font, but let's
           just get the thing working, and come back to that.  */
@@ -1004,17 +1072,17 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
             on the default font of this frame.  */
          int underline_position = f->output_data.x->font_baseline + 1;
 
-         if (underline_position >= f->output_data.x->line_height)
-           underline_position = f->output_data.x->line_height - 1;
+         if (underline_position >= line_height)
+           underline_position = line_height - 1;
 
          if (face->underline)
            XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                            FACE_GC (face),
-                           left, top + underline_position, pixel_width, 1);
+                           left, top + underline_position, run_width, 1);
        }
 
        if (!cmpcharp)
-         left += pixel_width;
+         left += run_width;
       }
     }
 
@@ -2166,7 +2234,7 @@ construct_menu_click (result, event, f)
   /* Make the event type no_event; we'll change that when we decide
      otherwise.  */
   result->kind = mouse_click;
-  XSETINT (result->code, event->button - Button1);
+  result->code = event->button - Button1;
   result->timestamp = event->time;
   result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
                                               event->state)
@@ -2266,8 +2334,9 @@ note_mouse_highlight (f, x, y)
   if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
       && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
       && EQ (w->window_end_valid, w->buffer)
-      && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
-      && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
+      && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
+      && (XFASTINT (w->last_overlay_modified)
+         == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
     {
       int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
       int i, pos;
@@ -2319,7 +2388,7 @@ note_mouse_highlight (f, x, y)
 
          /* Put all the overlays we want in a vector in overlay_vec.
             Store the length in len.  */
-         noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
+         noverlays = overlays_at (pos, 1, &overlay_vec, &len,
                                   NULL, NULL);
          noverlays = sort_overlays (overlay_vec, noverlays, w);
 
@@ -2426,7 +2495,7 @@ fast_find_position (window, pos, columnp, rowp)
   int i;
   int row = 0;
   int left = WINDOW_LEFT_MARGIN (w);
-  int top = w->top;
+  int top = XFASTINT (w->top);
   int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
   int width = window_internal_width (w);
   int *charstarts;
@@ -2665,6 +2734,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        Window win, child;
        int win_x, win_y;
        int parent_x, parent_y;
+       int count;
 
        win = root;
 
@@ -2672,7 +2742,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
           structure is changing at the same time this function
           is running.  So at least we must not crash from them.  */
 
-       x_catch_errors (FRAME_X_DISPLAY (*fp));
+       count = x_catch_errors (FRAME_X_DISPLAY (*fp));
 
        if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
            && FRAME_LIVE_P (last_mouse_frame))
@@ -2732,7 +2802,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
          f1 = 0;
 
-       x_uncatch_errors (FRAME_X_DISPLAY (*fp));
+       x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
 
        /* If not, is it one of our scroll bars?  */
        if (! f1)
@@ -3470,6 +3540,7 @@ process_expose_from_menu (event)
        {
          f->async_visible = 1;
          f->async_iconified = 0;
+         f->output_data.x->has_been_visible = 1;
          SET_FRAME_GARBAGED (f);
        }
       else
@@ -3904,6 +3975,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      f->async_visible = 1;
                      f->async_iconified = 0;
+                     f->output_data.x->has_been_visible = 1;
                      SET_FRAME_GARBAGED (f);
                    }
                  else
@@ -3960,15 +4032,19 @@ XTread_socket (sd, bufp, numchars, expected)
                  /* We can't distinguish, from the event, whether the window
                     has become iconified or invisible.  So assume, if it
                     was previously visible, than now it is iconified.
-                    We depend on x_make_frame_invisible to mark it invisible.  */
+                    But x_make_frame_invisible clears both
+                    the visible flag and the iconified flag;
+                    and that way, we know the window is not iconified now.  */
                  if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
-                   f->async_iconified = 1;
+                   {
+                     f->async_iconified = 1;
 
-                 bufp->kind = iconify_event;
-                 XSETFRAME (bufp->frame_or_window, f);
-                 bufp++;
-                 count++;
-                 numchars--;
+                     bufp->kind = iconify_event;
+                     XSETFRAME (bufp->frame_or_window, f);
+                     bufp++;
+                     count++;
+                     numchars--;
+                   }
                }
              goto OTHER;
 
@@ -3980,6 +4056,7 @@ XTread_socket (sd, bufp, numchars, expected)
                {
                  f->async_visible = 1;
                  f->async_iconified = 0;
+                 f->output_data.x->has_been_visible = 1;
 
                  /* wait_reading_process_input will notice this and update
                     the frame's display structures.  */
@@ -3993,7 +4070,7 @@ XTread_socket (sd, bufp, numchars, expected)
                      count++;
                      numchars--;
                    }
-                 else if (! NILP(Vframe_list)
+                 else if (! NILP (Vframe_list)
                           && ! NILP (XCONS (Vframe_list)->cdr))
                    /* Force a redisplay sooner or later
                       to update the frame titles
@@ -4077,6 +4154,9 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
                           || keysym == XK_Delete
+#ifdef XK_ISO_Left_Tab
+                          || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
+#endif
                           || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
                           || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
 #ifdef HPUX
@@ -4288,12 +4368,8 @@ XTread_socket (sd, bufp, numchars, expected)
              goto OTHER;
 
            case ConfigureNotify:
-             f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
-             if (f
-#ifdef USE_X_TOOLKIT
-                 && (event.xconfigure.window == XtWindow (f->output_data.x->widget))
-#endif
-                 )
+             f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
+             if (f)
                {
 #ifndef USE_X_TOOLKIT
                  /* In the toolkit version, change_frame_size
@@ -4317,63 +4393,21 @@ XTread_socket (sd, bufp, numchars, expected)
                    }
 #endif
 
-                 /* Formerly, in the USE_X_TOOLKIT version,
-                    we did not test send_event here.  */
-                 if (1
-#ifndef USE_X_TOOLKIT
-                     && ! event.xconfigure.send_event
-#endif
-                     )
-                   {
-                     Window win, child;
-                     int win_x, win_y;
-
-                     /* Find the position of the outside upper-left corner of
-                        the window, in the root coordinate system.  Don't
-                        refer to the parent window here; we may be processing
-                        this event after the window manager has changed our
-                        parent, but before we have reached the ReparentNotify.  */
-                     XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
-                                            /* From-window, to-window.  */
-                                            event.xconfigure.window,
-                                            FRAME_X_DISPLAY_INFO (f)->root_window,
-
-                                            /* From-position, to-position.  */
-                                            -event.xconfigure.border_width,
-                                            -event.xconfigure.border_width,
-                                            &win_x, &win_y,
-
-                                            /* Child of win.  */
-                                            &child);
-                     event.xconfigure.x = win_x;
-                     event.xconfigure.y = win_y;
-                   }
-
                  f->output_data.x->pixel_width = event.xconfigure.width;
                  f->output_data.x->pixel_height = event.xconfigure.height;
-                 f->output_data.x->left_pos = event.xconfigure.x;
-                 f->output_data.x->top_pos = event.xconfigure.y;
 
                  /* What we have now is the position of Emacs's own window.
                     Convert that to the position of the window manager window.  */
-                 {
-                   int x, y;
-                   x_real_positions (f, &x, &y);
-                   f->output_data.x->left_pos = x;
-                   f->output_data.x->top_pos = y;
-                   /* Formerly we did not do this in the USE_X_TOOLKIT
-                      version.  Let's try making them the same.  */
-/* #ifndef USE_X_TOOLKIT */
-                   if (y != event.xconfigure.y)
-                     {
-                       /* Since the WM decorations come below top_pos now,
-                          we must put them below top_pos in the future.  */
-                       f->output_data.x->win_gravity = NorthWestGravity;
-                       x_wm_set_size_hint (f, (long) 0, 0);
-                     }
-/* #endif */
-                 }
+                 x_real_positions (f, &f->output_data.x->left_pos,
+                                   &f->output_data.x->top_pos);
+
+                 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
+                   {
+                     /* Since the WM decorations come below top_pos now,
+                        we must put them below top_pos in the future.  */
+                     f->output_data.x->win_gravity = NorthWestGravity;
+                     x_wm_set_size_hint (f, (long) 0, 0);
+                   }
                }
              goto OTHER;
 
@@ -4895,6 +4929,147 @@ x_text_icon (f, icon_name)
   return 0;
 }
 \f
+#define X_ERROR_MESSAGE_SIZE 200
+
+/* If non-nil, this should be a string.
+   It means catch X errors  and store the error message in this string.  */
+
+static Lisp_Object x_error_message_string;
+
+/* An X error handler which stores the error message in
+   x_error_message_string.  This is called from x_error_handler if
+   x_catch_errors is in effect.  */
+
+static int
+x_error_catcher (display, error)
+     Display *display;
+     XErrorEvent *error;
+{
+  XGetErrorText (display, error->error_code,
+                XSTRING (x_error_message_string)->data,
+                X_ERROR_MESSAGE_SIZE);
+}
+
+/* Begin trapping X errors for display DPY.  Actually we trap X errors
+   for all displays, but DPY should be the display you are actually
+   operating on.
+
+   After calling this function, X protocol errors no longer cause
+   Emacs to exit; instead, they are recorded in the string
+   stored in x_error_message_string.
+
+   Calling x_check_errors signals an Emacs error if an X error has
+   occurred since the last call to x_catch_errors or x_check_errors.
+
+   Calling x_uncatch_errors resumes the normal error handling.  */
+
+void x_check_errors ();
+static Lisp_Object x_catch_errors_unwind ();
+
+int
+x_catch_errors (dpy)
+     Display *dpy;
+{
+  int count = specpdl_ptr - specpdl;
+
+  /* Make sure any errors from previous requests have been dealt with.  */
+  XSync (dpy, False);
+
+  record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
+
+  x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
+  XSTRING (x_error_message_string)->data[0] = 0;
+
+  return count;
+}
+
+/* Unbind the binding that we made to check for X errors.  */
+
+static Lisp_Object
+x_catch_errors_unwind (old_val)
+     Lisp_Object old_val;
+{
+  x_error_message_string = old_val;
+  return Qnil;
+}
+
+/* If any X protocol errors have arrived since the last call to
+   x_catch_errors or x_check_errors, signal an Emacs error using
+   sprintf (a buffer, FORMAT, the x error message text) as the text.  */
+
+void
+x_check_errors (dpy, format)
+     Display *dpy;
+     char *format;
+{
+  /* Make sure to catch any errors incurred so far.  */
+  XSync (dpy, False);
+
+  if (XSTRING (x_error_message_string)->data[0])
+    error (format, XSTRING (x_error_message_string)->data);
+}
+
+/* Nonzero if we had any X protocol errors
+   since we did x_catch_errors on DPY.  */
+
+int
+x_had_errors_p (dpy)
+     Display *dpy;
+{
+  /* Make sure to catch any errors incurred so far.  */
+  XSync (dpy, False);
+
+  return XSTRING (x_error_message_string)->data[0] != 0;
+}
+
+/* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
+
+int
+x_clear_errors (dpy)
+     Display *dpy;
+{
+  XSTRING (x_error_message_string)->data[0] = 0;
+}
+
+/* Stop catching X protocol errors and let them make Emacs die.
+   DPY should be the display that was passed to x_catch_errors.
+   COUNT should be the value that was returned by
+   the corresponding call to x_catch_errors.  */
+
+void
+x_uncatch_errors (dpy, count)
+     Display *dpy;
+     int count;
+{
+  unbind_to (count, Qnil);
+}
+
+#if 0
+static unsigned int x_wire_count;
+x_trace_wire ()
+{
+  fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
+}
+#endif /* ! 0 */
+
+\f
+/* Handle SIGPIPE, which can happen when the connection to a server
+   simply goes away.  SIGPIPE is handled by x_connection_signal.
+   Don't need to do anything, because the write which caused the 
+   SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
+   which will do the appropriate cleanup for us. */
+   
+static SIGTYPE
+x_connection_signal (signalnum)        /* If we don't have an argument, */
+     int signalnum;            /* some compilers complain in signal calls. */
+{
+#ifdef USG
+  /* USG systems forget handlers when they are used;
+     must reestablish each time */
+  signal (signalnum, x_connection_signal);
+#endif /* USG */
+}
+\f
 /* Handling X errors.  */
 
 /* Handle the loss of connection to display DISPLAY.  */
@@ -4909,9 +5084,9 @@ x_connection_closed (display, error_message)
 
   /* Indicate that this display is dead.  */
 
-  #ifdef USE_X_TOOLKIT
+#ifdef USE_X_TOOLKIT
   XtCloseDisplay (display);
-  #endif
+#endif
 
   dpyinfo->display = 0;
 
@@ -4983,138 +5158,35 @@ x_error_quitter (display, error)
   x_connection_closed (display, buf1);
 }
 
-/* This is the handler for X IO errors, always.
-   It kills all frames on the display that we lost touch with.
-   If that was the only one, it prints an error message and kills Emacs.  */
+/* This is the first-level handler for X protocol errors.
+   It calls x_error_quitter or x_error_catcher.  */
 
 static int
-x_io_error_quitter (display)
+x_error_handler (display, error)
      Display *display;
+     XErrorEvent *error;
 {
-  char buf[256];
+  char buf[256], buf1[356];
 
-  sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
-  x_connection_closed (display, buf);
-}
-\f
-/* Handle SIGPIPE, which can happen when the connection to a server
-   simply goes away.  SIGPIPE is handled by x_connection_signal.
-   Don't need to do anything, because the write which caused the 
-   SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
-   which will do the appropriate cleanup for us. */
-   
-static SIGTYPE
-x_connection_signal (signalnum)        /* If we don't have an argument, */
-     int signalnum;            /* some compilers complain in signal calls. */
-{
-#ifdef USG
-  /* USG systems forget handlers when they are used;
-     must reestablish each time */
-  signal (signalnum, x_connection_signal);
-#endif /* USG */
+  if (! NILP (x_error_message_string))
+    x_error_catcher (display, error);
+  else
+    x_error_quitter (display, error);
 }
-\f
-/* A buffer for storing X error messages.  */
-static char *x_caught_error_message;
-#define X_CAUGHT_ERROR_MESSAGE_SIZE 200
 
-/* An X error handler which stores the error message in
-   x_caught_error_message.  This is what's installed when
-   x_catch_errors is in effect.  */
+/* This is the handler for X IO errors, always.
+   It kills all frames on the display that we lost touch with.
+   If that was the only one, it prints an error message and kills Emacs.  */
 
 static int
-x_error_catcher (display, error)
+x_io_error_quitter (display)
      Display *display;
-     XErrorEvent *error;
-{
-  XGetErrorText (display, error->error_code,
-                x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
-}
-
-
-/* Begin trapping X errors for display DPY.  Actually we trap X errors
-   for all displays, but DPY should be the display you are actually
-   operating on.
-
-   After calling this function, X protocol errors no longer cause
-   Emacs to exit; instead, they are recorded in x_cfc_error_message.
-
-   Calling x_check_errors signals an Emacs error if an X error has
-   occurred since the last call to x_catch_errors or x_check_errors.
-
-   Calling x_uncatch_errors resumes the normal error handling.  */
-
-void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
-
-void
-x_catch_errors (dpy)
-     Display *dpy;
-{
-  /* Make sure any errors from previous requests have been dealt with.  */
-  XSync (dpy, False);
-
-  /* Set up the error buffer.  */
-  x_caught_error_message
-    = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
-  x_caught_error_message[0] = '\0';
-
-  /* Install our little error handler.  */
-  XSetErrorHandler (x_error_catcher);
-}
-
-/* If any X protocol errors have arrived since the last call to
-   x_catch_errors or x_check_errors, signal an Emacs error using
-   sprintf (a buffer, FORMAT, the x error message text) as the text.  */
-
-void
-x_check_errors (dpy, format)
-     Display *dpy;
-     char *format;
-{
-  /* Make sure to catch any errors incurred so far.  */
-  XSync (dpy, False);
-
-  if (x_caught_error_message[0])
-    {
-      char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
-
-      sprintf (buf, format, x_caught_error_message);
-      x_uncatch_errors (dpy);
-      error (buf);
-    }
-}
-
-/* Nonzero if we had any X protocol errors since we did x_catch_errors.  */
-
-int
-x_had_errors_p (dpy)
-     Display *dpy;
 {
-  /* Make sure to catch any errors incurred so far.  */
-  XSync (dpy, False);
-
-  return x_caught_error_message[0] != 0;
-}
-
-/* Stop catching X protocol errors and let them make Emacs die.  */
-
-void
-x_uncatch_errors (dpy)
-     Display *dpy;
-{
-  xfree (x_caught_error_message);
-  x_caught_error_message = 0;
-  XSetErrorHandler (x_error_quitter);
-}
+  char buf[256];
 
-#if 0
-static unsigned int x_wire_count;
-x_trace_wire ()
-{
-  fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
+  sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
+  x_connection_closed (display, buf);
 }
-#endif /* ! 0 */
-
 \f
 /* Changing the font of the frame.  */
 
@@ -5171,8 +5243,8 @@ x_new_font (f, fontname)
 
 /* 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 font that fits the pattern.
-   The return value shows which font we chose.  */
+   pattern; in that case, we choose some fontset that fits the pattern.
+   The return value shows which fontset we chose.  */
 
 Lisp_Object
 x_new_fontset (f, fontsetname)
@@ -5217,6 +5289,11 @@ x_calc_absolute_position (f)
   int flags = f->output_data.x->size_hint_flags;
   int this_window;
 
+  /* We have nothing to do if the current position
+     is already for the top-left corner.  */
+  if (! ((flags & XNegative) || (flags & YNegative)))
+    return;
+
 #ifdef USE_X_TOOLKIT
   this_window = XtWindow (f->output_data.x->widget);
 #else
@@ -5224,21 +5301,47 @@ x_calc_absolute_position (f)
 #endif
 
   /* Find the position of the outside upper-left corner of
-     the inner window, with respect to the outer window.  */
+     the inner window, with respect to the outer window.
+     But do this only if we will need the results.  */
   if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
     {
+      int count;
+
       BLOCK_INPUT;
-      XTranslateCoordinates (FRAME_X_DISPLAY (f),
+      count = x_catch_errors (FRAME_X_DISPLAY (f));
+      while (1)
+       {
+         x_clear_errors (FRAME_X_DISPLAY (f));
+         XTranslateCoordinates (FRAME_X_DISPLAY (f),
+
+                                /* From-window, to-window.  */
+                                this_window,
+                                f->output_data.x->parent_desc,
 
-                            /* From-window, to-window.  */
-                            this_window,
-                            f->output_data.x->parent_desc,
+                                /* From-position, to-position.  */
+                                0, 0, &win_x, &win_y,
 
-                            /* From-position, to-position.  */
-                            0, 0, &win_x, &win_y,
+                                /* Child of win.  */
+                                &child);
+         if (x_had_errors_p (FRAME_X_DISPLAY (f)))
+           {
+             Window newroot, newparent = 0xdeadbeef;
+             Window *newchildren;
+             int nchildren;
+
+             if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
+                               &newparent, &newchildren, &nchildren))
+               break;
+
+             XFree (newchildren);
+
+             f->output_data.x->parent_desc = newparent;
+           }
+         else
+           break;
+       }
 
-                            /* Child of win.  */
-                            &child);
+      x_uncatch_errors (FRAME_X_DISPLAY (f), count);
       UNBLOCK_INPUT;
     }
 
@@ -5293,15 +5396,18 @@ x_set_offset (f, xoff, yoff, change_gravity)
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
-  /* It is a mystery why we need to add the border_width here
-     when the frame is already visible, but experiment says we do.  */
   modified_left = f->output_data.x->left_pos;
   modified_top = f->output_data.x->top_pos;
+#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
+        this seems to be unnecessary and incorrect.  rms, 4/17/97.  */
+  /* It is a mystery why we need to add the border_width here
+     when the frame is already visible, but experiment says we do.  */
   if (change_gravity != 0)
     {
       modified_left += f->output_data.x->border_width;
       modified_top += f->output_data.x->border_width;
     }
+#endif
 
 #ifdef USE_X_TOOLKIT
   XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
@@ -5531,6 +5637,8 @@ x_make_frame_visible (f)
 {
   int mask;
   Lisp_Object type;
+  int starting_flags = f->output_data.x->size_hint_flags;
+  int original_top, original_left;
 
   BLOCK_INPUT;
 
@@ -5575,9 +5683,35 @@ x_make_frame_visible (f)
     Lisp_Object frame;
     int count = input_signal_count;
 
+    original_left = f->output_data.x->left_pos;
+    original_top = f->output_data.x->top_pos;
+
     /* This must come after we set COUNT.  */
     UNBLOCK_INPUT;
 
+    /* Arriving X events are processed here.  */
+
+    /* Now move the window back to where it was "supposed to be".
+       But don't do it if the gravity is negative.
+       When the gravity is negative, this uses a position
+       that is 3 pixels too low.  Perhaps that's really the border width.  */
+
+    if (! FRAME_VISIBLE_P (f)
+       && f->output_data.x->win_gravity == NorthWestGravity
+       && f->output_data.x->has_been_visible)
+      {
+       BLOCK_INPUT;
+
+#ifdef USE_X_TOOLKIT
+       XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
+                    original_left, original_top);
+#else /* not USE_X_TOOLKIT */
+       XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                    original_left, original_top);
+#endif /* not USE_X_TOOLKIT */
+       UNBLOCK_INPUT;
+      }
+
     XSETFRAME (frame, f);
 
     while (1)
@@ -5843,6 +5977,9 @@ x_destroy_window (f)
       XFlush (FRAME_X_DISPLAY (f));
     }
 
+  if (f->output_data.x->saved_menu_event)
+    free (f->output_data.x->saved_menu_event);
+
   xfree (f->output_data.x);
   f->output_data.x = 0;
   if (f == dpyinfo->x_focus_frame)
@@ -6128,30 +6265,39 @@ x_list_fonts (f, pattern, size, maxnames)
      int size;
      int maxnames;
 {
-  Lisp_Object list, newlist, key;
+  Lisp_Object list, patterns = Qnil, newlist = Qnil, key, tem, second_best;
   Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
 
-  key = Fcons (pattern, make_number (maxnames));
-
-  if (f == NULL)
-    list = Qnil;
-  else
-    /* See if we cached the result for this particular query.  */
-    list = Fassoc (key,
-                  XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
-
-  /* Now LIST has the form (KEY . FONT-DATA-LIST), where KEY is a
-    pattern which matches font names in FONT-DATA-LIST, FONT-DATA-LIST
-    is a list of cons cells for the form (FONTNAME . FONTWIDTH).  */
+  for (list = Valternative_fontname_alist; CONSP (list);
+       list = XCONS (list)->cdr)
+    {
+      tem = XCONS (list)->car;
+      if (CONSP (tem)
+         && STRINGP (XCONS (tem)->car)
+         && !NILP (Fstring_equal (XCONS (tem)->car, pattern)))
+       {
+         patterns = XCONS (tem)->cdr;
+         break;
+       }
+    }
 
-  if (!NILP (list))
-    list = XCONS (list)->cdr;
-  else
+  for (patterns = Fcons (pattern, patterns); CONSP (patterns);
+       patterns = XCONS (patterns)->cdr, pattern = XCONS (patterns)->car)
     {
-      /* At first, put PATTERN in the cache.  */
       int num_fonts;
       char **names;
 
+      /* See if we cached the result for this particular query.  */
+      if (f && (tem = XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr,
+               key = Fcons (pattern, make_number (maxnames)),
+               !NILP (list = Fassoc (key, tem))))
+       {
+         list = Fcdr_safe (list);
+         /* We have a cashed list.  Don't have to get the list again.  */
+         goto label_cached;
+       }
+
+      /* At first, put PATTERN in the cache.  */
       BLOCK_INPUT;
       names = XListFonts (dpy, XSTRING (pattern)->data, maxnames, &num_fonts);
       UNBLOCK_INPUT;
@@ -6159,7 +6305,6 @@ x_list_fonts (f, pattern, size, maxnames)
       if (names)
        {
          int i;
-         Lisp_Object tem;
 
          /* Make a list of all the fonts we got back.
             Store that in the font cache for the display.  */
@@ -6169,10 +6314,10 @@ x_list_fonts (f, pattern, size, maxnames)
              int average_width = -1, dashes = 0, width = 0;
 
              /* Count the number of dashes in NAMES[I].  If there are
-                14 dashes, and the field value following 12th dash
-                (AVERAGE_WIDTH) is 0, this is a auto-scaled font
-                which is usually too ugly to be used for editing.
-                Let's ignore it.  */
+               14 dashes, and the field value following 12th dash
+               (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
+               is usually too ugly to be used for editing.  Let's
+               ignore it.  */
              while (*p)
                if (*p++ == '-')
                  {
@@ -6188,11 +6333,11 @@ x_list_fonts (f, pattern, size, maxnames)
                  if (NILP (Fassoc (tem, list)))
                    {
                      if (STRINGP (Vx_pixel_size_width_font_regexp)
-                         && (fast_string_match_ignore_case
-                             (Vx_pixel_size_width_font_regexp, names[i])
+                         && ((fast_c_string_match_ignore_case
+                              (Vx_pixel_size_width_font_regexp, names[i]))
                              >= 0))
                        /* We can set the value of PIXEL_SIZE to the
-                           width of this font.  */
+                         width of this font.  */
                        list = Fcons (Fcons (tem, make_number (width)), list);
                      else
                        /* For the moment, width is not known.  */
@@ -6203,31 +6348,33 @@ x_list_fonts (f, pattern, size, maxnames)
          XFreeFontNames (names);
        }
 
+      /* Now store the result in the cache.  */
       if (f != NULL)
        XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr
          = Fcons (Fcons (key, list),
                   XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
-    }
 
-  if (NILP (list))
-    return Qnil;
+    label_cached:
+      if (NILP (list)) continue; /* Try the remaining alternatives.  */
 
-  newlist = Qnil;
+      newlist = second_best = Qnil;
+      /* Make a list of the fonts that have the right width.  */
+      for (; CONSP (list); list = XCONS (list)->cdr)
+       {
+         tem = XCONS (list)->car;
 
-  /* Make a list of the fonts that have the right width.  */
-  for (; CONSP (list); list = XCONS (list)->cdr)
-    {
-      Lisp_Object tem = XCONS (list)->car;
-      int keeper;
+         if (!CONSP (tem) || NILP (XCONS (tem)->car))
+           continue;
+         if (!size)
+           {
+             newlist = Fcons (XCONS (tem)->car, newlist);
+             continue;
+           }
 
-      if (!CONSP (tem) || NILP (XCONS (tem)->car))
-       continue;
-      if (!size)
-       keeper = 1;
-      else
-       {
          if (!INTEGERP (XCONS (tem)->cdr))
            {
+             /* Since we have not yet known the size of this font, we
+               must try slow function call XLoadQueryFont.  */
              XFontStruct *thisinfo;
 
              BLOCK_INPUT;
@@ -6241,12 +6388,35 @@ x_list_fonts (f, pattern, size, maxnames)
                  XFreeFont (dpy, thisinfo);
                }
              else
+               /* For unknown reason, the previous call of XListFont had
+                 retruned a font which can't be opened.  Record the size
+                 as 0 not to try to open it again.  */
                XCONS (tem)->cdr = make_number (0);
            }
-         keeper = XINT (XCONS (tem)->cdr) == size;
+         if (XINT (XCONS (tem)->cdr) == size)
+           newlist = Fcons (XCONS (tem)->car, newlist);
+         else if (NILP (second_best))
+           second_best = tem;
+         else if (XINT (XCONS (tem)->cdr) < size)
+           {
+             if (XINT (XCONS (second_best)->cdr) > size
+                 || XINT (XCONS (second_best)->cdr) < XINT (XCONS (tem)->cdr))
+               second_best = tem;
+           }
+         else
+           {
+             if (XINT (XCONS (second_best)->cdr) > size
+                 && XINT (XCONS (second_best)->cdr) > XINT (XCONS (tem)->cdr))
+               second_best = tem;
+           }
+       }
+      if (!NILP (newlist))
+       break;
+      else if (!NILP (second_best))
+       {
+         newlist = Fcons (XCONS (second_best)->car, Qnil);
+         break;
        }
-      if (keeper)
-       newlist = Fcons (XCONS (tem)->car, newlist);
     }
 
   return newlist;
@@ -6293,12 +6463,12 @@ x_load_font (f, fontname, size)
     unsigned long value;
 
     if (!NILP (font_names))
-      fontname = XSTRING (XCONS (font_names)->car)->data;
+      fontname = (char *) XSTRING (XCONS (font_names)->car)->data;
 
     BLOCK_INPUT;
     font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
     UNBLOCK_INPUT;
-    if (!font || (size && font->max_bounds.width != size))
+    if (!font)
       return NULL;
 
     /* Do we need to create the table?  */
@@ -6368,18 +6538,20 @@ x_load_font (f, fontname, size)
 
     /* The slot `encoding' specifies how to map a character
        code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
-       the font code-points (0x20..0x7F, 0xA0..0xFF, 0x2020..0x7F7F,
-       0xA0A0..0xFFFF, 0x20A0..0x7FFF, or 0xA020..0xFF7F).  For the
-       moment, we don't know which charset uses this font.  So, we set
-       informatoin in fontp->encoding[1] which is never used by any
-       charset.  If mapping can't be decided, set -1.  */
+       the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
+       the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
+       0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
+       2:0xA020..0xFF7F).  For the moment, we don't know which charset
+       uses this font.  So, we set informatoin in fontp->encoding[1]
+       which is never used by any charset.  If mapping can't be
+       decided, set FONT_ENCODING_NOT_DECIDED.  */
     fontp->encoding[1]
       = (font->max_byte1 == 0
         /* 1-byte font */
         ? (font->min_char_or_byte2 < 0x80
            ? (font->max_char_or_byte2 < 0x80
               ? 0              /* 0x20..0x7F */
-              : -1)            /* 0x20..0xFF (can't decide) */
+              : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
            : 1)                /* 0xA0..0xFF */
         /* 2-byte font */
         : (font->min_byte1 < 0x80
@@ -6387,13 +6559,13 @@ x_load_font (f, fontname, size)
               ? (font->min_char_or_byte2 < 0x80
                  ? (font->max_char_or_byte2 < 0x80
                     ? 0                /* 0x2020..0x7F7F */
-                    : -1)      /* 0x2020..0x7FFF (can't decide) */
+                    : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
                  : 3)          /* 0x20A0..0x7FFF */
-              : -1)            /* 0x20??..0xA0?? (can't decide) */
+              : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
            : (font->min_char_or_byte2 < 0x80
               ? (font->max_char_or_byte2 < 0x80
                  ? 2           /* 0xA020..0xFF7F */
-                 : -1)         /* 0xA020..0xFFFF (can't decide) */
+                 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
               : 1)));          /* 0xA0A0..0xFFFF */
 
     fontp->baseline_offset
@@ -6749,6 +6921,7 @@ x_term_init (display_name, xrm_option, resource_name)
     Display *dpy = dpyinfo->display;
     XrmValue d, fr, to;
     Font font;
+    int count;
     
     d.addr = (XPointer)&dpy;
     d.size = sizeof (Display *);
@@ -6756,12 +6929,12 @@ x_term_init (display_name, xrm_option, resource_name)
     fr.size = sizeof (XtDefaultFont);
     to.size = sizeof (Font *);
     to.addr = (XPointer)&font;
-    x_catch_errors (dpy);
+    count = x_catch_errors (dpy);
     if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
       abort ();
     if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
       XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
-    x_uncatch_errors (dpy);
+    x_uncatch_errors (dpy, count);
   }
 #endif
 
@@ -6877,7 +7050,7 @@ x_initialize ()
 
   /* Note that there is no real way portable across R3/R4 to get the
      original error handler.  */
-  XSetErrorHandler (x_error_quitter);
+  XSetErrorHandler (x_error_handler);
   XSetIOErrorHandler (x_io_error_quitter);
 
   /* Disable Window Change signals;  they are handled by X events. */
@@ -6891,6 +7064,9 @@ x_initialize ()
 void
 syms_of_xterm ()
 {
+  staticpro (&x_error_message_string);
+  x_error_message_string = Qnil;
+
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;