* dispnew.c (init_display): Use Qx, Qw32, and Qns.
[bpt/emacs.git] / src / dispnew.c
index a4219ea..5236d53 100644 (file)
@@ -1,14 +1,14 @@
 /* Updating of data structures for redisplay.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
                  1997, 1998, 1999, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <signal.h>
@@ -61,9 +59,9 @@ Boston, MA 02110-1301, USA.  */
 #include "w32term.h"
 #endif /* HAVE_NTGUI */
 
-#ifdef MAC_OS
-#include "macterm.h"
-#endif /* MAC_OS */
+#ifdef HAVE_NS
+#include "nsterm.h"
+#endif
 
 /* Include systime.h after xterm.h to avoid double inclusion of time.h.  */
 
@@ -324,7 +322,9 @@ static struct frame *frame_matrix_frame;
    matrix adjustments.  Redisplay must stop, and glyph matrices must
    be adjusted when this flag becomes non-zero during display.  The
    reason fonts can be loaded so late is that fonts of fontsets are
-   loaded on demand.  */
+   loaded on demand.  Another reason is that a line contains many
+   characters displayed by zero width or very narrow glyphs of
+   variable-width fonts.  */
 
 int fonts_changed_p;
 
@@ -633,7 +633,7 @@ adjust_glyph_matrix (w, matrix, x, y, dim)
   int header_line_changed_p = 0;
   int header_line_p = 0;
   int left = -1, right = -1;
-  int window_width = -1, window_height;
+  int window_width = -1, window_height = -1;
 
   /* See if W had a header line that has disappeared now, or vice versa.
      Get W's size.  */
@@ -1468,9 +1468,11 @@ line_draw_cost (matrix, vpos)
       len = 0;
       while (beg < end)
        {
-         GLYPH g = GLYPH_FROM_CHAR_GLYPH (*beg);
+         GLYPH g;
+
+         SET_GLYPH_FROM_CHAR_GLYPH (g, *beg);
 
-         if (g < 0
+         if (GLYPH_INVALID_P (g)
              || GLYPH_SIMPLE_P (glyph_table_base, glyph_table_len, g))
            len += 1;
          else
@@ -2175,7 +2177,7 @@ showing_window_margins_p (w)
       else if (!NILP (w->left_margin_cols)
               || !NILP (w->right_margin_cols))
        return 1;
+
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
     }
   return 0;
@@ -2740,7 +2742,9 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
   struct glyph_matrix *window_matrix;
   int window_y, frame_y;
   /* If non-zero, a glyph to insert at the right border of W.  */
-  GLYPH right_border_glyph = 0;
+  GLYPH right_border_glyph;
+
+  SET_GLYPH_FROM_CHAR (right_border_glyph, 0);
 
   /* Set window_matrix to the matrix we have to add to FRAME_MATRIX.  */
   if (w->must_be_updated_p)
@@ -2751,15 +2755,19 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
       if (!WINDOW_RIGHTMOST_P (w))
        {
          struct Lisp_Char_Table *dp = window_display_table (w);
+         Lisp_Object gc;
 
-         right_border_glyph
-           = ((dp && INTEGERP (DISP_BORDER_GLYPH (dp)))
-              ? spec_glyph_lookup_face (w, XINT (DISP_BORDER_GLYPH (dp)))
-              : '|');
+         SET_GLYPH_FROM_CHAR (right_border_glyph, '|');
+         if (dp
+             && (gc = DISP_BORDER_GLYPH (dp), GLYPH_CODE_P (gc))
+             && GLYPH_CODE_CHAR_VALID_P (gc))
+           {
+             SET_GLYPH_FROM_GLYPH_CODE (right_border_glyph, gc);
+             spec_glyph_lookup_face (w, &right_border_glyph);
+           }
 
-         if (FAST_GLYPH_FACE (right_border_glyph) <= 0)
-           right_border_glyph
-             = FAST_MAKE_GLYPH (right_border_glyph, VERTICAL_BORDER_FACE_ID);
+         if (GLYPH_FACE (right_border_glyph) <= 0)
+           SET_GLYPH_FACE (right_border_glyph, VERTICAL_BORDER_FACE_ID);
        }
     }
   else
@@ -2809,7 +2817,7 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
 
           /* Maybe insert a vertical border between horizontally adjacent
             windows.  */
-          if (right_border_glyph)
+          if (GLYPH_CHAR (right_border_glyph) != 0)
            {
               struct glyph *border = window_row->glyphs[LAST_AREA] - 1;
              SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph);
@@ -2845,21 +2853,19 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
    This is used for glyphs displayed specially and not part of the text;
    for instance, vertical separators, truncation markers, etc.  */
 
-GLYPH
+void
 spec_glyph_lookup_face (w, glyph)
      struct window *w;
-     GLYPH glyph;
+     GLYPH *glyph;
 {
-  int lface_id = FAST_GLYPH_FACE (glyph);
+  int lface_id = GLYPH_FACE (*glyph);
   /* Convert the glyph's specified face to a realized (cache) face.  */
   if (lface_id > 0)
     {
       int face_id = merge_faces (XFRAME (w->frame),
                                 Qt, lface_id, DEFAULT_FACE_ID);
-      glyph
-       = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), face_id);
+      SET_GLYPH_FACE (*glyph, face_id);
     }
-  return glyph;
 }
 
 /* Add spaces to a glyph row ROW in a window matrix.
@@ -3384,7 +3390,7 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
   update_begin (f);
 #ifdef MSDOS
   if (FRAME_MSDOS_P (f))
-    set_terminal_modes (FRAME_TERMINAL (f));
+    FRAME_TERMINAL (f)->set_terminal_modes_hook (FRAME_TERMINAL (f));
 #endif
   clear_frame (f);
   clear_current_matrices (f);
@@ -3508,6 +3514,7 @@ direct_output_for_insert (g)
       || g == '\t'
       || g == '\n'
       || g == '\r'
+      || (g == ' ' && !NILP (current_buffer->word_wrap))
       /* Give up if unable to display the cursor in the window.  */
       || w->cursor.vpos < 0
       /* Give up if we are showing a message or just cleared the message
@@ -3947,11 +3954,12 @@ update_frame (f, force_p, inhibit_hairy_id_p)
       paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p);
       update_end (f);
 
-      if (FRAME_TERMCAP_P (f))
+      if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
         {
           if (FRAME_TTY (f)->termscript)
             fflush (FRAME_TTY (f)->termscript);
-          fflush (FRAME_TTY (f)->output);
+         if (FRAME_TERMCAP_P (f))
+           fflush (FRAME_TTY (f)->output);
         }
 
       /* Check window matrices for lost pointers.  */
@@ -4058,7 +4066,7 @@ redraw_overlapped_rows (w, yb)
 {
   int i;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  
+
   /* If rows overlapping others have been changed, the rows being
      overlapped have to be redrawn.  This won't draw lines that have
      already been drawn in update_window_line because overlapped_p in
@@ -4109,7 +4117,7 @@ redraw_overlapping_rows (w, yb)
   int i, bottom_y;
   struct glyph_row *row;
   struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
-  
+
   for (i = 0; i < w->current_matrix->nrows; ++i)
     {
       row = w->current_matrix->rows + i;
@@ -4121,14 +4129,14 @@ redraw_overlapping_rows (w, yb)
 
       bottom_y = MATRIX_ROW_BOTTOM_Y (row);
 
-      if (row->overlapping_p && i > 0 && bottom_y < yb)
+      if (row->overlapping_p)
        {
          int overlaps = 0;
 
-         if (MATRIX_ROW_OVERLAPS_PRED_P (row)
+         if (MATRIX_ROW_OVERLAPS_PRED_P (row) && i > 0
              && !MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p)
            overlaps |= OVERLAPS_PRED;
-         if (MATRIX_ROW_OVERLAPS_SUCC_P (row)
+         if (MATRIX_ROW_OVERLAPS_SUCC_P (row) && bottom_y < yb
              && !MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p)
            overlaps |= OVERLAPS_SUCC;
 
@@ -4467,6 +4475,7 @@ update_text_area (w, vpos)
       struct glyph *desired_glyph = desired_row->glyphs[TEXT_AREA];
       int overlapping_glyphs_p = current_row->contains_overlapping_glyphs_p;
       int desired_stop_pos = desired_row->used[TEXT_AREA];
+      int abort_skipping = 0;
 
       /* If the desired row extends its face to the text area end, and
         unless the current row also does so at the same position,
@@ -4486,7 +4495,7 @@ update_text_area (w, vpos)
         in common.  */
       while (i < stop)
        {
-         int can_skip_p = 1;
+         int can_skip_p = !abort_skipping;
 
          /* Skip over glyphs that both rows have in common.  These
             don't have to be written.  We can't skip if the last
@@ -4503,11 +4512,13 @@ update_text_area (w, vpos)
 
              rif->get_glyph_overhangs (glyph, XFRAME (w->frame),
                                        &left, &right);
-             can_skip_p = right == 0;
+             can_skip_p = (right == 0 && !abort_skipping);
            }
 
          if (can_skip_p)
            {
+             int start_hpos = i;
+
              while (i < stop
                     && GLYPH_EQUAL_P (desired_glyph, current_glyph))
                {
@@ -4539,6 +4550,12 @@ update_text_area (w, vpos)
                      x -= desired_glyph->pixel_width;
                      left -= desired_glyph->pixel_width;
                    }
+
+                 /* Abort the skipping algorithm if we end up before
+                    our starting point, to avoid looping (bug#1070).
+                    This can happen when the lbearing is larger than
+                    the pixel width.  */
+                 abort_skipping = (i < start_hpos);
                }
            }
 
@@ -5296,22 +5313,26 @@ update_frame_1 (f, force_p, inhibit_id_p)
                 Also flush out if likely to have more than 1k buffered
                 otherwise.   I'm told that some telnet connections get
                 really screwed by more than 1k output at once.  */
-             int outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f)->output);
-             if (outq > 900
-                 || (outq > 20 && ((i - 1) % preempt_count == 0)))
+             FILE *display_output = FRAME_TTY (f)->output;
+             if (display_output)
                {
-                 fflush (FRAME_TTY (f)->output);
-                 if (preempt_count == 1)
+                 int outq = PENDING_OUTPUT_COUNT (display_output);
+                 if (outq > 900
+                     || (outq > 20 && ((i - 1) % preempt_count == 0)))
                    {
+                     fflush (display_output);
+                     if (preempt_count == 1)
+                       {
 #ifdef EMACS_OUTQSIZE
-                     if (EMACS_OUTQSIZE (0, &outq) < 0)
-                       /* Probably not a tty.  Ignore the error and reset
-                          the outq count.  */
-                       outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f->output));
+                         if (EMACS_OUTQSIZE (0, &outq) < 0)
+                           /* Probably not a tty.  Ignore the error and reset
+                              the outq count.  */
+                           outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f->output));
 #endif
-                     outq *= 10;
-                     if (baud_rate <= outq && baud_rate > 0)
-                       sleep (outq / baud_rate);
+                         outq *= 10;
+                         if (baud_rate <= outq && baud_rate > 0)
+                           sleep (outq / baud_rate);
+                       }
                    }
                }
            }
@@ -5912,7 +5933,7 @@ buffer_posn_from_coords (w, x, y, pos, object, dx, dy, width, height)
      int *width, *height;
 {
   struct it it;
-  struct buffer *old_current_buffer = current_buffer;
+  Lisp_Object old_current_buffer = Fcurrent_buffer ();
   struct text_pos startp;
   Lisp_Object string;
   struct glyph_row *row;
@@ -5921,7 +5942,9 @@ buffer_posn_from_coords (w, x, y, pos, object, dx, dy, width, height)
 #endif
   int x0, x1;
 
-  current_buffer = XBUFFER (w->buffer);
+  /* We used to set current_buffer directly here, but that does the
+     wrong thing with `face-remapping-alist' (bug#2044).  */
+  Fset_buffer (w->buffer);
   SET_TEXT_POS_FROM_MARKER (startp, w->start);
   CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp)));
   BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp)));
@@ -5931,7 +5954,7 @@ buffer_posn_from_coords (w, x, y, pos, object, dx, dy, width, height)
   move_it_to (&it, -1, x0 + it.first_visible_x, *y, -1,
              MOVE_TO_X | MOVE_TO_Y);
 
-  current_buffer = old_current_buffer;
+  Fset_buffer (old_current_buffer);
 
   *dx = x0 + it.first_visible_x - it.current_x;
   *dy = *y - it.current_y;
@@ -6195,11 +6218,16 @@ window_change_signal (signalnum) /* If we don't have an argument, */
     if (! tty->term_initted)
       continue;
 
+    /* Suspended tty frames have tty->input == NULL avoid trying to
+       use it.  */
+    if (!tty->input)
+      continue;
+
     get_tty_size (fileno (tty->input), &width, &height);
-    
+
     if (width > 5 && height > 2) {
       Lisp_Object tail, frame;
-      
+
       FOR_EACH_FRAME (tail, frame)
         if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty)
           /* Record the new sizes, but don't reallocate the data
@@ -6208,7 +6236,7 @@ window_change_signal (signalnum) /* If we don't have an argument, */
           change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
     }
   }
-  
+
   errno = old_errno;
 }
 #endif /* SIGWINCH */
@@ -6335,7 +6363,7 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe)
                             (newheight
                              - 1
                              - FRAME_TOP_MARGIN (f)),
-                             0);
+                            2);
          XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top_line,
                       newheight - 1);
          set_window_height (FRAME_MINIBUF_WINDOW (f), 1, 0);
@@ -6343,19 +6371,23 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe)
       else
        /* Frame has just one top-level window.  */
        set_window_height (FRAME_ROOT_WINDOW (f),
-                          newheight - FRAME_TOP_MARGIN (f), 0);
+                          newheight - FRAME_TOP_MARGIN (f), 2);
 
-      if (FRAME_TERMCAP_P (f) && !pretend)
+      /* MSDOS frames cannot PRETEND, as they change frame size by
+        manipulating video hardware.  */
+      if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
        FrameRows (FRAME_TTY (f)) = newheight;
     }
 
   if (new_frame_total_cols != FRAME_TOTAL_COLS (f))
     {
-      set_window_width (FRAME_ROOT_WINDOW (f), new_frame_total_cols, 0);
+      set_window_width (FRAME_ROOT_WINDOW (f), new_frame_total_cols, 2);
       if (FRAME_HAS_MINIBUF_P (f))
        set_window_width (FRAME_MINIBUF_WINDOW (f), new_frame_total_cols, 0);
 
-      if (FRAME_TERMCAP_P (f) && !pretend)
+      /* MSDOS frames cannot PRETEND, as they change frame size by
+        manipulating video hardware.  */
+      if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
        FrameCols (FRAME_TTY (f)) = newwidth;
 
       if (WINDOWP (f->tool_bar_window))
@@ -6406,7 +6438,8 @@ FILE = nil means just close any termscript file currently open.  */)
 {
   struct tty_display_info *tty;
 
-  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
+  if (! FRAME_TERMCAP_P (SELECTED_FRAME ())
+      && ! FRAME_MSDOS_P (SELECTED_FRAME ()))
     error ("Current frame is not on a tty device");
 
   tty = CURTTY ();
@@ -6436,7 +6469,7 @@ DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
 Control characters in STRING will have terminal-dependent effects.
 
 Optional parameter TERMINAL specifies the tty terminal device to use.
-It may be a terminal id, a frame, or nil for the terminal used by the
+It may be a terminal object, a frame, or nil for the terminal used by the
 currently selected frame.  */)
   (string, terminal)
      Lisp_Object string;
@@ -6453,7 +6486,10 @@ currently selected frame.  */)
     error ("Unknown terminal device");
 
   tty = t->display_info.tty;
-  
+
+  if (! tty->output)
+    error ("Terminal is currently suspended");
+
   if (tty->termscript)
     {
       fwrite (SDATA (string), 1, SBYTES (string), tty->termscript);
@@ -6792,7 +6828,7 @@ init_display ()
 
   /* Construct the space glyph.  */
   space_glyph.type = CHAR_GLYPH;
-  SET_CHAR_GLYPH_FROM_GLYPH (space_glyph, ' ');
+  SET_CHAR_GLYPH (space_glyph, ' ', DEFAULT_FACE_ID, 0);
   space_glyph.charpos = -1;
 
   inverse_video = 0;
@@ -6813,6 +6849,10 @@ init_display ()
     signal (SIGWINCH, window_change_signal);
 #endif /* SIGWINCH */
 
+  /* If running as a daemon, no need to initialize any frames/terminal. */
+  if (IS_DAEMON)
+      return;
+
   /* If the user wants to use a window system, we shouldn't bother
      initializing the terminal.  This is especially important when the
      terminal is so dumb that emacs gives up before and doesn't bother
@@ -6825,12 +6865,7 @@ init_display ()
   if (! inhibit_window_system && ! display_arg)
     {
       char *display;
-#ifdef VMS
-      display = getenv ("DECW$DISPLAY");
-#else
       display = getenv ("DISPLAY");
-#endif
-
       display_arg = (display != 0 && *display != 0);
 
       if (display_arg && !x_display_ok (display))
@@ -6847,11 +6882,9 @@ init_display ()
 #endif
      )
     {
-      Vinitial_window_system = intern ("x");
+      Vinitial_window_system = Qx;
 #ifdef HAVE_X11
       Vwindow_system_version = make_number (11);
-#else
-      Vwindow_system_version = make_number (10);
 #endif
 #if defined (GNU_LINUX) && defined (HAVE_LIBNCURSES)
       /* In some versions of ncurses,
@@ -6867,22 +6900,26 @@ init_display ()
 #ifdef HAVE_NTGUI
   if (!inhibit_window_system)
     {
-      Vinitial_window_system = intern ("w32");
+      Vinitial_window_system = Qw32;
       Vwindow_system_version = make_number (1);
       adjust_frame_glyphs_initially ();
       return;
     }
 #endif /* HAVE_NTGUI */
 
-#ifdef MAC_OS
-  if (!inhibit_window_system)
+#ifdef HAVE_NS
+  if (!inhibit_window_system
+#ifndef CANNOT_DUMP
+     && initialized
+#endif
+      )
     {
-      Vinitial_window_system = intern ("mac");
-      Vwindow_system_version = make_number (1);
+      Vinitial_window_system = Qns;
+      Vwindow_system_version = make_number(10);
       adjust_frame_glyphs_initially ();
       return;
     }
-#endif /* MAC_OS */
+#endif
 
   /* If no window system has been specified, try to use the terminal.  */
   if (! isatty (0))
@@ -6899,40 +6936,15 @@ init_display ()
 #endif
   if (!terminal_type)
     {
-#ifdef VMS
-      fprintf (stderr, "Please specify your terminal type.\n\
-For types defined in VMS, use  set term /device=TYPE.\n\
-For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
-\(The quotation marks are necessary since terminal types are lower case.)\n");
-#else /* not VMS */
-
 #ifdef HAVE_WINDOW_SYSTEM
       if (! inhibit_window_system)
        fprintf (stderr, "Please set the environment variable DISPLAY or TERM (see `tset').\n");
       else
 #endif /* HAVE_WINDOW_SYSTEM */
        fprintf (stderr, "Please set the environment variable TERM; see `tset'.\n");
-#endif /* not VMS */
       exit (1);
     }
 
-#ifdef VMS
-  /* VMS DCL tends to up-case things, so down-case term type.
-     Hardly any uppercase letters in terminal types; should be none.  */
-  {
-    char *new = (char *) xmalloc (strlen (terminal_type) + 1);
-    char *p;
-
-    strcpy (new, terminal_type);
-
-    for (p = new; *p; p++)
-      if (isupper (*p))
-       *p = tolower (*p);
-
-    terminal_type = new;
-  }
-#endif /* VMS */
-
   {
     struct terminal *t;
     struct frame *f = XFRAME (selected_frame);
@@ -6961,9 +6973,15 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
     Fmodify_frame_parameters
       (selected_frame, Fcons (Fcons (Qtty_type,
                                      Ftty_type (selected_frame)), Qnil));
-    Fmodify_frame_parameters (selected_frame, Fcons (Fcons (Qtty, Qnil), Qnil));
+    if (t->display_info.tty->name)
+      Fmodify_frame_parameters (selected_frame,
+                               Fcons (Fcons (Qtty, build_string (t->display_info.tty->name)),
+                                      Qnil));
+    else
+      Fmodify_frame_parameters (selected_frame, Fcons (Fcons (Qtty, Qnil),
+                                                      Qnil));
   }
-  
+
   {
     struct frame *sf = SELECTED_FRAME ();
     int width = FRAME_TOTAL_COLS (sf);
@@ -6983,13 +7001,6 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
   /* Set up faces of the initial terminal frame of a dumped Emacs.  */
   if (initialized
       && !noninteractive
-#ifdef MSDOS
-      /* The MSDOS terminal turns on its ``window system'' relatively
-        late into the startup, so we cannot do the frame faces'
-        initialization just yet.  It will be done later by pc-win.el
-        and internal_terminal_init.  */
-      && (strcmp (terminal_type, "internal") != 0 || inhibit_window_system)
-#endif
       && NILP (Vinitial_window_system))
     {
       /* For the initial frame, we don't have any way of knowing what
@@ -7051,6 +7062,18 @@ WINDOW nil or omitted means report on the selected window.  */)
   return w->cursor_off_p ? Qnil : Qt;
 }
 
+DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
+       Slast_nonminibuf_frame, 0, 0, 0,
+       doc: /* Value is last nonminibuffer frame. */)
+     ()
+{
+  Lisp_Object frame = Qnil;
+
+  if (last_nonminibuf_frame)
+    XSETFRAME (frame, last_nonminibuf_frame);
+
+  return frame;
+}
 \f
 /***********************************************************************
                            Initialization
@@ -7069,6 +7092,7 @@ syms_of_display ()
   defsubr (&Ssend_string_to_terminal);
   defsubr (&Sinternal_show_cursor);
   defsubr (&Sinternal_show_cursor_p);
+  defsubr (&Slast_nonminibuf_frame);
 
 #if GLYPH_DEBUG
   defsubr (&Sdump_redisplay_history);