Porting fixes for merged specpdl and backtrace stacks.
[bpt/emacs.git] / src / frame.c
index 3501fc3..ba9074d 100644 (file)
@@ -1,6 +1,6 @@
 /* Generic frame functions.
 
-Copyright (C) 1993-1995, 1997, 1999-201 Free Software Foundation, Inc.
+Copyright (C) 1993-1995, 1997, 1999-2013 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -60,7 +60,7 @@ Lisp_Object Qns_parse_geometry;
 Lisp_Object Qframep, Qframe_live_p;
 Lisp_Object Qicon, Qmodeline;
 Lisp_Object Qonly, Qnone;
-Lisp_Object Qx, Qw32, Qmac, Qpc, Qns;
+Lisp_Object Qx, Qw32, Qpc, Qns;
 Lisp_Object Qvisible;
 Lisp_Object Qdisplay_type;
 static Lisp_Object Qbackground_mode;
@@ -76,7 +76,6 @@ Lisp_Object Qterminal_live_p;
 Lisp_Object Qauto_raise, Qauto_lower;
 Lisp_Object Qborder_color, Qborder_width;
 Lisp_Object Qcursor_color, Qcursor_type;
-static Lisp_Object Qgeometry;  /* Not used */
 Lisp_Object Qheight, Qwidth;
 Lisp_Object Qleft, Qright;
 Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name;
@@ -115,6 +114,8 @@ Lisp_Object Qface_set_after_frame_default;
 
 static Lisp_Object Qdelete_frame_functions;
 
+static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
+
 #ifdef HAVE_WINDOW_SYSTEM
 static void x_report_frame_params (struct frame *, Lisp_Object *);
 #endif
@@ -149,25 +150,56 @@ decode_any_frame (register Lisp_Object frame)
   return XFRAME (frame);
 }
 
+bool
+window_system_available (struct frame *f)
+{
+  if (f)
+    return FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f);
+  else
+#ifdef HAVE_WINDOW_SYSTEM
+    return x_display_list != NULL;
+#else
+    return 0;
+#endif
+}
+
+struct frame *
+decode_window_system_frame (Lisp_Object frame)
+{
+  struct frame *f = decode_live_frame (frame);
+
+  if (!window_system_available (f))
+    error ("Window system frame should be used");
+  return f;
+}
+
+void
+check_window_system (struct frame *f)
+{
+  if (!window_system_available (f))
+    error (f ? "Window system frame should be used"
+          : "Window system is not in use or not initialized");
+}
+
 static void
 set_menu_bar_lines_1 (Lisp_Object window, int n)
 {
   struct window *w = XWINDOW (window);
 
   w->last_modified = 0;
-  wset_top_line (w, make_number (XFASTINT (w->top_line) + n));
-  wset_total_lines (w, make_number (XFASTINT (w->total_lines) - n));
+  w->top_line += n;
+  w->total_lines -= n;
 
   /* Handle just the top child in a vertical split.  */
-  if (!NILP (w->vchild))
-    set_menu_bar_lines_1 (w->vchild, n);
-
-  /* Adjust all children in a horizontal split.  */
-  for (window = w->hchild; !NILP (window); window = w->next)
-    {
-      w = XWINDOW (window);
-      set_menu_bar_lines_1 (window, n);
-    }
+  if (WINDOW_VERTICAL_COMBINATION_P (w))
+    set_menu_bar_lines_1 (w->contents, n);
+  else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
+    /* Adjust all children in a horizontal split.  */
+    for (window = w->contents; !NILP (window); window = w->next)
+      {
+       w = XWINDOW (window);
+       set_menu_bar_lines_1 (window, n);
+      }
 }
 
 void
@@ -225,8 +257,6 @@ See also `frame-live-p'.  */)
       return Qw32;
     case output_msdos_raw:
       return Qpc;
-    case output_mac:
-      return Qmac;
     case output_ns:
       return Qns;
     default:
@@ -334,25 +364,22 @@ make_frame (int mini_p)
   SET_FRAME_COLS (f, 10);
   FRAME_LINES (f) = 10;
 
-  wset_total_cols (XWINDOW (root_window), make_number (10));
-  wset_total_lines (XWINDOW (root_window), make_number (mini_p ? 9 : 10));
+  XWINDOW (root_window)->total_cols = 10;
+  XWINDOW (root_window)->total_lines = mini_p ? 9 : 10;
 
   if (mini_p)
     {
-      wset_total_cols (XWINDOW (mini_window), make_number (10));
-      wset_top_line (XWINDOW (mini_window), make_number (9));
-      wset_total_lines (XWINDOW (mini_window), make_number (1));
+      XWINDOW (mini_window)->total_cols = 10;
+      XWINDOW (mini_window)->top_line = 9;
+      XWINDOW (mini_window)->total_lines = 1;
     }
 
   /* Choose a buffer for the frame's root window.  */
   {
-    Lisp_Object buf;
+    Lisp_Object buf = Fcurrent_buffer ();
 
-    wset_buffer (XWINDOW (root_window), Qt);
-    buf = Fcurrent_buffer ();
-    /* If buf is a 'hidden' buffer (i.e. one whose name starts with
-       a space), try to find another one.  */
-    if (SREF (Fbuffer_name (buf), 0) == ' ')
+    /* If current buffer is hidden, try to find another one.  */
+    if (BUFFER_HIDDEN_P (XBUFFER (buf)))
       buf = other_buffer_safely (buf);
 
     /* Use set_window_buffer, not Fset_window_buffer, and don't let
@@ -366,14 +393,11 @@ make_frame (int mini_p)
   }
 
   if (mini_p)
-    {
-      wset_buffer (XWINDOW (mini_window), Qt);
-      set_window_buffer (mini_window,
-                        (NILP (Vminibuffer_list)
-                         ? get_minibuffer (0)
-                         : Fcar (Vminibuffer_list)),
-                        0, 0);
-    }
+    set_window_buffer (mini_window,
+                      (NILP (Vminibuffer_list)
+                       ? get_minibuffer (0)
+                       : Fcar (Vminibuffer_list)),
+                      0, 0);
 
   fset_root_window (f, root_window);
   fset_selected_window (f, root_window);
@@ -429,7 +453,7 @@ make_frame_without_minibuffer (register Lisp_Object mini_window, KBOARD *kb, Lis
 
   /* Make the chosen minibuffer window display the proper minibuffer,
      unless it is already showing a minibuffer.  */
-  if (NILP (Fmemq (XWINDOW (mini_window)->buffer, Vminibuffer_list)))
+  if (NILP (Fmemq (XWINDOW (mini_window)->contents, Vminibuffer_list)))
     /* Use set_window_buffer instead of Fset_window_buffer (see
        discussion of bug#11984, bug#12025, bug#12026).  */
     set_window_buffer (mini_window,
@@ -508,8 +532,7 @@ make_initial_frame (void)
   tty_frame_count = 1;
   fset_name (f, build_pure_c_string ("F1"));
 
-  f->visible = 1;
-  f->async_visible = 1;
+  SET_FRAME_VISIBLE (f, 1);
 
   f->output_method = terminal->type;
   f->terminal = terminal;
@@ -548,8 +571,8 @@ make_terminal_frame (struct terminal *terminal)
 
   fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
 
-  f->visible = 1;              /* FRAME_SET_VISIBLE wd set frame_garbaged. */
-  f->async_visible = 1;                /* Don't let visible be cleared later. */
+  SET_FRAME_VISIBLE (f, 1);
+
   f->terminal = terminal;
   f->terminal->reference_count++;
 #ifdef MSDOS
@@ -573,7 +596,7 @@ make_terminal_frame (struct terminal *terminal)
   /* Set the top frame to the newly created frame. */
   if (FRAMEP (FRAME_TTY (f)->top_frame)
       && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
-    XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */
+    SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
 
   FRAME_TTY (f)->top_frame = frame;
 
@@ -812,10 +835,18 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
 
   if (FRAME_TERMCAP_P (XFRAME (frame)) || FRAME_MSDOS_P (XFRAME (frame)))
     {
-      if (FRAMEP (FRAME_TTY (XFRAME (frame))->top_frame))
-       /* Mark previously displayed frame as now obscured.  */
-       XFRAME (FRAME_TTY (XFRAME (frame))->top_frame)->async_visible = 2;
-      XFRAME (frame)->async_visible = 1;
+      Lisp_Object top_frame = FRAME_TTY (XFRAME (frame))->top_frame;
+
+      /* Don't mark the frame garbaged and/or obscured if we are
+        switching to the frame that is already the top frame of that
+        TTY.  */
+      if (!EQ (frame, top_frame))
+       {
+         if (FRAMEP (top_frame))
+           /* Mark previously displayed frame as now obscured.  */
+           SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
+         SET_FRAME_VISIBLE (XFRAME (frame), 1);
+       }
       FRAME_TTY (XFRAME (frame))->top_frame = frame;
     }
 
@@ -895,13 +926,56 @@ DEFUN ("frame-list", Fframe_list, Sframe_list,
   return frames;
 }
 
-/* Return the next frame in the frame list after FRAME.
-   If MINIBUF is nil, exclude minibuffer-only frames.
-   If MINIBUF is a window, include only its own frame
-   and any frame now using that window as the minibuffer.
-   If MINIBUF is `visible', include all visible frames.
-   If MINIBUF is 0, include all visible and iconified frames.
-   Otherwise, include all frames.  */
+/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
+   same tty (for tty frames) or among frames which uses FRAME's keyboard.
+   If MINIBUF is nil, do not consider minibuffer-only candidate.
+   If MINIBUF is `visible', do not consider an invisible candidate.
+   If MINIBUF is a window, consider only its own frame and candidate now
+   using that window as the minibuffer.
+   If MINIBUF is 0, consider candidate if it is visible or iconified.
+   Otherwise consider any candidate and return nil if CANDIDATE is not
+   acceptable.  */
+
+static Lisp_Object
+candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
+{
+  struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
+
+  if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
+       && FRAME_KBOARD (c) == FRAME_KBOARD (f))
+      || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
+         && FRAME_TTY (c) == FRAME_TTY (f)))
+    {
+      if (NILP (minibuf))
+       {
+         if (!FRAME_MINIBUF_ONLY_P (c))
+           return candidate;
+       }
+      else if (EQ (minibuf, Qvisible))
+       {
+         if (FRAME_VISIBLE_P (c))
+           return candidate;
+       }
+      else if (WINDOWP (minibuf))
+       {
+         if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
+             || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
+             || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
+                    FRAME_FOCUS_FRAME (c)))
+           return candidate;
+       }
+      else if (XFASTINT (minibuf) == 0)
+       {
+         if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
+           return candidate;
+       }
+      else
+       return candidate;
+    }
+  return Qnil;
+}
+
+/* Return the next frame in the frame list after FRAME.  */
 
 static Lisp_Object
 next_frame (Lisp_Object frame, Lisp_Object minibuf)
@@ -910,72 +984,24 @@ next_frame (Lisp_Object frame, Lisp_Object minibuf)
   int passed = 0;
 
   /* There must always be at least one frame in Vframe_list.  */
-  if (! CONSP (Vframe_list))
-    emacs_abort ();
-
-  /* If this frame is dead, it won't be in Vframe_list, and we'll loop
-     forever.  Forestall that.  */
-  CHECK_LIVE_FRAME (frame);
+  eassert (CONSP (Vframe_list));
 
-  while (1)
+  while (passed < 2)
     FOR_EACH_FRAME (tail, f)
       {
-       if (passed
-           && ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
-                 && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
-                || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
-                    && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame)))))
+       if (passed)
          {
-           /* Decide whether this frame is eligible to be returned.  */
-
-           /* If we've looped all the way around without finding any
-              eligible frames, return the original frame.  */
-           if (EQ (f, frame))
-             return f;
-
-           /* Let minibuf decide if this frame is acceptable.  */
-           if (NILP (minibuf))
-             {
-               if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
-                 return f;
-             }
-           else if (EQ (minibuf, Qvisible))
-             {
-               FRAME_SAMPLE_VISIBILITY (XFRAME (f));
-               if (FRAME_VISIBLE_P (XFRAME (f)))
-                 return f;
-             }
-           else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
-             {
-               FRAME_SAMPLE_VISIBILITY (XFRAME (f));
-               if (FRAME_VISIBLE_P (XFRAME (f))
-                   || FRAME_ICONIFIED_P (XFRAME (f)))
-                 return f;
-             }
-           else if (WINDOWP (minibuf))
-             {
-               if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
-                   || EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
-                   || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
-                          FRAME_FOCUS_FRAME (XFRAME (f))))
-                 return f;
-             }
-           else
+           f = candidate_frame (f, frame, minibuf);
+           if (!NILP (f))
              return f;
          }
-
        if (EQ (frame, f))
          passed++;
       }
+  return frame;
 }
 
-/* Return the previous frame in the frame list before FRAME.
-   If MINIBUF is nil, exclude minibuffer-only frames.
-   If MINIBUF is a window, include only its own frame
-   and any frame now using that window as the minibuffer.
-   If MINIBUF is `visible', include all visible frames.
-   If MINIBUF is 0, include all visible and iconified frames.
-   Otherwise, include all frames.  */
+/* Return the previous frame in the frame list before FRAME.  */
 
 static Lisp_Object
 prev_frame (Lisp_Object frame, Lisp_Object minibuf)
@@ -989,43 +1015,9 @@ prev_frame (Lisp_Object frame, Lisp_Object minibuf)
     {
       if (EQ (frame, f) && !NILP (prev))
        return prev;
-
-      if ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
-           && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
-          || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
-              && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame))))
-       {
-         /* Decide whether this frame is eligible to be returned,
-            according to minibuf.  */
-         if (NILP (minibuf))
-           {
-             if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
-               prev = f;
-           }
-         else if (WINDOWP (minibuf))
-           {
-             if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
-                 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
-                 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
-                        FRAME_FOCUS_FRAME (XFRAME (f))))
-               prev = f;
-           }
-         else if (EQ (minibuf, Qvisible))
-           {
-             FRAME_SAMPLE_VISIBILITY (XFRAME (f));
-             if (FRAME_VISIBLE_P (XFRAME (f)))
-               prev = f;
-           }
-         else if (XFASTINT (minibuf) == 0)
-           {
-             FRAME_SAMPLE_VISIBILITY (XFRAME (f));
-             if (FRAME_VISIBLE_P (XFRAME (f))
-                 || FRAME_ICONIFIED_P (XFRAME (f)))
-               prev = f;
-           }
-         else
-           prev = f;
-       }
+      f = candidate_frame (f, frame, minibuf);
+      if (!NILP (f))
+       prev = f;
     }
 
   /* We've scanned the entire list.  */
@@ -1056,7 +1048,6 @@ Otherwise, include all frames.  */)
 {
   if (NILP (frame))
     frame = selected_frame;
-
   CHECK_LIVE_FRAME (frame);
   return next_frame (frame, miniframe);
 }
@@ -1098,10 +1089,7 @@ other_visible_frames (FRAME_PTR f)
         and note any recent change in visibility.  */
 #ifdef HAVE_WINDOW_SYSTEM
       if (FRAME_WINDOW_P (XFRAME (this)))
-       {
-         x_sync (XFRAME (this));
-         FRAME_SAMPLE_VISIBILITY (XFRAME (this));
-       }
+       x_sync (XFRAME (this));
 #endif
 
       if (FRAME_VISIBLE_P (XFRAME (this))
@@ -1241,7 +1229,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
       /* Use set_window_buffer instead of Fset_window_buffer (see
         discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-                        XWINDOW (minibuf_window)->buffer, 0, 0);
+                        XWINDOW (minibuf_window)->contents, 0, 0);
       minibuf_window = sf->minibuffer_window;
 
       /* If the dying minibuffer window was selected,
@@ -1277,7 +1265,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
   fset_root_window (f, Qnil);
 
   Vframe_list = Fdelq (frame, Vframe_list);
-  FRAME_SET_VISIBLE (f, 0);
+  SET_FRAME_VISIBLE (f, 0);
 
   /* Allow the vector of menu bar contents to be freed in the next
      garbage collection.  The frame object itself may not be garbage
@@ -1297,7 +1285,6 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
   xfree (FRAME_DELETEN_COST (f));
   xfree (FRAME_INSERTN_COST (f));
   xfree (FRAME_DELETE_COST (f));
-  xfree (FRAME_MESSAGE_BUF (f));
 
   /* Since some events are handled at the interrupt level, we may get
      an event for f at any time; if we zero out the frame's terminal
@@ -1312,10 +1299,10 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
   {
     struct terminal *terminal = FRAME_TERMINAL (f);
     f->output_data.nothing = 0;
-    f->terminal = 0;             /* Now the frame is dead. */
+    f->terminal = 0;             /* Now the frame is dead.  */
 
     /* If needed, delete the terminal that this frame was on.
-       (This must be done after the frame is killed.) */
+       (This must be done after the frame is killed.)  */
     terminal->reference_count--;
 #ifdef USE_GTK
     /* FIXME: Deleting the terminal crashes emacs because of a GTK
@@ -1626,10 +1613,7 @@ If omitted, FRAME defaults to the currently selected frame.  */)
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f))
-    {
-      FRAME_SAMPLE_VISIBILITY (f);
-      x_make_frame_visible (f);
-    }
+    x_make_frame_visible (f);
 #endif
 
   make_frame_visible_1 (f->root_window);
@@ -1649,17 +1633,13 @@ make_frame_visible_1 (Lisp_Object window)
 {
   struct window *w;
 
-  for (;!NILP (window); window = w->next)
+  for (; !NILP (window); window = w->next)
     {
       w = XWINDOW (window);
-
-      if (!NILP (w->buffer))
-       bset_display_time (XBUFFER (w->buffer), Fcurrent_time ());
-
-      if (!NILP (w->vchild))
-       make_frame_visible_1 (w->vchild);
-      if (!NILP (w->hchild))
-       make_frame_visible_1 (w->hchild);
+      if (WINDOWP (w->contents))
+       make_frame_visible_1 (w->contents);
+      else
+       bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
     }
 }
 
@@ -1690,7 +1670,7 @@ displayed in the terminal.  */)
       /* Use set_window_buffer instead of Fset_window_buffer (see
         discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-                        XWINDOW (minibuf_window)->buffer, 0, 0);
+                        XWINDOW (minibuf_window)->contents, 0, 0);
       minibuf_window = sf->minibuffer_window;
     }
 
@@ -1721,7 +1701,7 @@ If omitted, FRAME defaults to the currently selected frame.  */)
       /* Use set_window_buffer instead of Fset_window_buffer (see
         discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-                        XWINDOW (minibuf_window)->buffer, 0, 0);
+                        XWINDOW (minibuf_window)->contents, 0, 0);
       minibuf_window = sf->minibuffer_window;
     }
 
@@ -1752,8 +1732,6 @@ currently being displayed on the terminal.  */)
 {
   CHECK_LIVE_FRAME (frame);
 
-  FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
-
   if (FRAME_VISIBLE_P (XFRAME (frame)))
     return Qt;
   if (FRAME_ICONIFIED_P (XFRAME (frame)))
@@ -1877,7 +1855,7 @@ See `redirect-frame-focus'.  */)
 /* Return the value of frame parameter PROP in frame FRAME.  */
 
 #ifdef HAVE_WINDOW_SYSTEM
-#if !HAVE_NS
+#if !HAVE_NS && !defined(WINDOWSNT)
 static
 #endif
 Lisp_Object
@@ -2314,7 +2292,7 @@ For a terminal frame, the value is always 1.  */)
   struct frame *f = decode_any_frame (frame);
 
   if (FRAME_WINDOW_P (f))
-    return make_number (x_char_height (f));
+    return make_number (FRAME_LINE_HEIGHT (f));
   else
 #endif
     return make_number (1);
@@ -2333,7 +2311,7 @@ For a terminal screen, the value is always 1.  */)
   struct frame *f = decode_any_frame (frame);
 
   if (FRAME_WINDOW_P (f))
-    return make_number (x_char_width (f));
+    return make_number (FRAME_COLUMN_WIDTH (f));
   else
 #endif
     return make_number (1);
@@ -2938,7 +2916,6 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
                  make_formatted_string (buf, "%"pMu, w));
 #endif
   store_in_alist (alistptr, Qicon_name, f->icon_name);
-  FRAME_SAMPLE_VISIBILITY (f);
   store_in_alist (alistptr, Qvisibility,
                  (FRAME_VISIBLE_P (f) ? Qt
                   : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
@@ -2948,7 +2925,7 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
   if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
     tem = Qnil;
   else
-    XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
+    tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc);
   store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
   store_in_alist (alistptr, Qparent_id, tem);
   store_in_alist (alistptr, Qtool_bar_position, f->tool_bar_position);
@@ -3374,16 +3351,15 @@ x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       else if (FLOATP (item))
        {
          alpha = XFLOAT_DATA (item);
-         if (alpha < 0.0 || 1.0 < alpha)
+         if (! (0 <= alpha && alpha <= 1.0))
            args_out_of_range (make_float (0.0), make_float (1.0));
        }
       else if (INTEGERP (item))
        {
          EMACS_INT ialpha = XINT (item);
-         if (ialpha < 0 || 100 < ialpha)
+         if (! (0 <= ialpha && alpha <= 100))
            args_out_of_range (make_number (0), make_number (100));
-         else
-           alpha = ialpha / 100.0;
+         alpha = ialpha / 100.0;
        }
       else
        wrong_type_argument (Qnumberp, item);
@@ -3554,11 +3530,10 @@ 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'.  */)
-  (Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
+  (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
+   Lisp_Object subclass)
 {
-#ifdef HAVE_X_WINDOWS
-  check_x ();
-#endif
+  check_window_system (NULL);
 
   return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
                            attribute, class, component, subclass);
@@ -3567,7 +3542,9 @@ and the class is `Emacs.CLASS.SUBCLASS'.  */)
 /* Get an X resource, like Fx_get_resource, but for display DPYINFO.  */
 
 Lisp_Object
-display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
+display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
+                       Lisp_Object class, Lisp_Object component,
+                       Lisp_Object subclass)
 {
   return xrdb_get_resource (dpyinfo->xrdb,
                            attribute, class, component, subclass);
@@ -4153,6 +4130,76 @@ selected frame.  This is useful when `make-pointer-invisible' is set.  */)
   return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
 }
 
+
+\f
+/***********************************************************************
+                       Multimonitor data
+ ***********************************************************************/
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+# if (defined HAVE_NS \
+      || (!defined USE_GTK && (defined HAVE_XINERAMA || defined HAVE_XRANDR)))
+void
+free_monitors (struct MonitorInfo *monitors, int n_monitors)
+{
+  int i;
+  for (i = 0; i < n_monitors; ++i)
+    xfree (monitors[i].name);
+  xfree (monitors);
+}
+# endif
+
+Lisp_Object
+make_monitor_attribute_list (struct MonitorInfo *monitors,
+                             int n_monitors,
+                             int primary_monitor,
+                             Lisp_Object monitor_frames,
+                             const char *source)
+{
+  Lisp_Object attributes_list = Qnil;
+  Lisp_Object primary_monitor_attributes = Qnil;
+  int i;
+
+  for (i = 0; i < n_monitors; ++i)
+    {
+      Lisp_Object geometry, workarea, attributes = Qnil;
+      struct MonitorInfo *mi = &monitors[i];
+
+      if (mi->geom.width == 0) continue;
+
+      workarea = list4i (mi->work.x, mi->work.y,
+                        mi->work.width, mi->work.height);
+      geometry = list4i (mi->geom.x, mi->geom.y,
+                        mi->geom.width, mi->geom.height);
+      attributes = Fcons (Fcons (Qsource,
+                                 make_string (source, strlen (source))),
+                          attributes);
+      attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
+                         attributes);
+      attributes = Fcons (Fcons (Qmm_size,
+                                 list2i (mi->mm_width, mi->mm_height)),
+                          attributes);
+      attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
+      attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
+      if (mi->name)
+        attributes = Fcons (Fcons (Qname, make_string (mi->name,
+                                                       strlen (mi->name))),
+                            attributes);
+
+      if (i == primary_monitor)
+        primary_monitor_attributes = attributes;
+      else
+        attributes_list = Fcons (attributes, attributes_list);
+    }
+
+  if (!NILP (primary_monitor_attributes))
+    attributes_list = Fcons (primary_monitor_attributes, attributes_list);
+  return attributes_list;
+}
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
 \f
 /***********************************************************************
                                Initialization
@@ -4211,6 +4258,12 @@ syms_of_frame (void)
   DEFSYM (Qterminal, "terminal");
   DEFSYM (Qterminal_live_p, "terminal-live-p");
 
+  DEFSYM (Qgeometry, "geometry");
+  DEFSYM (Qworkarea, "workarea");
+  DEFSYM (Qmm_size, "mm-size");
+  DEFSYM (Qframes, "frames");
+  DEFSYM (Qsource, "source");
+
 #ifdef HAVE_NS
   DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
 #endif
@@ -4292,6 +4345,16 @@ Setting this variable does not affect existing frames, only new ones.  */);
   Vdefault_frame_scroll_bars = Qnil;
 #endif
 
+  DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
+               scroll_bar_adjust_thumb_portion_p,
+               doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
+Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
+even if the end of the buffer is shown (i.e. overscrolling).
+Set to nil if you want the thumb to be at the bottom when the end of the buffer
+is shown.  Also, the thumb fills the whole scroll bar when the entire buffer
+is visible.  In this case you can not overscroll.  */);
+  scroll_bar_adjust_thumb_portion_p = 1;
+
   DEFVAR_LISP ("terminal-frame", Vterminal_frame,
                doc: /* The initial frame-object, which represents Emacs's stdout.  */);