]> code.delx.au - gnu-emacs/blobdiff - src/xfns.c
2002-08-10 Andrew Choi <akochoi@shaw.ca>
[gnu-emacs] / src / xfns.c
index f08dddaad6e4fe3511cc0288ddda9d3a694733bc..4f23af432c8c889cc83af0dc2301a2681b70da38 100644 (file)
@@ -24,6 +24,10 @@ Boston, MA 02111-1307, USA.  */
 #include <stdio.h>
 #include <math.h>
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 /* This makes the fields of a Display accessible, in Xlib header files.  */
 
 #define XLIB_ILLEGAL_ACCESS
@@ -181,7 +185,7 @@ Lisp_Object Vx_pixel_size_width_font_regexp;
 
 Lisp_Object Qauto_raise;
 Lisp_Object Qauto_lower;
-Lisp_Object Qbar;
+Lisp_Object Qbar, Qhbar;
 Lisp_Object Qborder_color;
 Lisp_Object Qborder_width;
 Lisp_Object Qbox;
@@ -215,6 +219,10 @@ Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
 Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
 Lisp_Object Qcompound_text, Qcancel_timer;
 Lisp_Object Qwait_for_wm;
+Lisp_Object Qfullscreen;
+Lisp_Object Qfullwidth;
+Lisp_Object Qfullheight;
+Lisp_Object Qfullboth;
 
 /* The below are defined in frame.c.  */
 
@@ -261,7 +269,7 @@ check_x_frame (frame)
 
   if (NILP (frame))
     frame = selected_frame;
-  CHECK_LIVE_FRAME (frame, 0);
+  CHECK_LIVE_FRAME (frame);
   f = XFRAME (frame);
   if (! FRAME_X_P (f))
     error ("Non-X frame used");
@@ -293,12 +301,7 @@ check_x_display_info (frame)
     dpyinfo = x_display_info_for_name (frame);
   else
     {
-      FRAME_PTR f;
-
-      CHECK_LIVE_FRAME (frame, 0);
-      f = XFRAME (frame);
-      if (! FRAME_X_P (f))
-       error ("Non-X frame used");
+      FRAME_PTR f = check_x_frame (frame);
       dpyinfo = FRAME_X_DISPLAY_INFO (f);
     }
 
@@ -633,7 +636,7 @@ x_create_bitmap_from_file (f, file)
     {
       if (dpyinfo->bitmaps[id].refcount
          && dpyinfo->bitmaps[id].file
-         && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
+         && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
        {
          ++dpyinfo->bitmaps[id].refcount;
          return id + 1;
@@ -641,12 +644,12 @@ x_create_bitmap_from_file (f, file)
     }
 
   /* Search bitmap-file-path for the file, if appropriate.  */
-  fd = openp (Vx_bitmap_file_path, file, Qnil, &found, 0);
+  fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
   if (fd < 0)
     return -1;
   emacs_close (fd);
 
-  filename = (char *) XSTRING (found)->data;
+  filename = (char *) SDATA (found);
 
   result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                            filename, &width, &height, &bitmap, &xhot, &yhot);
@@ -657,11 +660,11 @@ x_create_bitmap_from_file (f, file)
   dpyinfo->bitmaps[id - 1].pixmap = bitmap;
   dpyinfo->bitmaps[id - 1].refcount = 1;
   dpyinfo->bitmaps[id - 1].file
-    = (char *) xmalloc (STRING_BYTES (XSTRING (file)) + 1);
+    = (char *) xmalloc (SBYTES (file) + 1);
   dpyinfo->bitmaps[id - 1].depth = 1;
   dpyinfo->bitmaps[id - 1].height = height;
   dpyinfo->bitmaps[id - 1].width = width;
-  strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
+  strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
 
   return id;
 }
@@ -729,6 +732,7 @@ static void x_disable_image P_ ((struct frame *, struct image *));
 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
+static void x_set_fullscreen P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
@@ -736,6 +740,7 @@ void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
+static void x_set_fringe_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
@@ -773,32 +778,36 @@ static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
 
 static struct x_frame_parm_table x_frame_parms[] =
 {
-  "auto-raise",                        x_set_autoraise,
-  "auto-lower",                        x_set_autolower,
-  "background-color",          x_set_background_color,
-  "border-color",              x_set_border_color,
-  "border-width",              x_set_border_width,
-  "cursor-color",              x_set_cursor_color,
-  "cursor-type",               x_set_cursor_type,
-  "font",                      x_set_font,
-  "foreground-color",          x_set_foreground_color,
-  "icon-name",                 x_set_icon_name,
-  "icon-type",                 x_set_icon_type,
-  "internal-border-width",     x_set_internal_border_width,
-  "menu-bar-lines",            x_set_menu_bar_lines,
-  "mouse-color",               x_set_mouse_color,
-  "name",                      x_explicitly_set_name,
-  "scroll-bar-width",          x_set_scroll_bar_width,
-  "title",                     x_set_title,
-  "unsplittable",              x_set_unsplittable,
-  "vertical-scroll-bars",      x_set_vertical_scroll_bars,
-  "visibility",                        x_set_visibility,
-  "tool-bar-lines",            x_set_tool_bar_lines,
-  "scroll-bar-foreground",     x_set_scroll_bar_foreground,
-  "scroll-bar-background",     x_set_scroll_bar_background,
-  "screen-gamma",              x_set_screen_gamma,
-  "line-spacing",              x_set_line_spacing,
-  "wait-for-wm",               x_set_wait_for_wm
+  {"auto-raise",               x_set_autoraise},
+  {"auto-lower",               x_set_autolower},
+  {"background-color",         x_set_background_color},
+  {"border-color",             x_set_border_color},
+  {"border-width",             x_set_border_width},
+  {"cursor-color",             x_set_cursor_color},
+  {"cursor-type",              x_set_cursor_type},
+  {"font",                     x_set_font},
+  {"foreground-color",         x_set_foreground_color},
+  {"icon-name",                        x_set_icon_name},
+  {"icon-type",                        x_set_icon_type},
+  {"internal-border-width",    x_set_internal_border_width},
+  {"menu-bar-lines",           x_set_menu_bar_lines},
+  {"mouse-color",              x_set_mouse_color},
+  {"name",                     x_explicitly_set_name},
+  {"scroll-bar-width",         x_set_scroll_bar_width},
+  {"title",                    x_set_title},
+  {"unsplittable",             x_set_unsplittable},
+  {"vertical-scroll-bars",     x_set_vertical_scroll_bars},
+  {"visibility",               x_set_visibility},
+  {"tool-bar-lines",           x_set_tool_bar_lines},
+  {"scroll-bar-foreground",    x_set_scroll_bar_foreground},
+  {"scroll-bar-background",    x_set_scroll_bar_background},
+  {"screen-gamma",             x_set_screen_gamma},
+  {"line-spacing",             x_set_line_spacing},
+  {"left-fringe",              x_set_fringe_width},
+  {"right-fringe",             x_set_fringe_width},
+  {"wait-for-wm",              x_set_wait_for_wm},
+  {"fullscreen",                x_set_fullscreen},
+  
 };
 
 /* Attach the `x-frame-parameter' properties to
@@ -814,6 +823,28 @@ init_x_parm_symbols ()
          make_number (i));
 }
 \f
+
+/* Really try to move where we want to be in case of fullscreen.  Some WMs
+   moves the window where we tell them.  Some (mwm, twm) moves the outer
+   window manager window there instead.
+   Try to compensate for those WM here. */
+static void
+x_fullscreen_move (f, new_top, new_left)
+     struct frame *f;
+     int new_top;
+     int new_left;
+{
+  if (new_top != f->output_data.x->top_pos
+      || new_left != f->output_data.x->left_pos)
+    {
+      int move_x = new_left + f->output_data.x->x_pixels_outer_diff;
+      int move_y = new_top + f->output_data.x->y_pixels_outer_diff;
+
+      f->output_data.x->want_fullscreen |= FULLSCREEN_MOVE_WAIT;
+      x_set_offset (f, move_x, move_y, 1);
+    }
+}
+
 /* Change the parameters of frame F as specified by ALIST.
    If a parameter is not specially recognized, do nothing special;
    otherwise call the `x_set_...' function for that parameter.
@@ -844,6 +875,7 @@ x_set_frame_parameters (f, alist)
   int i, p;
   int left_no_change = 0, top_no_change = 0;
   int icon_left_no_change = 0, icon_top_no_change = 0;
+  int fullscreen_is_being_set = 0;
 
   struct gcpro gcpro1, gcpro2;
 
@@ -892,23 +924,34 @@ x_set_frame_parameters (f, alist)
   /* Process foreground_color and background_color before anything else.
      They are independent of other properties, but other properties (e.g.,
      cursor_color) are dependent upon them.  */
+  /* Process default font as well, since fringe widths depends on it.  */
+  /* Also, process fullscreen, width and height depend upon that */
   for (p = 0; p < i; p++) 
     {
       Lisp_Object prop, val;
 
       prop = parms[p];
       val = values[p];
-      if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
+      if (EQ (prop, Qforeground_color)
+         || EQ (prop, Qbackground_color)
+         || EQ (prop, Qfont)
+          || EQ (prop, Qfullscreen))
        {
          register Lisp_Object param_index, old_value;
 
-         param_index = Fget (prop, Qx_frame_parameter);
          old_value = get_frame_param (f, prop);
-         store_frame_param (f, prop, val);
-         if (NATNUMP (param_index)
-             && (XFASTINT (param_index)
-                 < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
-           (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
+         fullscreen_is_being_set |= EQ (prop, Qfullscreen);
+         
+         if (NILP (Fequal (val, old_value)))
+           {
+             store_frame_param (f, prop, val);
+
+             param_index = Fget (prop, Qx_frame_parameter);
+             if (NATNUMP (param_index)
+                 && (XFASTINT (param_index)
+                     < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
+               (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
+           }
        }
     }
 
@@ -932,17 +975,22 @@ x_set_frame_parameters (f, alist)
        icon_top = val;
       else if (EQ (prop, Qicon_left))
        icon_left = val;
-      else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
+      else if (EQ (prop, Qforeground_color)
+              || EQ (prop, Qbackground_color)
+              || EQ (prop, Qfont)
+               || EQ (prop, Qfullscreen))
        /* Processed above.  */
        continue;
       else
        {
          register Lisp_Object param_index, old_value;
 
-         param_index = Fget (prop, Qx_frame_parameter);
          old_value = get_frame_param (f, prop);
+
          store_frame_param (f, prop, val);
-         if (NATNUMP (param_index)
+
+         param_index = Fget (prop, Qx_frame_parameter);
+         if (NATNUMP (param_index)
              && (XFASTINT (param_index)
                  < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
            (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
@@ -983,6 +1031,21 @@ x_set_frame_parameters (f, alist)
        XSETINT (icon_top, 0);
     }
 
+  if (FRAME_VISIBLE_P (f) && fullscreen_is_being_set)
+    {
+      /* If the frame is visible already and the fullscreen parameter is
+         being set, it is too late to set WM manager hints to specify
+         size and position.
+         Here we first get the width, height and position that applies to
+         fullscreen.  We then move the frame to the appropriate
+         position.  Resize of the frame is taken care of in the code after
+         this if-statement. */
+      int new_left, new_top;
+      
+      x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
+      x_fullscreen_move (f, new_top, new_left);
+    }
+  
   /* Don't set these parameters unless they've been explicitly
      specified.  The window might be mapped or resized while we're in
      this function, and we don't want to override that unless the lisp
@@ -1085,70 +1148,115 @@ x_real_positions (f, xptr, yptr)
      FRAME_PTR f;
      int *xptr, *yptr;
 {
-  int win_x, win_y;
-  Window child;
+  int win_x, win_y, outer_x, outer_y;
+  int real_x = 0, real_y = 0;
+  int had_errors = 0;
+  Window win = f->output_data.x->parent_desc;
 
-  /* This is pretty gross, but seems to be the easiest way out of
-     the problem that arises when restarting window-managers.  */
+  int count;
 
-#ifdef USE_X_TOOLKIT
-  Window outer = (f->output_data.x->widget
-                 ? XtWindow (f->output_data.x->widget)
-                 : FRAME_X_WINDOW (f));
-#else
-  Window outer = f->output_data.x->window_desc;
-#endif
-  Window tmp_root_window;
-  Window *tmp_children;
-  unsigned int tmp_nchildren;
+  BLOCK_INPUT;
+
+  count = x_catch_errors (FRAME_X_DISPLAY (f));
+
+  if (win == FRAME_X_DISPLAY_INFO (f)->root_window)
+    win = FRAME_OUTER_WINDOW (f);
 
-  while (1)
+  /* This loop traverses up the containment tree until we hit the root
+     window.  Window managers may intersect many windows between our window
+     and the root window.  The window we find just before the root window
+     should be the outer WM window. */
+  for (;;)
     {
-      int count = x_catch_errors (FRAME_X_DISPLAY (f));
-      Window outer_window;
+      Window wm_window, rootw;
+      Window *tmp_children;
+      unsigned int tmp_nchildren;
+      int success;
 
-      XQueryTree (FRAME_X_DISPLAY (f), outer, &tmp_root_window,
-                 &f->output_data.x->parent_desc,
-                 &tmp_children, &tmp_nchildren);
-      XFree ((char *) tmp_children);
+      success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
+                           &wm_window, &tmp_children, &tmp_nchildren);
 
-      win_x = win_y = 0;
+      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
 
-      /* Find the position of the outside upper-left corner of
-        the inner window, with respect to the outer window.  */
-      if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
-       outer_window = f->output_data.x->parent_desc;
-      else
-       outer_window = outer;
+      /* Don't free tmp_children if XQueryTree failed.  */
+      if (! success)
+       break;
 
+      XFree ((char *) tmp_children);
+
+      if (wm_window == rootw || had_errors)
+        break;
+
+      win = wm_window;
+    }
+    
+  if (! had_errors)
+    {
+      int ign;
+      Window child, rootw;
+          
+      /* Get the real coordinates for the WM window upper left corner */
+      XGetGeometry (FRAME_X_DISPLAY (f), win,
+                    &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);
+
+      /* Translate real coordinates to coordinates relative to our
+         window.  For our window, the upper left corner is 0, 0.
+         Since the upper left corner of the WM window is outside
+         our window, win_x and win_y will be negative:
+
+         ------------------          ---> x
+         |      title                |
+         | -----------------         v y
+         | |  our window
+      */
       XTranslateCoordinates (FRAME_X_DISPLAY (f),
 
                             /* From-window, to-window.  */
-                            outer_window,
                             FRAME_X_DISPLAY_INFO (f)->root_window,
+                             FRAME_X_WINDOW (f),
 
                             /* From-position, to-position.  */
-                            0, 0, &win_x, &win_y,
+                             real_x, real_y, &win_x, &win_y,
 
                             /* Child of win.  */
                             &child);
 
-      /* It is possible for the window returned by the XQueryNotify
-        to become invalid by the time we call XTranslateCoordinates.
-        That can happen when you restart some window managers.
-        If so, we get an error in XTranslateCoordinates.
-        Detect that and try the whole thing over.  */
-      if (! x_had_errors_p (FRAME_X_DISPLAY (f)))
+      if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
        {
-         x_uncatch_errors (FRAME_X_DISPLAY (f), count);
-         break;
+          outer_x = win_x;
+          outer_y = win_y;
        }
+      else
+        {
+          XTranslateCoordinates (FRAME_X_DISPLAY (f),
 
-      x_uncatch_errors (FRAME_X_DISPLAY (f), count);
+                                 /* From-window, to-window.  */
+                                 FRAME_X_DISPLAY_INFO (f)->root_window,
+                                 FRAME_OUTER_WINDOW (f),
+                                     
+                                 /* From-position, to-position.  */
+                                 real_x, real_y, &outer_x, &outer_y,
+                         
+                                 /* Child of win.  */
+                                 &child);
     }
 
-  *xptr = win_x;
-  *yptr = win_y;
+      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
+    }
+      
+  x_uncatch_errors (FRAME_X_DISPLAY (f), count);
+      
+  UNBLOCK_INPUT;
+
+  if (had_errors) return;
+      
+  f->output_data.x->x_pixels_diff = -win_x;
+  f->output_data.x->y_pixels_diff = -win_y;
+  f->output_data.x->x_pixels_outer_diff = -outer_x;
+  f->output_data.x->y_pixels_outer_diff = -outer_y;
+
+  *xptr = real_x;
+  *yptr = real_y;
 }
 
 /* Insert a description of internally-recorded parameters of frame X
@@ -1183,6 +1291,14 @@ x_report_frame_params (f, alistptr)
                   make_number (f->output_data.x->border_width));
   store_in_alist (alistptr, Qinternal_border_width,
                   make_number (f->output_data.x->internal_border_width));
+  store_in_alist (alistptr, Qleft_fringe,
+                  make_number (f->output_data.x->left_fringe_width));
+  store_in_alist (alistptr, Qright_fringe,
+                  make_number (f->output_data.x->right_fringe_width));
+  store_in_alist (alistptr, Qscroll_bar_width,
+           make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+                        ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f)
+                        : 0));
   sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
   store_in_alist (alistptr, Qwindow_id,
                   build_string (buf));
@@ -1264,14 +1380,14 @@ x_decode_color (f, color_name, mono_color)
 {
   XColor cdef;
 
-  CHECK_STRING (color_name, 0);
+  CHECK_STRING (color_name);
 
 #if 0 /* Don't do this.  It's wrong when we're not using the default
         colormap, it makes freeing difficult, and it's probably not
         an important optimization.  */
-  if (strcmp (XSTRING (color_name)->data, "black") == 0)
+  if (strcmp (SDATA (color_name), "black") == 0)
     return BLACK_PIX_DEFAULT (f);
-  else if (strcmp (XSTRING (color_name)->data, "white") == 0)
+  else if (strcmp (SDATA (color_name), "white") == 0)
     return WHITE_PIX_DEFAULT (f);
 #endif
 
@@ -1281,7 +1397,7 @@ x_decode_color (f, color_name, mono_color)
 
   /* x_defined_color is responsible for coping with failures
      by looking for a near-miss.  */
-  if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
+  if (x_defined_color (f, SDATA (color_name), &cdef, 1))
     return cdef.pixel;
 
   Fsignal (Qerror, Fcons (build_string ("Undefined color"),
@@ -1324,6 +1440,25 @@ x_set_wait_for_wm (f, new_value, old_value)
 }
 
 
+/* Change the `fullscreen' frame parameter of frame F.  OLD_VALUE is
+   the previous value of that parameter, NEW_VALUE is the new value. */
+
+static void
+x_set_fullscreen (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  if (NILP (new_value))
+    f->output_data.x->want_fullscreen = FULLSCREEN_NONE;
+  else if (EQ (new_value, Qfullboth))
+    f->output_data.x->want_fullscreen = FULLSCREEN_BOTH;
+  else if (EQ (new_value, Qfullwidth))
+    f->output_data.x->want_fullscreen = FULLSCREEN_WIDTH;
+  else if (EQ (new_value, Qfullheight))
+    f->output_data.x->want_fullscreen = FULLSCREEN_HEIGHT;
+}
+
+
 /* Change the `screen-gamma' frame parameter of frame F.  OLD_VALUE is
    the previous value of that parameter, NEW_VALUE is the new
    value.  */
@@ -1466,7 +1601,7 @@ x_set_mouse_color (f, arg, oldval)
 
   if (!NILP (Vx_pointer_shape))
     {
-      CHECK_NUMBER (Vx_pointer_shape, 0);
+      CHECK_NUMBER (Vx_pointer_shape);
       cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
     }
   else
@@ -1475,7 +1610,7 @@ x_set_mouse_color (f, arg, oldval)
 
   if (!NILP (Vx_nontext_pointer_shape))
     {
-      CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
+      CHECK_NUMBER (Vx_nontext_pointer_shape);
       nontext_cursor
        = XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
     }
@@ -1485,7 +1620,7 @@ x_set_mouse_color (f, arg, oldval)
 
   if (!NILP (Vx_hourglass_pointer_shape))
     {
-      CHECK_NUMBER (Vx_hourglass_pointer_shape, 0);
+      CHECK_NUMBER (Vx_hourglass_pointer_shape);
       hourglass_cursor
        = XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
     }
@@ -1496,7 +1631,7 @@ x_set_mouse_color (f, arg, oldval)
   x_check_errors (dpy, "bad nontext pointer cursor: %s");
   if (!NILP (Vx_mode_pointer_shape))
     {
-      CHECK_NUMBER (Vx_mode_pointer_shape, 0);
+      CHECK_NUMBER (Vx_mode_pointer_shape);
       mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
     }
   else
@@ -1505,16 +1640,16 @@ x_set_mouse_color (f, arg, oldval)
 
   if (!NILP (Vx_sensitive_text_pointer_shape))
     {
-      CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
+      CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
       cross_cursor
        = XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
     }
   else
-    cross_cursor = XCreateFontCursor (dpy, XC_crosshair);
+    cross_cursor = XCreateFontCursor (dpy, XC_hand2);
 
   if (!NILP (Vx_window_horizontal_drag_shape))
     {
-      CHECK_NUMBER (Vx_window_horizontal_drag_shape, 0);
+      CHECK_NUMBER (Vx_window_horizontal_drag_shape);
       horizontal_drag_cursor
        = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
     }
@@ -1668,7 +1803,7 @@ x_set_border_color (f, arg, oldval)
 {
   int pix;
 
-  CHECK_STRING (arg, 0);
+  CHECK_STRING (arg);
   pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
   x_set_border_pixel (f, pix);
   update_face_from_frame_parameter (f, Qborder_color, arg);
@@ -1723,6 +1858,19 @@ x_specified_cursor_type (arg, width)
       type = BAR_CURSOR;
       *width = XINT (XCDR (arg));
     }
+  else if (EQ (arg, Qhbar))
+    {
+      type = HBAR_CURSOR;
+      *width = 2;
+    }
+  else if (CONSP (arg)
+          && EQ (XCAR (arg), Qhbar)
+          && INTEGERP (XCDR (arg))
+          && XINT (XCDR (arg)) >= 0)
+    {
+      type = HBAR_CURSOR;
+      *width = XINT (XCDR (arg));
+    }
   else if (NILP (arg))
     type = NO_CURSOR;
   else
@@ -1744,9 +1892,8 @@ x_set_cursor_type (f, arg, oldval)
   FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
   f->output_data.x->cursor_width = width;
 
-  /* Make sure the cursor gets redrawn.  This is overkill, but how
-     often do people change cursor types?  */
-  update_mode_lines++;
+  /* Make sure the cursor gets redrawn.  */
+  cursor_type_changed = 1;
 }
 \f
 void
@@ -1767,9 +1914,9 @@ x_set_icon_type (f, arg, oldval)
   BLOCK_INPUT;
   if (NILP (arg))
     result = x_text_icon (f,
-                         (char *) XSTRING ((!NILP (f->icon_name)
+                         (char *) SDATA ((!NILP (f->icon_name)
                                             ? f->icon_name
-                                            : f->name))->data);
+                                            : f->name)));
   else
     result = x_bitmap_icon (f, arg);
 
@@ -1821,11 +1968,11 @@ x_set_icon_name (f, arg, oldval)
   BLOCK_INPUT;
 
   result = x_text_icon (f,
-                       (char *) XSTRING ((!NILP (f->icon_name)
-                                          ? f->icon_name
-                                          : !NILP (f->title)
-                                          ? f->title
-                                          : f->name))->data);
+                       (char *) SDATA ((!NILP (f->icon_name)
+                                        ? f->icon_name
+                                        : !NILP (f->title)
+                                        ? f->title
+                                        : f->name)));
 
   if (result)
     {
@@ -1847,18 +1994,18 @@ x_set_font (f, arg, oldval)
   Lisp_Object frame;
   int old_fontset = f->output_data.x->fontset;
 
-  CHECK_STRING (arg, 1);
+  CHECK_STRING (arg);
 
   fontset_name = Fquery_fontset (arg, Qnil);
 
   BLOCK_INPUT;
   result = (STRINGP (fontset_name)
-           ? x_new_fontset (f, XSTRING (fontset_name)->data)
-           : x_new_font (f, XSTRING (arg)->data));
+           ? x_new_fontset (f, SDATA (fontset_name))
+           : x_new_font (f, SDATA (arg)));
   UNBLOCK_INPUT;
   
   if (EQ (result, Qnil))
-    error ("Font `%s' is not defined", XSTRING (arg)->data);
+    error ("Font `%s' is not defined", SDATA (arg));
   else if (EQ (result, Qt))
     error ("The characters of the given font have varying widths");
   else if (STRINGP (result))
@@ -1893,12 +2040,20 @@ x_set_font (f, arg, oldval)
     }
 }
 
+static void
+x_set_fringe_width (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  x_compute_fringe_widths (f, 1);
+}
+
 void
 x_set_border_width (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  CHECK_NUMBER (arg, 0);
+  CHECK_NUMBER (arg);
 
   if (XINT (arg) == f->output_data.x->border_width)
     return;
@@ -1916,7 +2071,7 @@ x_set_internal_border_width (f, arg, oldval)
 {
   int old = f->output_data.x->internal_border_width;
 
-  CHECK_NUMBER (arg, 0);
+  CHECK_NUMBER (arg);
   f->output_data.x->internal_border_width = XINT (arg);
   if (f->output_data.x->internal_border_width < 0)
     f->output_data.x->internal_border_width = 0;
@@ -1935,6 +2090,8 @@ x_set_internal_border_width (f, arg, oldval)
       SET_FRAME_GARBAGED (f);
       do_pending_window_change (0);
     }
+  else
+    SET_FRAME_GARBAGED (f);
 }
 
 void
@@ -2201,6 +2358,10 @@ x_set_scroll_bar_background (f, value, oldval)
    CODING_SYSTEM, and return a newly allocated memory area which
    should be freed by `xfree' by a caller.
 
+   SELECTIONP non-zero means the string is being encoded for an X
+   selection, so it is safe to run pre-write conversions (which
+   may run Lisp code).
+
    Store the byte length of resulting text in *TEXT_BYTES.
 
    If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
@@ -2209,17 +2370,19 @@ x_set_scroll_bar_background (f, value, oldval)
    the result should be `COMPOUND_TEXT'.  */
 
 unsigned char *
-x_encode_text (string, coding_system, text_bytes, stringp)
+x_encode_text (string, coding_system, selectionp, text_bytes, stringp)
      Lisp_Object string, coding_system;
      int *text_bytes, *stringp;
+     int selectionp;
 {
-  unsigned char *str = XSTRING (string)->data;
-  int chars = XSTRING (string)->size;
-  int bytes = STRING_BYTES (XSTRING (string));
+  unsigned char *str = SDATA (string);
+  int chars = SCHARS (string);
+  int bytes = SBYTES (string);
   int charset_info;
   int bufsize;
   unsigned char *buf;
   struct coding_system coding;
+  extern Lisp_Object Qcompound_text_with_extensions;
 
   charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
   if (charset_info == 0)
@@ -2231,6 +2394,15 @@ x_encode_text (string, coding_system, text_bytes, stringp)
     }
 
   setup_coding_system (coding_system, &coding);
+  if (selectionp
+      && SYMBOLP (coding.pre_write_conversion)
+      && !NILP (Ffboundp (coding.pre_write_conversion)))
+    {
+      string = run_pre_post_conversion_on_str (string, &coding, 1);
+      str = SDATA (string);
+      chars = SCHARS (string);
+      bytes = SBYTES (string);
+    }
   coding.src_multibyte = 1;
   coding.dst_multibyte = 0;
   coding.mode |= CODING_MODE_LAST_BLOCK;
@@ -2242,7 +2414,9 @@ x_encode_text (string, coding_system, text_bytes, stringp)
   buf = (unsigned char *) xmalloc (bufsize);
   encode_coding (&coding, str, buf, bytes, bufsize);
   *text_bytes = coding.produced;
-  *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text));
+  *stringp = (charset_info == 1
+             || (!EQ (coding_system, Qcompound_text)
+                 && !EQ (coding_system, Qcompound_text_with_extensions)));
   return buf;
 }
 
@@ -2284,12 +2458,12 @@ x_set_name (f, name, explicit)
       /* Check for no change needed in this very common case
         before we do any consing.  */
       if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
-                  XSTRING (f->name)->data))
+                  SDATA (f->name)))
        return;
       name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
     }
   else
-    CHECK_STRING (name, 0);
+    CHECK_STRING (name);
 
   /* Don't change the name if it's already NAME.  */
   if (! NILP (Fstring_equal (name, f->name)))
@@ -2314,7 +2488,7 @@ x_set_name (f, name, explicit)
        coding_system = Vlocale_coding_system;
        if (NILP (coding_system))
          coding_system = Qcompound_text;
-       text.value = x_encode_text (name, coding_system, &bytes, &stringp);
+       text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
        text.encoding = (stringp ? XA_STRING
                         : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
        text.format = 8;
@@ -2326,7 +2500,7 @@ x_set_name (f, name, explicit)
          }
        else
          {
-           icon.value = x_encode_text (f->icon_name, coding_system,
+           icon.value = x_encode_text (f->icon_name, coding_system, 0,
                                        &bytes, &stringp);
            icon.encoding = (stringp ? XA_STRING
                             : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
@@ -2343,16 +2517,16 @@ x_set_name (f, name, explicit)
        XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
 #endif /* not USE_X_TOOLKIT */
        if (!NILP (f->icon_name)
-           && icon.value != XSTRING (f->icon_name)->data)
+           && icon.value != SDATA (f->icon_name))
          xfree (icon.value);
-       if (text.value != XSTRING (name)->data)
+       if (text.value != SDATA (name))
          xfree (text.value);
       }
 #else /* not HAVE_X11R4 */
       XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   XSTRING (name)->data);
+                   SDATA (name));
       XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 XSTRING (name)->data);
+                 SDATA (name));
 #endif /* not HAVE_X11R4 */
       UNBLOCK_INPUT;
     }
@@ -2407,7 +2581,7 @@ x_set_title (f, name, old_name)
   if (NILP (name))
     name = f->name;
   else
-    CHECK_STRING (name, 0);
+    CHECK_STRING (name);
 
   if (FRAME_X_WINDOW (f))
     {
@@ -2421,7 +2595,7 @@ x_set_title (f, name, old_name)
        coding_system = Vlocale_coding_system;
        if (NILP (coding_system))
          coding_system = Qcompound_text;
-       text.value = x_encode_text (name, coding_system, &bytes, &stringp);
+       text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
        text.encoding = (stringp ? XA_STRING
                         : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
        text.format = 8;
@@ -2433,7 +2607,7 @@ x_set_title (f, name, old_name)
          }
        else
          {
-           icon.value = x_encode_text (f->icon_name, coding_system,
+           icon.value = x_encode_text (f->icon_name, coding_system, 0,
                                        &bytes, &stringp);
            icon.encoding = (stringp ? XA_STRING
                             : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
@@ -2450,16 +2624,16 @@ x_set_title (f, name, old_name)
        XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
 #endif /* not USE_X_TOOLKIT */
        if (!NILP (f->icon_name)
-           && icon.value != XSTRING (f->icon_name)->data)
+           && icon.value != SDATA (f->icon_name))
          xfree (icon.value);
-       if (text.value != XSTRING (name)->data)
+       if (text.value != SDATA (name))
          xfree (text.value);
       }
 #else /* not HAVE_X11R4 */
       XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   XSTRING (name)->data);
+                   SDATA (name));
       XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 XSTRING (name)->data);
+                 SDATA (name));
 #endif /* not HAVE_X11R4 */
       UNBLOCK_INPUT;
     }
@@ -2584,10 +2758,10 @@ validate_x_resource_name ()
 
   if (STRINGP (Vx_resource_name))
     {
-      unsigned char *p = XSTRING (Vx_resource_name)->data;
+      unsigned char *p = SDATA (Vx_resource_name);
       int i;
 
-      len = STRING_BYTES (XSTRING (Vx_resource_name));
+      len = SBYTES (Vx_resource_name);
 
       /* Only letters, digits, - and _ are valid in resource names.
         Count the valid characters and count the invalid ones.  */
@@ -2626,12 +2800,12 @@ validate_x_resource_name ()
 
   for (i = 0; i < len; i++)
     {
-      int c = XSTRING (new)->data[i];
+      int c = SREF (new, i);
       if (! ((c >= 'a' && c <= 'z')
             || (c >= 'A' && c <= 'Z')
             || (c >= '0' && c <= '9')
             || c == '-' || c == '_'))
-       XSTRING (new)->data[i] = '_';
+       SSET (new, i, '_');
     }
 }
 
@@ -2639,16 +2813,16 @@ validate_x_resource_name ()
 extern char *x_get_string_resource ();
 
 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
-  "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
-This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
-class, where INSTANCE is the name under which Emacs was invoked, or\n\
-the name specified by the `-name' or `-rn' command-line arguments.\n\
-\n\
-The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
-class, respectively.  You must specify both of them or neither.\n\
-If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
-and the class is `Emacs.CLASS.SUBCLASS'.")
-  (attribute, class, component, subclass)
+       doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
+This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
+class, where INSTANCE is the name under which Emacs was invoked, or
+the name specified by the `-name' or `-rn' command-line arguments.
+
+The optional arguments COMPONENT and SUBCLASS add to the key and the
+class, respectively.  You must specify both of them or neither.
+If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
+and the class is `Emacs.CLASS.SUBCLASS'.  */)
+     (attribute, class, component, subclass)
      Lisp_Object attribute, class, component, subclass;
 {
   register char *value;
@@ -2657,13 +2831,13 @@ and the class is `Emacs.CLASS.SUBCLASS'.")
 
   check_x ();
 
-  CHECK_STRING (attribute, 0);
-  CHECK_STRING (class, 0);
+  CHECK_STRING (attribute);
+  CHECK_STRING (class);
 
   if (!NILP (component))
-    CHECK_STRING (component, 1);
+    CHECK_STRING (component);
   if (!NILP (subclass))
-    CHECK_STRING (subclass, 2);
+    CHECK_STRING (subclass);
   if (NILP (component) != NILP (subclass))
     error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
 
@@ -2671,37 +2845,37 @@ and the class is `Emacs.CLASS.SUBCLASS'.")
 
   /* Allocate space for the components, the dots which separate them,
      and the final '\0'.  Make them big enough for the worst case.  */
-  name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
+  name_key = (char *) alloca (SBYTES (Vx_resource_name)
                              + (STRINGP (component)
-                                ? STRING_BYTES (XSTRING (component)) : 0)
-                             + STRING_BYTES (XSTRING (attribute))
+                                ? SBYTES (component) : 0)
+                             + SBYTES (attribute)
                              + 3);
 
-  class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
-                              + STRING_BYTES (XSTRING (class))
+  class_key = (char *) alloca (SBYTES (Vx_resource_class)
+                              + SBYTES (class)
                               + (STRINGP (subclass)
-                                 ? STRING_BYTES (XSTRING (subclass)) : 0)
+                                 ? SBYTES (subclass) : 0)
                               + 3);
 
   /* Start with emacs.FRAMENAME for the name (the specific one)
      and with `Emacs' for the class key (the general one).  */
-  strcpy (name_key, XSTRING (Vx_resource_name)->data);
-  strcpy (class_key, XSTRING (Vx_resource_class)->data);
+  strcpy (name_key, SDATA (Vx_resource_name));
+  strcpy (class_key, SDATA (Vx_resource_class));
 
   strcat (class_key, ".");
-  strcat (class_key, XSTRING (class)->data);
+  strcat (class_key, SDATA (class));
 
   if (!NILP (component))
     {
       strcat (class_key, ".");
-      strcat (class_key, XSTRING (subclass)->data);
+      strcat (class_key, SDATA (subclass));
 
       strcat (name_key, ".");
-      strcat (name_key, XSTRING (component)->data);
+      strcat (name_key, SDATA (component));
     }
 
   strcat (name_key, ".");
-  strcat (name_key, XSTRING (attribute)->data);
+  strcat (name_key, SDATA (attribute));
 
   value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
                                 name_key, class_key);
@@ -2723,13 +2897,13 @@ display_x_get_resource (dpyinfo, attribute, class, component, subclass)
   char *name_key;
   char *class_key;
 
-  CHECK_STRING (attribute, 0);
-  CHECK_STRING (class, 0);
+  CHECK_STRING (attribute);
+  CHECK_STRING (class);
 
   if (!NILP (component))
-    CHECK_STRING (component, 1);
+    CHECK_STRING (component);
   if (!NILP (subclass))
-    CHECK_STRING (subclass, 2);
+    CHECK_STRING (subclass);
   if (NILP (component) != NILP (subclass))
     error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
 
@@ -2737,37 +2911,37 @@ display_x_get_resource (dpyinfo, attribute, class, component, subclass)
 
   /* Allocate space for the components, the dots which separate them,
      and the final '\0'.  Make them big enough for the worst case.  */
-  name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
+  name_key = (char *) alloca (SBYTES (Vx_resource_name)
                              + (STRINGP (component)
-                                ? STRING_BYTES (XSTRING (component)) : 0)
-                             + STRING_BYTES (XSTRING (attribute))
+                                ? SBYTES (component) : 0)
+                             + SBYTES (attribute)
                              + 3);
 
-  class_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_class))
-                              + STRING_BYTES (XSTRING (class))
+  class_key = (char *) alloca (SBYTES (Vx_resource_class)
+                              + SBYTES (class)
                               + (STRINGP (subclass)
-                                 ? STRING_BYTES (XSTRING (subclass)) : 0)
+                                 ? SBYTES (subclass) : 0)
                               + 3);
 
   /* Start with emacs.FRAMENAME for the name (the specific one)
      and with `Emacs' for the class key (the general one).  */
-  strcpy (name_key, XSTRING (Vx_resource_name)->data);
-  strcpy (class_key, XSTRING (Vx_resource_class)->data);
+  strcpy (name_key, SDATA (Vx_resource_name));
+  strcpy (class_key, SDATA (Vx_resource_class));
 
   strcat (class_key, ".");
-  strcat (class_key, XSTRING (class)->data);
+  strcat (class_key, SDATA (class));
 
   if (!NILP (component))
     {
       strcat (class_key, ".");
-      strcat (class_key, XSTRING (subclass)->data);
+      strcat (class_key, SDATA (subclass));
 
       strcat (name_key, ".");
-      strcat (name_key, XSTRING (component)->data);
+      strcat (name_key, SDATA (component));
     }
 
   strcat (name_key, ".");
-  strcat (name_key, XSTRING (attribute)->data);
+  strcat (name_key, SDATA (attribute));
 
   value = x_get_string_resource (dpyinfo->xrdb, name_key, class_key);
 
@@ -2789,13 +2963,13 @@ x_get_resource_string (attribute, class)
 
   /* Allocate space for the components, the dots which separate them,
      and the final '\0'.  */
-  name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
+  name_key = (char *) alloca (SBYTES (Vinvocation_name)
                              + strlen (attribute) + 2);
   class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
                               + strlen (class) + 2);
 
   sprintf (name_key, "%s.%s",
-          XSTRING (Vinvocation_name)->data,
+          SDATA (Vinvocation_name),
           attribute);
   sprintf (class_key, "%s.%s", EMACS_CLASS, class);
 
@@ -2853,15 +3027,15 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
          switch (type)
            {
            case RES_TYPE_NUMBER:
-             return make_number (atoi (XSTRING (tem)->data));
+             return make_number (atoi (SDATA (tem)));
 
            case RES_TYPE_FLOAT:
-             return make_float (atof (XSTRING (tem)->data));
+             return make_float (atof (SDATA (tem)));
 
            case RES_TYPE_BOOLEAN:
              tem = Fdowncase (tem);
-             if (!strcmp (XSTRING (tem)->data, "on")
-                 || !strcmp (XSTRING (tem)->data, "true"))
+             if (!strcmp (SDATA (tem), "on")
+                 || !strcmp (SDATA (tem), "true"))
                return Qt;
              else 
                return Qnil;
@@ -2875,11 +3049,11 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
              {
                Lisp_Object lower;
                lower = Fdowncase (tem);
-               if (!strcmp (XSTRING (lower)->data, "on")
-                   || !strcmp (XSTRING (lower)->data, "true"))
+               if (!strcmp (SDATA (lower), "on")
+                   || !strcmp (SDATA (lower), "true"))
                  return Qt;
-               else if (!strcmp (XSTRING (lower)->data, "off")
-                     || !strcmp (XSTRING (lower)->data, "false"))
+               else if (!strcmp (SDATA (lower), "off")
+                     || !strcmp (SDATA (lower), "false"))
                  return Qnil;
                else
                  return Fintern (tem, Qnil);
@@ -2997,12 +3171,12 @@ x_default_scroll_bar_color_parameter (f, alist, prop, xprop, xclass,
 
 \f
 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
-       "Parse an X-style geometry string STRING.\n\
-Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
-The properties returned may include `top', `left', `height', and `width'.\n\
-The value of `left' or `top' may be an integer,\n\
-or a list (+ N) meaning N pixels relative to top/left corner,\n\
-or a list (- N) meaning -N pixels relative to bottom/right corner.")
+       doc: /* Parse an X-style geometry string STRING.
+Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
+The properties returned may include `top', `left', `height', and `width'.
+The value of `left' or `top' may be an integer,
+or a list (+ N) meaning N pixels relative to top/left corner,
+or a list (- N) meaning -N pixels relative to bottom/right corner.  */)
      (string)
      Lisp_Object string;
 {
@@ -3010,9 +3184,9 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.")
   unsigned int width, height;
   Lisp_Object result;
 
-  CHECK_STRING (string, 0);
+  CHECK_STRING (string);
 
-  geometry = XParseGeometry ((char *) XSTRING (string)->data,
+  geometry = XParseGeometry ((char *) SDATA (string),
                             &x, &y, &width, &height);
 
 #if 0
@@ -3089,12 +3263,12 @@ x_figure_window_size (f, parms)
     {
       if (!EQ (tem0, Qunbound))
        {
-         CHECK_NUMBER (tem0, 0);
+         CHECK_NUMBER (tem0);
          f->height = XINT (tem0);
        }
       if (!EQ (tem1, Qunbound))
        {
-         CHECK_NUMBER (tem1, 0);
+         CHECK_NUMBER (tem1);
          SET_FRAME_WIDTH (f, XINT (tem1));
        }
       if (!NILP (tem2) && !EQ (tem2, Qunbound))
@@ -3107,8 +3281,9 @@ x_figure_window_size (f, parms)
     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
        ? 0
        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
-  f->output_data.x->flags_areas_extra
-    = FRAME_FLAGS_AREA_WIDTH (f);
+
+  x_compute_fringe_widths (f, 0);
+
   f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
   f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
 
@@ -3139,7 +3314,7 @@ x_figure_window_size (f, parms)
        f->output_data.x->top_pos = 0;
       else
        {
-         CHECK_NUMBER (tem0, 0);
+         CHECK_NUMBER (tem0);
          f->output_data.x->top_pos = XINT (tem0);
          if (f->output_data.x->top_pos < 0)
            window_prompting |= YNegative;
@@ -3167,7 +3342,7 @@ x_figure_window_size (f, parms)
        f->output_data.x->left_pos = 0;
       else
        {
-         CHECK_NUMBER (tem1, 0);
+         CHECK_NUMBER (tem1);
          f->output_data.x->left_pos = XINT (tem1);
          if (f->output_data.x->left_pos < 0)
            window_prompting |= XNegative;
@@ -3179,6 +3354,22 @@ x_figure_window_size (f, parms)
        window_prompting |= PPosition;
     }
 
+  if (f->output_data.x->want_fullscreen != FULLSCREEN_NONE)
+    {
+      int left, top;
+      int width, height;
+      
+      /* It takes both for some WM:s to place it where we want */
+      window_prompting = USPosition | PPosition;
+      x_fullscreen_adjust (f, &width, &height, &top, &left);
+      f->width = width;
+      f->height = height;
+      f->output_data.x->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
+      f->output_data.x->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
+      f->output_data.x->left_pos = left;
+      f->output_data.x->top_pos = top;
+    }
+  
   return window_prompting;
 }
 
@@ -3368,7 +3559,7 @@ create_frame_xic (f)
        {
          /* Determine the base fontname from the ASCII font name of
             FONTSET.  */
-         char *ascii_font = (char *) XSTRING (fontset_ascii (fontset))->data;
+         char *ascii_font = (char *) SDATA (fontset_ascii (fontset));
          char *p = ascii_font;
          int i;
 
@@ -3589,7 +3780,7 @@ x_window (f, window_prompting, minibuffer_only)
      Elsewhere we specify the window name for the window manager.  */
      
   {
-    char *str = (char *) XSTRING (Vx_resource_name)->data;
+    char *str = (char *) SDATA (Vx_resource_name);
     f->namebuf = (char *) xmalloc (strlen (str) + 1);
     strcpy (f->namebuf, str);
   }
@@ -3722,8 +3913,8 @@ x_window (f, window_prompting, minibuffer_only)
 
   validate_x_resource_name ();
 
-  class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
-  class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
+  class_hints.res_name = (char *) SDATA (Vx_resource_name);
+  class_hints.res_class = (char *) SDATA (Vx_resource_class);
   XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
 
 #ifdef HAVE_X_I18N
@@ -3850,8 +4041,8 @@ x_window (f)
   
   validate_x_resource_name ();
 
-  class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
-  class_hints.res_class = (char *) XSTRING (Vx_resource_class)->data;
+  class_hints.res_name = (char *) SDATA (Vx_resource_name);
+  class_hints.res_class = (char *) SDATA (Vx_resource_class);
   XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints);
 
   /* The menubar is part of the ordinary display;
@@ -3920,8 +4111,8 @@ x_icon (f, parms)
   icon_y = x_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
     {
-      CHECK_NUMBER (icon_x, 0);
-      CHECK_NUMBER (icon_y, 0);
+      CHECK_NUMBER (icon_x);
+      CHECK_NUMBER (icon_y);
     }
   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
     error ("Both left and top icon corners of icon must be specified");
@@ -3938,9 +4129,9 @@ x_icon (f, parms)
         ? IconicState
         : NormalState));
 
-  x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
+  x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
                                     ? f->icon_name
-                                    : f->name))->data);
+                                    : f->name)));
 
   UNBLOCK_INPUT;
 }
@@ -4090,16 +4281,16 @@ unwind_create_frame (frame)
 
 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
        1, 1, 0,
-  "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
-Returns an Emacs frame object.\n\
-ALIST is an alist of frame parameters.\n\
-If the parameters specify that the frame should not have a minibuffer,\n\
-and do not specify a specific minibuffer window to use,\n\
-then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
-be shared by the new frame.\n\
-\n\
-This function is an internal primitive--use `make-frame' instead.")
-  (parms)
+       doc: /* Make a new X window, which is called a "frame" in Emacs terms.
+Returns an Emacs frame object.
+ALIST is an alist of frame parameters.
+If the parameters specify that the frame should not have a minibuffer,
+and do not specify a specific minibuffer window to use,
+then `default-minibuffer-frame' must be a frame whose minibuffer can
+be shared by the new frame.
+
+This function is an internal primitive--use `make-frame' instead.  */)
+     (parms)
      Lisp_Object parms;
 {
   struct frame *f;
@@ -4108,7 +4299,7 @@ This function is an internal primitive--use `make-frame' instead.")
   int minibuffer_only = 0;
   long window_prompting = 0;
   int width, height;
-  int count = BINDING_STACK_SIZE ();
+  int count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   Lisp_Object display;
   struct x_display_info *dpyinfo = NULL;
@@ -4145,7 +4336,7 @@ This function is an internal primitive--use `make-frame' instead.")
   if (EQ (parent, Qunbound))
     parent = Qnil;
   if (! NILP (parent))
-    CHECK_NUMBER (parent, 0);
+    CHECK_NUMBER (parent);
 
   /* make_frame_without_minibuffer can run Lisp code and garbage collect.  */
   /* No need to protect DISPLAY because that's not used after passing
@@ -4273,9 +4464,9 @@ This function is an internal primitive--use `make-frame' instead.")
       {
        tem = Fquery_fontset (font, Qnil);
        if (STRINGP (tem))
-         font = x_new_fontset (f, XSTRING (tem)->data);
+         font = x_new_fontset (f, SDATA (tem));
        else
-         font = x_new_font (f, XSTRING (font)->data);
+         font = x_new_font (f, SDATA (font));
       }
     
     /* Try out a font which we hope has bold and italic variations.  */
@@ -4309,7 +4500,7 @@ This function is an internal primitive--use `make-frame' instead.")
   x_default_parameter (f, parms, Qborder_width, make_number (2),
                       "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
   
-  /* This defaults to 2 in order to match xterm.  We recognize either
+  /* This defaults to 1 in order to match xterm.  We recognize either
      internalBorderWidth or internalBorder (which is what xterm calls
      it).  */
   if (NILP (Fassq (Qinternal_border_width, parms)))
@@ -4344,6 +4535,10 @@ This function is an internal primitive--use `make-frame' instead.")
                       "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
   x_default_parameter (f, parms, Qline_spacing, Qnil,
                       "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
+  x_default_parameter (f, parms, Qleft_fringe, Qnil,
+                      "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
+  x_default_parameter (f, parms, Qright_fringe, Qnil,
+                      "rightFringe", "RightFringe", RES_TYPE_NUMBER);
 
   x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
                                        "scrollBarForeground",
@@ -4371,6 +4566,8 @@ This function is an internal primitive--use `make-frame' instead.")
                       "title", "Title", RES_TYPE_STRING);
   x_default_parameter (f, parms, Qwait_for_wm, Qt,
                       "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
+  x_default_parameter (f, parms, Qfullscreen, Qnil,
+                       "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
 
   f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
 
@@ -4384,7 +4581,7 @@ This function is an internal primitive--use `make-frame' instead.")
     {
       int margin, relief, bar_height;
       
-      relief = (tool_bar_button_relief > 0
+      relief = (tool_bar_button_relief >= 0
                ? tool_bar_button_relief
                : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
 
@@ -4553,9 +4750,9 @@ x_get_focus_frame (frame)
    following a user-command.  */
 
 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
-  "Set the input focus to FRAME.\n\
-FRAME nil means use the selected frame.")
-  (frame)
+       doc: /* Set the input focus to FRAME.
+FRAME nil means use the selected frame.  */)
+     (frame)
      Lisp_Object frame;
 {
   struct frame *f = check_x_frame (frame);
@@ -4574,32 +4771,32 @@ FRAME nil means use the selected frame.")
 
 \f
 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
-  "Internal function called by `color-defined-p', which see.")
-  (color, frame)
+       doc: /* Internal function called by `color-defined-p', which see.  */)
+     (color, frame)
      Lisp_Object color, frame;
 {
   XColor foo;
   FRAME_PTR f = check_x_frame (frame);
 
-  CHECK_STRING (color, 1);
+  CHECK_STRING (color);
 
-  if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
+  if (x_defined_color (f, SDATA (color), &foo, 0))
     return Qt;
   else
     return Qnil;
 }
 
 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
-  "Internal function called by `color-values', which see.")
-  (color, frame)
+       doc: /* Internal function called by `color-values', which see.  */)
+     (color, frame)
      Lisp_Object color, frame;
 {
   XColor foo;
   FRAME_PTR f = check_x_frame (frame);
 
-  CHECK_STRING (color, 1);
+  CHECK_STRING (color);
 
-  if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
+  if (x_defined_color (f, SDATA (color), &foo, 0))
     {
       Lisp_Object rgb[3];
 
@@ -4613,8 +4810,8 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
 }
 
 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
-  "Internal function called by `display-color-p', which see.")
-  (display)
+       doc: /* Internal function called by `display-color-p', which see.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4636,13 +4833,13 @@ DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
 }
 
 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
-  0, 1, 0,
-  "Return t if the X display supports shades of gray.\n\
-Note that color displays do support shades of gray.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       0, 1, 0,
+       doc: /* Return t if the X display supports shades of gray.
+Note that color displays do support shades of gray.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4666,12 +4863,12 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
-  0, 1, 0,
-  "Returns the width in pixels of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       0, 1, 0,
+       doc: /* Returns the width in pixels of the X display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4680,12 +4877,12 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
-  Sx_display_pixel_height, 0, 1, 0,
-  "Returns the height in pixels of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       Sx_display_pixel_height, 0, 1, 0,
+       doc: /* Returns the height in pixels of the X display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4694,12 +4891,12 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
-  0, 1, 0,
-  "Returns the number of bitplanes of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       0, 1, 0,
+       doc: /* Returns the number of bitplanes of the X display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4708,12 +4905,12 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
-  0, 1, 0,
-  "Returns the number of color cells of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       0, 1, 0,
+       doc: /* Returns the number of color cells of the X display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4724,12 +4921,12 @@ If omitted or nil, that stands for the selected frame's display.")
 
 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
        Sx_server_max_request_size,
-  0, 1, 0,
-  "Returns the maximum request size of the X server of display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       0, 1, 0,
+       doc: /* Returns the maximum request size of the X server of display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4738,11 +4935,11 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
-  "Returns the vendor ID string of the X server of display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       doc: /* Returns the vendor ID string of the X server of display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4753,14 +4950,15 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
-  "Returns the version numbers of the X server of display DISPLAY.\n\
-The value is a list of three integers: the major and minor\n\
-version numbers of the X Protocol in use, and the vendor-specific release\n\
-number.  See also the function `x-server-vendor'.\n\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       doc: /* Returns the version numbers of the X server of display DISPLAY.
+The value is a list of three integers: the major and minor
+version numbers of the X Protocol in use, and the vendor-specific release
+number.  See also the function `x-server-vendor'.
+
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4772,11 +4970,11 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
-  "Returns the number of screens on the X server of display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       doc: /* Return the number of screens on the X server of display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4785,11 +4983,11 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
-  "Returns the height in millimeters of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       doc: /* Return the height in millimeters of the X display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4798,11 +4996,11 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
-  "Returns the width in millimeters of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       doc: /* Return the width in millimeters of the X display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4811,13 +5009,13 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-backing-store", Fx_display_backing_store,
-  Sx_display_backing_store, 0, 1, 0,
-  "Returns an indication of whether X display DISPLAY does backing store.\n\
-The value may be `always', `when-mapped', or `not-useful'.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       Sx_display_backing_store, 0, 1, 0,
+       doc: /* Returns an indication of whether X display DISPLAY does backing store.
+The value may be `always', `when-mapped', or `not-useful'.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4846,14 +5044,15 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-visual-class", Fx_display_visual_class,
-  Sx_display_visual_class, 0, 1, 0,
-  "Returns the visual class of the X display DISPLAY.\n\
-The value is one of the symbols `static-gray', `gray-scale',\n\
-`static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-       (display)
+       Sx_display_visual_class, 0, 1, 0,
+       doc: /* Return the visual class of the X display DISPLAY.
+The value is one of the symbols `static-gray', `gray-scale',
+`static-color', `pseudo-color', `true-color', or `direct-color'.
+
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4888,12 +5087,12 @@ If omitted or nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-save-under", Fx_display_save_under,
-  Sx_display_save_under, 0, 1, 0,
-  "Returns t if the X display DISPLAY supports the save-under feature.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
-  (display)
+       Sx_display_save_under, 0, 1, 0,
+       doc: /* Returns t if the X display DISPLAY supports the save-under feature.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.  */)
+     (display)
      Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -4961,7 +5160,7 @@ visual_classes[] =
   {"PseudoColor",      PseudoColor},
   {"TrueColor",                TrueColor},
   {"DirectColor",      DirectColor},
-  NULL
+  {NULL, 0}
 };
 
 
@@ -4978,7 +5177,7 @@ XScreenNumberOfScreen (scr)
   int i;
 
   for (i = 0; i < dpy->nscreens; ++i)
-    if (scr == dpy->screens[i])
+    if (scr == dpy->screens + i)
       break;
 
   return i;
@@ -5008,12 +5207,12 @@ select_visual (dpyinfo)
       /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
         of `PseudoColor', `TrueColor' etc. and DEPTH is the color
         depth, a decimal number.  NAME is compared with case ignored.  */
-      char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
+      char *s = (char *) alloca (SBYTES (value) + 1);
       char *dash;
       int i, class = -1;
       XVisualInfo vinfo;
 
-      strcpy (s, XSTRING (value)->data);
+      strcpy (s, SDATA (value));
       dash = index (s, '-');
       if (dash)
        {
@@ -5037,7 +5236,7 @@ select_visual (dpyinfo)
       if (class == -1
          || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
                                dpyinfo->n_planes, class, &vinfo))
-       fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
+       fatal ("Invalid visual specification `%s'", SDATA (value));
       
       dpyinfo->visual = vinfo.visual;
     }
@@ -5075,7 +5274,7 @@ x_display_info_for_name (name)
   Lisp_Object names;
   struct x_display_info *dpyinfo;
 
-  CHECK_STRING (name, 0);
+  CHECK_STRING (name);
 
   if (! EQ (Vwindow_system, intern ("x")))
     error ("Not using X Windows");
@@ -5096,10 +5295,10 @@ x_display_info_for_name (name)
   validate_x_resource_name ();
 
   dpyinfo = x_term_init (name, (char *)0,
-                        (char *) XSTRING (Vx_resource_name)->data);
+                        (char *) SDATA (Vx_resource_name));
 
   if (dpyinfo == 0)
-    error ("Cannot connect to X server %s", XSTRING (name)->data);
+    error ("Cannot connect to X server %s", SDATA (name));
 
   x_in_use = 1;
   XSETFASTINT (Vwindow_system_version, 11);
@@ -5109,26 +5308,27 @@ x_display_info_for_name (name)
 
 
 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
-       1, 3, 0, "Open a connection to an X server.\n\
-DISPLAY is the name of the display to connect to.\n\
-Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
-If the optional third arg MUST-SUCCEED is non-nil,\n\
-terminate Emacs if we can't open the connection.")
-  (display, xrm_string, must_succeed)
+       1, 3, 0,
+       doc: /* Open a connection to an X server.
+DISPLAY is the name of the display to connect to.
+Optional second arg XRM-STRING is a string of resources in xrdb format.
+If the optional third arg MUST-SUCCEED is non-nil,
+terminate Emacs if we can't open the connection.  */)
+     (display, xrm_string, must_succeed)
      Lisp_Object display, xrm_string, must_succeed;
 {
   unsigned char *xrm_option;
   struct x_display_info *dpyinfo;
 
-  CHECK_STRING (display, 0);
+  CHECK_STRING (display);
   if (! NILP (xrm_string))
-    CHECK_STRING (xrm_string, 1);
+    CHECK_STRING (xrm_string);
 
   if (! EQ (Vwindow_system, intern ("x")))
     error ("Not using X Windows");
 
   if (! NILP (xrm_string))
-    xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
+    xrm_option = (unsigned char *) SDATA (xrm_string);
   else
     xrm_option = (unsigned char *) 0;
 
@@ -5137,7 +5337,7 @@ terminate Emacs if we can't open the connection.")
   /* This is what opens the connection and sets x_current_display.
      This also initializes many symbols, such as those used for input.  */
   dpyinfo = x_term_init (display, xrm_option,
-                        (char *) XSTRING (Vx_resource_name)->data);
+                        (char *) SDATA (Vx_resource_name));
 
   if (dpyinfo == 0)
     {
@@ -5146,9 +5346,9 @@ terminate Emacs if we can't open the connection.")
 Check the DISPLAY environment variable or use `-d'.\n\
 Also use the `xhost' program to verify that it is set to permit\n\
 connections from your machine.\n",
-              XSTRING (display)->data);
+              SDATA (display));
       else
-       error ("Cannot connect to X server %s", XSTRING (display)->data);
+       error ("Cannot connect to X server %s", SDATA (display));
     }
 
   x_in_use = 1;
@@ -5159,11 +5359,11 @@ connections from your machine.\n",
 
 DEFUN ("x-close-connection", Fx_close_connection,
        Sx_close_connection, 1, 1, 0,
-   "Close the connection to DISPLAY's X server.\n\
-For DISPLAY, specify either a frame or a display name (a string).\n\
-If DISPLAY is nil, that stands for the selected frame's display.")
-  (display)
-  Lisp_Object display;
+       doc: /* Close the connection to DISPLAY's X server.
+For DISPLAY, specify either a frame or a display name (a string).
+If DISPLAY is nil, that stands for the selected frame's display.  */)
+     (display)
+     Lisp_Object display;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
   int i;
@@ -5198,8 +5398,8 @@ If DISPLAY is nil, that stands for the selected frame's display.")
 }
 
 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
-  "Return the list of display names that Emacs has connections to.")
-  ()
+       doc: /* Return the list of display names that Emacs has connections to.  */)
+     ()
 {
   Lisp_Object tail, result;
 
@@ -5211,15 +5411,15 @@ DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
 }
 
 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
-   "If ON is non-nil, report X errors as soon as the erring request is made.\n\
-If ON is nil, allow buffering of requests.\n\
-Turning on synchronization prohibits the Xlib routines from buffering\n\
-requests and seriously degrades performance, but makes debugging much\n\
-easier.\n\
-The optional second argument DISPLAY specifies which display to act on.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If DISPLAY is omitted or nil, that stands for the selected frame's display.")
-  (on, display)
+       doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
+If ON is nil, allow buffering of requests.
+Turning on synchronization prohibits the Xlib routines from buffering
+requests and seriously degrades performance, but makes debugging much
+easier.
+The optional second argument DISPLAY specifies which display to act on.
+DISPLAY should be either a frame or a display name (a string).
+If DISPLAY is omitted or nil, that stands for the selected frame's display.  */)
+     (on, display)
     Lisp_Object display, on;
 {
   struct x_display_info *dpyinfo = check_x_display_info (display);
@@ -5266,8 +5466,8 @@ Lisp_Object Qxbm;
 /* Keywords.  */
 
 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
-extern Lisp_Object QCdata;
-Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
+extern Lisp_Object QCdata, QCtype;
+Lisp_Object QCascent, QCmargin, QCrelief;
 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
 
@@ -5462,7 +5662,7 @@ parse_image_spec (spec, keywords, nkeywords, type)
 
       /* Find key in KEYWORDS.  Error if not found.  */
       for (i = 0; i < nkeywords; ++i)
-       if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
+       if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
          break;
 
       if (i == nkeywords)
@@ -5598,12 +5798,12 @@ image_spec_value (spec, key, found)
      
 
 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
-  "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
-PIXELS non-nil means return the size in pixels, otherwise return the\n\
-size in canonical character units.\n\
-FRAME is the frame on which the image will be displayed.  FRAME nil\n\
-or omitted means use the selected frame.")
-  (spec, pixels, frame)
+       doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
+PIXELS non-nil means return the size in pixels, otherwise return the
+size in canonical character units.
+FRAME is the frame on which the image will be displayed.  FRAME nil
+or omitted means use the selected frame.  */)
+     (spec, pixels, frame)
      Lisp_Object spec, pixels, frame;
 {
   Lisp_Object size;
@@ -5631,10 +5831,10 @@ or omitted means use the selected frame.")
 
 
 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
-  "Return t if image SPEC has a mask bitmap.\n\
-FRAME is the frame on which the image will be displayed.  FRAME nil\n\
-or omitted means use the selected frame.")
-  (spec, frame)
+       doc: /* Return t if image SPEC has a mask bitmap.
+FRAME is the frame on which the image will be displayed.  FRAME nil
+or omitted means use the selected frame.  */)
+     (spec, frame)
      Lisp_Object spec, frame;
 {
   Lisp_Object mask;
@@ -5765,6 +5965,104 @@ image_ascent (img, face)
   return ascent;
 }
 
+\f
+/* Image background colors.  */
+
+static unsigned long
+four_corners_best (ximg, width, height)
+     XImage *ximg;
+     unsigned long width, height;
+{
+  unsigned long corners[4], best;
+  int i, best_count;
+
+  /* Get the colors at the corners of ximg.  */
+  corners[0] = XGetPixel (ximg, 0, 0);
+  corners[1] = XGetPixel (ximg, width - 1, 0);
+  corners[2] = XGetPixel (ximg, width - 1, height - 1);
+  corners[3] = XGetPixel (ximg, 0, height - 1);
+
+  /* Choose the most frequently found color as background.  */
+  for (i = best_count = 0; i < 4; ++i)
+    {
+      int j, n;
+         
+      for (j = n = 0; j < 4; ++j)
+       if (corners[i] == corners[j])
+         ++n;
+
+      if (n > best_count)
+       best = corners[i], best_count = n;
+    }
+
+  return best;
+}
+
+/* Return the `background' field of IMG.  If IMG doesn't have one yet,
+   it is guessed heuristically.  If non-zero, XIMG is an existing XImage
+   object to use for the heuristic.  */
+
+unsigned long
+image_background (img, f, ximg)
+     struct image *img;
+     struct frame *f;
+     XImage *ximg;
+{
+  if (! img->background_valid)
+    /* IMG doesn't have a background yet, try to guess a reasonable value.  */
+    {
+      int free_ximg = !ximg;
+
+      if (! ximg)
+       ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
+                         0, 0, img->width, img->height, ~0, ZPixmap);
+
+      img->background = four_corners_best (ximg, img->width, img->height);
+
+      if (free_ximg)
+       XDestroyImage (ximg);
+
+      img->background_valid = 1;
+    }
+
+  return img->background;
+}
+
+/* Return the `background_transparent' field of IMG.  If IMG doesn't
+   have one yet, it is guessed heuristically.  If non-zero, MASK is an
+   existing XImage object to use for the heuristic.  */
+
+int
+image_background_transparent (img, f, mask)
+     struct image *img;
+     struct frame *f;
+     XImage *mask;
+{
+  if (! img->background_transparent_valid)
+    /* IMG doesn't have a background yet, try to guess a reasonable value.  */
+    {
+      if (img->mask)
+       {
+         int free_mask = !mask;
+
+         if (! mask)
+           mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
+                             0, 0, img->width, img->height, ~0, ZPixmap);
+
+         img->background_transparent
+           = !four_corners_best (mask, img->width, img->height);
+
+         if (free_mask)
+           XDestroyImage (mask);
+       }
+      else
+       img->background_transparent = 0;
+
+      img->background_transparent_valid = 1;
+    }
+
+  return img->background_transparent;
+}
 
 \f
 /***********************************************************************
@@ -5795,12 +6093,14 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
     {
       XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
       img->pixmap = None;
+      img->background_valid = 0;
     }
 
   if (mask_p && img->mask)
     {
       XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
       img->mask = None;
+      img->background_transparent_valid = 0;
     }
       
   if (colors_p && img->ncolors)
@@ -5842,7 +6142,7 @@ x_alloc_image_color (f, img, color_name, dflt)
 
   xassert (STRINGP (color_name));
 
-  if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
+  if (x_defined_color (f, SDATA (color_name), &color, 1))
     {
       /* This isn't called frequently so we get away with simply
         reallocating the color vector to the needed size, here.  */
@@ -5977,10 +6277,10 @@ clear_image_cache (f, force_p)
 
 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
        0, 1, 0,
-  "Clear the image cache of FRAME.\n\
-FRAME nil or omitted means use the selected frame.\n\
-FRAME t means clear the image caches of all frames.")
-  (frame)
+       doc: /* Clear the image cache of FRAME.
+FRAME nil or omitted means use the selected frame.
+FRAME t means clear the image caches of all frames.  */)
+     (frame)
      Lisp_Object frame;
 {
   if (EQ (frame, Qt))
@@ -6130,8 +6430,9 @@ lookup_image (f, spec)
       else
        {
          /* Handle image type independent image attributes
-            `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'.  */
-         Lisp_Object ascent, margin, relief;
+            `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
+            `:background COLOR'.  */
+         Lisp_Object ascent, margin, relief, bg;
 
          ascent = image_spec_value (spec, QCascent, NULL);
          if (INTEGERP (ascent))
@@ -6159,6 +6460,18 @@ lookup_image (f, spec)
              img->vmargin += abs (img->relief);
            }
 
+         if (! img->background_valid)
+           {
+             bg = image_spec_value (img->spec, QCbackground, NULL);
+             if (!NILP (bg))
+               {
+                 img->background
+                   = x_alloc_image_color (f, img, bg,
+                                          FRAME_BACKGROUND_PIXEL (f));
+                 img->background_valid = 1;
+               }
+           }
+
          /* Do image transformations and compute masks, unless we
             don't have the image yet.  */
          if (!EQ (*img->type->type, Qpostscript))
@@ -6359,7 +6672,7 @@ x_find_image_file (file)
   GCPRO2 (file_found, search_path);
 
   /* Try to find FILE in data-directory, then x-bitmap-file-path.  */
-  fd = openp (search_path, file, Qnil, &file_found, 0);
+  fd = openp (search_path, file, Qnil, &file_found, Qnil);
   
   if (fd == -1)
     file_found = Qnil;
@@ -6567,7 +6880,7 @@ xbm_image_p (object)
 
              if (STRINGP (elt))
                {
-                 if (XSTRING (elt)->size
+                 if (SCHARS (elt)
                      < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
                    return 0;
                }
@@ -6582,7 +6895,7 @@ xbm_image_p (object)
        }
       else if (STRINGP (data))
        {
-         if (XSTRING (data)->size
+         if (SCHARS (data)
              < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
            return 0;
        }
@@ -6872,10 +7185,13 @@ xbm_load_image (f, img, contents, end)
       value = image_spec_value (img->spec, QCforeground, NULL);
       if (!NILP (value))
        foreground = x_alloc_image_color (f, img, value, foreground);
-      
       value = image_spec_value (img->spec, QCbackground, NULL);
       if (!NILP (value))
-       background = x_alloc_image_color (f, img, value, background);
+       {
+         background = x_alloc_image_color (f, img, value, background);
+         img->background = background;
+         img->background_valid = 1;
+       }
 
       img->pixmap
        = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
@@ -6909,9 +7225,9 @@ xbm_file_p (data)
 {
   int w, h;
   return (STRINGP (data)
-         && xbm_read_bitmap_data (XSTRING (data)->data,
-                                  (XSTRING (data)->data
-                                   + STRING_BYTES (XSTRING (data))),
+         && xbm_read_bitmap_data (SDATA (data),
+                                  (SDATA (data)
+                                   + SBYTES (data)),
                                   &w, &h, NULL));
 }
 
@@ -6947,7 +7263,7 @@ xbm_load (f, img)
          return 0;
        }
 
-      contents = slurp_file (XSTRING (file)->data, &size);
+      contents = slurp_file (SDATA (file), &size);
       if (contents == NULL)
        {
          image_error ("Error loading XBM image `%s'", img->spec, Qnil);
@@ -6997,9 +7313,9 @@ xbm_load (f, img)
                                          background);
 
       if (in_memory_file_p)
-       success_p = xbm_load_image (f, img, XSTRING (data)->data,
-                                   (XSTRING (data)->data
-                                    + STRING_BYTES (XSTRING (data))));
+       success_p = xbm_load_image (f, img, SDATA (data),
+                                   (SDATA (data)
+                                    + SBYTES (data)));
       else
        {
          if (VECTORP (data))
@@ -7013,13 +7329,13 @@ xbm_load (f, img)
                {
                  Lisp_Object line = XVECTOR (data)->contents[i];
                  if (STRINGP (line))
-                   bcopy (XSTRING (line)->data, p, nbytes);
+                   bcopy (SDATA (line), p, nbytes);
                  else
                    bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
                }
            }
          else if (STRINGP (data))
-           bits = XSTRING (data)->data;
+           bits = SDATA (data);
          else
            bits = XBOOL_VECTOR (data)->data;
 
@@ -7078,6 +7394,7 @@ enum xpm_keyword_index
   XPM_HEURISTIC_MASK,
   XPM_MASK,
   XPM_COLOR_SYMBOLS,
+  XPM_BACKGROUND,
   XPM_LAST
 };
 
@@ -7095,7 +7412,8 @@ static struct image_keyword xpm_format[XPM_LAST] =
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":color-symbols",   IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":color-symbols",   IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type XBM.  */
@@ -7419,10 +7737,10 @@ xpm_load (f, img)
        {
          Lisp_Object name = XCAR (XCAR (tail));
          Lisp_Object color = XCDR (XCAR (tail));
-         xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
-         strcpy (xpm_syms[i].name, XSTRING (name)->data);
-         xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
-         strcpy (xpm_syms[i].value, XSTRING (color)->data);
+         xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
+         strcpy (xpm_syms[i].name, SDATA (name));
+         xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
+         strcpy (xpm_syms[i].value, SDATA (color));
        }
     }
 
@@ -7443,14 +7761,14 @@ xpm_load (f, img)
        }
       
       rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                               XSTRING (file)->data, &img->pixmap, &img->mask,
+                               SDATA (file), &img->pixmap, &img->mask,
                                &attrs);
     }
   else
     {
       Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
       rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                                     XSTRING (buffer)->data,
+                                     SDATA (buffer),
                                      &img->pixmap, &img->mask,
                                      &attrs);
     }
@@ -7712,10 +8030,6 @@ colors_in_color_table (n)
                              Algorithms
  ***********************************************************************/
 
-static void x_laplace_write_row P_ ((struct frame *, long *,
-                                    int, XImage *, int));
-static void x_laplace_read_row P_ ((struct frame *, Colormap,
-                                   XColor *, int, XImage *, int));
 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
@@ -8042,13 +8356,14 @@ x_build_heuristic_mask (f, img, how)
 {
   Display *dpy = FRAME_X_DISPLAY (f);
   XImage *ximg, *mask_img;
-  int x, y, rc, look_at_corners_p;
+  int x, y, rc, use_img_background;
   unsigned long bg = 0;
 
   if (img->mask)
     {
       XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
       img->mask = None;
+      img->background_transparent_valid = 0;
     }
 
   /* Create an image and pixmap serving as mask.  */
@@ -8062,17 +8377,14 @@ x_build_heuristic_mask (f, img, how)
                    ~0, ZPixmap);
 
   /* Determine the background color of ximg.  If HOW is `(R G B)'
-     take that as color.  Otherwise, try to determine the color
-     heuristically. */
-  look_at_corners_p = 1;
+     take that as color.  Otherwise, use the image's background color. */
+  use_img_background = 1;
   
   if (CONSP (how))
     {
-      int rgb[3], i = 0;
+      int rgb[3], i;
 
-      while (i < 3
-            && CONSP (how)
-            && NATNUMP (XCAR (how)))
+      for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
        {
          rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
          how = XCDR (how);
@@ -8081,44 +8393,14 @@ x_build_heuristic_mask (f, img, how)
       if (i == 3 && NILP (how))
        {
          char color_name[30];
-         XColor exact, color;
-         Colormap cmap;
-
          sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
-         
-         cmap = FRAME_X_COLORMAP (f);
-         if (XLookupColor (dpy, cmap, color_name, &exact, &color))
-           {
-             bg = color.pixel;
-             look_at_corners_p = 0;
-           }
+         bg = x_alloc_image_color (f, img, build_string (color_name), 0);
+         use_img_background = 0;
        }
     }
   
-  if (look_at_corners_p)
-    {
-      unsigned long corners[4];
-      int i, best_count;
-
-      /* Get the colors at the corners of ximg.  */
-      corners[0] = XGetPixel (ximg, 0, 0);
-      corners[1] = XGetPixel (ximg, img->width - 1, 0);
-      corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
-      corners[3] = XGetPixel (ximg, 0, img->height - 1);
-
-      /* Choose the most frequently found color as background.  */
-      for (i = best_count = 0; i < 4; ++i)
-       {
-         int j, n;
-         
-         for (j = n = 0; j < 4; ++j)
-           if (corners[i] == corners[j])
-             ++n;
-
-         if (n > best_count)
-           bg = corners[i], best_count = n;
-       }
-    }
+  if (use_img_background)
+    bg = four_corners_best (ximg, img->width, img->height);
 
   /* Set all bits in mask_img to 1 whose color in ximg is different
      from the background color bg.  */
@@ -8126,6 +8408,9 @@ x_build_heuristic_mask (f, img, how)
     for (x = 0; x < img->width; ++x)
       XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
 
+  /* Fill in the background_transparent field while we have the mask handy. */
+  image_background_transparent (img, f, mask_img);
+
   /* Put mask_img into img->mask.  */
   x_put_x_image (f, mask_img, img->mask, img->width, img->height);
   x_destroy_x_image (mask_img);
@@ -8283,7 +8568,7 @@ pbm_load (f, img)
          return 0;
        }
 
-      contents = slurp_file (XSTRING (file)->data, &size);
+      contents = slurp_file (SDATA (file), &size);
       if (contents == NULL)
        {
          image_error ("Error reading `%s'", file, Qnil);
@@ -8298,8 +8583,8 @@ pbm_load (f, img)
     {
       Lisp_Object data;
       data = image_spec_value (img->spec, QCdata, NULL);
-      p = XSTRING (data)->data;
-      end = p + STRING_BYTES (XSTRING (data));
+      p = SDATA (data);
+      end = p + SBYTES (data);
     }
 
   /* Check magic number.  */
@@ -8384,7 +8669,11 @@ pbm_load (f, img)
        fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
       if (fmt[PBM_BACKGROUND].count
          && STRINGP (fmt[PBM_BACKGROUND].value))
-       bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
+       {
+         bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
+         img->background = bg;
+         img->background_valid = 1;
+       }
       
       for (y = 0; y < height; ++y)
        for (x = 0; x < width; ++x)
@@ -8447,6 +8736,10 @@ pbm_load (f, img)
      free the color table.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
   
   /* Put the image into a pixmap.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
@@ -8492,6 +8785,7 @@ enum png_keyword_index
   PNG_ALGORITHM,
   PNG_HEURISTIC_MASK,
   PNG_MASK,
+  PNG_BACKGROUND,
   PNG_LAST
 };
 
@@ -8508,7 +8802,8 @@ static struct image_keyword png_format[PNG_LAST] =
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `png'.  */
@@ -8617,7 +8912,6 @@ png_load (f, img)
   png_byte channels;
   png_uint_32 row_bytes;
   int transparent_p;
-  char *gamma_str;
   double screen_gamma, image_gamma;
   int intent;
   struct png_memory_storage tbr;  /* Data to be read */
@@ -8639,7 +8933,7 @@ png_load (f, img)
        }
 
       /* Open the image file.  */
-      fp = fopen (XSTRING (file)->data, "rb");
+      fp = fopen (SDATA (file), "rb");
       if (!fp)
        {
          image_error ("Cannot open image file `%s'", file, Qnil);
@@ -8661,8 +8955,8 @@ png_load (f, img)
   else
     {
       /* Read from memory.  */
-      tbr.bytes = XSTRING (specified_data)->data;
-      tbr.len = STRING_BYTES (XSTRING (specified_data));
+      tbr.bytes = SDATA (specified_data);
+      tbr.len = SBYTES (specified_data);
       tbr.index = 0;
 
       /* Check PNG signature.  */
@@ -8755,36 +9049,53 @@ png_load (f, img)
       || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
     png_set_gray_to_rgb (png_ptr);
 
-  /* The value 2.2 is a guess for PC monitors from PNG example.c.  */
-  gamma_str = getenv ("SCREEN_GAMMA");
-  screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
+  screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
 
   /* Tell the PNG lib to handle gamma correction for us.  */
 
 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
   if (png_get_sRGB (png_ptr, info_ptr, &intent))
-    /* There is a special chunk in the image specifying the gamma.  */
-    png_set_sRGB (png_ptr, info_ptr, intent);
+    /* The libpng documentation says this is right in this case.  */
+    png_set_gamma (png_ptr, screen_gamma, 0.45455);
   else
 #endif
   if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
     /* Image contains gamma information.  */
     png_set_gamma (png_ptr, screen_gamma, image_gamma);
   else
-    /* Use a default of 0.5 for the image gamma.  */
-    png_set_gamma (png_ptr, screen_gamma, 0.5);
+    /* Use the standard default for the image gamma.  */
+    png_set_gamma (png_ptr, screen_gamma, 0.45455);
 
   /* Handle alpha channel by combining the image with a background
      color.  Do this only if a real alpha channel is supplied.  For
      simple transparency, we prefer a clipping mask.  */
   if (!transparent_p)
     {
-      png_color_16 *image_background;
+      png_color_16 *image_bg;
+      Lisp_Object specified_bg
+       = image_spec_value (img->spec, QCbackground, NULL);
+
+      if (STRINGP (specified_bg))
+       /* The user specified `:background', use that.  */
+       {
+         XColor color;
+         if (x_defined_color (f, SDATA (specified_bg), &color, 0))
+           {
+             png_color_16 user_bg;
 
-      if (png_get_bKGD (png_ptr, info_ptr, &image_background))
+             bzero (&user_bg, sizeof user_bg);
+             user_bg.red = color.red;
+             user_bg.green = color.green;
+             user_bg.blue = color.blue;
+
+             png_set_background (png_ptr, &user_bg,
+                                 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+           }
+       }
+      else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
        /* Image contains a background color with which to 
           combine the image.  */
-       png_set_background (png_ptr, image_background,
+       png_set_background (png_ptr, image_bg,
                            PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
       else
        {
@@ -8897,6 +9208,18 @@ png_load (f, img)
        }
     }
 
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    /* Set IMG's background color from the PNG image, unless the user
+       overrode it.  */
+    {
+      png_color_16 *bg;
+      if (png_get_bKGD (png_ptr, info_ptr, &bg))
+       {
+         img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
+         img->background_valid = 1;
+       }
+    }
+
   /* Remember colors allocated for this image.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
@@ -8909,6 +9232,9 @@ png_load (f, img)
   img->width = width;
   img->height = height;
 
+  /* Maybe fill in the background field while we have ximg handy. */
+  IMAGE_BACKGROUND (img, f, ximg);
+
   /* Put the image into the pixmap, then free the X image and its buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
@@ -8916,6 +9242,10 @@ png_load (f, img)
   /* Same for the mask.  */
   if (mask_img)
     {
+      /* Fill in the background_transparent field while we have the mask
+        handy. */
+      image_background_transparent (img, f, mask_img);
+
       x_put_x_image (f, mask_img, img->mask, img->width, img->height);
       x_destroy_x_image (mask_img);
     }
@@ -8969,6 +9299,7 @@ enum jpeg_keyword_index
   JPEG_ALGORITHM,
   JPEG_HEURISTIC_MASK,
   JPEG_MASK,
+  JPEG_BACKGROUND,
   JPEG_LAST
 };
 
@@ -8985,7 +9316,8 @@ static struct image_keyword jpeg_format[JPEG_LAST] =
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `jpeg'.  */
@@ -9167,7 +9499,7 @@ jpeg_load (f, img)
          return 0;
        }
   
-      fp = fopen (XSTRING (file)->data, "r");
+      fp = fopen (SDATA (file), "r");
       if (fp == NULL)
        {
          image_error ("Cannot open `%s'", file, Qnil);
@@ -9214,8 +9546,8 @@ jpeg_load (f, img)
   if (NILP (specified_data))
     jpeg_stdio_src (&cinfo, (FILE *) fp);
   else
-    jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
-                    STRING_BYTES (XSTRING (specified_data)));
+    jpeg_memory_src (&cinfo, SDATA (specified_data),
+                    SBYTES (specified_data));
 
   jpeg_read_header (&cinfo, TRUE);
 
@@ -9284,6 +9616,10 @@ jpeg_load (f, img)
   jpeg_destroy_decompress (&cinfo);
   if (fp)
     fclose ((FILE *) fp);
+
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
   
   /* Put the image into the pixmap.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
@@ -9324,6 +9660,7 @@ enum tiff_keyword_index
   TIFF_ALGORITHM,
   TIFF_HEURISTIC_MASK,
   TIFF_MASK,
+  TIFF_BACKGROUND,
   TIFF_LAST
 };
 
@@ -9340,7 +9677,8 @@ static struct image_keyword tiff_format[TIFF_LAST] =
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `tiff'.  */
@@ -9555,7 +9893,7 @@ tiff_load (f, img)
        }
          
       /* Try to open the image file.  */
-      tiff = TIFFOpen (XSTRING (file)->data, "r");
+      tiff = TIFFOpen (SDATA (file), "r");
       if (tiff == NULL)
        {
          image_error ("Cannot open `%s'", file, Qnil);
@@ -9566,8 +9904,8 @@ tiff_load (f, img)
   else
     {
       /* Memory source! */
-      memsrc.bytes = XSTRING (specified_data)->data;
-      memsrc.len = STRING_BYTES (XSTRING (specified_data));
+      memsrc.bytes = SDATA (specified_data);
+      memsrc.len = SBYTES (specified_data);
       memsrc.index = 0;
 
       tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
@@ -9632,14 +9970,18 @@ tiff_load (f, img)
   /* Remember the colors allocated for the image.  Free the color table.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+      
+  img->width = width;
+  img->height = height;
+
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
 
   /* Put the image into the pixmap, then free the X image and its buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
   xfree (buf);
-      
-  img->width = width;
-  img->height = height;
 
   UNGCPRO;
   return 1;
@@ -9678,6 +10020,7 @@ enum gif_keyword_index
   GIF_HEURISTIC_MASK,
   GIF_MASK,
   GIF_IMAGE,
+  GIF_BACKGROUND,
   GIF_LAST
 };
 
@@ -9695,7 +10038,8 @@ static struct image_keyword gif_format[GIF_LAST] =
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":image",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0}
+  {":image",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `gif'.  */
@@ -9798,7 +10142,7 @@ gif_load (f, img)
        }
   
       /* Open the GIF file.  */
-      gif = DGifOpenFileName (XSTRING (file)->data);
+      gif = DGifOpenFileName (SDATA (file));
       if (gif == NULL)
        {
          image_error ("Cannot open `%s'", file, Qnil);
@@ -9810,8 +10154,8 @@ gif_load (f, img)
     {
       /* Read from memory! */
       current_gif_memory_src = &memsrc;
-      memsrc.bytes = XSTRING (specified_data)->data;
-      memsrc.len = STRING_BYTES (XSTRING (specified_data));
+      memsrc.bytes = SDATA (specified_data);
+      memsrc.len = SBYTES (specified_data);
       memsrc.index = 0;
 
       gif = DGifOpen(&memsrc, gif_read_from_memory);
@@ -9844,8 +10188,8 @@ gif_load (f, img)
       return 0;
     }
 
-  width = img->width = gif->SWidth;
-  height = img->height = gif->SHeight;
+  width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
+  height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
 
   /* Create the X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
@@ -9943,6 +10287,10 @@ gif_load (f, img)
     }
   
   DGifCloseFile (gif);
+
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
   
   /* Put the image into the pixmap, then free the X image and its buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
@@ -9988,6 +10336,7 @@ enum gs_keyword_index
   GS_ALGORITHM,
   GS_HEURISTIC_MASK,
   GS_MASK,
+  GS_BACKGROUND,
   GS_LAST
 };
 
@@ -10007,7 +10356,8 @@ static struct image_keyword gs_format[GS_LAST] =
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `ghostscript'.  */
@@ -10242,23 +10592,23 @@ x_kill_gs_process (pixmap, f)
 
 DEFUN ("x-change-window-property", Fx_change_window_property,
        Sx_change_window_property, 2, 3, 0,
-  "Change window property PROP to VALUE on the X window of FRAME.\n\
-PROP and VALUE must be strings.  FRAME nil or omitted means use the\n\
-selected frame.  Value is VALUE.")
-  (prop, value, frame)
+       doc: /* Change window property PROP to VALUE on the X window of FRAME.
+PROP and VALUE must be strings.  FRAME nil or omitted means use the
+selected frame.  Value is VALUE.  */)
+     (prop, value, frame)
      Lisp_Object frame, prop, value;
 {
   struct frame *f = check_x_frame (frame);
   Atom prop_atom;
 
-  CHECK_STRING (prop, 1);
-  CHECK_STRING (value, 2);
+  CHECK_STRING (prop);
+  CHECK_STRING (value);
 
   BLOCK_INPUT;
-  prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
+  prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
   XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                   prop_atom, XA_STRING, 8, PropModeReplace,
-                  XSTRING (value)->data, XSTRING (value)->size);
+                  SDATA (value), SCHARS (value));
 
   /* Make sure the property is set when we return.  */
   XFlush (FRAME_X_DISPLAY (f));
@@ -10270,17 +10620,17 @@ selected frame.  Value is VALUE.")
 
 DEFUN ("x-delete-window-property", Fx_delete_window_property,
        Sx_delete_window_property, 1, 2, 0,
-  "Remove window property PROP from X window of FRAME.\n\
-FRAME nil or omitted means use the selected frame.  Value is PROP.")
-  (prop, frame)
+       doc: /* Remove window property PROP from X window of FRAME.
+FRAME nil or omitted means use the selected frame.  Value is PROP.  */)
+     (prop, frame)
      Lisp_Object prop, frame;
 {
   struct frame *f = check_x_frame (frame);
   Atom prop_atom;
 
-  CHECK_STRING (prop, 1);
+  CHECK_STRING (prop);
   BLOCK_INPUT;
-  prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
+  prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
   XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
 
   /* Make sure the property is removed when we return.  */
@@ -10293,11 +10643,11 @@ FRAME nil or omitted means use the selected frame.  Value is PROP.")
 
 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
        1, 2, 0,
-  "Value is the value of window property PROP on FRAME.\n\
-If FRAME is nil or omitted, use the selected frame.  Value is nil\n\
-if FRAME hasn't a property with name PROP or if PROP has no string\n\
-value.")
-  (prop, frame)
+       doc: /* Value is the value of window property PROP on FRAME.
+If FRAME is nil or omitted, use the selected frame.  Value is nil
+if FRAME hasn't a property with name PROP or if PROP has no string
+value.  */)
+     (prop, frame)
      Lisp_Object prop, frame;
 {
   struct frame *f = check_x_frame (frame);
@@ -10309,9 +10659,9 @@ value.")
   int actual_format;
   unsigned long actual_size, bytes_remaining;
 
-  CHECK_STRING (prop, 1);
+  CHECK_STRING (prop);
   BLOCK_INPUT;
-  prop_atom = XInternAtom (FRAME_X_DISPLAY (f), XSTRING (prop)->data, False);
+  prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
   rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                           prop_atom, 0, 0, False, XA_STRING,
                           &actual_type, &actual_format, &actual_size,
@@ -10582,7 +10932,7 @@ x_create_tip_frame (dpyinfo, parms, text)
   Lisp_Object name;
   long window_prompting = 0;
   int width, height;
-  int count = BINDING_STACK_SIZE ();
+  int count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3;
   struct kboard *kb;
   int face_change_count_before = face_change_count;
@@ -10704,9 +11054,9 @@ x_create_tip_frame (dpyinfo, parms, text)
       {
        tem = Fquery_fontset (font, Qnil);
        if (STRINGP (tem))
-         font = x_new_fontset (f, XSTRING (tem)->data);
+         font = x_new_fontset (f, SDATA (tem));
        else
-         font = x_new_font (f, XSTRING (font)->data);
+         font = x_new_font (f, SDATA (font));
       }
     
     /* Try out a font which we hope has bold and italic variations.  */
@@ -10908,7 +11258,7 @@ compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
   
   /* Move the tooltip window where the mouse pointer is.  Resize and
      show it.  */
-  if (!INTEGERP (left) && !INTEGERP (top))
+  if (!INTEGERP (left) || !INTEGERP (top))
     {
       BLOCK_INPUT;
       XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
@@ -10928,69 +11278,73 @@ compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
 
   if (INTEGERP (left))
     *root_x = XINT (left);
-  else if (*root_x + XINT (dx) + width > FRAME_X_DISPLAY_INFO (f)->width)
+  else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
+    /* It fits to the right of the pointer.  */
+    *root_x += XINT (dx);
+  else if (width + XINT (dx) <= *root_x)
+    /* It fits to the left of the pointer.  */
     *root_x -= width + XINT (dx);
   else
-    *root_x += XINT (dx);
+    /* Put it left-justified on the screen--it ought to fit that way.  */
+    *root_x = 0;
 }
 
 
 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
-  "Show STRING in a \"tooltip\" window on frame FRAME.\n\
-A tooltip window is a small X window displaying a string.\n\
-\n\
-FRAME nil or omitted means use the selected frame.\n\
-\n\
-PARMS is an optional list of frame parameters which can be\n\
-used to change the tooltip's appearance.\n\
-\n\
-Automatically hide the tooltip after TIMEOUT seconds.\n\
-TIMEOUT nil means use the default timeout of 5 seconds.\n\
-\n\
-If the list of frame parameters PARAMS contains a `left' parameters,\n\
-the tooltip is displayed at that x-position.  Otherwise it is\n\
-displayed at the mouse position, with offset DX added (default is 5 if\n\
-DX isn't specified).  Likewise for the y-position; if a `top' frame\n\
-parameter is specified, it determines the y-position of the tooltip\n\
-window, otherwise it is displayed at the mouse position, with offset\n\
-DY added (default is -10).\n\
-\n\
-A tooltip's maximum size is specified by `x-max-tooltip-size'.\n\
-Text larger than the specified size is clipped.")
-  (string, frame, parms, timeout, dx, dy)
+       doc: /* Show STRING in a "tooltip" window on frame FRAME.
+A tooltip window is a small X window displaying a string.
+
+FRAME nil or omitted means use the selected frame.
+
+PARMS is an optional list of frame parameters which can be used to
+change the tooltip's appearance.
+
+Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
+means use the default timeout of 5 seconds.
+
+If the list of frame parameters PARAMS contains a `left' parameters,
+the tooltip is displayed at that x-position.  Otherwise it is
+displayed at the mouse position, with offset DX added (default is 5 if
+DX isn't specified).  Likewise for the y-position; if a `top' frame
+parameter is specified, it determines the y-position of the tooltip
+window, otherwise it is displayed at the mouse position, with offset
+DY added (default is -10).
+
+A tooltip's maximum size is specified by `x-max-tooltip-size'.
+Text larger than the specified size is clipped.  */)
+     (string, frame, parms, timeout, dx, dy)
      Lisp_Object string, frame, parms, timeout, dx, dy;
 {
   struct frame *f;
   struct window *w;
-  Lisp_Object buffer, top, left, max_width, max_height;
   int root_x, root_y;
   struct buffer *old_buffer;
   struct text_pos pos;
   int i, width, height;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   int old_windows_or_buffers_changed = windows_or_buffers_changed;
-  int count = BINDING_STACK_SIZE ();
+  int count = SPECPDL_INDEX ();
   
   specbind (Qinhibit_redisplay, Qt);
 
   GCPRO4 (string, parms, frame, timeout);
 
-  CHECK_STRING (string, 0);
+  CHECK_STRING (string);
   f = check_x_frame (frame);
   if (NILP (timeout))
     timeout = make_number (5);
   else
-    CHECK_NATNUM (timeout, 2);
+    CHECK_NATNUM (timeout);
   
   if (NILP (dx))
     dx = make_number (5);
   else
-    CHECK_NUMBER (dx, 5);
+    CHECK_NUMBER (dx);
   
   if (NILP (dy))
     dy = make_number (-10);
   else
-    CHECK_NUMBER (dy, 6);
+    CHECK_NUMBER (dy);
 
   if (NILP (last_show_tip_args))
     last_show_tip_args = Fmake_vector (make_number (3), Qnil);
@@ -11145,9 +11499,9 @@ Text larger than the specified size is clipped.")
 
 
 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
-  "Hide the current tooltip window, if there is any.\n\
-Value is t if tooltip was open, nil otherwise.")
-  ()
+       doc: /* Hide the current tooltip window, if there is any.
+Value is t if tooltip was open, nil otherwise.  */)
+     ()
 {
   int count;
   Lisp_Object deleted, frame, timer;
@@ -11162,7 +11516,7 @@ Value is t if tooltip was open, nil otherwise.")
   GCPRO2 (frame, timer);
   tip_frame = tip_timer = deleted = Qnil;
   
-  count = BINDING_STACK_SIZE ();
+  count = SPECPDL_INDEX ();
   specbind (Qinhibit_redisplay, Qt);
   specbind (Qinhibit_quit, Qt);
   
@@ -11235,12 +11589,12 @@ file_dialog_unmap_cb (widget, client_data, call_data)
 
 
 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
-  "Read file name, prompting with PROMPT in directory DIR.\n\
-Use a file selection dialog.\n\
-Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
-specified.  Don't let the user enter a file name in the file\n\
-selection dialog's entry field, if MUSTMATCH is non-nil.")
-  (prompt, dir, default_filename, mustmatch)
+       doc: /* Read file name, prompting with PROMPT in directory DIR.
+Use a file selection dialog.
+Select DEFAULT-FILENAME in the dialog's file selection box, if
+specified.  Don't let the user enter a file name in the file
+selection dialog's entry field, if MUSTMATCH is non-nil.  */)
+     (prompt, dir, default_filename, mustmatch)
      Lisp_Object prompt, dir, default_filename, mustmatch;
 {
   int result;
@@ -11251,12 +11605,12 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
   int ac = 0;
   extern XtAppContext Xt_app_con;
   XmString dir_xmstring, pattern_xmstring;
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
 
   GCPRO5 (prompt, dir, default_filename, mustmatch, file);
-  CHECK_STRING (prompt, 0);
-  CHECK_STRING (dir, 1);
+  CHECK_STRING (prompt);
+  CHECK_STRING (dir);
 
   /* Prevent redisplay.  */
   specbind (Qinhibit_redisplay, Qt);
@@ -11266,10 +11620,10 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
   /* 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 (XSTRING (dir)->data);
+  dir_xmstring = XmStringCreateLocalized (SDATA (dir));
   pattern_xmstring = XmStringCreateLocalized ("*");
     
-  XtSetArg (al[ac], XmNtitle, XSTRING (prompt)->data); ++ac;
+  XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
   XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
   XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
   XtSetArg (al[ac], XmNresizePolicy, XmRESIZE_GROW); ++ac;
@@ -11320,7 +11674,7 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
       int item_pos;
 
       default_xmstring
-       = XmStringCreateLocalized (XSTRING (default_filename)->data);
+       = XmStringCreateLocalized (SDATA (default_filename));
 
       if (!XmListItemExists (list, default_xmstring))
        {
@@ -11393,11 +11747,11 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
 
 DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
        Sx_backspace_delete_keys_p, 0, 1, 0,
-  "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\
-FRAME nil means use the selected frame.\n\
-Value is t if we know that both keys are present, and are mapped to the\n\
-usual X keysyms.")
-  (frame)
+       doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
+FRAME nil means use the selected frame.
+Value is t if we know that both keys are present, and are mapped to the
+usual X keysyms.  */)
+     (frame)
      Lisp_Object frame;
 {
 #ifdef HAVE_XKBGETKEYBOARD
@@ -11488,6 +11842,8 @@ syms_of_xfns ()
   staticpro (&Qauto_lower);
   Qbar = intern ("bar");
   staticpro (&Qbar);
+  Qhbar = intern ("hbar");
+  staticpro (&Qhbar);
   Qborder_color = intern ("border-color");
   staticpro (&Qborder_color);
   Qborder_width = intern ("border-width");
@@ -11558,6 +11914,14 @@ syms_of_xfns ()
   staticpro (&Qcancel_timer);
   Qwait_for_wm = intern ("wait-for-wm");
   staticpro (&Qwait_for_wm);
+  Qfullscreen = intern ("fullscreen");
+  staticpro (&Qfullscreen);
+  Qfullwidth = intern ("fullwidth");
+  staticpro (&Qfullwidth);
+  Qfullheight = intern ("fullheight");
+  staticpro (&Qfullheight);
+  Qfullboth = intern ("fullboth");
+  staticpro (&Qfullboth);
   /* This is the end of symbol initialization.  */
 
   /* Text property `display' should be nonsticky by default.  */
@@ -11591,131 +11955,131 @@ syms_of_xfns ()
   init_x_parm_symbols ();
 
   DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
-    "Non-nil means always draw a cross over disabled images.\n\
-Disabled images are those having an `:conversion disabled' property.\n\
-A cross is always drawn on black & white displays.");
+    doc: /* Non-nil means always draw a cross over disabled images.
+Disabled images are those having an `:conversion disabled' property.
+A cross is always drawn on black & white displays.  */);
   cross_disabled_images = 0;
 
   DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
-    "List of directories to search for bitmap files for X.");
+    doc: /* List of directories to search for bitmap files for X.  */);
   Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
 
   DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
-    "The shape of the pointer when over text.\n\
-Changing the value does not affect existing frames\n\
-unless you set the mouse color.");
+    doc: /* The shape of the pointer when over text.
+Changing the value does not affect existing frames
+unless you set the mouse color.  */);
   Vx_pointer_shape = Qnil;
 
   DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
-    "The name Emacs uses to look up X resources.\n\
-`x-get-resource' uses this as the first component of the instance name\n\
-when requesting resource values.\n\
-Emacs initially sets `x-resource-name' to the name under which Emacs\n\
-was invoked, or to the value specified with the `-name' or `-rn'\n\
-switches, if present.\n\
-\n\
-It may be useful to bind this variable locally around a call\n\
-to `x-get-resource'.  See also the variable `x-resource-class'.");
+    doc: /* The name Emacs uses to look up X resources.
+`x-get-resource' uses this as the first component of the instance name
+when requesting resource values.
+Emacs initially sets `x-resource-name' to the name under which Emacs
+was invoked, or to the value specified with the `-name' or `-rn'
+switches, if present.
+
+It may be useful to bind this variable locally around a call
+to `x-get-resource'.  See also the variable `x-resource-class'.  */);
   Vx_resource_name = Qnil;
 
   DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
-    "The class Emacs uses to look up X resources.\n\
-`x-get-resource' uses this as the first component of the instance class\n\
-when requesting resource values.\n\
-Emacs initially sets `x-resource-class' to \"Emacs\".\n\
-\n\
-Setting this variable permanently is not a reasonable thing to do,\n\
-but binding this variable locally around a call to `x-get-resource'\n\
-is a reasonable practice.  See also the variable `x-resource-name'.");
+    doc: /* The class Emacs uses to look up X resources.
+`x-get-resource' uses this as the first component of the instance class
+when requesting resource values.
+
+Emacs initially sets `x-resource-class' to "Emacs".
+
+Setting this variable permanently is not a reasonable thing to do,
+but binding this variable locally around a call to `x-get-resource'
+is a reasonable practice.  See also the variable `x-resource-name'.  */);
   Vx_resource_class = build_string (EMACS_CLASS);
 
 #if 0 /* This doesn't really do anything.  */
   DEFVAR_LISP ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
-             "The shape of the pointer when not over text.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
+    doc: /* The shape of the pointer when not over text.
+This variable takes effect when you create a new frame
+or when you set the mouse color.  */);
 #endif
   Vx_nontext_pointer_shape = Qnil;
 
   DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
-    "The shape of the pointer when Emacs is busy.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
+    doc: /* The shape of the pointer when Emacs is busy.
+This variable takes effect when you create a new frame
+or when you set the mouse color.  */);
   Vx_hourglass_pointer_shape = Qnil;
 
   DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
-    "Non-zero means Emacs displays an hourglass pointer on window systems.");
+    doc: /* Non-zero means Emacs displays an hourglass pointer on window systems.  */);
   display_hourglass_p = 1;
   
   DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
-     "*Seconds to wait before displaying an hourglass pointer.\n\
-Value must be an integer or float.");
+    doc: /* *Seconds to wait before displaying an hourglass pointer.
+Value must be an integer or float.  */);
   Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
 
 #if 0 /* This doesn't really do anything.  */
   DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
-             "The shape of the pointer when over the mode line.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
+    doc: /* The shape of the pointer when over the mode line.
+This variable takes effect when you create a new frame
+or when you set the mouse color.  */);
 #endif
   Vx_mode_pointer_shape = Qnil;
 
   DEFVAR_LISP ("x-sensitive-text-pointer-shape",
              &Vx_sensitive_text_pointer_shape,
-             "The shape of the pointer when over mouse-sensitive text.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
+              doc: /* The shape of the pointer when over mouse-sensitive text.
+This variable takes effect when you create a new frame
+or when you set the mouse color.  */);
   Vx_sensitive_text_pointer_shape = Qnil;
 
   DEFVAR_LISP ("x-window-horizontal-drag-cursor",
              &Vx_window_horizontal_drag_shape,
-  "Pointer shape to use for indicating a window can be dragged horizontally.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
+  doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
+This variable takes effect when you create a new frame
+or when you set the mouse color.  */);
   Vx_window_horizontal_drag_shape = Qnil;
 
   DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
-              "A string indicating the foreground color of the cursor box.");
+    doc: /* A string indicating the foreground color of the cursor box.  */);
   Vx_cursor_fore_pixel = Qnil;
 
   DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
-   "Maximum size for tooltips.  Value is a pair (COLUMNS . ROWS).\n\
-Text larger than this is clipped.");
+    doc: /* Maximum size for tooltips.  Value is a pair (COLUMNS . ROWS).
+Text larger than this is clipped.  */);
   Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
   
   DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
-              "Non-nil if no X window manager is in use.\n\
-Emacs doesn't try to figure this out; this is always nil\n\
-unless you set it to something else.");
+    doc: /* Non-nil if no X window manager is in use.
+Emacs doesn't try to figure this out; this is always nil
+unless you set it to something else.  */);
   /* We don't have any way to find this out, so set it to nil
      and maybe the user would like to set it to t.  */
   Vx_no_window_manager = Qnil;
 
   DEFVAR_LISP ("x-pixel-size-width-font-regexp",
               &Vx_pixel_size_width_font_regexp,
-     "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
-\n\
-Since Emacs gets width of a font matching with this regexp from\n\
-PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
-such a font.  This is especially effective for such large fonts as\n\
-Chinese, Japanese, and Korean.");
+    doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
+
+Since Emacs gets width of a font matching with this regexp from
+PIXEL_SIZE field of the name, font finding mechanism gets faster for
+such a font.  This is especially effective for such large fonts as
+Chinese, Japanese, and Korean.  */);
   Vx_pixel_size_width_font_regexp = Qnil;
 
   DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
-     "Time after which cached images are removed from the cache.\n\
-When an image has not been displayed this many seconds, remove it\n\
-from the image cache.  Value must be an integer or nil with nil\n\
-meaning don't clear the cache.");
+    doc: /* Time after which cached images are removed from the cache.
+When an image has not been displayed this many seconds, remove it
+from the image cache.  Value must be an integer or nil with nil
+meaning don't clear the cache.  */);
   Vimage_cache_eviction_delay = make_number (30 * 60);
 
 #ifdef USE_X_TOOLKIT
-  Fprovide (intern ("x-toolkit"));
-  
+  Fprovide (intern ("x-toolkit"), Qnil);
 #ifdef USE_MOTIF
-  Fprovide (intern ("motif"));
+  Fprovide (intern ("motif"), Qnil);
 
   DEFVAR_LISP ("motif-version-string", &Vmotif_version_string,
-     "Version info for LessTif/Motif.");
+              doc: /* Version info for LessTif/Motif.  */);
   Vmotif_version_string = build_string (XmVERSION_STRING);
 #endif /* USE_MOTIF */
 #endif /* USE_X_TOOLKIT */
@@ -11770,8 +12134,6 @@ meaning don't clear the cache.");
   /* Images.  */
   Qxbm = intern ("xbm");
   staticpro (&Qxbm);
-  QCtype = intern (":type");
-  staticpro (&QCtype);
   QCconversion = intern (":conversion");
   staticpro (&QCconversion);
   QCheuristic_mask = intern (":heuristic-mask");