Merge from emacs-24; up to 2012-12-06T01:39:03Z!monnier@iro.umontreal.ca
[bpt/emacs.git] / src / xfns.c
index a022991..315d509 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions for the X window system.
 
-Copyright (C) 1989, 1992-201 Free Software Foundation, Inc.
+Copyright (C) 1989, 1992-2013 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -20,8 +20,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <config.h>
 #include <stdio.h>
 #include <math.h>
-#include <setjmp.h>
-#include <ctype.h>
 #include <unistd.h>
 
 /* This makes the fields of a Display accessible, in Xlib header files.  */
@@ -50,7 +48,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #ifdef HAVE_X_WINDOWS
 
-#include <ctype.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -130,7 +127,6 @@ extern LWLIB_ID widget_id_tick;
 
 int x_in_use;
 
-static Lisp_Object Qnone;
 static Lisp_Object Qsuppress_icon;
 static Lisp_Object Qundefined_color;
 static Lisp_Object Qcompound_text, Qcancel_timer;
@@ -141,10 +137,6 @@ static ptrdiff_t image_cache_refcount;
 static int dpyinfo_refcount;
 #endif
 
-#if defined (USE_GTK) && defined (HAVE_FREETYPE)
-static char *x_last_font_name;
-#endif
-
 static struct x_display_info *x_display_info_for_name (Lisp_Object);
 
 \f
@@ -172,12 +164,8 @@ have_menus_p (void)
 FRAME_PTR
 check_x_frame (Lisp_Object frame)
 {
-  FRAME_PTR f;
+  struct frame *f = decode_live_frame (frame);
 
-  if (NILP (frame))
-    frame = selected_frame;
-  CHECK_LIVE_FRAME (frame);
-  f = XFRAME (frame);
   if (! FRAME_X_P (f))
     error ("Non-X frame used");
   return f;
@@ -236,13 +224,11 @@ x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
   Lisp_Object tail, frame;
   struct frame *f;
 
-  if (wdesc == None) return 0;
+  if (wdesc == None)
+    return NULL;
 
-  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_FRAME (tail, frame)
     {
-      frame = XCAR (tail);
-      if (!FRAMEP (frame))
-        continue;
       f = XFRAME (frame);
       if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
        continue;
@@ -282,18 +268,16 @@ struct frame *
 x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
 {
   Lisp_Object tail, frame;
-  struct frame *f, *found;
+  struct frame *f, *found = NULL;
   struct x_output *x;
 
-  if (wdesc == None) return NULL;
+  if (wdesc == None)
+    return NULL;
 
-  found = NULL;
-  for (tail = Vframe_list; CONSP (tail) && !found; tail = XCDR (tail))
+  FOR_EACH_FRAME (tail, frame)
     {
-      frame = XCAR (tail);
-      if (!FRAMEP (frame))
-        continue;
-
+      if (found)
+        break;
       f = XFRAME (frame);
       if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
        {
@@ -337,13 +321,11 @@ x_menubar_window_to_frame (struct x_display_info *dpyinfo, XEvent *event)
   struct frame *f;
   struct x_output *x;
 
-  if (wdesc == None) return 0;
+  if (wdesc == None)
+    return NULL;
 
-  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_FRAME (tail, frame)
     {
-      frame = XCAR (tail);
-      if (!FRAMEP (frame))
-        continue;
       f = XFRAME (frame);
       if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
        continue;
@@ -371,13 +353,11 @@ x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
   struct frame *f;
   struct x_output *x;
 
-  if (wdesc == None) return 0;
+  if (wdesc == None)
+    return NULL;
 
-  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_FRAME (tail, frame)
     {
-      frame = XCAR (tail);
-      if (!FRAMEP (frame))
-        continue;
       f = XFRAME (frame);
       if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
        continue;
@@ -433,7 +413,7 @@ x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
   unsigned char *tmp_data = NULL;
   Atom target_type = XA_CARDINAL;
 
-  BLOCK_INPUT;
+  block_input ();
 
   x_catch_errors (dpy);
 
@@ -460,7 +440,7 @@ x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
       if (! success)
        break;
 
-      XFree ((char *) tmp_children);
+      XFree (tmp_children);
 
       if (wm_window == rootw || had_errors)
         break;
@@ -551,7 +531,7 @@ x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
 
   x_uncatch_errors ();
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   if (had_errors) return;
 
@@ -583,27 +563,27 @@ gamma_correct (struct frame *f, XColor *color)
 
 
 /* Decide if color named COLOR_NAME is valid for use on frame F.  If
-   so, return the RGB values in COLOR.  If ALLOC_P is non-zero,
-   allocate the color.  Value is zero if COLOR_NAME is invalid, or
+   so, return the RGB values in COLOR.  If ALLOC_P,
+   allocate the color.  Value is false if COLOR_NAME is invalid, or
    no color could be allocated.  */
 
-int
+bool
 x_defined_color (struct frame *f, const char *color_name,
-                XColor *color, int alloc_p)
+                XColor *color, bool alloc_p)
 {
-  int success_p = 0;
+  bool success_p = 0;
   Display *dpy = FRAME_X_DISPLAY (f);
   Colormap cmap = FRAME_X_COLORMAP (f);
 
-  BLOCK_INPUT;
+  block_input ();
 #ifdef USE_GTK
   success_p = xg_check_special_colors (f, color_name, color);
 #endif
   if (!success_p)
-    success_p = XParseColor (dpy, cmap, color_name, color);
+    success_p = XParseColor (dpy, cmap, color_name, color) != 0;
   if (success_p && alloc_p)
     success_p = x_alloc_nearest_color (f, cmap, color);
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   return success_p;
 }
@@ -664,8 +644,8 @@ x_set_tool_bar_position (struct frame *f,
   if (EQ (new_value, old_value)) return;
 
 #ifdef USE_GTK
-  if (xg_change_toolbar_position (f, new_value))
-    f->tool_bar_position = new_value;
+  xg_change_toolbar_position (f, new_value);
+  fset_tool_bar_position (f, new_value);
 #endif
 }
 
@@ -687,7 +667,7 @@ xg_set_icon (FRAME_PTR f, Lisp_Object file)
       GdkPixbuf *pixbuf;
       GError *err = NULL;
       char *filename = SSDATA (found);
-      BLOCK_INPUT;
+      block_input ();
 
       pixbuf = gdk_pixbuf_new_from_file (filename, &err);
 
@@ -702,7 +682,7 @@ xg_set_icon (FRAME_PTR f, Lisp_Object file)
       else
        g_error_free (err);
 
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 
   return result;
@@ -745,7 +725,7 @@ x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
     {
       Display *dpy = FRAME_X_DISPLAY (f);
 
-      BLOCK_INPUT;
+      block_input ();
       XSetForeground (dpy, x->normal_gc, fg);
       XSetBackground (dpy, x->reverse_gc, fg);
 
@@ -756,7 +736,7 @@ x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
          XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
        }
 
-      UNBLOCK_INPUT;
+      unblock_input ();
 
       update_face_from_frame_parameter (f, Qforeground_color, arg);
 
@@ -781,7 +761,7 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
     {
       Display *dpy = FRAME_X_DISPLAY (f);
 
-      BLOCK_INPUT;
+      block_input ();
       XSetBackground (dpy, x->normal_gc, bg);
       XSetForeground (dpy, x->reverse_gc, bg);
       XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
@@ -805,7 +785,7 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       }
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
-      UNBLOCK_INPUT;
+      unblock_input ();
       update_face_from_frame_parameter (f, Qbackground_color, arg);
 
       if (FRAME_VISIBLE_P (f))
@@ -862,7 +842,7 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
   unload_color (f, x->mouse_pixel);
   x->mouse_pixel = pixel;
 
-  BLOCK_INPUT;
+  block_input ();
 
   /* It's not okay to crash if the user selects a screwy cursor.  */
   x_catch_errors (dpy);
@@ -982,7 +962,7 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
   x->horizontal_drag_cursor = horizontal_drag_cursor;
 
   XFlush (dpy);
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   update_face_from_frame_parameter (f, Qmouse_color, arg);
 }
@@ -1039,10 +1019,10 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 
   if (FRAME_X_WINDOW (f) != 0)
     {
-      BLOCK_INPUT;
+      block_input ();
       XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
       XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
-      UNBLOCK_INPUT;
+      unblock_input ();
 
       if (FRAME_VISIBLE_P (f))
        {
@@ -1066,9 +1046,9 @@ x_set_border_pixel (struct frame *f, int pix)
 
   if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
     {
-      BLOCK_INPUT;
+      block_input ();
       XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), pix);
-      UNBLOCK_INPUT;
+      unblock_input ();
 
       if (FRAME_VISIBLE_P (f))
         redraw_frame (f);
@@ -1120,7 +1100,7 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
   else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
     return;
 
-  BLOCK_INPUT;
+  block_input ();
   if (NILP (arg))
     result = x_text_icon (f,
                          SSDATA ((!NILP (f->icon_name)
@@ -1131,12 +1111,12 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 
   if (result)
     {
-      UNBLOCK_INPUT;
+      unblock_input ();
       error ("No icon window available");
     }
 
   XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 static void
@@ -1152,12 +1132,12 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
   else if (!NILP (arg) || NILP (oldval))
     return;
 
-  f->icon_name = arg;
+  fset_icon_name (f, arg);
 
   if (f->output_data.x->icon_bitmap != 0)
     return;
 
-  BLOCK_INPUT;
+  block_input ();
 
   result = x_text_icon (f,
                        SSDATA ((!NILP (f->icon_name)
@@ -1168,12 +1148,12 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 
   if (result)
     {
-      UNBLOCK_INPUT;
+      unblock_input ();
       error ("No icon window available");
     }
 
   XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 \f
@@ -1236,10 +1216,10 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
        {
          y = FRAME_TOP_MARGIN_HEIGHT (f);
 
-         BLOCK_INPUT;
+         block_input ();
          x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                        0, y, width, height, False);
-         UNBLOCK_INPUT;
+         unblock_input ();
        }
 
       if (nlines > 1 && nlines > olines)
@@ -1247,10 +1227,10 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
          y = (olines == 0 ? 1 : olines) * FRAME_LINE_HEIGHT (f);
          height = nlines * FRAME_LINE_HEIGHT (f) - y;
 
-         BLOCK_INPUT;
+         block_input ();
          x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                        0, y, width, height, False);
-         UNBLOCK_INPUT;
+         unblock_input ();
        }
 
       if (nlines == 0 && WINDOWP (f->menu_bar_window))
@@ -1346,10 +1326,10 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
       /* height can be zero here. */
       if (height > 0 && width > 0)
        {
-          BLOCK_INPUT;
+          block_input ();
           x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                         0, y, width, height, False);
-          UNBLOCK_INPUT;
+          unblock_input ();
         }
 
       if (WINDOWP (f->tool_bar_window))
@@ -1502,7 +1482,7 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name)
 {
   if (FRAME_X_WINDOW (f))
     {
-      BLOCK_INPUT;
+      block_input ();
       {
        XTextProperty text, icon;
        ptrdiff_t bytes;
@@ -1594,7 +1574,7 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name)
        if (do_free_text_value)
          xfree (text.value);
       }
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 
@@ -1643,7 +1623,7 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit)
   if (! NILP (Fstring_equal (name, f->name)))
     return;
 
-  f->name = name;
+  fset_name (f, name);
 
   /* For setting the frame title, the title parameter should override
      the name parameter.  */
@@ -1683,7 +1663,7 @@ x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
 
   update_mode_lines = 1;
 
-  f->title = name;
+  fset_title (f, name);
 
   if (NILP (name))
     name = f->name;
@@ -1787,7 +1767,7 @@ hack_wm_protocols (FRAME_PTR f, Widget widget)
   int need_focus = 1;
   int need_save = 1;
 
-  BLOCK_INPUT;
+  block_input ();
   {
     Atom type;
     unsigned char *catoms;
@@ -1835,7 +1815,7 @@ hack_wm_protocols (FRAME_PTR f, Widget widget)
                       XA_ATOM, 32, PropModeAppend,
                       (unsigned char *) props, count);
   }
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 #endif
 
@@ -2358,7 +2338,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
   Arg al [25];
   int ac;
 
-  BLOCK_INPUT;
+  block_input ();
 
   /* Use the resource name as the top-level widget name
      for looking up resources.  Make a non-Lisp copy
@@ -2572,7 +2552,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
 
     f->explicit_name = 0;
     name = f->name;
-    f->name = Qnil;
+    fset_name (f, Qnil);
     x_set_name (f, name, explicit);
   }
 
@@ -2580,7 +2560,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
                 f->output_data.x->current_cursor
                  = f->output_data.x->text_cursor);
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   /* This is a no-op, except under Motif.  Make sure main areas are
      set to something reasonable, in case we get an error later.  */
@@ -2599,7 +2579,7 @@ x_window (FRAME_PTR f)
   FRAME_XIC (f) = NULL;
   if (use_xim)
   {
-    BLOCK_INPUT;
+    block_input ();
     create_frame_xic (f);
     if (FRAME_XIC (f))
       {
@@ -2621,7 +2601,7 @@ x_window (FRAME_PTR f)
                                     attribute_mask, &attributes);
          }
       }
-    UNBLOCK_INPUT;
+    unblock_input ();
   }
 #endif
 }
@@ -2646,7 +2626,7 @@ x_window (struct frame *f)
   attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
                    | CWColormap);
 
-  BLOCK_INPUT;
+  block_input ();
   FRAME_X_WINDOW (f)
     = XCreateWindow (FRAME_X_DISPLAY (f),
                     f->output_data.x->parent_desc,
@@ -2715,7 +2695,7 @@ x_window (struct frame *f)
 
     f->explicit_name = 0;
     name = f->name;
-    f->name = Qnil;
+    fset_name (f, Qnil);
     x_set_name (f, name, explicit);
   }
 
@@ -2723,7 +2703,7 @@ x_window (struct frame *f)
                 f->output_data.x->current_cursor
                  = f->output_data.x->text_cursor);
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   if (FRAME_X_WINDOW (f) == 0)
     error ("Unable to create window");
@@ -2776,7 +2756,7 @@ x_icon (struct frame *f, Lisp_Object parms)
   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
     error ("Both left and top icon corners of icon must be specified");
 
-  BLOCK_INPUT;
+  block_input ();
 
   if (! EQ (icon_x, Qunbound))
     x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
@@ -2795,7 +2775,7 @@ x_icon (struct frame *f, Lisp_Object parms)
                           ? f->icon_name
                           : f->name)));
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 /* Make the GCs needed for this window, setting the
@@ -2807,7 +2787,7 @@ x_make_gc (struct frame *f)
 {
   XGCValues gc_values;
 
-  BLOCK_INPUT;
+  block_input ();
 
   /* Create the GCs of this frame.
      Note that many default values are used.  */
@@ -2855,7 +2835,7 @@ x_make_gc (struct frame *f)
        FRAME_BACKGROUND_PIXEL (f),
        DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 
@@ -2866,7 +2846,7 @@ x_free_gcs (struct frame *f)
 {
   Display *dpy = FRAME_X_DISPLAY (f);
 
-  BLOCK_INPUT;
+  block_input ();
 
   if (f->output_data.x->normal_gc)
     {
@@ -2892,7 +2872,7 @@ x_free_gcs (struct frame *f)
       f->output_data.x->border_tile = 0;
     }
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 
@@ -2956,7 +2936,7 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms)
          read yet.  */
       const char *system_font = xsettings_get_system_font ();
       if (system_font)
-       font = font_open_by_name (f, system_font, strlen (system_font));
+       font = font_open_by_name (f, build_unibyte_string (system_font));
     }
 
   if (NILP (font))
@@ -2986,7 +2966,7 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms)
 
       for (i = 0; names[i]; i++)
        {
-         font = font_open_by_name (f, names[i], strlen (names[i]));
+         font = font_open_by_name (f, build_unibyte_string (names[i]));
          if (! NILP (font))
            break;
        }
@@ -3008,17 +2988,15 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms)
 DEFUN ("x-wm-set-size-hint", Fx_wm_set_size_hint, Sx_wm_set_size_hint,
        0, 1, 0,
        doc: /* Send the size hints for frame FRAME to the window manager.
-If FRAME is nil, use the selected frame.  */)
+If FRAME is omitted or nil, use the selected frame.
+Signal error if FRAME is not an X frame.  */)
   (Lisp_Object frame)
 {
-  struct frame *f;
-  if (NILP (frame))
-    frame = selected_frame;
-  f = XFRAME (frame);
-  BLOCK_INPUT;
-  if (FRAME_X_P (f))
-    x_wm_set_size_hint (f, 0, 0);
-  UNBLOCK_INPUT;
+  struct frame *f = check_x_frame (frame);
+
+  block_input ();
+  x_wm_set_size_hint (f, 0, 0);
+  unblock_input ();
   return Qnil;
 }
 
@@ -3119,9 +3097,6 @@ This function is an internal primitive--use `make-frame' instead.  */)
 
   XSETFRAME (frame, f);
 
-  /* Note that X Windows does support scroll bars.  */
-  FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
-
   f->terminal = dpyinfo->terminal;
 
   f->output_method = output_x_window;
@@ -3135,11 +3110,11 @@ This function is an internal primitive--use `make-frame' instead.  */)
   f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
-  f->icon_name
-    = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
-                RES_TYPE_STRING);
+  fset_icon_name (f,
+                 x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
+                            RES_TYPE_STRING));
   if (! STRINGP (f->icon_name))
-    f->icon_name = Qnil;
+    fset_icon_name (f, Qnil);
 
   FRAME_X_DISPLAY_INFO (f) = dpyinfo;
 
@@ -3196,12 +3171,12 @@ This function is an internal primitive--use `make-frame' instead.  */)
      be set.  */
   if (EQ (name, Qunbound) || NILP (name))
     {
-      f->name = build_string (dpyinfo->x_id_name);
+      fset_name (f, build_string (dpyinfo->x_id_name));
       f->explicit_name = 0;
     }
   else
     {
-      f->name = name;
+      fset_name (f, name);
       f->explicit_name = 1;
       /* use the frame's title when getting resources for this frame.  */
       specbind (Qx_resource_name, name);
@@ -3413,9 +3388,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Tell the server what size and position, etc, we want, and how
      badly we want them.  This should be done after we have the menu
      bar so that its size can be taken into account.  */
-  BLOCK_INPUT;
+  block_input ();
   x_wm_set_size_hint (f, window_prompting, 0);
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   /* Make the window appear on the frame and enable display, unless
      the caller says not to.  However, with explicit parent, Emacs
@@ -3439,7 +3414,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
        }
     }
 
-  BLOCK_INPUT;
+  block_input ();
 
   /* Set machine name and pid for the purpose of window managers.  */
   set_machine_and_pid_properties (f);
@@ -3455,20 +3430,20 @@ This function is an internal primitive--use `make-frame' instead.  */)
                        (unsigned char *) &dpyinfo->client_leader_window, 1);
     }
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   /* Initialize `default-minibuffer-frame' in case this is the first
      frame on this terminal.  */
   if (FRAME_HAS_MINIBUF_P (f)
       && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
-    KVAR (kb, Vdefault_minibuffer_frame) = frame;
+    kset_default_minibuffer_frame (kb, frame);
 
   /* All remaining specified parameters, which have not been "used"
      by x_get_arg and friends, now go in the misc. alist of the frame.  */
   for (tem = parms; CONSP (tem); tem = XCDR (tem))
     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
-      f->param_alist = Fcons (XCAR (tem), f->param_alist);
+      fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
 
   UNGCPRO;
 
@@ -3514,7 +3489,7 @@ FRAME nil means use the selected frame.  */)
   struct frame *f = check_x_frame (frame);
   Display *dpy = FRAME_X_DISPLAY (f);
 
-  BLOCK_INPUT;
+  block_input ();
   x_catch_errors (dpy);
 
   if (FRAME_X_EMBEDDED_P (f))
@@ -3532,7 +3507,7 @@ FRAME nil means use the selected frame.  */)
     }
 
   x_uncatch_errors ();
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   return Qnil;
 }
@@ -3873,20 +3848,6 @@ x_pixel_height (register struct frame *f)
   return FRAME_PIXEL_HEIGHT (f);
 }
 
-int
-x_char_width (register struct frame *f)
-{
-  return FRAME_COLUMN_WIDTH (f);
-}
-
-int
-x_char_height (register struct frame *f)
-{
-  return FRAME_LINE_HEIGHT (f);
-}
-
-
-\f
 /************************************************************************
                              X Displays
  ************************************************************************/
@@ -4001,7 +3962,7 @@ select_visual (struct x_display_info *dpyinfo)
        fatal ("Can't get proper X visual info");
 
       dpyinfo->n_planes = vinfo->depth;
-      XFree ((char *) vinfo);
+      XFree (vinfo);
     }
 }
 
@@ -4160,9 +4121,9 @@ If TERMINAL is omitted or nil, that stands for the selected frame's display.  */
 void
 x_sync (FRAME_PTR f)
 {
-  BLOCK_INPUT;
+  block_input ();
   XSync (FRAME_X_DISPLAY (f), False);
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 \f
@@ -4237,7 +4198,7 @@ FRAME.  Default is to change on the edit X window.  */)
       nelements = SBYTES (value);
     }
 
-  BLOCK_INPUT;
+  block_input ();
   prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
   if (! NILP (type))
     {
@@ -4256,7 +4217,7 @@ FRAME.  Default is to change on the edit X window.  */)
 
   /* Make sure the property is set when we return.  */
   XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   return value;
 }
@@ -4272,13 +4233,13 @@ FRAME nil or omitted means use the selected frame.  Value is PROP.  */)
   Atom prop_atom;
 
   CHECK_STRING (prop);
-  BLOCK_INPUT;
+  block_input ();
   prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
   XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
 
   /* Make sure the property is removed when we return.  */
   XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   return prop;
 }
@@ -4326,7 +4287,7 @@ no value of TYPE (always string in the MS Windows case).  */)
        target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
     }
 
-  BLOCK_INPUT;
+  block_input ();
   if (STRINGP (type))
     {
       if (strcmp ("AnyPropertyType", SSDATA (type)) == 0)
@@ -4392,7 +4353,7 @@ no value of TYPE (always string in the MS Windows case).  */)
       if (tmp_data) XFree (tmp_data);
     }
 
-  UNBLOCK_INPUT;
+  unblock_input ();
   UNGCPRO;
   return prop_value;
 }
@@ -4423,7 +4384,7 @@ show_hourglass (struct atimer *timer)
     {
       Lisp_Object rest, frame;
 
-      BLOCK_INPUT;
+      block_input ();
 
       FOR_EACH_FRAME (rest, frame)
        {
@@ -4467,7 +4428,7 @@ show_hourglass (struct atimer *timer)
        }
 
       hourglass_shown_p = 1;
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 
@@ -4482,7 +4443,7 @@ hide_hourglass (void)
     {
       Lisp_Object rest, frame;
 
-      BLOCK_INPUT;
+      block_input ();
       FOR_EACH_FRAME (rest, frame)
        {
          struct frame *f = XFRAME (frame);
@@ -4501,7 +4462,7 @@ hide_hourglass (void)
        }
 
       hourglass_shown_p = 0;
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 
@@ -4592,17 +4553,18 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
   XSETFRAME (frame, f);
 
   buffer = Fget_buffer_create (build_string (" *tip*"));
-  Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
+  /* Use set_window_buffer instead of Fset_window_buffer (see
+     discussion of bug#11984, bug#12025, bug#12026).  */
+  set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, 0, 0);
   old_buffer = current_buffer;
   set_buffer_internal_1 (XBUFFER (buffer));
-  BVAR (current_buffer, truncate_lines) = Qnil;
+  bset_truncate_lines (current_buffer, Qnil);
   specbind (Qinhibit_read_only, Qt);
   specbind (Qinhibit_modification_hooks, Qt);
   Ferase_buffer ();
   Finsert (1, &text);
   set_buffer_internal_1 (old_buffer);
 
-  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   record_unwind_protect (unwind_create_tip_frame, frame);
 
   f->terminal = dpyinfo->terminal;
@@ -4621,7 +4583,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
   f->output_data.x->scroll_bar_top_shadow_pixel = -1;
   f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
 #endif /* USE_TOOLKIT_SCROLL_BARS */
-  f->icon_name = Qnil;
+  fset_icon_name (f, Qnil);
   FRAME_X_DISPLAY_INFO (f) = dpyinfo;
   f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
   f->output_data.x->explicit_parent = 0;
@@ -4663,12 +4625,12 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
      be set.  */
   if (EQ (name, Qunbound) || NILP (name))
     {
-      f->name = build_string (dpyinfo->x_id_name);
+      fset_name (f, build_string (dpyinfo->x_id_name));
       f->explicit_name = 0;
     }
   else
     {
-      f->name = name;
+      fset_name (f, name);
       f->explicit_name = 1;
       /* use the frame's title when getting resources for this frame.  */
       specbind (Qx_resource_name, name);
@@ -4749,7 +4711,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
     unsigned long mask;
     Atom type = FRAME_X_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip;
 
-    BLOCK_INPUT;
+    block_input ();
     mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
     if (DoesSaveUnders (dpyinfo->screen))
       mask |= CWSaveUnder;
@@ -4776,7 +4738,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
                      FRAME_X_DISPLAY_INFO (f)->Xatom_net_window_type,
                      XA_ATOM, 32, PropModeReplace,
                      (unsigned char *)&type, 1);
-    UNBLOCK_INPUT;
+    unblock_input ();
   }
 
   x_make_gc (f);
@@ -4890,10 +4852,10 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object
      show it.  */
   if (!INTEGERP (left) || !INTEGERP (top))
     {
-      BLOCK_INPUT;
+      block_input ();
       XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
                     &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 
   if (INTEGERP (top))
@@ -4991,20 +4953,21 @@ Text larger than the specified size is clipped.  */)
 #ifdef USE_GTK
   if (x_gtk_use_system_tooltips)
     {
-      int ok;
+      bool ok;
 
       /* Hide a previous tip, if any.  */
       Fx_hide_tip ();
 
-      BLOCK_INPUT;
-      if ((ok = xg_prepare_tooltip (f, string, &width, &height)) != 0)
+      block_input ();
+      ok = xg_prepare_tooltip (f, string, &width, &height);
+      if (ok)
         {
          compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
           xg_show_tooltip (f, root_x, root_y);
           /* This is used in Fx_hide_tip.  */
           XSETFRAME (tip_frame, f);
         }
-      UNBLOCK_INPUT;
+      unblock_input ();
       if (ok) goto start_timer;
     }
 #endif /* USE_GTK */
@@ -5032,12 +4995,12 @@ Text larger than the specified size is clipped.  */)
              call1 (Qcancel_timer, timer);
            }
 
-         BLOCK_INPUT;
+         block_input ();
          compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
                          FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
          XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
                       root_x, root_y);
-         UNBLOCK_INPUT;
+         unblock_input ();
          goto start_timer;
        }
     }
@@ -5069,19 +5032,20 @@ Text larger than the specified size is clipped.  */)
 
   /* Set up the frame's root window.  */
   w = XWINDOW (FRAME_ROOT_WINDOW (f));
-  w->left_col = w->top_line = make_number (0);
+  wset_left_col (w, make_number (0));
+  wset_top_line (w, make_number (0));
 
   if (CONSP (Vx_max_tooltip_size)
       && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
       && RANGED_INTEGERP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
     {
-      w->total_cols = XCAR (Vx_max_tooltip_size);
-      w->total_lines = XCDR (Vx_max_tooltip_size);
+      wset_total_cols (w, XCAR (Vx_max_tooltip_size));
+      wset_total_lines (w, XCDR (Vx_max_tooltip_size));
     }
   else
     {
-      w->total_cols = make_number (80);
-      w->total_lines = make_number (40);
+      wset_total_cols (w, make_number (80));
+      wset_total_lines (w, make_number (40));
     }
 
   FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
@@ -5091,7 +5055,7 @@ Text larger than the specified size is clipped.  */)
   /* Display the tooltip text in a temporary buffer.  */
   old_buffer = current_buffer;
   set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
-  BVAR (current_buffer, truncate_lines) = Qnil;
+  bset_truncate_lines (current_buffer, Qnil);
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);
   SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
@@ -5151,7 +5115,7 @@ Text larger than the specified size is clipped.  */)
       /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
         not in pixels.  */
       width /= WINDOW_FRAME_COLUMN_WIDTH (w);
-      w->total_cols = make_number (width);
+      wset_total_cols (w, make_number (width));
       FRAME_TOTAL_COLS (f) = width;
       adjust_glyphs (f);
       clear_glyph_matrix (w->desired_matrix);
@@ -5190,11 +5154,11 @@ Text larger than the specified size is clipped.  */)
      show it.  */
   compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
 
-  BLOCK_INPUT;
+  block_input ();
   XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                     root_x, root_y, width, height);
   XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   /* Draw into the window.  */
   w->must_be_updated_p = 1;
@@ -5266,9 +5230,9 @@ Value is t if tooltip was open, nil otherwise.  */)
        if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
            && w != NULL)
          {
-           BLOCK_INPUT;
+           block_input ();
            xlwmenu_redisplay (w);
-           UNBLOCK_INPUT;
+           unblock_input ();
          }
       }
 #endif /* USE_LUCID */
@@ -5332,11 +5296,11 @@ clean_up_file_dialog (Lisp_Object arg)
   Widget dialog = (Widget) p->pointer;
 
   /* Clean up.  */
-  BLOCK_INPUT;
+  block_input ();
   XtUnmanageChild (dialog);
   XtDestroyWidget (dialog);
   x_menu_set_in_use (0);
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   return Qnil;
 }
@@ -5348,7 +5312,7 @@ Use a file selection dialog.  Select DEFAULT-FILENAME in the dialog's file
 selection box, if specified.  If MUSTMATCH is non-nil, the returned file
 or directory must exist.
 
-This function is only defined on MS Windows, and X Windows with the
+This function is only defined on NS, MS Windows, and X Windows with the
 Motif or Gtk toolkits.  With the Motif toolkit, ONLY-DIR-P is ignored.
 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
@@ -5377,12 +5341,12 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
   /* Prevent redisplay.  */
   specbind (Qinhibit_redisplay, Qt);
 
-  BLOCK_INPUT;
+  block_input ();
 
   /* Create the dialog with PROMPT as title, using DIR as initial
      directory and using "*" as pattern.  */
   dir = Fexpand_file_name (dir, Qnil);
-  dir_xmstring = XmStringCreateLocalized (SDATA (dir));
+  dir_xmstring = XmStringCreateLocalized (SSDATA (dir));
   pattern_xmstring = XmStringCreateLocalized ("*");
 
   XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
@@ -5435,12 +5399,12 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
 
       XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
       XmTextFieldReplace (wtext, 0, last_pos,
-                          (SDATA (Ffile_name_nondirectory (default_filename))));
+                          (SSDATA (Ffile_name_nondirectory (default_filename))));
 
       /* Select DEFAULT_FILENAME in the files list box.  DEFAULT_FILENAME
          must include the path for this to work.  */
 
-      default_xmstring = XmStringCreateLocalized (SDATA (default_filename));
+      default_xmstring = XmStringCreateLocalized (SSDATA (default_filename));
 
       if (XmListItemExists (list, default_xmstring))
         {
@@ -5491,7 +5455,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
   else
     file = Qnil;
 
-  UNBLOCK_INPUT;
+  unblock_input ();
   UNGCPRO;
 
   /* Make "Cancel" equivalent to C-g.  */
@@ -5521,7 +5485,7 @@ Use a file selection dialog.  Select DEFAULT-FILENAME in the dialog's file
 selection box, if specified.  If MUSTMATCH is non-nil, the returned file
 or directory must exist.
 
-This function is only defined on MS Windows, and X Windows with the
+This function is only defined on NS, MS Windows, and X Windows with the
 Motif or Gtk toolkits.  With the Motif toolkit, ONLY-DIR-P is ignored.
 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
@@ -5548,7 +5512,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
   specbind (Qinhibit_redisplay, Qt);
   record_unwind_protect (clean_up_dialog, Qnil);
 
-  BLOCK_INPUT;
+  block_input ();
 
   if (STRINGP (default_filename))
     cdef_file = SSDATA (default_filename);
@@ -5565,7 +5529,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
       xfree (fn);
     }
 
-  UNBLOCK_INPUT;
+  unblock_input ();
   UNGCPRO;
 
   /* Make "Cancel" equivalent to C-g.  */
@@ -5581,14 +5545,15 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
 #ifdef HAVE_FREETYPE
 
 DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
-       doc: /* Read a font name using a GTK font selection dialog.
-Return a GTK-style font string corresponding to the selection.
+       doc: /* Read a font using a GTK dialog.
+Return either a font spec (for GTK versions >= 3.2) or a string
+containing a GTK-style font name.
 
-If FRAME is omitted or nil, it defaults to the selected frame. */)
+FRAME is the frame on which to pop up the font chooser.  If omitted or
+nil, it defaults to the selected frame. */)
   (Lisp_Object frame, Lisp_Object ignored)
 {
   FRAME_PTR f = check_x_frame (frame);
-  char *name;
   Lisp_Object font;
   Lisp_Object font_param;
   char *default_name = NULL;
@@ -5604,7 +5569,7 @@ If FRAME is omitted or nil, it defaults to the selected frame. */)
   specbind (Qinhibit_redisplay, Qt);
   record_unwind_protect (clean_up_dialog, Qnil);
 
-  BLOCK_INPUT;
+  block_input ();
 
   GCPRO2 (font_param, font);
 
@@ -5619,33 +5584,10 @@ If FRAME is omitted or nil, it defaults to the selected frame. */)
         default_name = xstrdup (SSDATA (font_param));
     }
 
-  if (default_name == NULL && x_last_font_name != NULL)
-    default_name = xstrdup (x_last_font_name);
-
-  /* Convert fontconfig names to Gtk names, i.e. remove - before number */
-  if (default_name)
-    {
-      char *p = strrchr (default_name, '-');
-      if (p)
-        {
-          char *ep = p+1;
-          while (isdigit (*ep))
-            ++ep;
-          if (*ep == '\0') *p = ' ';
-        }
-    }
-
-  name = xg_get_font_name (f, default_name);
+  font = xg_get_font (f, default_name);
   xfree (default_name);
 
-  if (name)
-    {
-      font = build_string (name);
-      g_free (x_last_font_name);
-      x_last_font_name = name;
-    }
-
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   if (NILP (font))
     Fsignal (Qquit, Qnil);
@@ -5682,14 +5624,14 @@ present and mapped to the usual X keysyms.  */)
   Lisp_Object have_keys;
   int major, minor, op, event, error_code;
 
-  BLOCK_INPUT;
+  block_input ();
 
   /* Check library version in case we're dynamically linked.  */
   major = XkbMajorVersion;
   minor = XkbMinorVersion;
   if (!XkbLibraryVersion (&major, &minor))
     {
-      UNBLOCK_INPUT;
+      unblock_input ();
       return Qlambda;
     }
 
@@ -5698,7 +5640,7 @@ present and mapped to the usual X keysyms.  */)
   minor = XkbMinorVersion;
   if (!XkbQueryExtension (dpy, &op, &event, &error_code, &major, &minor))
     {
-      UNBLOCK_INPUT;
+      unblock_input ();
       return Qlambda;
     }
 
@@ -5751,7 +5693,7 @@ present and mapped to the usual X keysyms.  */)
          && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
        have_keys = Qt;
     }
-  UNBLOCK_INPUT;
+  unblock_input ();
   return have_keys;
 #else /* not HAVE_XKBGETKEYBOARD */
   return Qlambda;
@@ -5813,7 +5755,6 @@ syms_of_xfns (void)
   /* The section below is built by the lisp expression at the top of the file,
      just above where these variables are declared.  */
   /*&&& init symbols here &&&*/
-  DEFSYM (Qnone, "none");
   DEFSYM (Qsuppress_icon, "suppress-icon");
   DEFSYM (Qundefined_color, "undefined-color");
   DEFSYM (Qcompound_text, "compound-text");
@@ -5822,7 +5763,7 @@ syms_of_xfns (void)
   /* This is the end of symbol initialization.  */
 
   Fput (Qundefined_color, Qerror_conditions,
-       pure_cons (Qundefined_color, pure_cons (Qerror, Qnil)));
+       listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
   Fput (Qundefined_color, Qerror_message,
        build_pure_c_string ("Undefined color"));
 
@@ -6010,7 +5951,6 @@ When using Gtk+ tooltips, the tooltip face is not used.  */);
 
 #if defined (USE_GTK) && defined (HAVE_FREETYPE)
   defsubr (&Sx_select_font);
-  x_last_font_name = NULL;
 #endif
 }