Use XCAR and XCDR instead of explicit member references.
[bpt/emacs.git] / src / xfns.c
index 2d7a250..654b42f 100644 (file)
@@ -20,7 +20,7 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 /* Image support (XBM, XPM, PBM, JPEG, TIFF, GIF, PNG, GS). tooltips,
-   toolbars, busy-cursor, file selection dialog added by Gerd
+   tool-bars, busy-cursor, file selection dialog added by Gerd
    Moellmann <gerd@gnu.org>.  */
 
 /* Completely rewritten by Richard Stallman.  */
@@ -30,6 +30,7 @@ Boston, MA 02111-1307, USA.  */
 #include <signal.h>
 #include <config.h>
 #include <stdio.h>
+#include <math.h>
 
 /* This makes the fields of a Display accessible, in Xlib header files.  */
 
@@ -50,7 +51,13 @@ Boston, MA 02111-1307, USA.  */
 #include "termhooks.h"
 
 #ifdef HAVE_X_WINDOWS
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
 extern void abort ();
+#endif
+#include <ctype.h>
 
 /* On some systems, the character-composition stuff is broken in X11R5.  */
 
@@ -114,6 +121,7 @@ extern XFontStruct *xlwmenu_default_font;
 #endif
 
 extern void free_frame_menubar ();
+extern double atof ();
 
 #endif /* USE_X_TOOLKIT */
 
@@ -245,12 +253,13 @@ Lisp_Object Quser_position;
 Lisp_Object Quser_size;
 Lisp_Object Qdisplay;
 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
+Lisp_Object Qscreen_gamma;
 
 /* The below are defined in frame.c.  */
 
 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
-extern Lisp_Object Qtoolbar_lines;
+extern Lisp_Object Qtool_bar_lines;
 
 extern Lisp_Object Vwindow_system_version;
 
@@ -342,9 +351,9 @@ x_window_to_frame (dpyinfo, wdesc)
   Lisp_Object tail, frame;
   struct frame *f;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       if (!GC_FRAMEP (frame))
         continue;
       f = XFRAME (frame);
@@ -380,9 +389,9 @@ x_any_window_to_frame (dpyinfo, wdesc)
   struct frame *f;
   struct x_output *x;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       if (!GC_FRAMEP (frame))
         continue;
       f = XFRAME (frame);
@@ -418,9 +427,9 @@ x_non_menubar_window_to_frame (dpyinfo, wdesc)
   struct frame *f;
   struct x_output *x;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       if (!GC_FRAMEP (frame))
         continue;
       f = XFRAME (frame);
@@ -453,9 +462,9 @@ x_menubar_window_to_frame (dpyinfo, wdesc)
   struct frame *f;
   struct x_output *x;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       if (!GC_FRAMEP (frame))
         continue;
       f = XFRAME (frame);
@@ -482,9 +491,9 @@ x_top_window_to_frame (dpyinfo, wdesc)
   struct frame *f;
   struct x_output *x;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       if (!GC_FRAMEP (frame))
         continue;
       f = XFRAME (frame);
@@ -735,30 +744,32 @@ x_destroy_all_bitmaps (dpyinfo)
 struct x_frame_parm_table
 {
   char *name;
-  void (*setter)( /* struct frame *frame, Lisp_Object val, oldval */ );
+  void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
 };
 
-void x_set_foreground_color ();
-void x_set_background_color ();
-void x_set_mouse_color ();
-void x_set_cursor_color ();
-void x_set_border_color ();
-void x_set_cursor_type ();
-void x_set_icon_type ();
-void x_set_icon_name ();
-void x_set_font ();
-void x_set_border_width ();
-void x_set_internal_border_width ();
-void x_explicitly_set_name ();
-void x_set_autoraise ();
-void x_set_autolower ();
-void x_set_vertical_scroll_bars ();
-void x_set_visibility ();
-void x_set_menu_bar_lines ();
-void x_set_scroll_bar_width ();
-void x_set_title ();
-void x_set_unsplittable ();
-void x_set_toolbar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_foreground_color 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));
+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));
+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,
+                                     Lisp_Object));
+void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
+                                    Lisp_Object));
+void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
                                      Lisp_Object));
 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
@@ -768,6 +779,7 @@ static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
                                                             Lisp_Object,
                                                             char *, char *,
                                                             int));
+static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
 
 static struct x_frame_parm_table x_frame_parms[] =
 {
@@ -791,9 +803,10 @@ static struct x_frame_parm_table x_frame_parms[] =
   "unsplittable", x_set_unsplittable,
   "vertical-scroll-bars", x_set_vertical_scroll_bars,
   "visibility", x_set_visibility,
-  "toolbar-lines", x_set_toolbar_lines,
+  "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
 };
 
 /* Attach the `x-frame-parameter' properties to
@@ -834,7 +847,7 @@ x_set_frame_parameters (f, alist)
   /* Record in these vectors all the parms specified.  */
   Lisp_Object *parms;
   Lisp_Object *values;
-  int i;
+  int i, p;
   int left_no_change = 0, top_no_change = 0;
   int icon_left_no_change = 0, icon_top_no_change = 0;
 
@@ -882,6 +895,29 @@ x_set_frame_parameters (f, alist)
   else
     height = FRAME_HEIGHT (f);
 
+  /* 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.  */
+  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))
+       {
+         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);
+       }
+    }
+
   /* Now process them in reverse of specified order.  */
   for (i--; i >= 0; i--)
     {
@@ -902,6 +938,9 @@ 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))
+       /* Processed above.  */
+       continue;
       else
        {
          register Lisp_Object param_index, old_value;
@@ -988,18 +1027,18 @@ x_set_frame_parameters (f, alist)
            if (leftpos < 0)
              f->output_data.x->size_hint_flags |= XNegative;
          }
-       else if (CONSP (left) && EQ (XCONS (left)->car, Qminus)
-                && CONSP (XCONS (left)->cdr)
-                && INTEGERP (XCONS (XCONS (left)->cdr)->car))
+       else if (CONSP (left) && EQ (XCAR (left), Qminus)
+                && CONSP (XCDR (left))
+                && INTEGERP (XCAR (XCDR (left))))
          {
-           leftpos = - XINT (XCONS (XCONS (left)->cdr)->car);
+           leftpos = - XINT (XCAR (XCDR (left)));
            f->output_data.x->size_hint_flags |= XNegative;
          }
-       else if (CONSP (left) && EQ (XCONS (left)->car, Qplus)
-                && CONSP (XCONS (left)->cdr)
-                && INTEGERP (XCONS (XCONS (left)->cdr)->car))
+       else if (CONSP (left) && EQ (XCAR (left), Qplus)
+                && CONSP (XCDR (left))
+                && INTEGERP (XCAR (XCDR (left))))
          {
-           leftpos = XINT (XCONS (XCONS (left)->cdr)->car);
+           leftpos = XINT (XCAR (XCDR (left)));
          }
 
        if (EQ (top, Qminus))
@@ -1010,18 +1049,18 @@ x_set_frame_parameters (f, alist)
            if (toppos < 0)
              f->output_data.x->size_hint_flags |= YNegative;
          }
-       else if (CONSP (top) && EQ (XCONS (top)->car, Qminus)
-                && CONSP (XCONS (top)->cdr)
-                && INTEGERP (XCONS (XCONS (top)->cdr)->car))
+       else if (CONSP (top) && EQ (XCAR (top), Qminus)
+                && CONSP (XCDR (top))
+                && INTEGERP (XCAR (XCDR (top))))
          {
-           toppos = - XINT (XCONS (XCONS (top)->cdr)->car);
+           toppos = - XINT (XCAR (XCDR (top)));
            f->output_data.x->size_hint_flags |= YNegative;
          }
-       else if (CONSP (top) && EQ (XCONS (top)->car, Qplus)
-                && CONSP (XCONS (top)->cdr)
-                && INTEGERP (XCONS (XCONS (top)->cdr)->car))
+       else if (CONSP (top) && EQ (XCAR (top), Qplus)
+                && CONSP (XCDR (top))
+                && INTEGERP (XCAR (XCDR (top))))
          {
-           toppos = XINT (XCONS (XCONS (top)->cdr)->car);
+           toppos = XINT (XCAR (XCDR (top)));
          }
 
 
@@ -1166,7 +1205,7 @@ x_report_frame_params (f, alistptr)
                  (FRAME_VISIBLE_P (f) ? Qt
                   : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
   store_in_alist (alistptr, Qdisplay,
-                 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->car);
+                 XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
 
   if (f->output_data.x->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
     tem = Qnil;
@@ -1176,6 +1215,23 @@ x_report_frame_params (f, alistptr)
 }
 \f
 
+
+/* Gamma-correct COLOR on frame F.  */
+
+void
+gamma_correct (f, color)
+     struct frame *f;
+     XColor *color;
+{
+  if (f->gamma)
+    {
+      color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
+      color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
+      color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
+    }
+}
+
+
 /* Decide if color named COLOR is valid for the display associated with
    the selected frame; if so, return the rgb values in COLOR_DEF.
    If ALLOC is nonzero, allocate a new colormap cell.  */
@@ -1197,6 +1253,9 @@ defined_color (f, color, color_def, alloc)
   status = XParseColor (display, screen_colormap, color, color_def);
   if (status && alloc) 
     {
+      /* Apply gamma correction.  */
+      gamma_correct (f, color_def);
+      
       status = XAllocColor (display, screen_colormap, color_def);
       if (!status)
        {
@@ -1298,6 +1357,27 @@ x_decode_color (f, arg, def)
                          Fcons (arg, Qnil)));
 }
 \f
+/* Change the `screen-gamma' frame parameter of frame F.  OLD_VALUE is
+   the previous value of that parameter, NEW_VALUE is the new value.  */
+
+static void
+x_set_screen_gamma (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  if (NILP (new_value))
+    f->gamma = 0;
+  else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
+    /* The value 0.4545 is the normal viewing gamma.  */
+    f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
+  else
+    Fsignal (Qerror, Fcons (build_string ("Illegal screen-gamma"),
+                           Fcons (new_value, Qnil)));
+
+  clear_face_cache (0);
+}
+
+
 /* Functions called only from `x_set_frame_param'
    to set individual parameters.
 
@@ -1325,7 +1405,7 @@ x_set_foreground_color (f, arg, oldval)
       XSetBackground (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
                      f->output_data.x->foreground_pixel);
       UNBLOCK_INPUT;
-      recompute_basic_faces (f);
+      update_face_from_frame_parameter (f, Qforeground_color, arg);
       if (FRAME_VISIBLE_P (f))
         redraw_frame (f);
     }
@@ -1367,7 +1447,7 @@ x_set_background_color (f, arg, oldval)
       }
       UNBLOCK_INPUT;
 
-      recompute_basic_faces (f);
+      update_face_from_frame_parameter (f, Qbackground_color, arg);
 
       if (FRAME_VISIBLE_P (f))
         redraw_frame (f);
@@ -1506,6 +1586,8 @@ x_set_mouse_color (f, arg, oldval)
 
   XFlush (FRAME_X_DISPLAY (f));
   UNBLOCK_INPUT;
+
+  update_face_from_frame_parameter (f, Qmouse_color, arg);
 }
 
 void
@@ -1551,6 +1633,8 @@ x_set_cursor_color (f, arg, oldval)
          x_update_cursor (f, 1);
        }
     }
+
+  update_face_from_frame_parameter (f, Qcursor_color, arg);
 }
 \f
 /* Set the border-color of frame F to value described by ARG.
@@ -1569,15 +1653,12 @@ x_set_border_color (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  unsigned char *str;
   int pix;
 
   CHECK_STRING (arg, 0);
-  str = XSTRING (arg)->data;
-
   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);
 }
 
 /* Set the border-color of frame F to pixel value PIX.
@@ -1617,11 +1698,11 @@ x_set_cursor_type (f, arg, oldval)
       FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
       f->output_data.x->cursor_width = 2;
     }
-  else if (CONSP (arg) && EQ (XCONS (arg)->car, Qbar)
-          && INTEGERP (XCONS (arg)->cdr))
+  else if (CONSP (arg) && EQ (XCAR (arg), Qbar)
+          && INTEGERP (XCDR (arg)))
     {
       FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
-      f->output_data.x->cursor_width = XINT (XCONS (arg)->cdr);
+      f->output_data.x->cursor_width = XINT (XCDR (arg));
     }
   else
     /* Treat anything unknown as "box cursor".
@@ -1678,7 +1759,7 @@ x_icon_type (f)
 
   tem = assq_no_quit (Qicon_type, f->param_alist);
   if (CONSP (tem))
-    return XCONS (tem)->cdr;
+    return XCDR (tem);
   else
     return Qnil;
 }
@@ -1753,7 +1834,7 @@ x_set_font (f, arg, oldval)
   else
     abort ();
 
-  do_pending_window_change ();
+  do_pending_window_change (0);
 
   /* Don't call `face-set-after-frame-default' when faces haven't been
      initialized yet.  This is the case when called from
@@ -1807,7 +1888,7 @@ x_set_internal_border_width (f, arg, oldval)
     {
       x_set_window_size (f, 0, f->width, f->height);
       SET_FRAME_GARBAGED (f);
-      do_pending_window_change ();
+      do_pending_window_change (0);
     }
 }
 
@@ -1904,7 +1985,7 @@ x_set_menu_bar_lines (f, value, oldval)
    The frame's height doesn't change.  */
 
 void
-x_set_toolbar_lines (f, value, oldval)
+x_set_tool_bar_lines (f, value, oldval)
      struct frame *f;
      Lisp_Object value, oldval;
 {
@@ -1919,8 +2000,8 @@ x_set_toolbar_lines (f, value, oldval)
   /* Make sure we redisplay all windows in this frame.  */
   ++windows_or_buffers_changed;
 
-  delta = nlines - FRAME_TOOLBAR_LINES (f);
-  FRAME_TOOLBAR_LINES (f) = nlines;
+  delta = nlines - FRAME_TOOL_BAR_LINES (f);
+  FRAME_TOOL_BAR_LINES (f) = nlines;
   x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f), delta);
   adjust_glyphs (f);
 }
@@ -1954,7 +2035,8 @@ x_set_scroll_bar_foreground (f, value, oldval)
        (*condemn_scroll_bars_hook) (f);
       if (judge_scroll_bars_hook)
        (*judge_scroll_bars_hook) (f);
-      
+
+      update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
       redraw_frame (f);
     }
 }
@@ -1989,6 +2071,7 @@ x_set_scroll_bar_background (f, value, oldval)
       if (judge_scroll_bars_hook)
        (*judge_scroll_bars_hook) (f);
       
+      update_face_from_frame_parameter (f, Qscroll_bar_background, value);
       redraw_frame (f);
     }
 }
@@ -2122,9 +2205,9 @@ x_implicitly_set_name (f, arg, oldval)
        F->explicit_name is set, ignore the new name; otherwise, set it.  */
 
 void
-x_set_title (f, name)
+x_set_title (f, name, old_name)
      struct frame *f;
-     Lisp_Object name;
+     Lisp_Object name, old_name;
 {
   /* Don't change the title if it's already NAME.  */
   if (EQ (name, f->title))
@@ -2225,7 +2308,7 @@ x_set_vertical_scroll_bars (f, arg, oldval)
         call x_set_window_size.  */
       if (FRAME_X_WINDOW (f))
        x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
-      do_pending_window_change ();
+      do_pending_window_change (0);
     }
 }
 
@@ -2238,8 +2321,8 @@ x_set_scroll_bar_width (f, arg, oldval)
 
   if (NILP (arg))
     {
-#ifdef USE_X_TOOLKIT
-      /* A too wide or narrow toolkit scroll bar doesn't look good.  */
+#ifdef USE_TOOLKIT_SCROLL_BARS
+      /* A minimum width of 14 doesn't look good for toolkit scroll bars.  */
       int width = 16 + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM;
       FRAME_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid;
       FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = width;
@@ -2255,7 +2338,7 @@ x_set_scroll_bar_width (f, arg, oldval)
 
       if (FRAME_X_WINDOW (f))
         x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
-      do_pending_window_change ();
+      do_pending_window_change (0);
     }
   else if (INTEGERP (arg) && XINT (arg) > 0
           && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
@@ -2269,7 +2352,7 @@ x_set_scroll_bar_width (f, arg, oldval)
        x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
     }
 
-  change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0);
+  change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
 }
@@ -2521,6 +2604,7 @@ x_get_resource_string (attribute, class)
 enum resource_types
 {
   RES_TYPE_NUMBER,
+  RES_TYPE_FLOAT,
   RES_TYPE_BOOLEAN,
   RES_TYPE_STRING,
   RES_TYPE_SYMBOL
@@ -2568,6 +2652,9 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
            case RES_TYPE_NUMBER:
              return make_number (atoi (XSTRING (tem)->data));
 
+           case RES_TYPE_FLOAT:
+             return make_float (atof (XSTRING (tem)->data));
+
            case RES_TYPE_BOOLEAN:
              tem = Fdowncase (tem);
              if (!strcmp (XSTRING (tem)->data, "on")
@@ -2820,7 +2907,7 @@ x_figure_window_size (f, parms)
        ? 0
        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
   f->output_data.x->flags_areas_extra
-    = 2 * FRAME_FLAGS_AREA_WIDTH (f);
+    = FRAME_FLAGS_AREA_WIDTH (f);
   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);
 
@@ -2834,18 +2921,18 @@ x_figure_window_size (f, parms)
          f->output_data.x->top_pos = 0;
          window_prompting |= YNegative;
        }
-      else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qminus)
-              && CONSP (XCONS (tem0)->cdr)
-              && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
+      else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
+              && CONSP (XCDR (tem0))
+              && INTEGERP (XCAR (XCDR (tem0))))
        {
-         f->output_data.x->top_pos = - XINT (XCONS (XCONS (tem0)->cdr)->car);
+         f->output_data.x->top_pos = - XINT (XCAR (XCDR (tem0)));
          window_prompting |= YNegative;
        }
-      else if (CONSP (tem0) && EQ (XCONS (tem0)->car, Qplus)
-              && CONSP (XCONS (tem0)->cdr)
-              && INTEGERP (XCONS (XCONS (tem0)->cdr)->car))
+      else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
+              && CONSP (XCDR (tem0))
+              && INTEGERP (XCAR (XCDR (tem0))))
        {
-         f->output_data.x->top_pos = XINT (XCONS (XCONS (tem0)->cdr)->car);
+         f->output_data.x->top_pos = XINT (XCAR (XCDR (tem0)));
        }
       else if (EQ (tem0, Qunbound))
        f->output_data.x->top_pos = 0;
@@ -2862,18 +2949,18 @@ x_figure_window_size (f, parms)
          f->output_data.x->left_pos = 0;
          window_prompting |= XNegative;
        }
-      else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qminus)
-              && CONSP (XCONS (tem1)->cdr)
-              && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
+      else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
+              && CONSP (XCDR (tem1))
+              && INTEGERP (XCAR (XCDR (tem1))))
        {
-         f->output_data.x->left_pos = - XINT (XCONS (XCONS (tem1)->cdr)->car);
+         f->output_data.x->left_pos = - XINT (XCAR (XCDR (tem1)));
          window_prompting |= XNegative;
        }
-      else if (CONSP (tem1) && EQ (XCONS (tem1)->car, Qplus)
-              && CONSP (XCONS (tem1)->cdr)
-              && INTEGERP (XCONS (XCONS (tem1)->cdr)->car))
+      else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
+              && CONSP (XCDR (tem1))
+              && INTEGERP (XCAR (XCDR (tem1))))
        {
-         f->output_data.x->left_pos = XINT (XCONS (XCONS (tem1)->cdr)->car);
+         f->output_data.x->left_pos = XINT (XCAR (XCDR (tem1)));
        }
       else if (EQ (tem1, Qunbound))
        f->output_data.x->left_pos = 0;
@@ -3208,12 +3295,9 @@ x_window (f, window_prompting, minibuffer_only)
 
   UNBLOCK_INPUT;
 
-  if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
-    initialize_frame_menubar (f);
-  lw_set_main_areas (pane_widget, f->output_data.x->menubar_widget, frame_widget);
-
-  if (FRAME_X_WINDOW (f) == 0)
-    error ("Unable to create window");
+  /* This is a no-op, except under Motif.  Make sure main areas are
+     set to something reasonable, in case we get an error later.  */
+  lw_set_main_areas (pane_widget, 0, frame_widget);
 }
 
 #else /* not USE_X_TOOLKIT */
@@ -3589,8 +3673,8 @@ This function is an internal primitive--use `make-frame' instead.")
     }
 
   /* Create fontsets from `global_fontset_alist' before handling fonts.  */
-  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCONS (tem)->cdr)
-    fs_register_fontset (f, XCONS (tem)->car);
+  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCDR (tem))
+    fs_register_fontset (f, XCAR (tem));
 
   /* Extract the window parameters from the supplied values
      that are needed to determine window geometry.  */
@@ -3672,6 +3756,8 @@ This function is an internal primitive--use `make-frame' instead.")
                       "cursorColor", "Foreground", RES_TYPE_STRING);
   x_default_parameter (f, parms, Qborder_color, build_string ("black"),
                       "borderColor", "BorderColor", RES_TYPE_STRING);
+  x_default_parameter (f, parms, Qscreen_gamma, Qnil,
+                      "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
 
   x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
                                        "scrollBarForeground",
@@ -3690,7 +3776,7 @@ This function is an internal primitive--use `make-frame' instead.")
   
   x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
                       "menuBar", "MenuBar", RES_TYPE_NUMBER);
-  x_default_parameter (f, parms, Qtoolbar_lines, make_number (0),
+  x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
                       "toolBar", "ToolBar", RES_TYPE_NUMBER);
   x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
                       "scrollBarWidth", "ScrollBarWidth",
@@ -3721,23 +3807,30 @@ This function is an internal primitive--use `make-frame' instead.")
 
   f->output_data.x->size_hint_flags = window_prompting;
 
-  /* Create the X widget or window.  Add the toolbar height to the
+  tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
+  f->no_split = minibuffer_only || EQ (tem, Qt);
+
+  /* Create the X widget or window.  Add the tool-bar height to the
      initial frame height so that the user gets a text display area of
      the size he specified with -g or via .Xdefaults.  Later changes
-     of the toolbar height don't change the frame size.  This is done
+     of the tool-bar height don't change the frame size.  This is done
      so that users can create tall Emacs frames without having to
-     guess how tall the toolbar will get.  */
-  f->height += FRAME_TOOLBAR_LINES (f);
+     guess how tall the tool-bar will get.  */
+  f->height += FRAME_TOOL_BAR_LINES (f);
+
 #ifdef USE_X_TOOLKIT
   x_window (f, window_prompting, minibuffer_only);
 #else
   x_window (f);
 #endif
+  
   x_icon (f, parms);
   x_make_gc (f);
 
-  call1 (Qface_set_after_frame_default, frame);
-  
+  /* Now consider the frame official.  */
+  FRAME_X_DISPLAY_INFO (f)->reference_count++;
+  Vframe_list = Fcons (frame, Vframe_list);
+
   /* We need to do this after creating the X window, so that the
      icon-creation functions can say whose icon they're describing.  */
   x_default_parameter (f, parms, Qicon_type, Qnil,
@@ -3757,32 +3850,37 @@ This function is an internal primitive--use `make-frame' instead.")
   height = f->height;
   f->height = 0;
   SET_FRAME_WIDTH (f, 0);
-  change_frame_size (f, height, width, 1, 0);
-
-  /* Tell the server what size and position, etc, we want,
-     and how badly we want them.  */
-  BLOCK_INPUT;
-  x_wm_set_size_hint (f, window_prompting, 0);
-  UNBLOCK_INPUT;
+  change_frame_size (f, height, width, 1, 0, 0);
 
-  tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
-  f->no_split = minibuffer_only || EQ (tem, Qt);
+  /* Set up faces after all frame parameters are known.  */
+  call1 (Qface_set_after_frame_default, frame);
 
-  UNGCPRO;
+#ifdef USE_X_TOOLKIT
+  /* Create the menu bar.  */
+  if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
+    {
+      /* If this signals an error, we haven't set size hints for the
+        frame and we didn't make it visible.  */
+      initialize_frame_menubar (f);
 
-  /* It is now ok to make the frame official
-     even if we get an error below.
-     And the frame needs to be on Vframe_list
-     or making it visible won't work.  */
-  Vframe_list = Fcons (frame, Vframe_list);
+      /* This is a no-op, except under Motif where it arranges the
+        main window for the widgets on it.  */
+      lw_set_main_areas (f->output_data.x->column_widget,
+                        f->output_data.x->menubar_widget,
+                        f->output_data.x->edit_widget);
+    }
+#endif /* USE_X_TOOLKIT */
 
-  /* Now that the frame is official, it counts as a reference to
-     its display.  */
-  FRAME_X_DISPLAY_INFO (f)->reference_count++;
+  /* Tell the server what size and position, etc, we want, and how
+     badly we want them.  This should be done after we have the menu
+     bar so that its size can be taken into account.  */
+  BLOCK_INPUT;
+  x_wm_set_size_hint (f, window_prompting, 0);
+  UNBLOCK_INPUT;
 
-  /* Make the window appear on the frame and enable display,
-     unless the caller says not to.  However, with explicit parent,
-     Emacs cannot control visibility, so don't try.  */
+  /* Make the window appear on the frame and enable display, unless
+     the caller says not to.  However, with explicit parent, Emacs
+     cannot control visibility, so don't try.  */
   if (! f->output_data.x->explicit_parent)
     {
       Lisp_Object visibility;
@@ -3801,6 +3899,7 @@ This function is an internal primitive--use `make-frame' instead.")
        ;
     }
 
+  UNGCPRO;
   return unbind_to (count, frame);
 }
 
@@ -5163,10 +5262,10 @@ x_display_info_for_name (name)
 
   for (dpyinfo = x_display_list, names = x_display_name_list;
        dpyinfo;
-       dpyinfo = dpyinfo->next, names = XCONS (names)->cdr)
+       dpyinfo = dpyinfo->next, names = XCDR (names))
     {
       Lisp_Object tem;
-      tem = Fstring_equal (XCONS (XCONS (names)->car)->car, name);
+      tem = Fstring_equal (XCAR (XCAR (names)), name);
       if (!NILP (tem))
        return dpyinfo;
     }
@@ -5284,8 +5383,8 @@ DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
   Lisp_Object tail, result;
 
   result = Qnil;
-  for (tail = x_display_name_list; ! NILP (tail); tail = XCONS (tail)->cdr)
-    result = Fcons (XCONS (XCONS (tail)->car)->car, result);
+  for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
+    result = Fcons (XCAR (XCAR (tail)), result);
 
   return result;
 }
@@ -5352,7 +5451,7 @@ Lisp_Object Qxbm;
 Lisp_Object QCtype, QCdata, QCfile, QCascent, QCmargin, QCrelief;
 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground;
 Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
-extern Lisp_Object QCimage;
+Lisp_Object QCindex;
 
 /* Other symbols.  */
 
@@ -5361,7 +5460,7 @@ Lisp_Object Qlaplace;
 /* Time in seconds after which images should be removed from the cache
    if not displayed.  */
 
-Lisp_Object Vimage_eviction_seconds;
+Lisp_Object Vimage_cache_eviction_delay;
 
 /* Function prototypes.  */
 
@@ -5890,14 +5989,14 @@ clear_image_cache (f, force_p)
 {
   struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
 
-  if (c && INTEGERP (Vimage_eviction_seconds))
+  if (c && INTEGERP (Vimage_cache_eviction_delay))
     {
       EMACS_TIME t;
       unsigned long old;
       int i, any_freed_p = 0;
 
       EMACS_GET_TIME (t);
-      old = EMACS_SECS (t) - XFASTINT (Vimage_eviction_seconds);
+      old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
       
       for (i = 0; i < c->used; ++i)
        {
@@ -6948,8 +7047,13 @@ xpm_load (f, img)
   attrs.visual = FRAME_X_DISPLAY_INFO (f)->visual;
   attrs.valuemask |= XpmVisual;
   attrs.valuemask |= XpmReturnAllocPixels;
+#ifdef XpmAllocCloseColors
   attrs.alloc_close_colors = 1;
   attrs.valuemask |= XpmAllocCloseColors;
+#else
+  attrs.closeness = 600;
+  attrs.valuemask |= XpmCloseness;
+#endif
 
   /* If image specification contains symbolic color definitions, add
      these to `attrs'.  */
@@ -7166,8 +7270,7 @@ lookup_rgb_color (f, r, g, b)
       
       BLOCK_INPUT;
       cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-      rc = x_alloc_nearest_color (FRAME_X_DISPLAY (f), FRAME_X_SCREEN (f),
-                                 cmap, &color);
+      rc = x_alloc_nearest_color (f, cmap, &color);
       UNBLOCK_INPUT;
 
       if (rc)
@@ -7216,8 +7319,7 @@ lookup_pixel_color (f, pixel)
       cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
       color.pixel = pixel;
       XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
-      rc = x_alloc_nearest_color (FRAME_X_DISPLAY (f), FRAME_X_SCREEN (f),
-                                 cmap, &color);
+      rc = x_alloc_nearest_color (f, cmap, &color);
       UNBLOCK_INPUT;
 
       if (rc)
@@ -7414,10 +7516,10 @@ x_laplace (f, img)
 
 /* Build a mask for image IMG which is used on frame F.  FILE is the
    name of an image file, for error messages.  HOW determines how to
-   determine the background color of IMG.  If it is an integer, take
-   that as the pixel value of the background.  Otherwise, determine
-   the background color of IMG heuristically.  Value is non-zero
-   if successful.  */
+   determine the background color of IMG.  If it is a list '(R G B)',
+   with R, G, and B being integers >= 0, take that as the color of the
+   background.  Otherwise, determine the background color of IMG
+   heuristically.  Value is non-zero if successful. */
 
 static int
 x_build_heuristic_mask (f, file, img, how)
@@ -7429,7 +7531,7 @@ x_build_heuristic_mask (f, file, img, how)
   Display *dpy = FRAME_X_DISPLAY (f);
   Window win = FRAME_X_WINDOW (f);
   XImage *ximg, *mask_img;
-  int x, y, rc;
+  int x, y, rc, look_at_corners_p;
   unsigned long bg;
 
   BLOCK_INPUT;
@@ -7447,12 +7549,41 @@ x_build_heuristic_mask (f, file, img, how)
   ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
                    ~0, ZPixmap);
 
-  /* Determine the background color of ximg.  If HOW is an integer,
-     take that as a pixel color.  Otherwise, try to determine the
-     color heuristically.  */
-  if (NATNUMP (how))
-    bg = XFASTINT (how);
-  else
+  /* 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;
+  
+  if (CONSP (how))
+    {
+      int rgb[3], i = 0;
+
+      while (i < 3
+            && CONSP (how)
+            && NATNUMP (XCAR (how)))
+       {
+         rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
+         how = XCDR (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 = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+         if (XLookupColor (dpy, cmap, color_name, &exact, &color))
+           {
+             bg = color.pixel;
+             look_at_corners_p = 0;
+           }
+       }
+    }
+  
+  if (look_at_corners_p)
     {
       unsigned long corners[4];
       int i, best_count;
@@ -8216,10 +8347,21 @@ png_load (f, img)
 
 #if HAVE_JPEG
 
+/* Work around a warning about HAVE_STDLIB_H being redefined in
+   jconfig.h.  */
+#ifdef HAVE_STDLIB_H
+#define HAVE_STDLIB_H_1
+#undef HAVE_STDLIB_H
+#endif /* HAVE_STLIB_H */
+
 #include <jpeglib.h>
 #include <jerror.h>
 #include <setjmp.h>
 
+#ifdef HAVE_STLIB_H_1
+#define HAVE_STDLIB_H 1
+#endif
+
 static int jpeg_image_p P_ ((Lisp_Object object));
 static int jpeg_load P_ ((struct frame *f, struct image *img));
 
@@ -8466,7 +8608,7 @@ jpeg_load (f, img)
 
 #if HAVE_TIFF
 
-#include <tiff34/tiffio.h>
+#include <tiffio.h>
 
 static int tiff_image_p P_ ((Lisp_Object object));
 static int tiff_load P_ ((struct frame *f, struct image *img));
@@ -8756,7 +8898,7 @@ gif_load (f, img)
       return 0;
     }
 
-  image = image_spec_value (img->spec, QCimage, NULL);
+  image = image_spec_value (img->spec, QCindex, NULL);
   ino = INTEGERP (image) ? XFASTINT (image) : 0;
   if (ino >= gif->ImageCount)
     {
@@ -8877,9 +9019,9 @@ static int gs_image_p P_ ((Lisp_Object object));
 static int gs_load P_ ((struct frame *f, struct image *img));
 static void gs_clear_image P_ ((struct frame *f, struct image *img));
 
-/* The symbol `ghostscript' identifying images of this type.  */
+/* The symbol `postscript' identifying images of this type.  */
 
-Lisp_Object Qghostscript;
+Lisp_Object Qpostscript;
 
 /* Keyword symbols.  */
 
@@ -8925,7 +9067,7 @@ static struct image_keyword gs_format[GS_LAST] =
 
 static struct image_type gs_type =
 {
-  &Qghostscript,
+  &Qpostscript,
   gs_image_p,
   gs_load,
   gs_clear_image,
@@ -8959,7 +9101,7 @@ gs_image_p (object)
   
   bcopy (gs_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, GS_LAST, Qghostscript, 1)
+  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript, 1)
       || (fmt[GS_ASCENT].count 
          && XFASTINT (fmt[GS_ASCENT].value) > 100))
     return 0;
@@ -9449,8 +9591,8 @@ x_create_tip_frame (dpyinfo, parms)
     }
 
   /* Create fontsets from `global_fontset_alist' before handling fonts.  */
-  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCONS (tem)->cdr)
-    fs_register_fontset (f, XCONS (tem)->car);
+  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCDR (tem))
+    fs_register_fontset (f, XCAR (tem));
 
   /* Extract the window parameters from the supplied values
      that are needed to determine window geometry.  */
@@ -9595,7 +9737,7 @@ x_create_tip_frame (dpyinfo, parms)
   height = f->height;
   f->height = 0;
   SET_FRAME_WIDTH (f, 0);
-  change_frame_size (f, height, width, 1, 0);
+  change_frame_size (f, height, width, 1, 0, 0);
 
   f->no_split = 1;
 
@@ -9615,7 +9757,9 @@ x_create_tip_frame (dpyinfo, parms)
 
 
 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 4, 0,
-  "Show tooltip STRING on frame FRAME.\n\
+  "Show STRING in a \"tooltip\" window on frame FRAME.\n\
+A tooltip window is a small X window displaying STRING at\n\
+the current mouse position.\n\
 FRAME nil or omitted means use the selected frame.\n\
 PARMS is an optional list of frame parameters which can be\n\
 used to change the tooltip's appearance.\n\
@@ -9753,7 +9897,7 @@ TIMEOUT nil means use the default timeout of 5 seconds.")
 
 
 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
-  "Hide the current tooltip, if there is any.\n\
+  "Hide the current tooltip window, if there is any.\n\
 Value is t is tooltip was open, nil otherwise.")
   ()
 {
@@ -10069,6 +10213,8 @@ syms_of_xfns ()
   staticpro (&Qscroll_bar_foreground);
   Qscroll_bar_background = intern ("scroll-bar-background");
   staticpro (&Qscroll_bar_background);
+  Qscreen_gamma = intern ("screen-gamma");
+  staticpro (&Qscreen_gamma);
   /* This is the end of symbol initialization.  */
 
   Qlaplace = intern ("laplace");
@@ -10172,12 +10318,12 @@ such a font.  This is especially effective for such large fonts as\n\
 Chinese, Japanese, and Korean.");
   Vx_pixel_size_width_font_regexp = Qnil;
 
-  DEFVAR_LISP ("image-eviction-seconds", &Vimage_eviction_seconds,
+  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.");
-  Vimage_eviction_seconds = make_number (30 * 60);
+  Vimage_cache_eviction_delay = make_number (30 * 60);
 
   DEFVAR_LISP ("image-types", &Vimage_types,
      "List of supported image types.\n\
@@ -10273,8 +10419,8 @@ Each element of the list is a symbol for a supported image type.");
   staticpro (&QCmargin);
   QCrelief = intern (":relief");
   staticpro (&QCrelief);
-  Qghostscript = intern ("ghostscript");
-  staticpro (&Qghostscript);
+  Qpostscript = intern ("postscript");
+  staticpro (&Qpostscript);
   QCloader = intern (":loader");
   staticpro (&QCloader);
   QCbounding_box = intern (":bounding-box");
@@ -10283,6 +10429,8 @@ Each element of the list is a symbol for a supported image type.");
   staticpro (&QCpt_width);
   QCpt_height = intern (":pt-height");
   staticpro (&QCpt_height);
+  QCindex = intern (":index");
+  staticpro (&QCindex);
   Qpbm = intern ("pbm");
   staticpro (&Qpbm);