root/src/window.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. CHECK_WINDOW_CONFIGURATION
  2. wset_combination_limit
  3. wset_dedicated
  4. wset_display_table
  5. wset_new_normal
  6. wset_new_total
  7. wset_normal_cols
  8. wset_normal_lines
  9. wset_parent
  10. wset_pointm
  11. wset_old_pointm
  12. wset_start
  13. wset_temslot
  14. wset_vertical_scroll_bar_type
  15. wset_window_parameters
  16. wset_combination
  17. window_outdated
  18. decode_live_window
  19. decode_any_window
  20. decode_valid_window
  21. adjust_window_count
  22. wset_buffer
  23. wset_old_buffer
  24. DEFUN
  25. DEFUN
  26. DEFUN
  27. DEFUN
  28. DEFUN
  29. DEFUN
  30. DEFUN
  31. DEFUN
  32. DEFUN
  33. DEFUN
  34. DEFUN
  35. DEFUN
  36. select_window
  37. select_window_1
  38. DEFUN
  39. DEFUN
  40. DEFUN
  41. DEFUN
  42. DEFUN
  43. DEFUN
  44. DEFUN
  45. DEFUN
  46. DEFUN
  47. DEFUN
  48. DEFUN
  49. DEFUN
  50. DEFUN
  51. DEFUN
  52. DEFUN
  53. DEFUN
  54. DEFUN
  55. DEFUN
  56. DEFUN
  57. DEFUN
  58. DEFUN
  59. window_body_unit_from_symbol
  60. window_body_height
  61. window_body_width
  62. DEFUN
  63. DEFUN
  64. DEFUN
  65. DEFUN
  66. DEFUN
  67. DEFUN
  68. DEFUN
  69. DEFUN
  70. DEFUN
  71. DEFUN
  72. set_window_hscroll
  73. coordinates_in_window
  74. window_relative_x_coord
  75. check_window_containing
  76. window_from_coordinates
  77. window_point
  78. DEFUN
  79. DEFUN
  80. DEFUN
  81. DEFUN
  82. DEFUN
  83. DEFUN
  84. DEFUN
  85. window_parameter
  86. DEFUN
  87. window_display_table
  88. unshow_buffer
  89. replace_window
  90. recombine_windows
  91. delete_deletable_window
  92. add_window_to_list
  93. window_list
  94. candidate_window_p
  95. decode_next_window_args
  96. next_window
  97. window_list_1
  98. window_loop
  99. check_all_windows
  100. resize_root_window
  101. window_pixel_to_total
  102. replace_buffer_in_windows
  103. replace_buffer_in_windows_safely
  104. run_funs
  105. select_window_norecord
  106. select_frame_norecord
  107. run_window_configuration_change_hook
  108. DEFUN
  109. DEFUN
  110. window_sub_list
  111. window_change_record_windows
  112. window_change_record
  113. run_window_change_functions_1
  114. run_window_change_functions
  115. set_window_buffer
  116. display_buffer
  117. DEFUN
  118. temp_output_buffer_show
  119. allocate_window
  120. make_parent_window
  121. make_window
  122. window_resize_check
  123. window_resize_apply
  124. window_resize_apply_total
  125. resize_frame_windows
  126. DEFUN
  127. resize_mini_window_apply
  128. grow_mini_window
  129. shrink_mini_window
  130. DEFUN
  131. mark_window_cursors_off
  132. window_wants_mode_line
  133. window_wants_header_line
  134. window_wants_tab_line
  135. window_internal_height
  136. window_scroll
  137. window_scroll_margin
  138. sanitize_next_screen_context_lines
  139. window_scroll_for_long_lines
  140. window_scroll_pixel_based
  141. window_scroll_line_based
  142. scroll_command
  143. DEFUN
  144. DEFUN
  145. DEFUN
  146. DEFUN
  147. displayed_window_lines
  148. DEFUN
  149. DEFUN
  150. DEFUN
  151. restore_window_configuration
  152. delete_all_child_windows
  153. count_windows
  154. get_leaf_windows
  155. get_phys_cursor_glyph
  156. save_window_save
  157. DEFUN
  158. apply_window_adjustment
  159. extract_dimension
  160. set_window_margins
  161. DEFUN
  162. set_window_fringes
  163. DEFUN
  164. set_window_scroll_bars
  165. DEFUN
  166. foreach_window
  167. foreach_window_1
  168. compare_window_configurations
  169. init_window_once
  170. init_window_once_for_pdumper
  171. init_window
  172. syms_of_window

     1 /* Window creation, deletion and examination for GNU Emacs.
     2    Does not include redisplay.
     3    Copyright (C) 1985-1987, 1993-1998, 2000-2023 Free Software
     4    Foundation, Inc.
     5 
     6 This file is part of GNU Emacs.
     7 
     8 GNU Emacs is free software: you can redistribute it and/or modify
     9 it under the terms of the GNU General Public License as published by
    10 the Free Software Foundation, either version 3 of the License, or (at
    11 your option) any later version.
    12 
    13 GNU Emacs is distributed in the hope that it will be useful,
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16 GNU General Public License for more details.
    17 
    18 You should have received a copy of the GNU General Public License
    19 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    20 
    21 #include <config.h>
    22 
    23 /* Work around GCC bug 102671.  */
    24 #if 10 <= __GNUC__
    25 # pragma GCC diagnostic ignored "-Wanalyzer-null-dereference"
    26 #endif
    27 
    28 #include "lisp.h"
    29 #include "buffer.h"
    30 #include "keyboard.h"
    31 #include "keymap.h"
    32 #include "frame.h"
    33 #include "window.h"
    34 #include "commands.h"
    35 #include "indent.h"
    36 #include "termchar.h"
    37 #include "disptab.h"
    38 #include "dispextern.h"
    39 #include "blockinput.h"
    40 #include "termhooks.h"          /* For FRAME_TERMINAL.  */
    41 #include "xwidget.h"
    42 #ifdef HAVE_WINDOW_SYSTEM
    43 #include TERM_HEADER
    44 #endif /* HAVE_WINDOW_SYSTEM */
    45 #ifdef MSDOS
    46 #include "msdos.h"
    47 #endif
    48 #include "pdumper.h"
    49 
    50 static ptrdiff_t count_windows (struct window *);
    51 static ptrdiff_t get_leaf_windows (struct window *, struct window **,
    52                                    ptrdiff_t);
    53 static void window_scroll_pixel_based (Lisp_Object, int, bool, bool);
    54 static void window_scroll_line_based (Lisp_Object, int, bool, bool);
    55 static void window_scroll_for_long_lines (struct window *, int, bool);
    56 static void foreach_window (struct frame *,
    57                             bool (* fn) (struct window *, void *),
    58                             void *);
    59 static bool foreach_window_1 (struct window *,
    60                               bool (* fn) (struct window *, void *),
    61                               void *);
    62 static bool window_resize_check (struct window *, bool);
    63 static void window_resize_apply (struct window *, bool);
    64 static void select_window_1 (Lisp_Object, bool);
    65 static void run_window_configuration_change_hook (struct frame *);
    66 
    67 static struct window *set_window_fringes (struct window *, Lisp_Object,
    68                                           Lisp_Object, Lisp_Object,
    69                                           Lisp_Object);
    70 static struct window *set_window_margins (struct window *, Lisp_Object,
    71                                           Lisp_Object);
    72 static struct window *set_window_scroll_bars (struct window *, Lisp_Object,
    73                                               Lisp_Object, Lisp_Object,
    74                                               Lisp_Object, Lisp_Object);
    75 static void apply_window_adjustment (struct window *);
    76 
    77 /* This is the window in which the terminal's cursor should
    78    be left when nothing is being done with it.  This must
    79    always be a leaf window, and its buffer is selected by
    80    the top level editing loop at the end of each command.
    81 
    82    This value is always the same as
    83    FRAME_SELECTED_WINDOW (selected_frame).  */
    84 Lisp_Object selected_window;
    85 
    86 /* The value of selected_window at the last time window change
    87    functions were run.  This is always the same as
    88    FRAME_OLD_SELECTED_WINDOW (old_selected_frame).  */
    89 static Lisp_Object old_selected_window;
    90 
    91 /* A list of all windows for use by next_window and Fwindow_list.
    92    Functions creating or deleting windows should invalidate this cache
    93    by setting it to nil.  */
    94 Lisp_Object Vwindow_list;
    95 
    96 /* True mean window_change_record has to record all live frames.  */
    97 static bool window_change_record_frames;
    98 
    99 /* The mini-buffer window of the selected frame.
   100    Note that you cannot test for mini-bufferness of an arbitrary window
   101    by comparing against this; but you can test for mini-bufferness of
   102    the selected window.  */
   103 Lisp_Object minibuf_window;
   104 
   105 /* Non-nil means it is the window whose mode line should be
   106    shown as the selected window when the minibuffer is selected.  */
   107 Lisp_Object minibuf_selected_window;
   108 
   109 /* Incremented for each window created.  */
   110 static EMACS_INT sequence_number;
   111 
   112 /* Used by the function window_scroll_pixel_based.  */
   113 static int window_scroll_pixel_based_preserve_x;
   114 static int window_scroll_pixel_based_preserve_y;
   115 
   116 /* Same for window_scroll_line_based.  */
   117 static EMACS_INT window_scroll_preserve_hpos;
   118 static EMACS_INT window_scroll_preserve_vpos;
   119 
   120 static void
   121 CHECK_WINDOW_CONFIGURATION (Lisp_Object x)
   122 {
   123   CHECK_TYPE (WINDOW_CONFIGURATIONP (x), Qwindow_configuration_p, x);
   124 }
   125 
   126 /* These setters are used only in this file, so they can be private.  */
   127 static void
   128 wset_combination_limit (struct window *w, Lisp_Object val)
   129 {
   130   w->combination_limit = val;
   131 }
   132 
   133 static void
   134 wset_dedicated (struct window *w, Lisp_Object val)
   135 {
   136   w->dedicated = val;
   137 }
   138 
   139 static void
   140 wset_display_table (struct window *w, Lisp_Object val)
   141 {
   142   w->display_table = val;
   143 }
   144 
   145 static void
   146 wset_new_normal (struct window *w, Lisp_Object val)
   147 {
   148   w->new_normal = val;
   149 }
   150 
   151 static void
   152 wset_new_total (struct window *w, Lisp_Object val)
   153 {
   154   w->new_total = val;
   155 }
   156 
   157 static void
   158 wset_normal_cols (struct window *w, Lisp_Object val)
   159 {
   160   w->normal_cols = val;
   161 }
   162 
   163 static void
   164 wset_normal_lines (struct window *w, Lisp_Object val)
   165 {
   166   w->normal_lines = val;
   167 }
   168 
   169 static void
   170 wset_parent (struct window *w, Lisp_Object val)
   171 {
   172   w->parent = val;
   173 }
   174 
   175 static void
   176 wset_pointm (struct window *w, Lisp_Object val)
   177 {
   178   w->pointm = val;
   179 }
   180 
   181 static void
   182 wset_old_pointm (struct window *w, Lisp_Object val)
   183 {
   184   w->old_pointm = val;
   185 }
   186 
   187 static void
   188 wset_start (struct window *w, Lisp_Object val)
   189 {
   190   w->start = val;
   191 }
   192 
   193 static void
   194 wset_temslot (struct window *w, Lisp_Object val)
   195 {
   196   w->temslot = val;
   197 }
   198 
   199 static void
   200 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
   201 {
   202   w->vertical_scroll_bar_type = val;
   203 }
   204 
   205 static void
   206 wset_window_parameters (struct window *w, Lisp_Object val)
   207 {
   208   w->window_parameters = val;
   209 }
   210 
   211 static void
   212 wset_combination (struct window *w, bool horflag, Lisp_Object val)
   213 {
   214   /* Since leaf windows never becomes non-leaf, there should
   215      be no buffer and markers in start and pointm fields of W.  */
   216   eassert (!BUFFERP (w->contents) && NILP (w->start) && NILP (w->pointm));
   217   w->contents = val;
   218   /* When an internal window is deleted and VAL is nil, HORFLAG
   219      is meaningless.  */
   220   if (!NILP (val))
   221     w->horizontal = horflag;
   222 }
   223 
   224 /* True if leaf window W doesn't reflect the actual state
   225    of displayed buffer due to its text or overlays change.  */
   226 
   227 bool
   228 window_outdated (struct window *w)
   229 {
   230   struct buffer *b = XBUFFER (w->contents);
   231   return (w->last_modified < BUF_MODIFF (b)
   232           || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b));
   233 }
   234 
   235 struct window *
   236 decode_live_window (register Lisp_Object window)
   237 {
   238   if (NILP (window))
   239     return XWINDOW (selected_window);
   240 
   241   CHECK_LIVE_WINDOW (window);
   242   return XWINDOW (window);
   243 }
   244 
   245 struct window *
   246 decode_any_window (register Lisp_Object window)
   247 {
   248   struct window *w;
   249 
   250   if (NILP (window))
   251     return XWINDOW (selected_window);
   252 
   253   CHECK_WINDOW (window);
   254   w = XWINDOW (window);
   255   return w;
   256 }
   257 
   258 static struct window *
   259 decode_valid_window (register Lisp_Object window)
   260 {
   261   struct window *w;
   262 
   263   if (NILP (window))
   264     return XWINDOW (selected_window);
   265 
   266   CHECK_VALID_WINDOW (window);
   267   w = XWINDOW (window);
   268   return w;
   269 }
   270 
   271 /* Called when W's buffer slot is changed.  ARG -1 means that W is about to
   272    cease its buffer, and 1 means that W is about to set up the new one.  */
   273 
   274 static void
   275 adjust_window_count (struct window *w, int arg)
   276 {
   277   eassert (eabs (arg) == 1);
   278   if (BUFFERP (w->contents))
   279     {
   280       struct buffer *b = XBUFFER (w->contents);
   281 
   282       if (b->base_buffer)
   283         b = b->base_buffer;
   284       b->window_count += arg;
   285       eassert (b->window_count >= 0);
   286       /* These should be recalculated by redisplay code.  */
   287       w->window_end_valid = false;
   288       w->base_line_pos = 0;
   289     }
   290 }
   291 
   292 /* Set W's buffer slot to VAL and recompute number
   293    of windows showing VAL if it is a buffer.  */
   294 
   295 void
   296 wset_buffer (struct window *w, Lisp_Object val)
   297 {
   298   adjust_window_count (w, -1);
   299   if (BUFFERP (val))
   300     /* Make sure that we do not assign the buffer
   301        to an internal window.  */
   302     eassert (MARKERP (w->start) && MARKERP (w->pointm));
   303   w->contents = val;
   304   adjust_window_count (w, 1);
   305 }
   306 
   307 static void
   308 wset_old_buffer (struct window *w, Lisp_Object val)
   309 {
   310   w->old_buffer = val;
   311 }
   312 
   313 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
   314        doc: /* Return t if OBJECT is a window and nil otherwise.  */)
   315   (Lisp_Object object)
   316 {
   317   return WINDOWP (object) ? Qt : Qnil;
   318 }
   319 
   320 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
   321        doc: /* Return t if OBJECT is a valid window and nil otherwise.
   322 A valid window is either a window that displays a buffer or an internal
   323 window.  Windows that have been deleted are not valid.  */)
   324   (Lisp_Object object)
   325 {
   326   return WINDOW_VALID_P (object) ? Qt : Qnil;
   327 }
   328 
   329 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
   330        doc: /* Return t if OBJECT is a live window and nil otherwise.
   331 A live window is a window that displays a buffer.
   332 Internal windows and deleted windows are not live.  */)
   333   (Lisp_Object object)
   334 {
   335   return WINDOW_LIVE_P (object) ? Qt : Qnil;
   336 }
   337 
   338 /* Frames and windows.  */
   339 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
   340        doc: /* Return the frame that window WINDOW is on.
   341 WINDOW must be a valid window and defaults to the selected one.  */)
   342   (Lisp_Object window)
   343 {
   344   return decode_valid_window (window)->frame;
   345 }
   346 
   347 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
   348        doc: /* Return the root window of FRAME-OR-WINDOW.
   349 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
   350 With a frame argument, return that frame's root window.
   351 With a window argument, return the root window of that window's frame.  */)
   352   (Lisp_Object frame_or_window)
   353 {
   354   Lisp_Object window;
   355 
   356   if (NILP (frame_or_window))
   357     window = SELECTED_FRAME ()->root_window;
   358   else if (WINDOW_VALID_P (frame_or_window))
   359       window = XFRAME (XWINDOW (frame_or_window)->frame)->root_window;
   360   else
   361     {
   362       CHECK_LIVE_FRAME (frame_or_window);
   363       window = XFRAME (frame_or_window)->root_window;
   364     }
   365 
   366   return window;
   367 }
   368 
   369 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
   370        doc: /* Return the minibuffer window for frame FRAME.
   371 If FRAME is omitted or nil, it defaults to the selected frame.  */)
   372   (Lisp_Object frame)
   373 {
   374   return FRAME_MINIBUF_WINDOW (decode_live_frame (frame));
   375 }
   376 
   377 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
   378        Swindow_minibuffer_p, 0, 1, 0,
   379        doc: /* Return t if WINDOW is a minibuffer window.
   380 WINDOW must be a valid window and defaults to the selected one.  */)
   381   (Lisp_Object window)
   382 {
   383   return MINI_WINDOW_P (decode_valid_window (window)) ? Qt : Qnil;
   384 }
   385 
   386 /* Don't move this to window.el - this must be a safe routine.  */
   387 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
   388        doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
   389 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
   390 Else if FRAME-OR-WINDOW denotes a valid window, return the first window
   391 of that window's frame.  If FRAME-OR-WINDOW denotes a live frame, return
   392 the first window of that frame.  */)
   393   (Lisp_Object frame_or_window)
   394 {
   395   Lisp_Object window;
   396 
   397   if (NILP (frame_or_window))
   398     window = SELECTED_FRAME ()->root_window;
   399   else if (WINDOW_VALID_P (frame_or_window))
   400     window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
   401   else
   402     {
   403       CHECK_LIVE_FRAME (frame_or_window);
   404       window = XFRAME (frame_or_window)->root_window;
   405     }
   406 
   407   while (WINDOWP (XWINDOW (window)->contents))
   408     window = XWINDOW (window)->contents;
   409 
   410   return window;
   411 }
   412 
   413 DEFUN ("frame-selected-window", Fframe_selected_window,
   414        Sframe_selected_window, 0, 1, 0,
   415        doc: /* Return the selected window of FRAME-OR-WINDOW.
   416 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
   417 Else if FRAME-OR-WINDOW denotes a valid window, return the selected
   418 window of that window's frame.  If FRAME-OR-WINDOW denotes a live frame,
   419 return the selected window of that frame.  */)
   420   (Lisp_Object frame_or_window)
   421 {
   422   Lisp_Object window;
   423 
   424   if (NILP (frame_or_window))
   425     window = SELECTED_FRAME ()->selected_window;
   426   else if (WINDOW_VALID_P (frame_or_window))
   427     window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
   428   else
   429     {
   430       CHECK_LIVE_FRAME (frame_or_window);
   431       window = XFRAME (frame_or_window)->selected_window;
   432     }
   433 
   434   return window;
   435 }
   436 
   437 DEFUN ("frame-old-selected-window", Fframe_old_selected_window,
   438        Sframe_old_selected_window, 0, 1, 0,
   439        doc: /* Return old selected window of FRAME.
   440 FRAME must be a live frame and defaults to the selected one.
   441 
   442 The return value is the window selected on FRAME the last time window
   443 change functions were run for FRAME.  */)
   444   (Lisp_Object frame)
   445 {
   446   if (NILP (frame))
   447     frame = selected_frame;
   448   CHECK_LIVE_FRAME (frame);
   449 
   450   return XFRAME (frame)->old_selected_window;
   451 }
   452 
   453 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
   454        Sset_frame_selected_window, 2, 3, 0,
   455        doc: /* Set selected window of FRAME to WINDOW.
   456 FRAME must be a live frame and defaults to the selected one.  If FRAME
   457 is the selected frame, this makes WINDOW the selected window.  Optional
   458 argument NORECORD non-nil means to neither change the order of recently
   459 selected windows nor the buffer list.  WINDOW must denote a live window.
   460 Return WINDOW.  */)
   461   (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
   462 {
   463   if (NILP (frame))
   464     frame = selected_frame;
   465 
   466   CHECK_LIVE_FRAME (frame);
   467   CHECK_LIVE_WINDOW (window);
   468 
   469   if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
   470     error ("In `set-frame-selected-window', WINDOW is not on FRAME");
   471 
   472   if (EQ (frame, selected_frame))
   473     return Fselect_window (window, norecord);
   474   else
   475     {
   476       fset_selected_window (XFRAME (frame), window);
   477       /* Don't clear FRAME's select_mini_window_flag here.  */
   478       return window;
   479     }
   480 }
   481 
   482 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
   483        doc: /* Return the selected window.
   484 The selected window is the window in which the standard cursor for
   485 selected windows appears and to which many commands apply.
   486 
   487 Also see `old-selected-window' and `minibuffer-selected-window'.  */)
   488   (void)
   489 {
   490   return selected_window;
   491 }
   492 
   493 DEFUN ("old-selected-window", Fold_selected_window,
   494        Sold_selected_window, 0, 0, 0,
   495        doc: /* Return the old selected window.
   496 The return value is the window selected the last time window change
   497 functions were run.  */)
   498   (void)
   499 {
   500   return old_selected_window;
   501 }
   502 
   503 EMACS_INT window_select_count;
   504 
   505 /* If select_window is called with inhibit_point_swap true it will
   506    not store point of the old selected window's buffer back into that
   507    window's pointm slot.  This is needed by Fset_window_configuration to
   508    avoid that the display routine is called with selected_window set to
   509    Qnil causing a subsequent crash.  */
   510 static Lisp_Object
   511 select_window (Lisp_Object window, Lisp_Object norecord,
   512                bool inhibit_point_swap)
   513 {
   514   struct window *w;
   515   struct frame *sf;
   516   Lisp_Object frame;
   517   struct frame *f;
   518 
   519   CHECK_LIVE_WINDOW (window);
   520 
   521   w = XWINDOW (window);
   522   frame = WINDOW_FRAME (w);
   523   f = XFRAME (frame);
   524 
   525   if (FRAME_TOOLTIP_P (f))
   526     /* Do not select a tooltip window (Bug#47207).  */
   527     error ("Cannot select a tooltip window");
   528 
   529   /* We deinitely want to select WINDOW, not the mini-window.  */
   530   f->select_mini_window_flag = false;
   531 
   532   /* Make the selected window's buffer current.  */
   533   Fset_buffer (w->contents);
   534 
   535   if (EQ (window, selected_window) && !inhibit_point_swap)
   536     /* `switch-to-buffer' uses (select-window (selected-window)) as a "clever"
   537        way to call record_buffer from Elisp, so it's important that we call
   538        record_buffer before returning here.  */
   539     goto record_and_return;
   540 
   541   if (NILP (norecord) || EQ (norecord, Qmark_for_redisplay))
   542     { /* Mark the window for redisplay since the selected-window has
   543          a different mode-line.  */
   544       wset_redisplay (XWINDOW (selected_window));
   545       wset_redisplay (w);
   546     }
   547   else
   548     redisplay_other_windows ();
   549 
   550   sf = SELECTED_FRAME ();
   551   if (f != sf)
   552     {
   553       fset_selected_window (f, window);
   554       /* Use this rather than Fhandle_switch_frame
   555          so that FRAME_FOCUS_FRAME is moved appropriately as we
   556          move around in the state where a minibuffer in a separate
   557          frame is active.  */
   558       Fselect_frame (frame, norecord);
   559       /* Fselect_frame called us back so we've done all the work already.  */
   560       eassert (EQ (window, selected_window)
   561                || (EQ (window, f->minibuffer_window)
   562                    && NILP (Fminibufferp (XWINDOW (window)->contents, Qt))));
   563       return window;
   564     }
   565   else
   566     fset_selected_window (sf, window);
   567 
   568   select_window_1 (window, inhibit_point_swap);
   569   bset_last_selected_window (XBUFFER (w->contents), window);
   570 
   571  record_and_return:
   572   /* record_buffer can call maybe_quit, so make sure it is run only
   573      after we have re-established the invariant between
   574      selected_window and selected_frame, otherwise the temporary
   575      broken invariant might "escape" (Bug#14161).  */
   576   if (NILP (norecord))
   577     {
   578       w->use_time = ++window_select_count;
   579       record_buffer (w->contents);
   580     }
   581 
   582   return window;
   583 }
   584 
   585 /* Select window with a minimum of fuss, i.e. don't record the change anywhere
   586    (not even for redisplay's benefit), and assume that the window's frame is
   587    already selected.  */
   588 static void
   589 select_window_1 (Lisp_Object window, bool inhibit_point_swap)
   590 {
   591   /* Store the old selected window's buffer's point in pointm of the old
   592      selected window.  It belongs to that window, and when the window is
   593      not selected, must be in the window.  */
   594   if (!inhibit_point_swap)
   595     {
   596       struct window *ow = XWINDOW (selected_window);
   597       if (BUFFERP (ow->contents))
   598         set_marker_both (ow->pointm, ow->contents,
   599                          BUF_PT (XBUFFER (ow->contents)),
   600                          BUF_PT_BYTE (XBUFFER (ow->contents)));
   601     }
   602 
   603   selected_window = window;
   604 
   605   /* Go to the point recorded in the window.
   606      This is important when the buffer is in more
   607      than one window.  It also matters when
   608      redisplay_window has altered point after scrolling,
   609      because it makes the change only in the window.  */
   610   set_point_from_marker (XWINDOW (window)->pointm);
   611 }
   612 
   613 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
   614        doc: /* Select WINDOW which must be a live window.
   615 Also make WINDOW's frame the selected frame and WINDOW that frame's
   616 selected window.  In addition, make WINDOW's buffer current and set its
   617 buffer's value of `point' to the value of WINDOW's `window-point'.
   618 Return WINDOW.
   619 
   620 Optional second arg NORECORD non-nil means do not put this buffer at the
   621 front of the buffer list and do not make this window the most recently
   622 selected one.  Also, do not mark WINDOW for redisplay unless NORECORD
   623 equals the special symbol `mark-for-redisplay'.
   624 
   625 Run `buffer-list-update-hook' unless NORECORD is non-nil.  Note that
   626 applications and internal routines often select a window temporarily for
   627 various purposes; mostly, to simplify coding.  As a rule, such
   628 selections should not be recorded and therefore will not pollute
   629 `buffer-list-update-hook'.  Selections that "really count" are those
   630 causing a visible change in the next redisplay of WINDOW's frame and
   631 should always be recorded.  So if you think of running a function each
   632 time a window gets selected, put it on `buffer-list-update-hook' or
   633 `window-selection-change-functions'.
   634 
   635 Also note that the main editor command loop sets the current buffer to
   636 the buffer of the selected window before each command.  */)
   637   (Lisp_Object window, Lisp_Object norecord)
   638 {
   639   return select_window (window, norecord, false);
   640 }
   641 
   642 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
   643        doc: /* Return the buffer displayed in window WINDOW.
   644 If WINDOW is omitted or nil, it defaults to the selected window.
   645 Return nil for an internal window or a deleted window.  */)
   646   (Lisp_Object window)
   647 {
   648   struct window *w = decode_any_window (window);
   649 
   650   return WINDOW_LEAF_P (w) ? w->contents : Qnil;
   651 }
   652 
   653 DEFUN ("window-old-buffer", Fwindow_old_buffer, Swindow_old_buffer, 0, 1, 0,
   654        doc: /* Return the old buffer displayed by WINDOW.
   655 WINDOW must be a live window and defaults to the selected one.
   656 
   657 The return value is the buffer shown in WINDOW at the last time window
   658 change functions were run.  It is nil if WINDOW was created after
   659 that.  It is t if WINDOW has been restored from a window configuration
   660 after that.  */)
   661   (Lisp_Object window)
   662 {
   663   struct window *w = decode_live_window (window);
   664 
   665   return (NILP (w->old_buffer)
   666           /* A new window.  */
   667           ? Qnil
   668           : (w->change_stamp != WINDOW_XFRAME (w)->change_stamp)
   669           /* A window restored from a configuration.  */
   670           ? Qt
   671           /* A window that was live the last time seen by window
   672              change functions.  */
   673           : w->old_buffer);
   674 }
   675 
   676 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
   677        doc: /* Return the parent window of window WINDOW.
   678 WINDOW must be a valid window and defaults to the selected one.
   679 Return nil for a window with no parent (e.g. a root window).  */)
   680   (Lisp_Object window)
   681 {
   682   return decode_valid_window (window)->parent;
   683 }
   684 
   685 DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 0, 1, 0,
   686        doc: /* Return the topmost child window of window WINDOW.
   687 WINDOW must be a valid window and defaults to the selected one.
   688 Return nil if WINDOW is a live window (live windows have no children).
   689 Return nil if WINDOW is an internal window whose children form a
   690 horizontal combination.  */)
   691   (Lisp_Object window)
   692 {
   693   struct window *w = decode_valid_window (window);
   694   return WINDOW_VERTICAL_COMBINATION_P (w) ? w->contents : Qnil;
   695 }
   696 
   697 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
   698        doc: /* Return the leftmost child window of window WINDOW.
   699 WINDOW must be a valid window and defaults to the selected one.
   700 Return nil if WINDOW is a live window (live windows have no children).
   701 Return nil if WINDOW is an internal window whose children form a
   702 vertical combination.  */)
   703   (Lisp_Object window)
   704 {
   705   struct window *w = decode_valid_window (window);
   706   return WINDOW_HORIZONTAL_COMBINATION_P (w) ? w->contents : Qnil;
   707 }
   708 
   709 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
   710        doc: /* Return the next sibling window of window WINDOW.
   711 WINDOW must be a valid window and defaults to the selected one.
   712 Return nil if WINDOW has no next sibling.  */)
   713   (Lisp_Object window)
   714 {
   715   return decode_valid_window (window)->next;
   716 }
   717 
   718 DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
   719        doc: /* Return the previous sibling window of window WINDOW.
   720 WINDOW must be a valid window and defaults to the selected one.
   721 Return nil if WINDOW has no previous sibling.  */)
   722   (Lisp_Object window)
   723 {
   724   return decode_valid_window (window)->prev;
   725 }
   726 
   727 DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
   728        doc: /* Return combination limit of window WINDOW.
   729 WINDOW must be a valid window used in horizontal or vertical combination.
   730 If the return value is nil, child windows of WINDOW can be recombined with
   731 WINDOW's siblings.  A return value of t means that child windows of
   732 WINDOW are never (re-)combined with WINDOW's siblings.  */)
   733   (Lisp_Object window)
   734 {
   735   struct window *w;
   736 
   737   CHECK_VALID_WINDOW (window);
   738   w = XWINDOW (window);
   739   if (WINDOW_LEAF_P (w))
   740     error ("Combination limit is meaningful for internal windows only");
   741   return w->combination_limit;
   742 }
   743 
   744 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
   745        doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
   746 WINDOW must be a valid window used in horizontal or vertical combination.
   747 If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
   748 siblings.  LIMIT t means that child windows of WINDOW are never
   749 \(re-)combined with WINDOW's siblings.  Other values are reserved for
   750 future use.  */)
   751   (Lisp_Object window, Lisp_Object limit)
   752 {
   753   struct window *w;
   754 
   755   CHECK_VALID_WINDOW (window);
   756   w = XWINDOW (window);
   757   if (WINDOW_LEAF_P (w))
   758     error ("Combination limit is meaningful for internal windows only");
   759   wset_combination_limit (w, limit);
   760   return limit;
   761 }
   762 
   763 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
   764        doc: /* Return the use time of window WINDOW.
   765 WINDOW must specify a live window and defaults to the selected one.
   766 
   767 The window with the highest use time is usually the one most recently
   768 selected by calling `select-window' with NORECORD nil.  The window with
   769 the lowest use time is usually the least recently selected one chosen in
   770 such a way.
   771 
   772 Note that the use time of a window can be also changed by calling
   773 `window-bump-use-time' for that window.  */)
   774   (Lisp_Object window)
   775 {
   776   return make_fixnum (decode_live_window (window)->use_time);
   777 }
   778 
   779 DEFUN ("window-bump-use-time", Fwindow_bump_use_time,
   780        Swindow_bump_use_time, 0, 1, 0,
   781        doc: /* Mark WINDOW as second most recently used.
   782 WINDOW must specify a live window.
   783 
   784 If WINDOW is not selected and the selected window has the highest use
   785 time of all windows, set the use time of WINDOW to that of the selected
   786 window, increase the use time of the selected window by one and return
   787 the new use time of WINDOW.  Otherwise, do nothing and return nil.  */)
   788   (Lisp_Object window)
   789 {
   790   struct window *w = decode_live_window (window);
   791   struct window *sw = XWINDOW (selected_window);
   792 
   793   if (w != sw && sw->use_time == window_select_count)
   794     {
   795       w->use_time = window_select_count;
   796       sw->use_time = ++window_select_count;
   797 
   798       return make_fixnum (w->use_time);
   799     }
   800   else
   801     return Qnil;
   802 }
   803 
   804 DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0,
   805        doc: /* Return the width of window WINDOW in pixels.
   806 WINDOW must be a valid window and defaults to the selected one.
   807 
   808 The return value includes the fringes and margins of WINDOW as well as
   809 any vertical dividers or scroll bars belonging to WINDOW.  If WINDOW is
   810 an internal window, its pixel width is the width of the screen areas
   811 spanned by its children.  */)
   812      (Lisp_Object window)
   813 {
   814   return make_fixnum (decode_valid_window (window)->pixel_width);
   815 }
   816 
   817 DEFUN ("window-pixel-height", Fwindow_pixel_height, Swindow_pixel_height, 0, 1, 0,
   818        doc: /* Return the height of window WINDOW in pixels.
   819 WINDOW must be a valid window and defaults to the selected one.
   820 
   821 The return value includes the mode line and header line and the bottom
   822 divider, if any.  If WINDOW is an internal window, its pixel height is
   823 the height of the screen areas spanned by its children.  */)
   824   (Lisp_Object window)
   825 {
   826   return make_fixnum (decode_valid_window (window)->pixel_height);
   827 }
   828 
   829 DEFUN ("window-old-pixel-width", Fwindow_old_pixel_width,
   830        Swindow_old_pixel_width, 0, 1, 0,
   831        doc: /* Return old total pixel width of WINDOW.
   832 WINDOW must be a valid window and defaults to the selected one.
   833 
   834 The return value is the total pixel width of WINDOW after the last
   835 time window change functions found WINDOW live on its frame.  It is
   836 zero if WINDOW was created after that.  */)
   837   (Lisp_Object window)
   838 {
   839   return (make_fixnum
   840           (decode_valid_window (window)->old_pixel_width));
   841 }
   842 
   843 DEFUN ("window-old-pixel-height", Fwindow_old_pixel_height,
   844        Swindow_old_pixel_height, 0, 1, 0,
   845        doc: /* Return old total pixel height of WINDOW.
   846 WINDOW must be a valid window and defaults to the selected one.
   847 
   848 The return value is the total pixel height of WINDOW after the last
   849 time window change functions found WINDOW live on its frame.  It is
   850 zero if WINDOW was created after that.  */)
   851   (Lisp_Object window)
   852 {
   853   return (make_fixnum
   854           (decode_valid_window (window)->old_pixel_height));
   855 }
   856 
   857 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0,
   858        doc: /* Return the height of window WINDOW in lines.
   859 WINDOW must be a valid window and defaults to the selected one.
   860 
   861 The return value includes the heights of WINDOW's mode and header line
   862 and its bottom divider, if any.  If WINDOW is an internal window, the
   863 total height is the height of the screen areas spanned by its children.
   864 
   865 If WINDOW's pixel height is not an integral multiple of its frame's
   866 character height, the number of lines occupied by WINDOW is rounded
   867 internally.  This is done in a way such that, if WINDOW is a parent
   868 window, the sum of the total heights of all its children internally
   869 equals the total height of WINDOW.
   870 
   871 If the optional argument ROUND is `ceiling', return the smallest integer
   872 larger than WINDOW's pixel height divided by the character height of
   873 WINDOW's frame.  ROUND `floor' means to return the largest integer
   874 smaller than WINDOW's pixel height divided by the character height of
   875 WINDOW's frame.  Any other value of ROUND means to return the internal
   876 total height of WINDOW.  */)
   877   (Lisp_Object window, Lisp_Object round)
   878 {
   879   struct window *w = decode_valid_window (window);
   880 
   881   if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
   882     return make_fixnum (w->total_lines);
   883   else
   884     {
   885       int unit = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
   886 
   887       return make_fixnum (EQ (round, Qceiling)
   888                           ? ((w->pixel_height + unit - 1) /unit)
   889                           : (w->pixel_height / unit));
   890     }
   891 }
   892 
   893 DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 2, 0,
   894        doc: /* Return the total width of window WINDOW in columns.
   895 WINDOW must be a valid window and defaults to the selected one.
   896 
   897 The return value includes the widths of WINDOW's fringes, margins,
   898 scroll bars and its right divider, if any.  If WINDOW is an internal
   899 window, the total width is the width of the screen areas spanned by its
   900 children.
   901 
   902 If WINDOW's pixel width is not an integral multiple of its frame's
   903 character width, the number of lines occupied by WINDOW is rounded
   904 internally.  This is done in a way such that, if WINDOW is a parent
   905 window, the sum of the total widths of all its children internally
   906 equals the total width of WINDOW.
   907 
   908 If the optional argument ROUND is `ceiling', return the smallest integer
   909 larger than WINDOW's pixel width divided by the character width of
   910 WINDOW's frame.  ROUND `floor' means to return the largest integer
   911 smaller than WINDOW's pixel width divided by the character width of
   912 WINDOW's frame.  Any other value of ROUND means to return the internal
   913 total width of WINDOW.  */)
   914   (Lisp_Object window, Lisp_Object round)
   915 {
   916   struct window *w = decode_valid_window (window);
   917 
   918   if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
   919     return make_fixnum (w->total_cols);
   920   else
   921     {
   922       int unit = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
   923 
   924       return make_fixnum (EQ (round, Qceiling)
   925                           ? ((w->pixel_width + unit - 1) /unit)
   926                           : (w->pixel_width / unit));
   927     }
   928 }
   929 
   930 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
   931        doc: /* Return the new total size of window WINDOW.
   932 WINDOW must be a valid window and defaults to the selected one.
   933 
   934 The new total size of WINDOW is the value set by the last call of
   935 `set-window-new-total' for WINDOW.  If it is valid, it will be shortly
   936 installed as WINDOW's total height (see `window-total-height') or total
   937 width (see `window-total-width').  */)
   938   (Lisp_Object window)
   939 {
   940   return decode_valid_window (window)->new_total;
   941 }
   942 
   943 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
   944        doc: /* Return the normal height of window WINDOW.
   945 WINDOW must be a valid window and defaults to the selected one.
   946 If HORIZONTAL is non-nil, return the normal width of WINDOW.
   947 
   948 The normal height of a frame's root window or a window that is
   949 horizontally combined (a window that has a left or right sibling) is
   950 1.0.  The normal height of a window that is vertically combined (has a
   951 sibling above or below) is the fraction of the window's height with
   952 respect to its parent.  The sum of the normal heights of all windows in a
   953 vertical combination equals 1.0.
   954 
   955 Similarly, the normal width of a frame's root window or a window that is
   956 vertically combined equals 1.0.  The normal width of a window that is
   957 horizontally combined is the fraction of the window's width with respect
   958 to its parent.  The sum of the normal widths of all windows in a
   959 horizontal combination equals 1.0.
   960 
   961 The normal sizes of windows are used to restore the proportional sizes
   962 of windows after they have been shrunk to their minimum sizes; for
   963 example when a frame is temporarily made very small and afterwards gets
   964 re-enlarged to its previous size.  */)
   965   (Lisp_Object window, Lisp_Object horizontal)
   966 {
   967   struct window *w = decode_valid_window (window);
   968 
   969   return NILP (horizontal) ? w->normal_lines : w->normal_cols;
   970 }
   971 
   972 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
   973        doc: /* Return new normal size of window WINDOW.
   974 WINDOW must be a valid window and defaults to the selected one.
   975 
   976 The new normal size of WINDOW is the value set by the last call of
   977 `set-window-new-normal' for WINDOW.  If valid, it will be shortly
   978 installed as WINDOW's normal size (see `window-normal-size').  */)
   979   (Lisp_Object window)
   980 {
   981   return decode_valid_window (window)->new_normal;
   982 }
   983 
   984 DEFUN ("window-new-pixel", Fwindow_new_pixel, Swindow_new_pixel, 0, 1, 0,
   985        doc: /* Return new pixel size of window WINDOW.
   986 WINDOW must be a valid window and defaults to the selected one.
   987 
   988 The new pixel size of WINDOW is the value set by the last call of
   989 `set-window-new-pixel' for WINDOW.  If it is valid, it will be shortly
   990 installed as WINDOW's pixel height (see `window-pixel-height') or pixel
   991 width (see `window-pixel-width').  */)
   992   (Lisp_Object window)
   993 {
   994   return decode_valid_window (window)->new_pixel;
   995 }
   996 
   997 DEFUN ("window-pixel-left", Fwindow_pixel_left, Swindow_pixel_left, 0, 1, 0,
   998        doc: /* Return left pixel edge of window WINDOW.
   999 WINDOW must be a valid window and defaults to the selected one.  */)
  1000   (Lisp_Object window)
  1001 {
  1002   return make_fixnum (decode_valid_window (window)->pixel_left);
  1003 }
  1004 
  1005 DEFUN ("window-pixel-top", Fwindow_pixel_top, Swindow_pixel_top, 0, 1, 0,
  1006        doc: /* Return top pixel edge of window WINDOW.
  1007 WINDOW must be a valid window and defaults to the selected one.  */)
  1008   (Lisp_Object window)
  1009 {
  1010   return make_fixnum (decode_valid_window (window)->pixel_top);
  1011 }
  1012 
  1013 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
  1014        doc: /* Return left column of window WINDOW.
  1015 This is the distance, in columns, between the left edge of WINDOW and
  1016 the left edge of the frame's window area.  For instance, the return
  1017 value is 0 if there is no window to the left of WINDOW.
  1018 
  1019 WINDOW must be a valid window and defaults to the selected one.  */)
  1020   (Lisp_Object window)
  1021 {
  1022   return make_fixnum (decode_valid_window (window)->left_col);
  1023 }
  1024 
  1025 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
  1026        doc: /* Return top line of window WINDOW.
  1027 This is the distance, in lines, between the top of WINDOW and the top
  1028 of the frame's window area.  For instance, the return value is 0 if
  1029 there is no window above WINDOW.
  1030 
  1031 WINDOW must be a valid window and defaults to the selected one.  */)
  1032   (Lisp_Object window)
  1033 {
  1034   return make_fixnum (decode_valid_window (window)->top_line);
  1035 }
  1036 
  1037 static enum window_body_unit
  1038 window_body_unit_from_symbol (Lisp_Object unit)
  1039 {
  1040   return
  1041     EQ (unit, Qremap)
  1042     ? WINDOW_BODY_IN_REMAPPED_CHARS
  1043     : (NILP (unit)
  1044        ? WINDOW_BODY_IN_CANONICAL_CHARS
  1045        : WINDOW_BODY_IN_PIXELS);
  1046 }
  1047 
  1048 /* Return the number of lines/pixels of W's body.  Don't count any mode
  1049    or header line or horizontal divider of W.  Rounds down to nearest
  1050    integer when not working pixelwise. */
  1051 int
  1052 window_body_height (struct window *w, enum window_body_unit pixelwise)
  1053 {
  1054   int height = (w->pixel_height
  1055                 - WINDOW_TAB_LINE_HEIGHT (w)
  1056                 - WINDOW_HEADER_LINE_HEIGHT (w)
  1057                 - (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
  1058                    ? WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
  1059                    : 0)
  1060                 - WINDOW_MODE_LINE_HEIGHT (w)
  1061                 - WINDOW_BOTTOM_DIVIDER_WIDTH (w));
  1062 
  1063   int denom = 1;
  1064   if (pixelwise == WINDOW_BODY_IN_REMAPPED_CHARS)
  1065     {
  1066       if (!NILP (Vface_remapping_alist))
  1067         {
  1068           struct frame *f = XFRAME (WINDOW_FRAME (w));
  1069           int face_id = lookup_named_face (NULL, f, Qdefault, true);
  1070           struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
  1071           if (face && face->font && face->font->height)
  1072             denom = face->font->height;
  1073         }
  1074       /* For performance, use canonical chars if no face remapping.  */
  1075       else
  1076         pixelwise = WINDOW_BODY_IN_CANONICAL_CHARS;
  1077     }
  1078 
  1079   if (pixelwise == WINDOW_BODY_IN_CANONICAL_CHARS)
  1080     denom = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
  1081 
  1082   /* Don't return a negative value.  */
  1083   return max (height / denom, 0);
  1084 }
  1085 
  1086 /* Return the number of columns/pixels of W's body.  Don't count columns
  1087    occupied by the scroll bar or the divider/vertical bar separating W
  1088    from its right sibling or margins.  On window-systems don't count
  1089    fringes either.  Round down to nearest integer when not working
  1090    pixelwise.  */
  1091 int
  1092 window_body_width (struct window *w, enum window_body_unit pixelwise)
  1093 {
  1094   struct frame *f = XFRAME (WINDOW_FRAME (w));
  1095 
  1096   int width = (w->pixel_width
  1097                - WINDOW_RIGHT_DIVIDER_WIDTH (w)
  1098                - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
  1099                   ? WINDOW_SCROLL_BAR_AREA_WIDTH (w)
  1100                   : (/* A vertical bar is either 1 or 0.  */
  1101                      !FRAME_WINDOW_P (f)
  1102                      && !WINDOW_RIGHTMOST_P (w)
  1103                      && !WINDOW_RIGHT_DIVIDER_WIDTH (w)))
  1104                 - WINDOW_MARGINS_WIDTH (w)
  1105                 - (FRAME_WINDOW_P (f)
  1106                    ? WINDOW_FRINGES_WIDTH (w)
  1107                    : 0));
  1108 
  1109   int denom = 1;
  1110   if (pixelwise == WINDOW_BODY_IN_REMAPPED_CHARS)
  1111     {
  1112       if (!NILP (Vface_remapping_alist))
  1113         {
  1114           int face_id = lookup_named_face (NULL, f, Qdefault, true);
  1115           struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
  1116           if (face && face->font)
  1117             {
  1118               if (face->font->average_width)
  1119                 denom = face->font->average_width;
  1120               else if (face->font->space_width)
  1121                 denom = face->font->space_width;
  1122             }
  1123         }
  1124       /* For performance, use canonical chars if no face remapping.  */
  1125       else
  1126         pixelwise = WINDOW_BODY_IN_CANONICAL_CHARS;
  1127     }
  1128 
  1129   if (pixelwise == WINDOW_BODY_IN_CANONICAL_CHARS)
  1130     denom = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
  1131 
  1132   /* Don't return a negative value.  */
  1133   return max (width / denom, 0);
  1134 }
  1135 
  1136 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
  1137        doc: /* Return the width of WINDOW's text area.
  1138 WINDOW must be a live window and defaults to the selected one.  The
  1139 return value does not include any vertical dividers, fringes or
  1140 marginal areas, or scroll bars.
  1141 
  1142 The optional argument PIXELWISE defines the units to use for the
  1143 width.  If nil, return the largest integer smaller than WINDOW's pixel
  1144 width in units of the character width of WINDOW's frame.  If PIXELWISE
  1145 is `remap' and the default face is remapped (see
  1146 `face-remapping-alist'), use the remapped face to determine the
  1147 character width.  For any other non-nil value, return the width in
  1148 pixels.
  1149 
  1150 Note that the returned value includes the column reserved for the
  1151 continuation glyph.
  1152 
  1153 Also see `window-max-chars-per-line'.  */)
  1154   (Lisp_Object window, Lisp_Object pixelwise)
  1155 {
  1156   return (make_fixnum
  1157           (window_body_width (decode_live_window (window),
  1158                               window_body_unit_from_symbol (pixelwise))));
  1159 }
  1160 
  1161 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
  1162        doc: /* Return the height of WINDOW's text area.
  1163 WINDOW must be a live window and defaults to the selected one.  The
  1164 return value does not include the mode line or header line or any
  1165 horizontal divider.
  1166 
  1167 The optional argument PIXELWISE defines the units to use for the
  1168 height.  If nil, return the largest integer smaller than WINDOW's
  1169 pixel height in units of the character height of WINDOW's frame.  If
  1170 PIXELWISE is `remap' and the default face is remapped (see
  1171 `face-remapping-alist'), use the remapped face to determine the
  1172 character height.  For any other non-nil value, return the height in
  1173 pixels.  */)
  1174   (Lisp_Object window, Lisp_Object pixelwise)
  1175 {
  1176   return (make_fixnum
  1177           (window_body_height (decode_live_window (window),
  1178                                window_body_unit_from_symbol (pixelwise))));
  1179 }
  1180 
  1181 DEFUN ("window-old-body-pixel-width",
  1182        Fwindow_old_body_pixel_width,
  1183        Swindow_old_body_pixel_width, 0, 1, 0,
  1184        doc: /* Return old width of WINDOW's text area in pixels.
  1185 WINDOW must be a live window and defaults to the selected one.
  1186 
  1187 The return value is the pixel width of WINDOW's text area after the
  1188 last time window change functions found WINDOW live on its frame.  It
  1189 is zero if WINDOW was created after that.  */)
  1190   (Lisp_Object window)
  1191 {
  1192   return (make_fixnum
  1193           (decode_live_window (window)->old_body_pixel_width));
  1194 }
  1195 
  1196 DEFUN ("window-old-body-pixel-height",
  1197        Fwindow_old_body_pixel_height,
  1198        Swindow_old_body_pixel_height, 0, 1, 0,
  1199        doc: /* Return old height of WINDOW's text area in pixels.
  1200 WINDOW must be a live window and defaults to the selected one.
  1201 
  1202 The return value is the pixel height of WINDOW's text area after the
  1203 last time window change functions found WINDOW live on its frame.  It
  1204 is zero if WINDOW was created after that.  */)
  1205   (Lisp_Object window)
  1206 {
  1207   return (make_fixnum
  1208           (decode_live_window (window)->old_body_pixel_height));
  1209 }
  1210 
  1211 DEFUN ("window-mode-line-height", Fwindow_mode_line_height,
  1212        Swindow_mode_line_height, 0, 1, 0,
  1213        doc: /* Return the height in pixels of WINDOW's mode-line.
  1214 WINDOW must be a live window and defaults to the selected one.  */)
  1215   (Lisp_Object window)
  1216 {
  1217   return make_fixnum (WINDOW_MODE_LINE_HEIGHT (decode_live_window (window)));
  1218 }
  1219 
  1220 DEFUN ("window-header-line-height", Fwindow_header_line_height,
  1221        Swindow_header_line_height, 0, 1, 0,
  1222        doc: /* Return the height in pixels of WINDOW's header-line.
  1223 WINDOW must be a live window and defaults to the selected one.  */)
  1224   (Lisp_Object window)
  1225 {
  1226   return make_fixnum (WINDOW_HEADER_LINE_HEIGHT (decode_live_window (window)));
  1227 }
  1228 
  1229 DEFUN ("window-tab-line-height", Fwindow_tab_line_height,
  1230        Swindow_tab_line_height, 0, 1, 0,
  1231        doc: /* Return the height in pixels of WINDOW's tab-line.
  1232 WINDOW must be a live window and defaults to the selected one.  */)
  1233   (Lisp_Object window)
  1234 {
  1235   return make_fixnum (WINDOW_TAB_LINE_HEIGHT (decode_live_window (window)));
  1236 }
  1237 
  1238 DEFUN ("window-right-divider-width", Fwindow_right_divider_width,
  1239        Swindow_right_divider_width, 0, 1, 0,
  1240        doc: /* Return the width in pixels of WINDOW's right divider.
  1241 WINDOW must be a live window and defaults to the selected one.  */)
  1242   (Lisp_Object window)
  1243 {
  1244   return make_fixnum (WINDOW_RIGHT_DIVIDER_WIDTH (decode_live_window (window)));
  1245 }
  1246 
  1247 DEFUN ("window-bottom-divider-width", Fwindow_bottom_divider_width,
  1248        Swindow_bottom_divider_width, 0, 1, 0,
  1249        doc: /* Return the width in pixels of WINDOW's bottom divider.
  1250 WINDOW must be a live window and defaults to the selected one.  */)
  1251   (Lisp_Object window)
  1252 {
  1253   return make_fixnum (WINDOW_BOTTOM_DIVIDER_WIDTH (decode_live_window (window)));
  1254 }
  1255 
  1256 DEFUN ("window-scroll-bar-width", Fwindow_scroll_bar_width,
  1257        Swindow_scroll_bar_width, 0, 1, 0,
  1258        doc: /* Return the width in pixels of WINDOW's vertical scrollbar.
  1259 WINDOW must be a live window and defaults to the selected one.  */)
  1260   (Lisp_Object window)
  1261 {
  1262   return make_fixnum (WINDOW_SCROLL_BAR_AREA_WIDTH (decode_live_window (window)));
  1263 }
  1264 
  1265 DEFUN ("window-scroll-bar-height", Fwindow_scroll_bar_height,
  1266        Swindow_scroll_bar_height, 0, 1, 0,
  1267        doc: /* Return the height in pixels of WINDOW's horizontal scrollbar.
  1268 WINDOW must be a live window and defaults to the selected one.  */)
  1269   (Lisp_Object window)
  1270 {
  1271   return make_fixnum (WINDOW_SCROLL_BAR_AREA_HEIGHT (decode_live_window (window)));
  1272 }
  1273 
  1274 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
  1275        doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
  1276 WINDOW must be a live window and defaults to the selected one.  */)
  1277   (Lisp_Object window)
  1278 {
  1279   return make_fixnum (decode_live_window (window)->hscroll);
  1280 }
  1281 
  1282 /* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
  1283    range, returning the new amount as a fixnum.  */
  1284 static Lisp_Object
  1285 set_window_hscroll (struct window *w, EMACS_INT hscroll)
  1286 {
  1287   /* Horizontal scrolling has problems with large scroll amounts.
  1288      It's too slow with long lines, and even with small lines the
  1289      display can be messed up.  For now, though, impose only the limits
  1290      required by the internal representation: horizontal scrolling must
  1291      fit in fixnum (since it's visible to Elisp) and into ptrdiff_t
  1292      (since it's stored in a ptrdiff_t).  */
  1293   ptrdiff_t hscroll_max = min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX);
  1294   ptrdiff_t new_hscroll = clip_to_bounds (0, hscroll, hscroll_max);
  1295 
  1296   /* Prevent redisplay shortcuts when changing the hscroll.  */
  1297   if (w->hscroll != new_hscroll)
  1298     {
  1299       XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
  1300       wset_redisplay (w);
  1301     }
  1302 
  1303   w->hscroll = new_hscroll;
  1304   w->suspend_auto_hscroll = true;
  1305 
  1306   return make_fixnum (new_hscroll);
  1307 }
  1308 
  1309 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
  1310        doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
  1311 WINDOW must be a live window and defaults to the selected one.
  1312 Clip the number to a reasonable value if out of range.
  1313 Return the new number.  NCOL should be zero or positive.
  1314 
  1315 Note that if `auto-hscroll-mode' is non-nil, you cannot scroll the
  1316 window so that the location of point moves off-window.  */)
  1317   (Lisp_Object window, Lisp_Object ncol)
  1318 {
  1319   CHECK_FIXNUM (ncol);
  1320   return set_window_hscroll (decode_live_window (window), XFIXNUM (ncol));
  1321 }
  1322 
  1323 /* Test if the character at column X, row Y is within window W.
  1324    If it is not, return ON_NOTHING;
  1325    if it is on the window's vertical divider, return
  1326       ON_RIGHT_DIVIDER;
  1327    if it is on the window's horizontal divider, return
  1328       ON_BOTTOM_DIVIDER;
  1329    if it is in the window's text area, return ON_TEXT;
  1330    if it is on the window's modeline, return ON_MODE_LINE;
  1331    if it is on the border between the window and its right sibling,
  1332       return ON_VERTICAL_BORDER;
  1333    if it is on a scroll bar, return ON_SCROLL_BAR;
  1334    if it is on the window's top line, return ON_TAB_LINE;
  1335    if it is on the window's header line, return ON_HEADER_LINE;
  1336    if it is in left or right fringe of the window,
  1337       return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
  1338    if it is in the marginal area to the left/right of the window,
  1339       return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
  1340 
  1341    X and Y are frame relative pixel coordinates.  */
  1342 
  1343 static enum window_part
  1344 coordinates_in_window (register struct window *w, int x, int y)
  1345 {
  1346   struct frame *f = XFRAME (WINDOW_FRAME (w));
  1347   enum window_part part;
  1348   int ux = FRAME_COLUMN_WIDTH (f);
  1349   int left_x = WINDOW_LEFT_EDGE_X (w);
  1350   int right_x = WINDOW_RIGHT_EDGE_X (w);
  1351   int top_y = WINDOW_TOP_EDGE_Y (w);
  1352   int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
  1353   /* The width of the area where the vertical line can be dragged.
  1354      (Between mode lines for instance.  */
  1355   int grabbable_width = ux;
  1356   int lmargin_width, rmargin_width, text_left, text_right;
  1357 
  1358   /* Outside any interesting row or column?  */
  1359   if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
  1360     return ON_NOTHING;
  1361 
  1362   /* On the horizontal window divider (which prevails the vertical
  1363      divider)?  */
  1364   if (WINDOW_BOTTOM_DIVIDER_WIDTH (w) > 0
  1365       && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
  1366       && y <= bottom_y)
  1367     return ON_BOTTOM_DIVIDER;
  1368   /* On vertical window divider?  */
  1369   else if (!WINDOW_RIGHTMOST_P (w)
  1370            && WINDOW_RIGHT_DIVIDER_WIDTH (w) > 0
  1371            && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
  1372            && x <= right_x)
  1373     return ON_RIGHT_DIVIDER;
  1374   /* On the horizontal scroll bar?  (Including the empty space at its
  1375      right!)  */
  1376   else if ((WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
  1377             && y >= (bottom_y
  1378                      - WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
  1379                      - CURRENT_MODE_LINE_HEIGHT (w)
  1380                      - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
  1381             && y <= (bottom_y
  1382                      - CURRENT_MODE_LINE_HEIGHT (w)
  1383                      - WINDOW_BOTTOM_DIVIDER_WIDTH (w))))
  1384     return ON_HORIZONTAL_SCROLL_BAR;
  1385   /* On the mode or header/tab line?   */
  1386   else if ((window_wants_mode_line (w)
  1387             && y >= (bottom_y
  1388                      - CURRENT_MODE_LINE_HEIGHT (w)
  1389                      - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
  1390             && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
  1391             && (part = ON_MODE_LINE))
  1392            || (window_wants_tab_line (w)
  1393                && y < top_y + CURRENT_TAB_LINE_HEIGHT (w)
  1394                && (part = ON_TAB_LINE))
  1395            || (window_wants_header_line (w)
  1396                && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
  1397                + (window_wants_tab_line (w)
  1398                   ? CURRENT_TAB_LINE_HEIGHT (w)
  1399                   : 0)
  1400                && (part = ON_HEADER_LINE)))
  1401     {
  1402       /* If it's under/over the scroll bar portion of the mode/header
  1403          line, say it's on the vertical line.  That's to be able to
  1404          resize windows horizontally in case we're using toolkit scroll
  1405          bars.  Note: If scrollbars are on the left, the window that
  1406          must be eventually resized is that on the left of WINDOW.  */
  1407       if ((WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0)
  1408           && ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
  1409                && !WINDOW_LEFTMOST_P (w)
  1410                && eabs (x - left_x) < grabbable_width)
  1411               || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
  1412                   && !WINDOW_RIGHTMOST_P (w)
  1413                   && eabs (x - right_x) < grabbable_width)))
  1414         return ON_VERTICAL_BORDER;
  1415       else
  1416         return part;
  1417     }
  1418 
  1419   /* In what's below, we subtract 1 when computing right_x because we
  1420      want the rightmost pixel, which is given by left_pixel+width-1.  */
  1421   if (w->pseudo_window_p)
  1422     {
  1423       left_x = 0;
  1424       right_x = WINDOW_PIXEL_WIDTH (w) - 1;
  1425     }
  1426   else
  1427     {
  1428       left_x = WINDOW_BOX_LEFT_EDGE_X (w);
  1429       right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
  1430     }
  1431 
  1432   /* Outside any interesting column?  */
  1433   if (x < left_x || x > right_x)
  1434     return ON_VERTICAL_SCROLL_BAR;
  1435 
  1436   lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
  1437   rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
  1438 
  1439   text_left = window_box_left (w, TEXT_AREA);
  1440   text_right = text_left + window_box_width (w, TEXT_AREA);
  1441 
  1442   if (FRAME_WINDOW_P (f))
  1443     {
  1444       if (!w->pseudo_window_p
  1445           && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
  1446           && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
  1447           && !WINDOW_RIGHTMOST_P (w)
  1448           && (eabs (x - right_x) < grabbable_width))
  1449         return ON_VERTICAL_BORDER;
  1450     }
  1451   /* Need to say "x > right_x" rather than >=, since on character
  1452      terminals, the vertical line's x coordinate is right_x.  */
  1453   else if (!w->pseudo_window_p
  1454            && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
  1455            && !WINDOW_RIGHTMOST_P (w)
  1456            /* Why check ux if we are not the rightmost window?  Also
  1457               shouldn't a pseudo window always be rightmost?  */
  1458            && x > right_x - ux)
  1459     return ON_VERTICAL_BORDER;
  1460 
  1461   if (x < text_left)
  1462     {
  1463       if (lmargin_width > 0
  1464           && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
  1465               ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
  1466               : (x < left_x + lmargin_width)))
  1467         return ON_LEFT_MARGIN;
  1468       else
  1469         return ON_LEFT_FRINGE;
  1470     }
  1471 
  1472   if (x >= text_right)
  1473     {
  1474       if (rmargin_width > 0
  1475           && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
  1476               ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
  1477               : (x >= right_x - rmargin_width)))
  1478         return ON_RIGHT_MARGIN;
  1479       else
  1480         return ON_RIGHT_FRINGE;
  1481     }
  1482 
  1483   /* Everything special ruled out - must be on text area */
  1484   return ON_TEXT;
  1485 }
  1486 
  1487 /* Take X is the frame-relative pixel x-coordinate, and return the
  1488    x-coordinate relative to part PART of window W. */
  1489 int
  1490 window_relative_x_coord (struct window *w, enum window_part part, int x)
  1491 {
  1492   int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
  1493 
  1494   switch (part)
  1495     {
  1496     case ON_TEXT:
  1497       return x - window_box_left (w, TEXT_AREA);
  1498 
  1499     case ON_TAB_LINE:
  1500     case ON_HEADER_LINE:
  1501     case ON_MODE_LINE:
  1502     case ON_LEFT_FRINGE:
  1503       return x - left_x;
  1504 
  1505     case ON_RIGHT_FRINGE:
  1506       return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
  1507 
  1508     case ON_LEFT_MARGIN:
  1509       return (x - left_x
  1510               - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
  1511                  ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
  1512 
  1513     case ON_RIGHT_MARGIN:
  1514       return (x + 1
  1515               - ((w->pseudo_window_p)
  1516                  ? WINDOW_PIXEL_WIDTH (w)
  1517                  : WINDOW_BOX_RIGHT_EDGE_X (w))
  1518               + window_box_width (w, RIGHT_MARGIN_AREA)
  1519               + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
  1520                  ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
  1521 
  1522     case ON_NOTHING:
  1523     case ON_VERTICAL_BORDER:
  1524     case ON_VERTICAL_SCROLL_BAR:
  1525     case ON_HORIZONTAL_SCROLL_BAR:
  1526     case ON_RIGHT_DIVIDER:
  1527     case ON_BOTTOM_DIVIDER:
  1528       return 0;
  1529 
  1530     default:
  1531       emacs_abort ();
  1532     }
  1533 }
  1534 
  1535 
  1536 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
  1537        Scoordinates_in_window_p, 2, 2, 0,
  1538        doc: /* Return non-nil if COORDINATES are in WINDOW.
  1539 WINDOW must be a live window and defaults to the selected one.
  1540 COORDINATES is a cons of the form (X . Y), X and Y being distances
  1541 measured in characters from the upper-left corner of the frame.
  1542 \(0 . 0) denotes the character in the upper left corner of the
  1543 frame.
  1544 If COORDINATES are in the text portion of WINDOW,
  1545    the coordinates relative to the window are returned.
  1546 If they are in the bottom divider of WINDOW, `bottom-divider' is returned.
  1547 If they are in the right divider of WINDOW, `right-divider' is returned.
  1548 If they are in the mode line of WINDOW, `mode-line' is returned.
  1549 If they are in the header line of WINDOW, `header-line' is returned.
  1550 If they are in the tab line of WINDOW, `tab-line' is returned.
  1551 If they are in the left fringe of WINDOW, `left-fringe' is returned.
  1552 If they are in the right fringe of WINDOW, `right-fringe' is returned.
  1553 If they are on the border between WINDOW and its right sibling,
  1554   `vertical-line' is returned.
  1555 If they are in the windows's left or right marginal areas, `left-margin'\n\
  1556   or `right-margin' is returned.  */)
  1557   (register Lisp_Object coordinates, Lisp_Object window)
  1558 {
  1559   struct window *w;
  1560   struct frame *f;
  1561   int x, y;
  1562   Lisp_Object lx, ly;
  1563 
  1564   w = decode_live_window (window);
  1565   f = XFRAME (w->frame);
  1566   CHECK_CONS (coordinates);
  1567   lx = Fcar (coordinates);
  1568   ly = Fcdr (coordinates);
  1569   CHECK_NUMBER (lx);
  1570   CHECK_NUMBER (ly);
  1571   x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
  1572   y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
  1573 
  1574   switch (coordinates_in_window (w, x, y))
  1575     {
  1576     case ON_NOTHING:
  1577       return Qnil;
  1578 
  1579     case ON_TEXT:
  1580       /* Convert X and Y to window relative pixel coordinates, and
  1581          return the canonical char units.  */
  1582       x -= window_box_left (w, TEXT_AREA);
  1583       y -= WINDOW_TOP_EDGE_Y (w);
  1584       return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
  1585                     FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
  1586 
  1587     case ON_MODE_LINE:
  1588       return Qmode_line;
  1589 
  1590     case ON_VERTICAL_BORDER:
  1591       return Qvertical_line;
  1592 
  1593     case ON_HEADER_LINE:
  1594       return Qheader_line;
  1595 
  1596     case ON_TAB_LINE:
  1597       return Qtab_line;
  1598 
  1599     case ON_LEFT_FRINGE:
  1600       return Qleft_fringe;
  1601 
  1602     case ON_RIGHT_FRINGE:
  1603       return Qright_fringe;
  1604 
  1605     case ON_LEFT_MARGIN:
  1606       return Qleft_margin;
  1607 
  1608     case ON_RIGHT_MARGIN:
  1609       return Qright_margin;
  1610 
  1611     case ON_VERTICAL_SCROLL_BAR:
  1612       /* Historically we are supposed to return nil in this case.  */
  1613       return Qnil;
  1614 
  1615     case ON_HORIZONTAL_SCROLL_BAR:
  1616       return Qnil;
  1617 
  1618     case ON_RIGHT_DIVIDER:
  1619       return Qright_divider;
  1620 
  1621     case ON_BOTTOM_DIVIDER:
  1622       return Qbottom_divider;
  1623 
  1624     default:
  1625       emacs_abort ();
  1626     }
  1627 }
  1628 
  1629 
  1630 /* Callback for foreach_window, used in window_from_coordinates.
  1631    Check if window W contains coordinates specified by USER_DATA which
  1632    is actually a pointer to a struct check_window_data CW.
  1633 
  1634    Check if window W contains coordinates *CW->x and *CW->y.  If it
  1635    does, return W in *CW->window, as Lisp_Object, and return in
  1636    *CW->part the part of the window under coordinates *X,*Y.  Return
  1637    false from this function to stop iterating over windows.  */
  1638 
  1639 struct check_window_data
  1640 {
  1641   Lisp_Object *window;
  1642   int x, y;
  1643   enum window_part *part;
  1644 };
  1645 
  1646 static bool
  1647 check_window_containing (struct window *w, void *user_data)
  1648 {
  1649   struct check_window_data *cw = user_data;
  1650   enum window_part found = coordinates_in_window (w, cw->x, cw->y);
  1651   if (found == ON_NOTHING)
  1652     return true;
  1653   else
  1654     {
  1655       *cw->part = found;
  1656       XSETWINDOW (*cw->window, w);
  1657       return false;
  1658     }
  1659 }
  1660 
  1661 
  1662 /* Find the window containing frame-relative pixel position X/Y and
  1663    return it as a Lisp_Object.
  1664 
  1665    If X, Y is on one of the window's special `window_part' elements,
  1666    set *PART to the id of that element.
  1667 
  1668    If there is no window under X, Y return nil and leave *PART
  1669    unmodified.  TOOL_BAR_P means detect tool-bar windows, and
  1670    TAB_BAR_P means detect tab-bar windows.
  1671 
  1672    This function was previously implemented with a loop cycling over
  1673    windows with Fnext_window, and starting with the frame's selected
  1674    window.  It turned out that this doesn't work with an
  1675    implementation of next_window using Vwindow_list, because
  1676    FRAME_SELECTED_WINDOW (F) is not always contained in the window
  1677    tree of F when this function is called asynchronously from
  1678    note_mouse_highlight.  The original loop didn't terminate in this
  1679    case.  */
  1680 
  1681 Lisp_Object
  1682 window_from_coordinates (struct frame *f, int x, int y,
  1683                          enum window_part *part, bool tab_bar_p, bool tool_bar_p)
  1684 {
  1685   Lisp_Object window;
  1686   struct check_window_data cw;
  1687   enum window_part dummy;
  1688 
  1689   if (part == 0)
  1690     part = &dummy;
  1691 
  1692   window = Qnil;
  1693   cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
  1694   foreach_window (f, check_window_containing, &cw);
  1695 
  1696 #if defined (HAVE_WINDOW_SYSTEM)
  1697   /* If not found above, see if it's in the tab bar window, if a tab
  1698      bar exists.  */
  1699   if (NILP (window)
  1700       && tab_bar_p
  1701       && WINDOWP (f->tab_bar_window)
  1702       && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0
  1703       && (coordinates_in_window (XWINDOW (f->tab_bar_window), x, y)
  1704           != ON_NOTHING))
  1705     {
  1706       *part = ON_TEXT;
  1707       window = f->tab_bar_window;
  1708     }
  1709 #endif
  1710 
  1711 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
  1712   /* If not found above, see if it's in the tool bar window, if a tool
  1713      bar exists.  */
  1714   if (NILP (window)
  1715       && tool_bar_p
  1716       && WINDOWP (f->tool_bar_window)
  1717       && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
  1718       && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
  1719           != ON_NOTHING))
  1720     {
  1721       *part = ON_TEXT;
  1722       window = f->tool_bar_window;
  1723     }
  1724 #endif
  1725 
  1726   return window;
  1727 }
  1728 
  1729 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
  1730        doc: /* Return window containing coordinates X and Y on FRAME.
  1731 FRAME must be a live frame and defaults to the selected one.
  1732 X and Y are measured in units of canonical columns and rows.
  1733 The top left corner of the frame is considered to be column 0, row 0.
  1734 Tool-bar and tab-bar pseudo-windows are ignored by this function: if
  1735 the specified coordinates are in any of these two windows, this
  1736 function returns nil.  */)
  1737   (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
  1738 {
  1739   struct frame *f = decode_live_frame (frame);
  1740 
  1741   CHECK_NUMBER (x);
  1742   CHECK_NUMBER (y);
  1743 
  1744   return window_from_coordinates (f,
  1745                                   (FRAME_PIXEL_X_FROM_CANON_X (f, x)
  1746                                    + FRAME_INTERNAL_BORDER_WIDTH (f)),
  1747                                   (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
  1748                                    + FRAME_INTERNAL_BORDER_WIDTH (f)),
  1749                                   0, false, false);
  1750 }
  1751 
  1752 ptrdiff_t
  1753 window_point (struct window *w)
  1754 {
  1755   return (w == XWINDOW (selected_window)
  1756           ? BUF_PT (XBUFFER (w->contents))
  1757           : XMARKER (w->pointm)->charpos);
  1758 }
  1759 
  1760 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
  1761        doc: /* Return current value of point in WINDOW.
  1762 WINDOW must be a live window and defaults to the selected one.
  1763 
  1764 For a nonselected window, this is the value point would have if that
  1765 window were selected.
  1766 
  1767 Note that, when WINDOW is selected, the value returned is the same as
  1768 that returned by `point' for WINDOW's buffer.  It would be more strictly
  1769 correct to return the top-level value of `point', outside of any
  1770 `save-excursion' forms.  But that is hard to define.  */)
  1771   (Lisp_Object window)
  1772 {
  1773   return make_fixnum (window_point (decode_live_window (window)));
  1774 }
  1775 
  1776 DEFUN ("window-old-point", Fwindow_old_point, Swindow_old_point, 0, 1, 0,
  1777        doc: /* Return old value of point in WINDOW.
  1778 WINDOW must be a live window and defaults to the selected one.  */)
  1779   (Lisp_Object window)
  1780 {
  1781   return Fmarker_position (decode_live_window (window)->old_pointm);
  1782 }
  1783 
  1784 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
  1785        doc: /* Return position at which display currently starts in WINDOW.
  1786 WINDOW must be a live window and defaults to the selected one.
  1787 This is updated by redisplay or by calling `set-window-start'.  */)
  1788   (Lisp_Object window)
  1789 {
  1790   return Fmarker_position (decode_live_window (window)->start);
  1791 }
  1792 
  1793 /* This is text temporarily removed from the doc string below.
  1794 
  1795 This function returns nil if the position is not currently known.
  1796 That happens when redisplay is preempted and doesn't finish.
  1797 If in that case you want to compute where the end of the window would
  1798 have been if redisplay had finished, do this:
  1799     (save-excursion
  1800       (goto-char (window-start window))
  1801       (vertical-motion (1- (window-height window)) window)
  1802       (point))")  */
  1803 
  1804 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
  1805        doc: /* Return position at which display currently ends in WINDOW.
  1806 This is the position after the final character in WINDOW.
  1807 
  1808 WINDOW must be a live window and defaults to the selected one.  This
  1809 is updated by redisplay, when it runs to completion.  Simply changing
  1810 the buffer text or setting `window-start' does not update this value.
  1811 
  1812 Return nil if there is no recorded value.  (This can happen if the
  1813 last redisplay of WINDOW was preempted, and did not finish.)  If
  1814 UPDATE is non-nil, compute the up-to-date position if it isn't already
  1815 recorded.  */)
  1816   (Lisp_Object window, Lisp_Object update)
  1817 {
  1818   Lisp_Object value;
  1819   struct window *w = decode_live_window (window);
  1820   Lisp_Object buf;
  1821   struct buffer *b;
  1822 
  1823   buf = w->contents;
  1824   CHECK_BUFFER (buf);
  1825   b = XBUFFER (buf);
  1826 
  1827   if (! NILP (update)
  1828       && (windows_or_buffers_changed
  1829           || !w->window_end_valid
  1830           || b->clip_changed
  1831           || b->prevent_redisplay_optimizations_p
  1832           || window_outdated (w))
  1833       /* Don't call display routines if we didn't yet create any real
  1834          frames, because the glyph matrices are not yet allocated in
  1835          that case.  This could happen in some code that runs in the
  1836          daemon during initialization (e.g., see bug#20565).  */
  1837       && !(noninteractive || FRAME_INITIAL_P (WINDOW_XFRAME (w))))
  1838     {
  1839       struct text_pos startp;
  1840       struct it it;
  1841       struct buffer *old_buffer = NULL;
  1842       void *itdata = NULL;
  1843 
  1844       /* Cannot use Fvertical_motion because that function doesn't
  1845          cope with variable-height lines.  */
  1846       if (b != current_buffer)
  1847         {
  1848           old_buffer = current_buffer;
  1849           set_buffer_internal (b);
  1850         }
  1851 
  1852       /* In case W->start is out of the range, use something
  1853          reasonable.  This situation occurred when loading a file with
  1854          `-l' containing a call to `rmail' with subsequent other
  1855          commands.  At the end, W->start happened to be BEG, while
  1856          rmail had already narrowed the buffer.  */
  1857       CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
  1858 
  1859       itdata = bidi_shelve_cache ();
  1860       start_display (&it, w, startp);
  1861       move_it_vertically (&it, window_box_height (w));
  1862       if (it.current_y < it.last_visible_y)
  1863         move_it_past_eol (&it);
  1864       value = make_fixnum (IT_CHARPOS (it));
  1865       bidi_unshelve_cache (itdata, false);
  1866 
  1867       if (old_buffer)
  1868         set_buffer_internal (old_buffer);
  1869     }
  1870   else
  1871     XSETINT (value, BUF_Z (b) - w->window_end_pos);
  1872 
  1873   return value;
  1874 }
  1875 
  1876 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
  1877        doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
  1878 WINDOW must be a live window and defaults to the selected one.
  1879 Return POS.  */)
  1880   (Lisp_Object window, Lisp_Object pos)
  1881 {
  1882   register struct window *w = decode_live_window (window);
  1883 
  1884   /* Type of POS is checked by Fgoto_char or set_marker_restricted ...  */
  1885 
  1886   if (w == XWINDOW (selected_window))
  1887     {
  1888       if (XBUFFER (w->contents) == current_buffer)
  1889         Fgoto_char (pos);
  1890       else
  1891         {
  1892           struct buffer *old_buffer = current_buffer;
  1893 
  1894           /* ... but here we want to catch type error before buffer change.  */
  1895           CHECK_FIXNUM_COERCE_MARKER (pos);
  1896           set_buffer_internal (XBUFFER (w->contents));
  1897           Fgoto_char (pos);
  1898           set_buffer_internal (old_buffer);
  1899         }
  1900     }
  1901   else
  1902     {
  1903       set_marker_restricted (w->pointm, pos, w->contents);
  1904       /* We have to make sure that redisplay updates the window to show
  1905          the new value of point.  */
  1906       wset_redisplay (w);
  1907     }
  1908 
  1909   return pos;
  1910 }
  1911 
  1912 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
  1913        doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
  1914 WINDOW must be a live window and defaults to the selected one.  Return
  1915 POS.
  1916 
  1917 Optional third arg NOFORCE non-nil prevents next redisplay from
  1918 moving point if displaying the window at POS makes point invisible;
  1919 redisplay will then choose the WINDOW's start position by itself in
  1920 that case, i.e. it will disregard POS if adhering to it will make
  1921 point not visible in the window.
  1922 
  1923 For reliable setting of WINDOW start position, make sure point is
  1924 at a position that will be visible when that start is in effect,
  1925 otherwise there's a chance POS will be disregarded, e.g., if point
  1926 winds up in a partially-visible line.
  1927 
  1928 The setting of the WINDOW's start position takes effect during the
  1929 next redisplay cycle, not immediately.  If NOFORCE is nil or
  1930 omitted, forcing the display of WINDOW to start at POS cancels
  1931 any setting of WINDOW's vertical scroll (\"vscroll\") amount
  1932 set by `set-window-vscroll' and by scrolling functions.  */)
  1933   (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
  1934 {
  1935   register struct window *w = decode_live_window (window);
  1936 
  1937   set_marker_restricted (w->start, pos, w->contents);
  1938   /* This is not right, but much easier than doing what is right.  */
  1939   w->start_at_line_beg = false;
  1940   if (NILP (noforce))
  1941     w->force_start = true;
  1942   wset_update_mode_line (w);
  1943   /* Bug#15957.  */
  1944   w->window_end_valid = false;
  1945   wset_redisplay (w);
  1946 
  1947   return pos;
  1948 }
  1949 
  1950 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
  1951        Spos_visible_in_window_p, 0, 3, 0,
  1952        doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
  1953 WINDOW must be a live window and defaults to the selected one.
  1954 
  1955 Return nil if that position is scrolled vertically out of view.  If a
  1956 character is only partially visible, nil is returned, unless the
  1957 optional argument PARTIALLY is non-nil.  If POS is only out of view
  1958 because of horizontal scrolling, return non-nil.  If POS is t, it
  1959 specifies either the first position displayed on the last visible
  1960 screen line in WINDOW, or the end-of-buffer position, whichever comes
  1961 first.  POS defaults to point in WINDOW; WINDOW defaults to the
  1962 selected window.
  1963 
  1964 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
  1965 the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
  1966 where X and Y are the pixel coordinates relative to the top left corner
  1967 of the window.  The remaining elements are omitted if the character after
  1968 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
  1969 off-window at the top and bottom of the screen line ("row") containing
  1970 POS, ROWH is the visible height of that row, and VPOS is the row number
  1971 \(zero-based).  */)
  1972   (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
  1973 {
  1974   struct window *w;
  1975   EMACS_INT posint;
  1976   struct buffer *buf;
  1977   struct text_pos top;
  1978   Lisp_Object in_window = Qnil;
  1979   int rtop, rbot, rowh, vpos;
  1980   bool fully_p = true;
  1981   int x, y;
  1982 
  1983   w = decode_live_window (window);
  1984   buf = XBUFFER (w->contents);
  1985   SET_TEXT_POS_FROM_MARKER (top, w->start);
  1986 
  1987   if (EQ (pos, Qt))
  1988     posint = -1;
  1989   else if (!NILP (pos))
  1990     posint = fix_position (pos);
  1991   else if (w == XWINDOW (selected_window))
  1992     posint = PT;
  1993   else
  1994     posint = marker_position (w->pointm);
  1995 
  1996   /* If position is above window start or outside buffer boundaries,
  1997      or if window start is out of range, position is not visible.  */
  1998   if ((EQ (pos, Qt)
  1999        || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
  2000       && CHARPOS (top) >= BUF_BEGV (buf)
  2001       && CHARPOS (top) <= BUF_ZV (buf)
  2002       && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos))
  2003     {
  2004       fully_p = !rtop && !rbot;
  2005       if (!NILP (partially) || fully_p)
  2006         in_window = Qt;
  2007     }
  2008 
  2009   if (!NILP (in_window) && !NILP (partially))
  2010     {
  2011       Lisp_Object part = Qnil;
  2012       if (!fully_p)
  2013         part = list4i (rtop, rbot, rowh, vpos);
  2014       in_window = Fcons (make_fixnum (x),
  2015                          Fcons (make_fixnum (y), part));
  2016     }
  2017 
  2018   return in_window;
  2019 }
  2020 
  2021 DEFUN ("window-line-height", Fwindow_line_height,
  2022        Swindow_line_height, 0, 2, 0,
  2023        doc: /* Return height in pixels of text line LINE in window WINDOW.
  2024 WINDOW must be a live window and defaults to the selected one.
  2025 
  2026 Return height of current line if LINE is omitted or nil.  Return height of
  2027 header or mode line if LINE is `header-line' or `mode-line'.
  2028 Otherwise, LINE is a text line number starting from 0.  A negative number
  2029 counts from the end of the window.
  2030 
  2031 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
  2032 in pixels of the visible part of the line, VPOS and YPOS are the
  2033 vertical position in lines and pixels of the line, relative to the top
  2034 of the first text line, and OFFBOT is the number of off-window pixels at
  2035 the bottom of the text line.  If there are off-window pixels at the top
  2036 of the (first) text line, YPOS is negative.
  2037 
  2038 Return nil if window display is not up-to-date.  In that case, use
  2039 `pos-visible-in-window-p' to obtain the information.  */)
  2040   (Lisp_Object line, Lisp_Object window)
  2041 {
  2042   register struct window *w;
  2043   register struct buffer *b;
  2044   struct glyph_row *row, *end_row;
  2045   int max_y, crop, i;
  2046   EMACS_INT n;
  2047 
  2048   w = decode_live_window (window);
  2049 
  2050   if (noninteractive || w->pseudo_window_p)
  2051     return Qnil;
  2052 
  2053   CHECK_BUFFER (w->contents);
  2054   b = XBUFFER (w->contents);
  2055 
  2056   /* Fail if current matrix is not up-to-date.  */
  2057   if (!w->window_end_valid
  2058       || windows_or_buffers_changed
  2059       || b->clip_changed
  2060       || b->prevent_redisplay_optimizations_p
  2061       || window_outdated (w))
  2062     return Qnil;
  2063 
  2064   if (NILP (line))
  2065     {
  2066       i = w->cursor.vpos;
  2067       if (i < 0 || i >= w->current_matrix->nrows
  2068           || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
  2069         return Qnil;
  2070       max_y = window_text_bottom_y (w);
  2071       goto found_row;
  2072     }
  2073 
  2074   if (EQ (line, Qtab_line))
  2075     {
  2076       if (!window_wants_tab_line (w))
  2077         return Qnil;
  2078       row = MATRIX_TAB_LINE_ROW (w->current_matrix);
  2079       return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
  2080     }
  2081 
  2082   if (EQ (line, Qheader_line))
  2083     {
  2084       if (!window_wants_header_line (w))
  2085         return Qnil;
  2086       row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
  2087       return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
  2088     }
  2089 
  2090   if (EQ (line, Qmode_line))
  2091     {
  2092       row = MATRIX_MODE_LINE_ROW (w->current_matrix);
  2093       return (row->enabled_p ?
  2094               list4i (row->height,
  2095                       0, /* not accurate */
  2096                       (WINDOW_TAB_LINE_HEIGHT (w)
  2097                        + WINDOW_HEADER_LINE_HEIGHT (w)
  2098                        + window_text_bottom_y (w)),
  2099                       0)
  2100               : Qnil);
  2101     }
  2102 
  2103   CHECK_FIXNUM (line);
  2104   n = XFIXNUM (line);
  2105 
  2106   row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
  2107   end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
  2108   max_y = window_text_bottom_y (w);
  2109   i = 0;
  2110 
  2111   while ((n < 0 || i < n)
  2112          && row <= end_row && row->enabled_p
  2113          && row->y + row->height < max_y)
  2114     row++, i++;
  2115 
  2116   if (row > end_row || !row->enabled_p)
  2117     return Qnil;
  2118 
  2119   if (++n < 0)
  2120     {
  2121       if (-n > i)
  2122         return Qnil;
  2123       row += n;
  2124       i += n;
  2125     }
  2126 
  2127  found_row:
  2128   crop = max (0, (row->y + row->height) - max_y);
  2129   return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
  2130 }
  2131 
  2132 DEFUN ("window-lines-pixel-dimensions", Fwindow_lines_pixel_dimensions, Swindow_lines_pixel_dimensions, 0, 6, 0,
  2133        doc: /* Return pixel dimensions of WINDOW's lines.
  2134 The return value is a list of the x- and y-coordinates of the lower
  2135 right corner of the last character of each line.  Return nil if the
  2136 current glyph matrix of WINDOW is not up-to-date.
  2137 
  2138 Optional argument WINDOW specifies the window whose lines' dimensions
  2139 shall be returned.  Nil or omitted means to return the dimensions for
  2140 the selected window.
  2141 
  2142 FIRST, if non-nil, specifies the index of the first line whose
  2143 dimensions shall be returned.  If FIRST is nil and BODY is non-nil,
  2144 start with the first text line of WINDOW.  Otherwise, start with the
  2145 first line of WINDOW.
  2146 
  2147 LAST, if non-nil, specifies the last line whose dimensions shall be
  2148 returned.  If LAST is nil and BODY is non-nil, the last line is the last
  2149 line of the body (text area) of WINDOW.  Otherwise, last is the last
  2150 line of WINDOW.
  2151 
  2152 INVERSE, if nil, means that the y-pixel value returned for a specific
  2153 line specifies the distance in pixels from the left edge (body edge if
  2154 BODY is non-nil) of WINDOW to the right edge of the last glyph of that
  2155 line.  INVERSE non-nil means that the y-pixel value returned for a
  2156 specific line specifies the distance in pixels from the right edge of
  2157 the last glyph of that line to the right edge (body edge if BODY is
  2158 non-nil) of WINDOW.
  2159 
  2160 LEFT non-nil means to return the x- and y-coordinates of the lower left
  2161 corner of the leftmost character on each line.  This is the value that
  2162 should be used for buffers that mostly display text from right to left.
  2163 
  2164 If LEFT is non-nil and INVERSE is nil, this means that the y-pixel value
  2165 returned for a specific line specifies the distance in pixels from the
  2166 left edge of the last (leftmost) glyph of that line to the right edge
  2167 (body edge if BODY is non-nil) of WINDOW.  If LEFT and INVERSE are both
  2168 non-nil, the y-pixel value returned for a specific line specifies the
  2169 distance in pixels from the left edge (body edge if BODY is non-nil) of
  2170 WINDOW to the left edge of the last (leftmost) glyph of that line.
  2171 
  2172 Normally, the value of this function is not available while Emacs is
  2173 busy, for example, when processing a command.  It should be retrievable
  2174 though when run from an idle timer with a delay of zero seconds.  */)
  2175   (Lisp_Object window, Lisp_Object first, Lisp_Object last, Lisp_Object body, Lisp_Object inverse, Lisp_Object left)
  2176 {
  2177   struct window *w = decode_live_window (window);
  2178   struct buffer *b;
  2179   struct glyph_row *row, *end_row;
  2180   int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w);
  2181   Lisp_Object rows = Qnil;
  2182   int window_width = NILP (body)
  2183     ? w->pixel_width : window_body_width (w, WINDOW_BODY_IN_PIXELS);
  2184   int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
  2185   int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
  2186   int subtract = NILP (body) ? 0 : (tab_line_height + header_line_height);
  2187   bool invert = !NILP (inverse);
  2188   bool left_flag = !NILP (left);
  2189 
  2190   if (noninteractive || w->pseudo_window_p)
  2191     return Qnil;
  2192 
  2193   CHECK_BUFFER (w->contents);
  2194   b = XBUFFER (w->contents);
  2195 
  2196   /* Fail if current matrix is not up-to-date.  */
  2197   if (!w->window_end_valid
  2198       || windows_or_buffers_changed
  2199       || b->clip_changed
  2200       || b->prevent_redisplay_optimizations_p
  2201       || window_outdated (w))
  2202     return Qnil;
  2203 
  2204   row = (!NILP (first)
  2205          ? MATRIX_ROW (w->current_matrix,
  2206                        check_integer_range (first, 0,
  2207                                             w->current_matrix->nrows))
  2208          : NILP (body)
  2209          ? MATRIX_ROW (w->current_matrix, 0)
  2210          : MATRIX_FIRST_TEXT_ROW (w->current_matrix));
  2211   end_row = (!NILP (last)
  2212              ? MATRIX_ROW (w->current_matrix,
  2213                            check_integer_range (last, 0,
  2214                                                 w->current_matrix->nrows))
  2215              : NILP (body)
  2216              ? MATRIX_ROW (w->current_matrix, w->current_matrix->nrows)
  2217              : MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w));
  2218 
  2219   while (row <= end_row && row->enabled_p
  2220          && row->y + row->height < max_y)
  2221     {
  2222 
  2223       if (left_flag)
  2224         {
  2225           struct glyph *glyph = row->glyphs[TEXT_AREA];
  2226 
  2227           rows = Fcons (Fcons (make_fixnum
  2228                                (invert
  2229                                 ? glyph->pixel_width
  2230                                 : window_width - glyph->pixel_width),
  2231                                make_fixnum (row->y + row->height - subtract)),
  2232                         rows);
  2233         }
  2234       else
  2235         rows = Fcons (Fcons (make_fixnum
  2236                              (invert
  2237                               ? window_width - row->pixel_width
  2238                               : row->pixel_width),
  2239                              make_fixnum (row->y + row->height - subtract)),
  2240                       rows);
  2241       row++;
  2242     }
  2243 
  2244   return Fnreverse (rows);
  2245 }
  2246 
  2247 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
  2248        0, 1, 0,
  2249        doc: /* Return non-nil when WINDOW is dedicated to its buffer.
  2250 More precisely, return the value assigned by the last call of
  2251 `set-window-dedicated-p' for WINDOW.  Return nil if that function was
  2252 never called with WINDOW as its argument, or the value set by that
  2253 function was internally reset since its last call.  WINDOW must be a
  2254 live window and defaults to the selected one.
  2255 
  2256 When a window is dedicated to its buffer, `display-buffer' will refrain
  2257 from displaying another buffer in it.  `get-lru-window' and
  2258 `get-largest-window' treat dedicated windows specially.
  2259 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
  2260 `kill-buffer' can delete a dedicated window and the containing frame.
  2261 
  2262 Functions like `set-window-buffer' may change the buffer displayed by a
  2263 window, unless that window is "strongly" dedicated to its buffer, that
  2264 is the value returned by `window-dedicated-p' is t.  */)
  2265   (Lisp_Object window)
  2266 {
  2267   return decode_live_window (window)->dedicated;
  2268 }
  2269 
  2270 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
  2271        Sset_window_dedicated_p, 2, 2, 0,
  2272        doc: /* Mark WINDOW as dedicated according to FLAG.
  2273 WINDOW must be a live window and defaults to the selected one.  FLAG
  2274 non-nil means mark WINDOW as dedicated to its buffer.  FLAG nil means
  2275 mark WINDOW as non-dedicated.  Return FLAG.
  2276 
  2277 When a window is dedicated to its buffer, `display-buffer' will refrain
  2278 from displaying another buffer in it.  `get-lru-window' and
  2279 `get-largest-window' treat dedicated windows specially.
  2280 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
  2281 `quit-restore-window' and `kill-buffer' can delete a dedicated window
  2282 and the containing frame.
  2283 
  2284 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
  2285 its buffer.  Functions like `set-window-buffer' may change the buffer
  2286 displayed by a window, unless that window is strongly dedicated to its
  2287 buffer.  If and when `set-window-buffer' displays another buffer in a
  2288 window, it also makes sure that the window is no more dedicated.  */)
  2289   (Lisp_Object window, Lisp_Object flag)
  2290 {
  2291   wset_dedicated (decode_live_window (window), flag);
  2292   return flag;
  2293 }
  2294 
  2295 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
  2296        0, 1, 0,
  2297        doc:  /* Return buffers previously shown in WINDOW.
  2298 WINDOW must be a live window and defaults to the selected one.
  2299 
  2300 The return value is a list of elements (BUFFER WINDOW-START POS),
  2301 where BUFFER is a buffer, WINDOW-START is the start position of the
  2302 window for that buffer, and POS is a window-specific point value.  */)
  2303   (Lisp_Object window)
  2304 {
  2305   return decode_live_window (window)->prev_buffers;
  2306 }
  2307 
  2308 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
  2309        Sset_window_prev_buffers, 2, 2, 0,
  2310        doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
  2311 WINDOW must be a live window and defaults to the selected one.
  2312 
  2313 PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
  2314 where BUFFER is a buffer, WINDOW-START is the start position of the
  2315 window for that buffer, and POS is a window-specific point value.  */)
  2316      (Lisp_Object window, Lisp_Object prev_buffers)
  2317 {
  2318   wset_prev_buffers (decode_live_window (window), prev_buffers);
  2319   return prev_buffers;
  2320 }
  2321 
  2322 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
  2323        0, 1, 0,
  2324        doc:  /* Return list of buffers recently re-shown in WINDOW.
  2325 WINDOW must be a live window and defaults to the selected one.  */)
  2326      (Lisp_Object window)
  2327 {
  2328   return decode_live_window (window)->next_buffers;
  2329 }
  2330 
  2331 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
  2332        Sset_window_next_buffers, 2, 2, 0,
  2333        doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
  2334 WINDOW must be a live window and defaults to the selected one.
  2335 NEXT-BUFFERS should be a list of buffers.  */)
  2336      (Lisp_Object window, Lisp_Object next_buffers)
  2337 {
  2338   wset_next_buffers (decode_live_window (window), next_buffers);
  2339   return next_buffers;
  2340 }
  2341 
  2342 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
  2343        0, 1, 0,
  2344        doc: /* Return the parameters of WINDOW and their values.
  2345 WINDOW must be a valid window and defaults to the selected one.  The
  2346 return value is a list of elements of the form (PARAMETER . VALUE).  */)
  2347   (Lisp_Object window)
  2348 {
  2349   return Fcopy_alist (decode_valid_window (window)->window_parameters);
  2350 }
  2351 
  2352 Lisp_Object
  2353 window_parameter (struct window *w, Lisp_Object parameter)
  2354 {
  2355   Lisp_Object result = assq_no_quit (parameter, w->window_parameters);
  2356 
  2357   return CDR_SAFE (result);
  2358 }
  2359 
  2360 
  2361 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
  2362        2, 2, 0,
  2363        doc:  /* Return WINDOW's value for PARAMETER.
  2364 WINDOW can be any window and defaults to the selected one.  */)
  2365   (Lisp_Object window, Lisp_Object parameter)
  2366 {
  2367   struct window *w = decode_any_window (window);
  2368 
  2369   return window_parameter (w, parameter);
  2370 }
  2371 
  2372 DEFUN ("set-window-parameter", Fset_window_parameter,
  2373        Sset_window_parameter, 3, 3, 0,
  2374        doc: /* Set WINDOW's value of PARAMETER to VALUE.
  2375 WINDOW can be any window and defaults to the selected one.
  2376 Return VALUE.  */)
  2377   (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
  2378 {
  2379   register struct window *w = decode_any_window (window);
  2380   Lisp_Object old_alist_elt;
  2381 
  2382   old_alist_elt = Fassq (parameter, w->window_parameters);
  2383   if (NILP (old_alist_elt))
  2384     wset_window_parameters
  2385       (w, Fcons (Fcons (parameter, value), w->window_parameters));
  2386   else
  2387     Fsetcdr (old_alist_elt, value);
  2388   return value;
  2389 }
  2390 
  2391 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
  2392        0, 1, 0,
  2393        doc: /* Return the display-table that WINDOW is using.
  2394 WINDOW must be a live window and defaults to the selected one.  */)
  2395   (Lisp_Object window)
  2396 {
  2397   return decode_live_window (window)->display_table;
  2398 }
  2399 
  2400 /* Get the display table for use on window W.  This is either W's
  2401    display table or W's buffer's display table.  Ignore the specified
  2402    tables if they are not valid; if no valid table is specified,
  2403    return 0.  */
  2404 
  2405 struct Lisp_Char_Table *
  2406 window_display_table (struct window *w)
  2407 {
  2408   struct Lisp_Char_Table *dp = NULL;
  2409 
  2410   if (DISP_TABLE_P (w->display_table))
  2411     dp = XCHAR_TABLE (w->display_table);
  2412   else if (BUFFERP (w->contents))
  2413     {
  2414       struct buffer *b = XBUFFER (w->contents);
  2415 
  2416       if (DISP_TABLE_P (BVAR (b, display_table)))
  2417         dp = XCHAR_TABLE (BVAR (b, display_table));
  2418       else if (DISP_TABLE_P (Vstandard_display_table))
  2419         dp = XCHAR_TABLE (Vstandard_display_table);
  2420     }
  2421 
  2422   return dp;
  2423 }
  2424 
  2425 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
  2426        doc: /* Set WINDOW's display-table to TABLE.
  2427 WINDOW must be a live window and defaults to the selected one.  */)
  2428   (register Lisp_Object window, Lisp_Object table)
  2429 {
  2430   wset_display_table (decode_live_window (window), table);
  2431   return table;
  2432 }
  2433 
  2434 /* Record info on buffer window W is displaying
  2435    when it is about to cease to display that buffer.  */
  2436 static void
  2437 unshow_buffer (register struct window *w)
  2438 {
  2439   Lisp_Object buf = w->contents;
  2440   struct buffer *b = XBUFFER (buf);
  2441 
  2442   eassert (b == XMARKER (w->pointm)->buffer);
  2443 
  2444 #if false
  2445   if (w == XWINDOW (selected_window)
  2446       || ! EQ (buf, XWINDOW (selected_window)->contents))
  2447     /* Do this except when the selected window's buffer
  2448        is being removed from some other window.  */
  2449 #endif
  2450     /* last_window_start records the start position that this buffer
  2451        had in the last window to be disconnected from it.
  2452        Now that this statement is unconditional,
  2453        it is possible for the buffer to be displayed in the
  2454        selected window, while last_window_start reflects another
  2455        window which was recently showing the same buffer.
  2456        Some people might say that might be a good thing.  Let's see.  */
  2457     b->last_window_start = marker_position (w->start);
  2458 
  2459   /* Point in the selected window's buffer
  2460      is actually stored in that buffer, and the window's pointm isn't used.
  2461      So don't clobber point in that buffer.  */
  2462   if (! EQ (buf, XWINDOW (selected_window)->contents)
  2463       /* Don't clobber point in current buffer either (this could be
  2464          useful in connection with bug#12208).
  2465       && XBUFFER (buf) != current_buffer  */
  2466       /* This line helps to fix Horsley's testbug.el bug.  */
  2467       && !(WINDOWP (BVAR (b, last_selected_window))
  2468            && w != XWINDOW (BVAR (b, last_selected_window))
  2469            && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->contents)))
  2470     temp_set_point_both (b,
  2471                          clip_to_bounds (BUF_BEGV (b),
  2472                                          marker_position (w->pointm),
  2473                                          BUF_ZV (b)),
  2474                          clip_to_bounds (BUF_BEGV_BYTE (b),
  2475                                          marker_byte_position (w->pointm),
  2476                                          BUF_ZV_BYTE (b)));
  2477 
  2478   if (WINDOWP (BVAR (b, last_selected_window))
  2479       && w == XWINDOW (BVAR (b, last_selected_window)))
  2480     bset_last_selected_window (b, Qnil);
  2481 }
  2482 
  2483 /* Put NEW into the window structure in place of OLD.  SETFLAG false
  2484    means change window structure only.  Otherwise store geometry and
  2485    other settings as well.  */
  2486 static void
  2487 replace_window (Lisp_Object old, Lisp_Object new, bool setflag)
  2488 {
  2489   Lisp_Object tem;
  2490   struct window *o = XWINDOW (old), *n = XWINDOW (new);
  2491 
  2492   /* If OLD is its frame's root window, then NEW is the new
  2493      root window for that frame.  */
  2494   if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
  2495     fset_root_window (XFRAME (o->frame), new);
  2496 
  2497   if (setflag)
  2498     {
  2499       n->pixel_left = o->pixel_left;
  2500       n->pixel_top = o->pixel_top;
  2501       n->pixel_width = o->pixel_width;
  2502       n->pixel_height = o->pixel_height;
  2503       n->left_col = o->left_col;
  2504       n->top_line = o->top_line;
  2505       n->total_cols = o->total_cols;
  2506       n->total_lines = o->total_lines;
  2507       wset_normal_cols (n, o->normal_cols);
  2508       wset_normal_cols (o, make_float (1.0));
  2509       wset_normal_lines (n, o->normal_lines);
  2510       wset_normal_lines (o, make_float (1.0));
  2511       n->desired_matrix = n->current_matrix = 0;
  2512       n->vscroll = 0;
  2513       memset (&n->cursor, 0, sizeof (n->cursor));
  2514       memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
  2515       n->last_cursor_vpos = 0;
  2516 #ifdef HAVE_WINDOW_SYSTEM
  2517       n->phys_cursor_type = NO_CURSOR;
  2518       n->phys_cursor_width = -1;
  2519 #endif
  2520       n->must_be_updated_p = false;
  2521       n->pseudo_window_p = false;
  2522       n->window_end_vpos = 0;
  2523       n->window_end_pos = 0;
  2524       n->window_end_valid = false;
  2525     }
  2526 
  2527   tem = o->next;
  2528   wset_next (n, tem);
  2529   if (!NILP (tem))
  2530     wset_prev (XWINDOW (tem), new);
  2531 
  2532   tem = o->prev;
  2533   wset_prev (n, tem);
  2534   if (!NILP (tem))
  2535     wset_next (XWINDOW (tem), new);
  2536 
  2537   tem = o->parent;
  2538   wset_parent (n, tem);
  2539   if (!NILP (tem) && EQ (XWINDOW (tem)->contents, old))
  2540     wset_combination (XWINDOW (tem), XWINDOW (tem)->horizontal, new);
  2541 }
  2542 
  2543 /* If window WINDOW and its parent window are iso-combined, merge
  2544    WINDOW's children into those of its parent window and mark WINDOW as
  2545    deleted.  */
  2546 
  2547 static void
  2548 recombine_windows (Lisp_Object window)
  2549 {
  2550   struct window *w, *p, *c;
  2551   Lisp_Object parent, child;
  2552   bool horflag;
  2553 
  2554   w = XWINDOW (window);
  2555   parent = w->parent;
  2556   if (!NILP (parent) && NILP (w->combination_limit))
  2557     {
  2558       p = XWINDOW (parent);
  2559       if (WINDOWP (p->contents) && WINDOWP (w->contents)
  2560           && p->horizontal == w->horizontal)
  2561         /* WINDOW and PARENT are both either a vertical or a horizontal
  2562            combination.  */
  2563         {
  2564           horflag = WINDOW_HORIZONTAL_COMBINATION_P (w);
  2565           child = w->contents;
  2566           c = XWINDOW (child);
  2567 
  2568           /* Splice WINDOW's children into its parent's children and
  2569              assign new normal sizes.  */
  2570           if (NILP (w->prev))
  2571             wset_combination (p, horflag, child);
  2572           else
  2573             {
  2574               wset_prev (c, w->prev);
  2575               wset_next (XWINDOW (w->prev), child);
  2576             }
  2577 
  2578           while (c)
  2579             {
  2580               wset_parent (c, parent);
  2581 
  2582               if (horflag)
  2583                 wset_normal_cols
  2584                   (c, make_float ((double) c->pixel_width
  2585                                   / (double) p->pixel_width));
  2586               else
  2587                 wset_normal_lines
  2588                   (c, make_float ((double) c->pixel_height
  2589                                   / (double) p->pixel_height));
  2590 
  2591               if (NILP (c->next))
  2592                 {
  2593                   if (!NILP (w->next))
  2594                     {
  2595                       wset_next (c, w->next);
  2596                       wset_prev (XWINDOW (c->next), child);
  2597                     }
  2598 
  2599                   c = 0;
  2600                 }
  2601               else
  2602                 {
  2603                   child = c->next;
  2604                   c = XWINDOW (child);
  2605                 }
  2606             }
  2607 
  2608           /* WINDOW can be deleted now.  */
  2609           wset_combination (w, false, Qnil);
  2610         }
  2611     }
  2612 }
  2613 
  2614 /* If WINDOW can be deleted, delete it.  */
  2615 static void
  2616 delete_deletable_window (Lisp_Object window)
  2617 {
  2618   if (!NILP (call1 (Qwindow_deletable_p, window)))
  2619     call1 (Qdelete_window, window);
  2620 }
  2621 
  2622 /***********************************************************************
  2623                              Window List
  2624  ***********************************************************************/
  2625 
  2626 /* Add window W to *USER_DATA.  USER_DATA is actually a Lisp_Object
  2627    pointer.  This is a callback function for foreach_window, used in
  2628    the window_list function.  */
  2629 
  2630 static bool
  2631 add_window_to_list (struct window *w, void *user_data)
  2632 {
  2633   Lisp_Object *list = user_data;
  2634   Lisp_Object window;
  2635   XSETWINDOW (window, w);
  2636   *list = Fcons (window, *list);
  2637   return true;
  2638 }
  2639 
  2640 
  2641 /* Return a list of all windows, for use by next_window.  If
  2642    Vwindow_list is a list, return that list.  Otherwise, build a new
  2643    list, cache it in Vwindow_list, and return that.  */
  2644 
  2645 Lisp_Object
  2646 window_list (void)
  2647 {
  2648   if (!CONSP (Vwindow_list))
  2649     {
  2650       Lisp_Object tail, frame;
  2651       specpdl_ref count = SPECPDL_INDEX ();
  2652 
  2653       Vwindow_list = Qnil;
  2654       /*  Don't allow quitting in Fnconc.  Otherwise we might end up
  2655           with a too short Vwindow_list and Fkill_buffer not being able
  2656           to replace a buffer in all windows showing it (Bug#47244).  */
  2657       specbind (Qinhibit_quit, Qt);
  2658       FOR_EACH_FRAME (tail, frame)
  2659         {
  2660           Lisp_Object arglist = Qnil;
  2661 
  2662           /* We are visiting windows in canonical order, and add
  2663              new windows at the front of arglist, which means we
  2664              have to reverse this list at the end.  */
  2665           foreach_window (XFRAME (frame), add_window_to_list, &arglist);
  2666           arglist = Fnreverse (arglist);
  2667           Vwindow_list = nconc2 (Vwindow_list, arglist);
  2668         }
  2669 
  2670       unbind_to (count, Qnil);
  2671     }
  2672 
  2673   return Vwindow_list;
  2674 }
  2675 
  2676 
  2677 /* Value is true if WINDOW satisfies the constraints given by
  2678    OWINDOW, MINIBUF and ALL_FRAMES.
  2679 
  2680    MINIBUF      t means WINDOW may be minibuffer windows.
  2681                 `lambda' means WINDOW may not be a minibuffer window.
  2682                 a window means a specific minibuffer window
  2683 
  2684    ALL_FRAMES   t means search all frames,
  2685                 nil means search just current frame,
  2686                 `visible' means search just visible frames on the
  2687                 current terminal,
  2688                 0 means search visible and iconified frames on the
  2689                 current terminal,
  2690                 a window means search the frame that window belongs to,
  2691                 a frame means consider windows on that frame, only.  */
  2692 
  2693 static bool
  2694 candidate_window_p (Lisp_Object window, Lisp_Object owindow,
  2695                     Lisp_Object minibuf, Lisp_Object all_frames)
  2696 {
  2697   struct window *w = XWINDOW (window);
  2698   struct frame *f = XFRAME (w->frame);
  2699   bool candidate_p = true;
  2700 
  2701   if (!BUFFERP (w->contents))
  2702     candidate_p = false;
  2703   else if (MINI_WINDOW_P (w)
  2704            && (EQ (minibuf, Qlambda)
  2705                || (WINDOW_LIVE_P (minibuf) && !EQ (minibuf, window))))
  2706     {
  2707       /* If MINIBUF is `lambda' don't consider any mini-windows.
  2708          If it is a window, consider only that one.  */
  2709       candidate_p = false;
  2710     }
  2711   else if (EQ (all_frames, Qt))
  2712     candidate_p = true;
  2713   else if (NILP (all_frames))
  2714     {
  2715       eassert (WINDOWP (owindow));
  2716       candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
  2717     }
  2718   else if (EQ (all_frames, Qvisible))
  2719     {
  2720       candidate_p = FRAME_VISIBLE_P (f)
  2721         && (FRAME_TERMINAL (XFRAME (w->frame))
  2722             == FRAME_TERMINAL (XFRAME (selected_frame)));
  2723 
  2724     }
  2725   else if (FIXNUMP (all_frames) && XFIXNUM (all_frames) == 0)
  2726     {
  2727       candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
  2728 #ifdef HAVE_X_WINDOWS
  2729                      /* Yuck!!  If we've just created the frame and the
  2730                         window-manager requested the user to place it
  2731                         manually, the window may still not be considered
  2732                         `visible'.  I'd argue it should be at least
  2733                         something like `iconified', but don't know how to do
  2734                         that yet.  --Stef  */
  2735                      || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
  2736                          && !f->output_data.x->has_been_visible)
  2737 #endif
  2738                      )
  2739         && (FRAME_TERMINAL (XFRAME (w->frame))
  2740             == FRAME_TERMINAL (XFRAME (selected_frame)));
  2741     }
  2742   else if (WINDOWP (all_frames))
  2743     /*  To qualify as candidate, it's not sufficient for WINDOW's frame
  2744         to just share the minibuffer window - it must be active as well
  2745         (see Bug#24500).  */
  2746     candidate_p = ((EQ (XWINDOW (all_frames)->frame, w->frame)
  2747                     || (EQ (f->minibuffer_window, all_frames)
  2748                         && EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f))))
  2749                    && (EQ (minibuf, Qt)
  2750                        || !is_minibuffer (0, XWINDOW (all_frames)->contents)));
  2751   else if (FRAMEP (all_frames))
  2752     candidate_p = EQ (all_frames, w->frame);
  2753 
  2754   return candidate_p;
  2755 }
  2756 
  2757 
  2758 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
  2759    Fwindow_list.  See candidate_window_p for the meaning of WINDOW,
  2760    MINIBUF, and ALL_FRAMES.  */
  2761 
  2762 static void
  2763 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
  2764 {
  2765   struct window *w = decode_live_window (*window);
  2766   Lisp_Object miniwin = XFRAME (w->frame)->minibuffer_window;
  2767 
  2768   XSETWINDOW (*window, w);
  2769   /* MINIBUF nil may or may not include minibuffer windows.  Decide if
  2770      it does.  But first make sure that this frame's minibuffer window
  2771      is live (Bug#47207).  */
  2772   if (WINDOW_LIVE_P (miniwin) && NILP (*minibuf))
  2773     *minibuf = (this_minibuffer_depth (XWINDOW (miniwin)->contents)
  2774                 ? miniwin : Qlambda);
  2775   else if (!EQ (*minibuf, Qt))
  2776     *minibuf = Qlambda;
  2777 
  2778   /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
  2779      => count none of them, or a specific minibuffer window (the
  2780      active one) to count.  */
  2781 
  2782   /* ALL_FRAMES nil doesn't specify which frames to include.  */
  2783   if (NILP (*all_frames))
  2784     *all_frames
  2785       /* Once more make sure that this frame's minibuffer window is live
  2786          before including it (Bug#47207).  */
  2787       = ((WINDOW_LIVE_P (miniwin) && !EQ (*minibuf, Qlambda))
  2788          ? miniwin : Qnil);
  2789   else if (EQ (*all_frames, Qvisible))
  2790     ;
  2791   else if (BASE_EQ (*all_frames, make_fixnum (0)))
  2792     ;
  2793   else if (FRAMEP (*all_frames))
  2794     ;
  2795   else if (!EQ (*all_frames, Qt))
  2796     *all_frames = Qnil;
  2797 }
  2798 
  2799 
  2800 /* Return the next or previous window of WINDOW in cyclic ordering
  2801    of windows.  NEXT_P means return the next window.  See the
  2802    documentation string of next-window for the meaning of MINIBUF and
  2803    ALL_FRAMES.  */
  2804 
  2805 static Lisp_Object
  2806 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
  2807              bool next_p)
  2808 {
  2809   specpdl_ref count = SPECPDL_INDEX ();
  2810 
  2811   decode_next_window_args (&window, &minibuf, &all_frames);
  2812 
  2813   /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
  2814      return the first window on the frame.  */
  2815   if (FRAMEP (all_frames)
  2816       && !EQ (all_frames, XWINDOW (window)->frame))
  2817     return Fframe_first_window (all_frames);
  2818 
  2819   /*  Don't allow quitting in Fmemq.  */
  2820   specbind (Qinhibit_quit, Qt);
  2821 
  2822   if (next_p)
  2823     {
  2824       Lisp_Object list;
  2825 
  2826       /* Find WINDOW in the list of all windows.  */
  2827       list = Fmemq (window, window_list ());
  2828 
  2829       /* Scan forward from WINDOW to the end of the window list.  */
  2830       if (CONSP (list))
  2831         for (list = XCDR (list); CONSP (list); list = XCDR (list))
  2832           if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
  2833             break;
  2834 
  2835       /* Scan from the start of the window list up to WINDOW.  */
  2836       if (!CONSP (list))
  2837         for (list = Vwindow_list;
  2838              CONSP (list) && !EQ (XCAR (list), window);
  2839              list = XCDR (list))
  2840           if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
  2841             break;
  2842 
  2843       if (CONSP (list))
  2844         window = XCAR (list);
  2845     }
  2846   else
  2847     {
  2848       Lisp_Object candidate, list;
  2849 
  2850       /* Scan through the list of windows for candidates.  If there are
  2851          candidate windows in front of WINDOW, the last one of these
  2852          is the one we want.  If there are candidates following WINDOW
  2853          in the list, again the last one of these is the one we want.  */
  2854       candidate = Qnil;
  2855       for (list = window_list (); CONSP (list); list = XCDR (list))
  2856         {
  2857           if (EQ (XCAR (list), window))
  2858             {
  2859               if (WINDOWP (candidate))
  2860                 break;
  2861             }
  2862           else if (candidate_window_p (XCAR (list), window, minibuf,
  2863                                        all_frames))
  2864             candidate = XCAR (list);
  2865         }
  2866 
  2867       if (WINDOWP (candidate))
  2868         window = candidate;
  2869     }
  2870 
  2871   unbind_to (count, Qnil);
  2872 
  2873   return window;
  2874 }
  2875 
  2876 
  2877 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
  2878        doc: /* Return live window after WINDOW in the cyclic ordering of windows.
  2879 WINDOW must be a live window and defaults to the selected one.  The
  2880 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
  2881 consider.
  2882 
  2883 MINIBUF nil or omitted means consider the minibuffer window only if the
  2884 minibuffer is active.  MINIBUF t means consider the minibuffer window
  2885 even if the minibuffer is not active.  Any other value means do not
  2886 consider the minibuffer window even if the minibuffer is active.
  2887 
  2888 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
  2889 plus the minibuffer window if specified by the MINIBUF argument.  If the
  2890 minibuffer counts, consider all windows on all frames that share that
  2891 minibuffer too.  The following non-nil values of ALL-FRAMES have special
  2892 meanings:
  2893 
  2894 - t means consider all windows on all existing frames.
  2895 
  2896 - `visible' means consider all windows on all visible frames.
  2897 
  2898 - 0 (the number zero) means consider all windows on all visible and
  2899   iconified frames.
  2900 
  2901 - A frame means consider all windows on that frame only.
  2902 
  2903 Anything else means consider all windows on WINDOW's frame and no
  2904 others.
  2905 
  2906 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
  2907 `next-window' to iterate through the entire cycle of acceptable
  2908 windows, eventually ending up back at the window you started with.
  2909 `previous-window' traverses the same cycle, in the reverse order.  */)
  2910   (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
  2911 {
  2912   return next_window (window, minibuf, all_frames, true);
  2913 }
  2914 
  2915 
  2916 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
  2917        doc: /* Return live window before WINDOW in the cyclic ordering of windows.
  2918 WINDOW must be a live window and defaults to the selected one.  The
  2919 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
  2920 consider.
  2921 
  2922 MINIBUF nil or omitted means consider the minibuffer window only if the
  2923 minibuffer is active.  MINIBUF t means consider the minibuffer window
  2924 even if the minibuffer is not active.  Any other value means do not
  2925 consider the minibuffer window even if the minibuffer is active.
  2926 
  2927 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
  2928 plus the minibuffer window if specified by the MINIBUF argument.  If the
  2929 minibuffer counts, consider all windows on all frames that share that
  2930 minibuffer too.  The following non-nil values of ALL-FRAMES have special
  2931 meanings:
  2932 
  2933 - t means consider all windows on all existing frames.
  2934 
  2935 - `visible' means consider all windows on all visible frames.
  2936 
  2937 - 0 (the number zero) means consider all windows on all visible and
  2938   iconified frames.
  2939 
  2940 - A frame means consider all windows on that frame only.
  2941 
  2942 Anything else means consider all windows on WINDOW's frame and no
  2943 others.
  2944 
  2945 If you use consistent values for MINIBUF and ALL-FRAMES, you can
  2946 use `previous-window' to iterate through the entire cycle of
  2947 acceptable windows, eventually ending up back at the window you
  2948 started with.  `next-window' traverses the same cycle, in the
  2949 reverse order.  */)
  2950   (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
  2951 {
  2952   return next_window (window, minibuf, all_frames, false);
  2953 }
  2954 
  2955 
  2956 /* Return a list of windows in cyclic ordering.  Arguments are like
  2957    for `next-window'.  */
  2958 
  2959 static Lisp_Object
  2960 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
  2961 {
  2962   Lisp_Object tail, list, rest;
  2963   specpdl_ref count = SPECPDL_INDEX ();
  2964 
  2965   decode_next_window_args (&window, &minibuf, &all_frames);
  2966   list = Qnil;
  2967 
  2968   /*  Don't allow quitting in Fmemq and Fnconc.  */
  2969   specbind (Qinhibit_quit, Qt);
  2970 
  2971   for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
  2972     if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
  2973       list = Fcons (XCAR (tail), list);
  2974 
  2975   /* Rotate the list to start with WINDOW.  */
  2976   list = Fnreverse (list);
  2977   rest = Fmemq (window, list);
  2978   if (!NILP (rest) && !EQ (rest, list))
  2979     {
  2980       for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
  2981         ;
  2982       XSETCDR (tail, Qnil);
  2983       list = nconc2 (rest, list);
  2984     }
  2985 
  2986   unbind_to (count, Qnil);
  2987 
  2988   return list;
  2989 }
  2990 
  2991 
  2992 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
  2993        doc: /* Return a list of windows on FRAME, starting with WINDOW.
  2994 FRAME nil or omitted means use the selected frame.
  2995 WINDOW nil or omitted means use the window selected within FRAME.
  2996 MINIBUF t means include the minibuffer window, even if it isn't active.
  2997 MINIBUF nil or omitted means include the minibuffer window only
  2998 if it's active.
  2999 MINIBUF neither nil nor t means never include the minibuffer window.  */)
  3000   (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
  3001 {
  3002   if (NILP (window))
  3003     window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
  3004   CHECK_WINDOW (window);
  3005   if (NILP (frame))
  3006     frame = selected_frame;
  3007 
  3008   if (!EQ (frame, XWINDOW (window)->frame))
  3009     error ("Window is on a different frame");
  3010 
  3011   return window_list_1 (window, minibuf, frame);
  3012 }
  3013 
  3014 
  3015 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
  3016        doc: /* Return a list of all live windows.
  3017 WINDOW specifies the first window to list and defaults to the selected
  3018 window.
  3019 
  3020 Optional argument MINIBUF nil or omitted means consider the minibuffer
  3021 window only if the minibuffer is active.  MINIBUF t means consider the
  3022 minibuffer window even if the minibuffer is not active.  Any other value
  3023 means do not consider the minibuffer window even if the minibuffer is
  3024 active.
  3025 
  3026 Optional argument ALL-FRAMES nil or omitted means consider all windows
  3027 on WINDOW's frame, plus the minibuffer window if specified by the
  3028 MINIBUF argument.  If the minibuffer counts, consider all windows on all
  3029 frames that share that minibuffer too.  The following non-nil values of
  3030 ALL-FRAMES have special meanings:
  3031 
  3032 - t means consider all windows on all existing frames.
  3033 
  3034 - `visible' means consider all windows on all visible frames.
  3035 
  3036 - 0 (the number zero) means consider all windows on all visible and
  3037   iconified frames.
  3038 
  3039 - A frame means consider all windows on that frame only.
  3040 
  3041 Anything else means consider all windows on WINDOW's frame and no
  3042 others.
  3043 
  3044 If WINDOW is not on the list of windows returned, some other window will
  3045 be listed first but no error is signaled.  */)
  3046   (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
  3047 {
  3048   return window_list_1 (window, minibuf, all_frames);
  3049 }
  3050 
  3051 /* Look at all windows, performing an operation specified by TYPE
  3052    with argument OBJ.
  3053    If FRAMES is Qt, look at all frames;
  3054                 Qnil, look at just the selected frame;
  3055                 Qvisible, look at visible frames;
  3056                 a frame, just look at windows on that frame.
  3057    If MINI, perform the operation on minibuffer windows too.  */
  3058 
  3059 enum window_loop
  3060 {
  3061   WINDOW_LOOP_UNUSED,
  3062   GET_BUFFER_WINDOW,                /* Arg is buffer */
  3063   REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
  3064   REDISPLAY_BUFFER_WINDOWS,         /* Arg is buffer */
  3065   CHECK_ALL_WINDOWS                 /* Arg is ignored */
  3066 };
  3067 
  3068 static Lisp_Object
  3069 window_loop (enum window_loop type, Lisp_Object obj, bool mini,
  3070              Lisp_Object frames)
  3071 {
  3072   Lisp_Object window, windows, best_window, frame_arg;
  3073   bool frame_best_window_flag = false;
  3074   struct frame *f;
  3075 
  3076   /* If we're only looping through windows on a particular frame,
  3077      frame points to that frame.  If we're looping through windows
  3078      on all frames, frame is 0.  */
  3079   if (FRAMEP (frames))
  3080     f = XFRAME (frames);
  3081   else if (NILP (frames))
  3082     f = SELECTED_FRAME ();
  3083   else
  3084     f = NULL;
  3085 
  3086   if (f)
  3087     frame_arg = Qlambda;
  3088   else if (BASE_EQ (frames, make_fixnum (0)))
  3089     frame_arg = frames;
  3090   else if (EQ (frames, Qvisible))
  3091     frame_arg = frames;
  3092   else
  3093     frame_arg = Qt;
  3094 
  3095   /* frame_arg is Qlambda to stick to one frame,
  3096      Qvisible to consider all visible frames,
  3097      or Qt otherwise.  */
  3098 
  3099   /* Pick a window to start with.  */
  3100   if (WINDOWP (obj))
  3101     window = obj;
  3102   else if (f)
  3103     window = FRAME_SELECTED_WINDOW (f);
  3104   else
  3105     window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
  3106 
  3107   windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
  3108   best_window = Qnil;
  3109 
  3110   for (; CONSP (windows); windows = XCDR (windows))
  3111     {
  3112       struct window *w;
  3113 
  3114       window = XCAR (windows);
  3115       w = XWINDOW (window);
  3116 
  3117       /* Note that we do not pay attention here to whether the frame
  3118          is visible, since Fwindow_list skips non-visible frames if
  3119          that is desired, under the control of frame_arg.  */
  3120       if (!MINI_WINDOW_P (w)
  3121           /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
  3122              consider all windows.  */
  3123           || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
  3124           || (mini && minibuf_level > 0))
  3125         switch (type)
  3126           {
  3127           case GET_BUFFER_WINDOW:
  3128             if (EQ (w->contents, obj)
  3129                 /* Don't find any minibuffer window except the one that
  3130                    is currently in use.  */
  3131                 && (!MINI_WINDOW_P (w) || EQ (window, minibuf_window)))
  3132               {
  3133                 if (EQ (window, selected_window))
  3134                   /* Preferably return the selected window.  */
  3135                   return window;
  3136                 else if (EQ (XWINDOW (window)->frame, selected_frame)
  3137                          && !frame_best_window_flag)
  3138                   /* Prefer windows on the current frame (but don't
  3139                      choose another one if we have one already).  */
  3140                   {
  3141                     best_window = window;
  3142                     frame_best_window_flag = true;
  3143                   }
  3144                 else if (NILP (best_window))
  3145                   best_window = window;
  3146               }
  3147             break;
  3148 
  3149           case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
  3150             /* We could simply check whether the buffer shown by window
  3151                is live, and show another buffer in case it isn't.  */
  3152             if (EQ (w->contents, obj))
  3153               {
  3154                 /* Undedicate WINDOW.  */
  3155                 wset_dedicated (w, Qnil);
  3156                 /* Make WINDOW show the buffer returned by
  3157                    other_buffer_safely, don't run any hooks.  */
  3158                 set_window_buffer
  3159                   (window, other_buffer_safely (w->contents), false, false);
  3160                 /* If WINDOW is the selected window, make its buffer
  3161                    current.  But do so only if the window shows the
  3162                    current buffer (Bug#6454).  */
  3163                 if (EQ (window, selected_window)
  3164                     && XBUFFER (w->contents) == current_buffer)
  3165                   Fset_buffer (w->contents);
  3166               }
  3167             break;
  3168 
  3169           case REDISPLAY_BUFFER_WINDOWS:
  3170             if (EQ (w->contents, obj))
  3171               {
  3172                 mark_window_display_accurate (window, false);
  3173                 w->update_mode_line = true;
  3174                 XBUFFER (obj)->prevent_redisplay_optimizations_p = true;
  3175                 update_mode_lines = 27;
  3176                 best_window = window;
  3177               }
  3178             break;
  3179 
  3180             /* Check for a leaf window that has a killed buffer
  3181                or broken markers.  */
  3182           case CHECK_ALL_WINDOWS:
  3183             if (BUFFERP (w->contents))
  3184               {
  3185                 struct buffer *b = XBUFFER (w->contents);
  3186 
  3187                 if (!BUFFER_LIVE_P (b))
  3188                   emacs_abort ();
  3189                 if (!MARKERP (w->start) || XMARKER (w->start)->buffer != b)
  3190                   emacs_abort ();
  3191                 if (!MARKERP (w->pointm) || XMARKER (w->pointm)->buffer != b)
  3192                   emacs_abort ();
  3193               }
  3194             break;
  3195 
  3196           case WINDOW_LOOP_UNUSED:
  3197             break;
  3198           }
  3199     }
  3200 
  3201   return best_window;
  3202 }
  3203 
  3204 /* Used for debugging.  Abort if any window has a dead buffer.  */
  3205 
  3206 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
  3207 void
  3208 check_all_windows (void)
  3209 {
  3210   window_loop (CHECK_ALL_WINDOWS, Qnil, true, Qt);
  3211 }
  3212 
  3213 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
  3214        doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
  3215 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
  3216 the current buffer.
  3217 
  3218 The optional argument ALL-FRAMES specifies the frames to consider:
  3219 
  3220 - t means consider all windows on all existing frames.
  3221 
  3222 - `visible' means consider all windows on all visible frames.
  3223 
  3224 - 0 (the number zero) means consider all windows on all visible
  3225     and iconified frames.
  3226 
  3227 - A frame means consider all windows on that frame only.
  3228 
  3229 Any other value of ALL-FRAMES means consider all windows on the
  3230 selected frame and no others.  */)
  3231      (Lisp_Object buffer_or_name, Lisp_Object all_frames)
  3232 {
  3233   Lisp_Object buffer;
  3234 
  3235   if (NILP (buffer_or_name))
  3236     buffer = Fcurrent_buffer ();
  3237   else
  3238     buffer = Fget_buffer (buffer_or_name);
  3239 
  3240   if (BUFFERP (buffer))
  3241     return window_loop (GET_BUFFER_WINDOW, buffer, true, all_frames);
  3242   else
  3243     return Qnil;
  3244 }
  3245 
  3246 
  3247 static Lisp_Object
  3248 resize_root_window (Lisp_Object window, Lisp_Object delta,
  3249                     Lisp_Object horizontal, Lisp_Object ignore,
  3250                     Lisp_Object pixelwise)
  3251 {
  3252   return call5 (Qwindow__resize_root_window, window, delta,
  3253                 horizontal, ignore, pixelwise);
  3254 }
  3255 
  3256 
  3257 static Lisp_Object
  3258 window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
  3259 {
  3260   return call2 (Qwindow__pixel_to_total, frame, horizontal);
  3261 }
  3262 
  3263 
  3264 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
  3265        Sdelete_other_windows_internal, 0, 2, "",
  3266        doc: /* Make WINDOW fill its frame.
  3267 Only the frame WINDOW is on is affected.  WINDOW must be a valid window
  3268 and defaults to the selected one.
  3269 
  3270 Optional argument ROOT, if non-nil, must specify an internal window such
  3271 that WINDOW is in its window subtree.  If this is the case, replace ROOT
  3272 by WINDOW and leave alone any windows not part of ROOT's subtree.
  3273 
  3274 When WINDOW is live try to reduce display jumps by keeping the text
  3275 previously visible in WINDOW in the same place on the frame.  Doing this
  3276 depends on the value of (window-start WINDOW), so if calling this
  3277 function in a program gives strange scrolling, make sure the
  3278 window-start value is reasonable when this function is called.  */)
  3279      (Lisp_Object window, Lisp_Object root)
  3280 {
  3281   struct window *w = decode_valid_window (window);
  3282   struct window *r, *s;
  3283   Lisp_Object frame = w->frame;
  3284   struct frame *f = XFRAME (frame);
  3285   Lisp_Object sibling, pwindow, delta;
  3286   Lisp_Object swindow UNINIT;
  3287   ptrdiff_t startpos UNINIT, startbyte UNINIT;
  3288   int top UNINIT;
  3289   int new_top;
  3290   bool resize_failed = false;
  3291 
  3292   XSETWINDOW (window, w);
  3293 
  3294   if (NILP (root))
  3295     /* ROOT is the frame's root window.  */
  3296     {
  3297       root = FRAME_ROOT_WINDOW (f);
  3298       r = XWINDOW (root);
  3299     }
  3300   else
  3301     /* ROOT must be an ancestor of WINDOW.  */
  3302     {
  3303       r = decode_valid_window (root);
  3304       pwindow = XWINDOW (window)->parent;
  3305       while (!NILP (pwindow))
  3306         if (EQ (pwindow, root))
  3307           break;
  3308         else
  3309           pwindow = XWINDOW (pwindow)->parent;
  3310       if (!EQ (pwindow, root))
  3311         error ("Specified root is not an ancestor of specified window");
  3312     }
  3313 
  3314   if (EQ (window, root))
  3315     /* A noop.  */
  3316     return Qnil;
  3317   /* I don't understand the "top > 0" part below.  If we deal with a
  3318      standalone minibuffer it would have been caught by the preceding
  3319      test.  */
  3320   else if (MINI_WINDOW_P (w)) /* && top > 0) */
  3321     error ("Can't expand minibuffer to full frame");
  3322 
  3323   if (BUFFERP (w->contents))
  3324     {
  3325       startpos = marker_position (w->start);
  3326       startbyte = marker_byte_position (w->start);
  3327       top = (WINDOW_TOP_EDGE_LINE (w)
  3328              - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))));
  3329       /* Make sure WINDOW is the frame's selected window.  */
  3330       if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
  3331         {
  3332           if (EQ (selected_frame, frame))
  3333             Fselect_window (window, Qnil);
  3334           else
  3335             /* Do not clear f->select_mini_window_flag here.  If the
  3336                last selected window on F was an active minibuffer, we
  3337                want to return to it on a later Fselect_frame.  */
  3338             fset_selected_window (f, window);
  3339         }
  3340     }
  3341   else
  3342     {
  3343       /* See if the frame's selected window is a part of the window
  3344          subtree rooted at WINDOW, by finding all the selected window's
  3345          parents and comparing each one with WINDOW.  If it isn't we
  3346          need a new selected window for this frame.  */
  3347       swindow = FRAME_SELECTED_WINDOW (f);
  3348       while (true)
  3349         {
  3350           pwindow = swindow;
  3351           while (!NILP (pwindow) && !EQ (window, pwindow))
  3352             pwindow = XWINDOW (pwindow)->parent;
  3353 
  3354           if (EQ (window, pwindow))
  3355             /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
  3356                as the new selected window.  */
  3357             break;
  3358           else
  3359             /* Else try the previous window of SWINDOW.  */
  3360             swindow = Fprevious_window (swindow, Qlambda, Qnil);
  3361         }
  3362 
  3363       if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
  3364         {
  3365           if (EQ (selected_frame, frame))
  3366             Fselect_window (swindow, Qnil);
  3367           else
  3368             fset_selected_window (f, swindow);
  3369         }
  3370     }
  3371 
  3372   block_input ();
  3373   if (!FRAME_INITIAL_P (f))
  3374     {
  3375       Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
  3376 
  3377       /* We are going to free the glyph matrices of WINDOW, and with
  3378          that we might lose any information about glyph rows that have
  3379          some of their glyphs highlighted in mouse face.  (These rows
  3380          are marked with a mouse_face_p flag.)  If WINDOW
  3381          indeed has some glyphs highlighted in mouse face, signal to
  3382          frame's up-to-date hook that mouse highlight was overwritten,
  3383          so that it will arrange for redisplaying the highlight.  */
  3384       if (EQ (hlinfo->mouse_face_window, window))
  3385         reset_mouse_highlight (hlinfo);
  3386     }
  3387   free_window_matrices (r);
  3388 
  3389   fset_redisplay (f);
  3390   Vwindow_list = Qnil;
  3391 
  3392   if (!WINDOW_LEAF_P (w))
  3393     {
  3394       /* Resize child windows vertically.  */
  3395       XSETINT (delta, r->pixel_height - w->pixel_height);
  3396       w->pixel_top = r->pixel_top;
  3397       w->top_line = r->top_line;
  3398       resize_root_window (window, delta, Qnil, Qnil, Qt);
  3399       if (window_resize_check (w, false))
  3400         window_resize_apply (w, false);
  3401       else
  3402         {
  3403           resize_root_window (window, delta, Qnil, Qt, Qt);
  3404           if (window_resize_check (w, false))
  3405             window_resize_apply (w, false);
  3406           else
  3407             resize_failed = true;
  3408         }
  3409 
  3410       /* Resize child windows horizontally.  */
  3411       if (!resize_failed)
  3412         {
  3413           w->left_col = r->left_col;
  3414           w->pixel_left = r->pixel_left;
  3415           XSETINT (delta, r->pixel_width - w->pixel_width);
  3416           resize_root_window (window, delta, Qt, Qnil, Qt);
  3417           if (window_resize_check (w, true))
  3418             window_resize_apply (w, true);
  3419           else
  3420             {
  3421               resize_root_window (window, delta, Qt, Qt, Qt);
  3422               if (window_resize_check (w, true))
  3423                 window_resize_apply (w, true);
  3424               else
  3425                 resize_failed = true;
  3426             }
  3427         }
  3428 
  3429       if (resize_failed)
  3430         /* Play safe, if we still can ...  */
  3431         {
  3432           window = swindow;
  3433           w = XWINDOW (window);
  3434         }
  3435     }
  3436 
  3437   /* Cleanly unlink WINDOW from window-tree.  */
  3438   if (!NILP (w->prev))
  3439     /* Get SIBLING above (on the left of) WINDOW.  */
  3440     {
  3441       sibling = w->prev;
  3442       s = XWINDOW (sibling);
  3443       wset_next (s, w->next);
  3444       if (!NILP (s->next))
  3445         wset_prev (XWINDOW (s->next), sibling);
  3446     }
  3447   else
  3448     /* Get SIBLING below (on the right of) WINDOW.  */
  3449     {
  3450       sibling = w->next;
  3451       s = XWINDOW (sibling);
  3452       wset_prev (s, Qnil);
  3453       wset_combination (XWINDOW (w->parent),
  3454                         XWINDOW (w->parent)->horizontal, sibling);
  3455     }
  3456 
  3457   /* Delete ROOT and all child windows of ROOT.  */
  3458   if (WINDOWP (r->contents))
  3459     {
  3460       delete_all_child_windows (r->contents);
  3461       wset_combination (r, false, Qnil);
  3462     }
  3463 
  3464   replace_window (root, window, true);
  3465   /* Assign new total sizes to all windows on FRAME.  We can't do that
  3466      _before_ WINDOW replaces ROOT since 'window--pixel-to-total' works
  3467      on the whole frame and thus would work on the frame's old window
  3468      configuration (Bug#51007).  */
  3469   window_pixel_to_total (frame, Qnil);
  3470   window_pixel_to_total (frame, Qt);
  3471 
  3472   /* This must become SWINDOW anyway .......  */
  3473   if (BUFFERP (w->contents) && !resize_failed)
  3474     {
  3475       /* Try to minimize scrolling, by setting the window start to the
  3476          point will cause the text at the old window start to be at the
  3477          same place on the frame.  But don't try to do this if the
  3478          window start is outside the visible portion (as might happen
  3479          when the display is not current, due to typeahead).  */
  3480       new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
  3481       if (new_top != top
  3482           && startpos >= BUF_BEGV (XBUFFER (w->contents))
  3483           && startpos <= BUF_ZV (XBUFFER (w->contents)))
  3484         {
  3485           struct position pos;
  3486           struct buffer *obuf = current_buffer;
  3487 
  3488           Fset_buffer (w->contents);
  3489           /* This computation used to temporarily move point, but that
  3490              can have unwanted side effects due to text properties.  */
  3491           pos = *vmotion (startpos, startbyte, -top, w);
  3492 
  3493           set_marker_both (w->start, w->contents, pos.bufpos, pos.bytepos);
  3494           w->window_end_valid = false;
  3495           w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
  3496                                     || FETCH_BYTE (pos.bytepos - 1) == '\n');
  3497           /* We need to do this, so that the window-scroll-functions
  3498              get called.  */
  3499           w->optional_new_start = true;
  3500 
  3501           set_buffer_internal (obuf);
  3502         }
  3503     }
  3504 
  3505   adjust_frame_glyphs (f);
  3506   unblock_input ();
  3507 
  3508   FRAME_WINDOW_CHANGE (f) = true;
  3509 
  3510   return Qnil;
  3511 }
  3512 
  3513 
  3514 void
  3515 replace_buffer_in_windows (Lisp_Object buffer)
  3516 {
  3517   /* When kill-buffer is called early during loadup, this function is
  3518      undefined.  */
  3519   if (!NILP (Ffboundp (Qreplace_buffer_in_windows)))
  3520     call1 (Qreplace_buffer_in_windows, buffer);
  3521 }
  3522 
  3523 /* If BUFFER is shown in a window, safely replace it with some other
  3524    buffer in all windows of all frames, even those on other keyboards.  */
  3525 
  3526 void
  3527 replace_buffer_in_windows_safely (Lisp_Object buffer)
  3528 {
  3529   if (buffer_window_count (XBUFFER (buffer)))
  3530     {
  3531       Lisp_Object tail, frame;
  3532 
  3533       /* A single call to window_loop won't do the job because it only
  3534          considers frames on the current keyboard.  So loop manually over
  3535          frames, and handle each one.  */
  3536       FOR_EACH_FRAME (tail, frame)
  3537         window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, true, frame);
  3538     }
  3539 }
  3540 
  3541 /* The following three routines are needed for running a window's
  3542    configuration change hook.  */
  3543 static void
  3544 run_funs (Lisp_Object funs)
  3545 {
  3546   for (; CONSP (funs); funs = XCDR (funs))
  3547     if (!EQ (XCAR (funs), Qt))
  3548       call0 (XCAR (funs));
  3549 }
  3550 
  3551 static void
  3552 select_window_norecord (Lisp_Object window)
  3553 {
  3554   if (WINDOW_LIVE_P (window))
  3555     Fselect_window (window, Qt);
  3556 }
  3557 
  3558 static void
  3559 select_frame_norecord (Lisp_Object frame)
  3560 {
  3561   if (FRAME_LIVE_P (XFRAME (frame)))
  3562     Fselect_frame (frame, Qt);
  3563 }
  3564 
  3565 /**
  3566  * run_window_configuration_change_hook:
  3567  *
  3568  * Run any functions on 'window-configuration-change-hook' for the
  3569  * frame specified by F.  The buffer-local values are run with the
  3570  * window showing the buffer selected.  The default value is run with
  3571  * the frame specified by F selected.  All functions are called with
  3572  * the selected window's buffer current.
  3573  */
  3574 static void
  3575 run_window_configuration_change_hook (struct frame *f)
  3576 {
  3577   specpdl_ref count = SPECPDL_INDEX ();
  3578   Lisp_Object frame, global_wcch
  3579     = Fdefault_value (Qwindow_configuration_change_hook);
  3580   XSETFRAME (frame, f);
  3581 
  3582   if (NILP (Vrun_hooks)
  3583       || !f->can_set_window_size
  3584       || !f->after_make_frame)
  3585     return;
  3586 
  3587   /* Use the right buffer.  Matters when running the local hooks.  */
  3588   if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
  3589     {
  3590       record_unwind_current_buffer ();
  3591       Fset_buffer (Fwindow_buffer (Qnil));
  3592     }
  3593 
  3594   if (SELECTED_FRAME () != f)
  3595     {
  3596       record_unwind_protect (select_frame_norecord, selected_frame);
  3597       select_frame_norecord (frame);
  3598     }
  3599 
  3600   /* Look for buffer-local values.  */
  3601   {
  3602     Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
  3603     for (; CONSP (windows); windows = XCDR (windows))
  3604       {
  3605         Lisp_Object window = XCAR (windows);
  3606         Lisp_Object buffer = Fwindow_buffer (window);
  3607         if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
  3608                                       buffer)))
  3609           {
  3610             specpdl_ref inner_count = SPECPDL_INDEX ();
  3611             record_unwind_protect (select_window_norecord, selected_window);
  3612             select_window_norecord (window);
  3613             run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
  3614                                            buffer));
  3615             unbind_to (inner_count, Qnil);
  3616           }
  3617       }
  3618   }
  3619 
  3620   run_funs (global_wcch);
  3621   unbind_to (count, Qnil);
  3622 }
  3623 
  3624 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
  3625        Srun_window_configuration_change_hook, 0, 1, 0,
  3626        doc: /* Run `window-configuration-change-hook' for FRAME.
  3627 If FRAME is omitted or nil, it defaults to the selected frame.
  3628 
  3629 This function should not be needed any more and will be therefore
  3630 considered obsolete.  */)
  3631   (Lisp_Object frame)
  3632 {
  3633   run_window_configuration_change_hook (decode_live_frame (frame));
  3634   return Qnil;
  3635 }
  3636 
  3637 DEFUN ("run-window-scroll-functions", Frun_window_scroll_functions,
  3638        Srun_window_scroll_functions, 0, 1, 0,
  3639        doc: /* Run `window-scroll-functions' for WINDOW.
  3640 If WINDOW is omitted or nil, it defaults to the selected window.
  3641 
  3642 This function is called by `split-window' for the new window, after it
  3643 has established the size of the new window.  */)
  3644   (Lisp_Object window)
  3645 {
  3646   struct window *w = decode_live_window (window);
  3647   specpdl_ref count = SPECPDL_INDEX ();
  3648 
  3649   record_unwind_current_buffer ();
  3650   Fset_buffer (w->contents);
  3651   if (!NILP (Vwindow_scroll_functions))
  3652     run_hook_with_args_2 (Qwindow_scroll_functions, window,
  3653                           Fmarker_position (w->start));
  3654   unbind_to (count, Qnil);
  3655 
  3656   return Qnil;
  3657 }
  3658 
  3659 
  3660 /**
  3661  * window_sub_list:
  3662  *
  3663  * Return list of live windows constructed by traversing any window
  3664  * sub-tree rooted at WINDOW in preorder followed by right siblings of
  3665  * WINDOW.  Called from outside with second argument WINDOWS nil.  The
  3666  * returned list is in reverse order.
  3667  */
  3668 static Lisp_Object
  3669 window_sub_list (Lisp_Object window, Lisp_Object windows)
  3670 {
  3671 
  3672   struct window *w = XWINDOW (window);
  3673 
  3674   while (w)
  3675     {
  3676       if (WINDOW_INTERNAL_P (w))
  3677         windows = window_sub_list (w->contents, windows);
  3678       else
  3679         windows = Fcons (window, windows);
  3680 
  3681       window = w->next;
  3682       w = NILP (window) ? 0 : XWINDOW (window);
  3683     }
  3684 
  3685   return windows;
  3686 }
  3687 
  3688 
  3689 /**
  3690  * window_change_record_windows:
  3691  *
  3692  * Record changes for all live windows found by traversing any window
  3693  * sub-tree rooted at WINDOW in preorder followed by any right
  3694  * siblings of WINDOW.  This sets the old buffer, old pixel and old
  3695  * body pixel sizes of each live window found to the respective
  3696  * current values.  It also sets the change stamp of each window found
  3697  * to STAMP.  Return the number of live windows found.
  3698  *
  3699  * When not called by itself recursively, WINDOW is its frame's root
  3700  * window, STAMP is the current change stamp of WINDOW's frame and
  3701  * NUMBER is 0.
  3702  */
  3703 static ptrdiff_t
  3704 window_change_record_windows (Lisp_Object window, int stamp, ptrdiff_t number)
  3705 {
  3706   struct window *w = XWINDOW (window);
  3707 
  3708   while (w)
  3709     {
  3710       if (WINDOW_INTERNAL_P (w))
  3711         number = window_change_record_windows (w->contents, stamp, number);
  3712       else
  3713         {
  3714           number += 1;
  3715           w->change_stamp = stamp;
  3716           wset_old_buffer (w, w->contents);
  3717           w->old_pixel_width = w->pixel_width;
  3718           w->old_pixel_height = w->pixel_height;
  3719           w->old_body_pixel_width
  3720             = window_body_width (w, WINDOW_BODY_IN_PIXELS);
  3721           w->old_body_pixel_height
  3722             = window_body_height (w, WINDOW_BODY_IN_PIXELS);
  3723         }
  3724 
  3725       w = NILP (w->next) ? 0 : XWINDOW (w->next);
  3726     }
  3727 
  3728   return number;
  3729 }
  3730 
  3731 
  3732 /**
  3733  * window_change_record:
  3734  *
  3735  * For each frame that has recorded changes, record its selected
  3736  * window, update Fchange stamp, record the states of all its live
  3737  * windows via window_change_record_windows and reset its
  3738  * window_change and window_state_change flags.
  3739  *
  3740  * Record selected window in old_selected_window and selected frame in
  3741  * old_selected_frame.
  3742  */
  3743 static void
  3744 window_change_record (void)
  3745 {
  3746   if (window_change_record_frames)
  3747     {
  3748       Lisp_Object tail, frame;
  3749 
  3750       FOR_EACH_FRAME (tail, frame)
  3751         {
  3752           struct frame *f = XFRAME (frame);
  3753 
  3754           /* Record FRAME's selected window.  */
  3755           fset_old_selected_window (f, FRAME_SELECTED_WINDOW (f));
  3756 
  3757           /* Bump up FRAME's change stamp.  If this wraps, make it 1 to avoid
  3758              that a new window (whose change stamp is always set to 0) gets
  3759              reported as "existing before".  */
  3760           f->change_stamp += 1;
  3761           if (f->change_stamp == 0)
  3762             f->change_stamp = 1;
  3763 
  3764           /* Bump up the change stamps of all live windows on this frame so
  3765              the next call of this function can tell whether any of them
  3766              "existed before" and record state for each of these windows.  */
  3767           f->number_of_windows
  3768             = window_change_record_windows (f->root_window, f->change_stamp, 0);
  3769 
  3770           /* Reset our flags.  */
  3771           FRAME_WINDOW_CHANGE (f) = false;
  3772           FRAME_WINDOW_STATE_CHANGE (f) = false;
  3773         }
  3774     }
  3775 
  3776   /* Strictly spoken we don't need old_selected_window at all - its
  3777      value is the old selected window of old_selected_frame.  */
  3778   old_selected_window = selected_window;
  3779   old_selected_frame = selected_frame;
  3780 }
  3781 
  3782 
  3783 /**
  3784  * run_window_change_functions_1:
  3785  *
  3786  * Run window change functions specified by SYMBOL with argument
  3787  * WINDOW_OR_FRAME.  If BUFFER is nil, WINDOW_OR_FRAME specifies a
  3788  * frame.  In this case, run the default value of SYMBOL.  Otherwise,
  3789  * WINDOW_OR_FRAME denotes a window showing BUFFER.  In this case, run
  3790  * the buffer local value of SYMBOL in BUFFER, if any.
  3791  */
  3792 static void
  3793 run_window_change_functions_1 (Lisp_Object symbol, Lisp_Object buffer,
  3794                                Lisp_Object window_or_frame)
  3795 {
  3796   Lisp_Object funs = Qnil;
  3797 
  3798   if (NILP (buffer))
  3799     funs = Fdefault_value (symbol);
  3800   else if (!NILP (Fassoc (symbol, BVAR (XBUFFER (buffer), local_var_alist),
  3801                           Qnil)))
  3802     /* Don't run global value buffer-locally.  */
  3803     funs = buffer_local_value (symbol, buffer);
  3804 
  3805   while (CONSP (funs))
  3806     {
  3807       if (!EQ (XCAR (funs), Qt)
  3808           && (NILP (buffer)
  3809               ? FRAME_LIVE_P (XFRAME (window_or_frame))
  3810               : WINDOW_LIVE_P (window_or_frame)))
  3811         {
  3812           /* Any function called here may change the state of any
  3813              frame.  Make sure to record changes for each live frame
  3814              in window_change_record later.  */
  3815           window_change_record_frames = true;
  3816           safe_call1 (XCAR (funs), window_or_frame);
  3817         }
  3818 
  3819       funs = XCDR (funs);
  3820     }
  3821 }
  3822 
  3823 
  3824 /**
  3825  * run_window_change_functions:
  3826  *
  3827  * Run window change functions for each live frame.  This function
  3828  * must be called from a "safe" position in redisplay_internal.
  3829  *
  3830  * Do not run any functions for a frame whose window_change flag is
  3831  * nil, where no window selection happened and whose window state
  3832  * change flag was not set since the last time this function was
  3833  * called.  Never run any functions for tooltip frames.
  3834  *
  3835  * The change functions run are, in this order:
  3836  *
  3837  * 'window-buffer-change-functions' which are run for a window that
  3838  * changed its buffer or that was not shown the last time window
  3839  * change functions were run.  The default value is also run when a
  3840  * window was deleted since the last time window change functions were
  3841  * run.
  3842  *
  3843  * `window-size-change-functions' run for a window that changed its
  3844  * body or total size, a window that changed its buffer or a window
  3845  * that was not shown the last time window change functions were run.
  3846  *
  3847  * `window-selected-change-functions' run for a window that was
  3848  * (de-)selected since the last time window change functions were run.
  3849  *
  3850  * `window-state-change-functions' run for a window for which any of
  3851  * the above three changes occurred.
  3852  *
  3853  * A buffer-local value of these functions is run if and only if the
  3854  * window for which the functions are run currently shows the buffer.
  3855  * Each call gets one argument - the window showing the buffer.  This
  3856  * means that the buffer-local value of these functions may be called
  3857  * as many times as the buffer is shown on the frame.
  3858  *
  3859  * The default values of these functions are called only after all
  3860  * buffer-local values for all of these functions have been run.  Each
  3861  * such call receives one argument - the frame for which a change
  3862  * occurred.  Functions on `window-state-change-functions' are run
  3863  * also if the corresponding frame's window state change flag has been
  3864  * set.
  3865  *
  3866  * After the four change functions cited above have been run in the
  3867  * indicated way, functions on 'window-configuration-change-hook' are
  3868  * run.  A buffer-local value is run if a window shows that buffer and
  3869  * has either changed its buffer or its body or total size or did not
  3870  * appear on this frame since the last time window change functions
  3871  * were run.  The functions are called without argument and with the
  3872  * buffer's window selected.  The default value is run without
  3873  * argument and with the frame for which the function is run selected.
  3874  *
  3875  * In a final step, functions on `window-state-change-hook' are run
  3876  * provided a window state change has occurred or the window state
  3877  * change flag has been set on at least one frame.  Each of these
  3878  * functions is called without argument.
  3879  *
  3880  * This function does not save and restore match data.  Any functions
  3881  * it calls are responsible for doing that themselves.
  3882  *
  3883  * Additionally, report changes to each frame's selected window to the
  3884  * input method in textconv.c.
  3885  */
  3886 void
  3887 run_window_change_functions (void)
  3888 {
  3889   Lisp_Object tail, frame;
  3890   bool selected_frame_change = !EQ (selected_frame, old_selected_frame);
  3891   bool run_window_state_change_hook = false;
  3892   specpdl_ref count = SPECPDL_INDEX ();
  3893 
  3894   window_change_record_frames = false;
  3895   record_unwind_protect_void (window_change_record);
  3896   specbind (Qinhibit_redisplay, Qt);
  3897 
  3898   FOR_EACH_FRAME (tail, frame)
  3899     {
  3900       struct frame *f = XFRAME (frame);
  3901       Lisp_Object root = FRAME_ROOT_WINDOW (f);
  3902       bool frame_window_change = FRAME_WINDOW_CHANGE (f);
  3903       bool window_buffer_change, window_size_change;
  3904       bool frame_buffer_change = false, frame_size_change = false;
  3905       bool frame_selected_change
  3906         = (selected_frame_change
  3907            && (EQ (frame, old_selected_frame)
  3908                || EQ (frame, selected_frame)));
  3909       bool frame_selected_window_change
  3910         = !EQ (FRAME_OLD_SELECTED_WINDOW (f), FRAME_SELECTED_WINDOW (f));
  3911       bool frame_window_state_change = FRAME_WINDOW_STATE_CHANGE (f);
  3912       bool window_deleted = false;
  3913       Lisp_Object windows;
  3914       ptrdiff_t number_of_windows;
  3915 
  3916       if (!FRAME_LIVE_P (f)
  3917           || !f->can_set_window_size
  3918           || !f->after_make_frame
  3919           || FRAME_TOOLTIP_P (f)
  3920           || !(frame_window_change
  3921                || frame_selected_change
  3922                || frame_selected_window_change
  3923                || frame_window_state_change))
  3924         /* Either we are not allowed to run hooks for this frame or no
  3925            window change has been reported for it since the last time
  3926            we ran window change functions on it.  */
  3927         continue;
  3928 
  3929       /* Analyze windows and run buffer locals hooks in pre-order.  */
  3930       windows = Fnreverse (window_sub_list (root, Qnil));
  3931       number_of_windows = 0;
  3932 
  3933       /* The following loop collects all data needed to tell whether
  3934          the default value of a hook shall be run and runs any buffer
  3935          local hooks right away.  */
  3936       for (; CONSP (windows); windows = XCDR (windows))
  3937         {
  3938           Lisp_Object window = XCAR (windows);
  3939           struct window *w = XWINDOW (window);
  3940           Lisp_Object buffer = WINDOW_BUFFER (w);
  3941 
  3942           /* Count this window even if it has been deleted while
  3943              running a hook.  */
  3944           number_of_windows += 1;
  3945 
  3946           if (!WINDOW_LIVE_P (window))
  3947             continue;
  3948 
  3949           /* A "buffer change" means either the window's buffer
  3950              changed or the window was not part of this frame the last
  3951              time window change functions were run for it.  */
  3952           window_buffer_change =
  3953             (frame_window_change
  3954              && (!EQ (buffer, w->old_buffer)
  3955                  || w->change_stamp != f->change_stamp));
  3956           /* A "size change" means either a buffer change or that the
  3957              total or body size of the window has changed.
  3958 
  3959              Note: A buffer change implies a size change because either
  3960              this window didn't show the buffer before or this window
  3961              didn't show the buffer the last time the window change
  3962              functions were run.  In either case, an application
  3963              tracing size changes in a buffer-locally fashion might
  3964              want to be informed about that change.  */
  3965           window_size_change =
  3966             (frame_window_change
  3967              && (window_buffer_change
  3968                  || w->pixel_width != w->old_pixel_width
  3969                  || w->pixel_height != w->old_pixel_height
  3970                  || (window_body_width (w, WINDOW_BODY_IN_PIXELS)
  3971                      != w->old_body_pixel_width)
  3972                  || (window_body_height (w, WINDOW_BODY_IN_PIXELS)
  3973                      != w->old_body_pixel_height)));
  3974 
  3975           /* The following two are needed when running the default
  3976              values for this frame below.  */
  3977           frame_buffer_change = frame_buffer_change || window_buffer_change;
  3978           frame_size_change = frame_size_change || window_size_change;
  3979 
  3980           if (window_buffer_change)
  3981             run_window_change_functions_1
  3982               (Qwindow_buffer_change_functions, buffer, window);
  3983 
  3984           if (window_size_change && WINDOW_LIVE_P (window))
  3985             run_window_change_functions_1
  3986               (Qwindow_size_change_functions, buffer, window);
  3987 
  3988           /* This window's selection has changed when it was
  3989              (de-)selected as its frame's or the globally selected
  3990              window.  */
  3991           if (((frame_selected_change
  3992                 && (EQ (window, old_selected_window)
  3993                     || EQ (window, selected_window)))
  3994                || (frame_selected_window_change
  3995                    && (EQ (window, FRAME_OLD_SELECTED_WINDOW (f))
  3996                        || EQ (window, FRAME_SELECTED_WINDOW (f)))))
  3997               && WINDOW_LIVE_P (window))
  3998             run_window_change_functions_1
  3999               (Qwindow_selection_change_functions, buffer, window);
  4000 
  4001           /* This window's state has changed when its buffer or size
  4002              changed or it was (de-)selected as its frame's or the
  4003              globally selected window.  */
  4004           if ((window_buffer_change
  4005                || window_size_change
  4006                || ((frame_selected_change
  4007                     && (EQ (window, old_selected_window)
  4008                         || EQ (window, selected_window)))
  4009                    || (frame_selected_window_change
  4010                        && (EQ (window, FRAME_OLD_SELECTED_WINDOW (f))
  4011                            || EQ (window, FRAME_SELECTED_WINDOW (f))))))
  4012               && WINDOW_LIVE_P (window))
  4013             run_window_change_functions_1
  4014               (Qwindow_state_change_functions, buffer, window);
  4015         }
  4016 
  4017       /* When the number of windows on a frame has decreased, at least
  4018          one window of that frame was deleted.  In that case, we want
  4019          to run the default buffer and configuration change hooks.  The
  4020          default size change hook is not necessarily run in that case,
  4021          but usually will be unless the deletion was "compensated" by
  4022          a reduction of the frame size or an increase of a minibuffer
  4023          window size.  */
  4024       window_deleted = number_of_windows < f->number_of_windows;
  4025       /* A frame changed buffers when one of its windows has changed
  4026          its buffer or at least one window was deleted.  */
  4027       if ((frame_buffer_change || window_deleted) && FRAME_LIVE_P (f))
  4028         run_window_change_functions_1
  4029           (Qwindow_buffer_change_functions, Qnil, frame);
  4030 
  4031       /* A size change occurred when at least one of the frame's
  4032          windows has changed size.  */
  4033       if (frame_size_change && FRAME_LIVE_P (f))
  4034         run_window_change_functions_1
  4035           (Qwindow_size_change_functions, Qnil, frame);
  4036 
  4037       /* A frame has changed its window selection when its selected
  4038          window has changed or when it was (de-)selected.  */
  4039       if ((frame_selected_change || frame_selected_window_change)
  4040           && FRAME_LIVE_P (f))
  4041         run_window_change_functions_1
  4042           (Qwindow_selection_change_functions, Qnil, frame);
  4043 
  4044 #if defined HAVE_TEXT_CONVERSION
  4045 
  4046       /* If the buffer or selected window has changed, also reset the
  4047          input method composition state.  */
  4048 
  4049       if ((frame_selected_window_change || frame_buffer_change)
  4050           && FRAME_LIVE_P (f)
  4051           && FRAME_WINDOW_P (f))
  4052         report_selected_window_change (f);
  4053 
  4054 #endif
  4055 
  4056       /* A frame has changed state when a size or buffer change
  4057          occurred, its selected window has changed, when it was
  4058          (de-)selected or its window state change flag was set.  */
  4059       if ((frame_selected_change || frame_selected_window_change
  4060            || frame_buffer_change || window_deleted
  4061            || frame_size_change || frame_window_state_change)
  4062           && FRAME_LIVE_P (f))
  4063         {
  4064           run_window_change_functions_1
  4065             (Qwindow_state_change_functions, Qnil, frame);
  4066           /* Make sure to run 'window-state-change-hook' later.  */
  4067           run_window_state_change_hook = true;
  4068           /*  Make sure to record changes for each live frame in
  4069              window_change_record later.  */
  4070           window_change_record_frames = true;
  4071         }
  4072 
  4073       /* A frame's configuration changed when one of its windows has
  4074          changed buffer or size or at least one window was deleted.  */
  4075       if ((frame_size_change || window_deleted) && FRAME_LIVE_P (f))
  4076         /* This will run any buffer local window configuration change
  4077            hook as well.  */
  4078         run_window_configuration_change_hook (f);
  4079     }
  4080 
  4081   /* Run 'window-state-change-hook' if at least one frame has changed
  4082      state.  */
  4083   if (run_window_state_change_hook && !NILP (Vwindow_state_change_hook))
  4084     safe_run_hooks (Qwindow_state_change_hook);
  4085 
  4086   /* Record changes for all frames (if asked for), selected window and
  4087      frame.  */
  4088   unbind_to (count, Qnil);
  4089 }
  4090 
  4091 /* Make WINDOW display BUFFER.  RUN_HOOKS_P means it's allowed
  4092    to run hooks.  See make_frame for a case where it's not allowed.
  4093    KEEP_MARGINS_P means that the current margins, fringes, and
  4094    scroll bar settings of the window are not reset from the buffer's
  4095    local settings.  */
  4096 
  4097 void
  4098 set_window_buffer (Lisp_Object window, Lisp_Object buffer,
  4099                    bool run_hooks_p, bool keep_margins_p)
  4100 {
  4101   struct window *w = XWINDOW (window);
  4102   struct buffer *b = XBUFFER (buffer);
  4103   specpdl_ref count = SPECPDL_INDEX ();
  4104   bool samebuf = EQ (buffer, w->contents);
  4105 
  4106   wset_buffer (w, buffer);
  4107 
  4108   if (EQ (window, selected_window))
  4109     bset_last_selected_window (b, window);
  4110 
  4111   /* Let redisplay errors through.  */
  4112   b->display_error_modiff = 0;
  4113 
  4114   /* Update time stamps of buffer display.  */
  4115   if (INTEGERP (BVAR (b, display_count)))
  4116     bset_display_count (b, Fadd1 (BVAR (b, display_count)));
  4117   bset_display_time (b, Fcurrent_time ());
  4118 
  4119   w->window_end_pos = 0;
  4120   w->window_end_vpos = 0;
  4121   w->last_cursor_vpos = 0;
  4122 
  4123   if (!(keep_margins_p && samebuf))
  4124     { /* If we're not actually changing the buffer, don't reset hscroll
  4125          and vscroll.  Resetting hscroll and vscroll here is problematic
  4126          for things like image-mode and doc-view-mode since it resets
  4127          the image's position whenever we resize the frame.  */
  4128       w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
  4129       w->suspend_auto_hscroll = false;
  4130       w->vscroll = 0;
  4131       set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
  4132       set_marker_both (w->old_pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
  4133       set_marker_restricted (w->start,
  4134                              make_fixnum (b->last_window_start),
  4135                              buffer);
  4136       w->start_at_line_beg = false;
  4137       w->force_start = false;
  4138     }
  4139 
  4140   wset_redisplay (w);
  4141   wset_update_mode_line (w);
  4142 
  4143   /* We must select BUFFER to run the window-scroll-functions and to look up
  4144      the buffer-local value of Vwindow_point_insertion_type.  */
  4145   record_unwind_current_buffer ();
  4146   Fset_buffer (buffer);
  4147 
  4148   XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
  4149   XMARKER (w->old_pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
  4150 
  4151   if (!keep_margins_p)
  4152     {
  4153       /* Set fringes and scroll bars from buffer unless they have been
  4154          declared as persistent.  */
  4155       if (!w->fringes_persistent)
  4156         set_window_fringes (w, BVAR (b, left_fringe_width),
  4157                             BVAR (b, right_fringe_width),
  4158                             BVAR (b, fringes_outside_margins), Qnil);
  4159       if (!w->scroll_bars_persistent)
  4160         set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
  4161                                 BVAR (b, vertical_scroll_bar_type),
  4162                                 BVAR (b, scroll_bar_height),
  4163                                 BVAR (b, horizontal_scroll_bar_type), Qnil);
  4164       /* Set left and right marginal area width from buffer.  */
  4165       set_window_margins (w, BVAR (b, left_margin_cols),
  4166                           BVAR (b, right_margin_cols));
  4167       apply_window_adjustment (w);
  4168     }
  4169 
  4170   if (run_hooks_p && !NILP (Vwindow_scroll_functions))
  4171     run_hook_with_args_2 (Qwindow_scroll_functions, window,
  4172                           Fmarker_position (w->start));
  4173 
  4174   /* Ensure that window change functions are run later if the buffer
  4175      differs and the window is neither a mini nor a pseudo window.
  4176 
  4177      Note: Running window change functions for the minibuffer is noisy
  4178      and was generally suppressed in the past.  Is there any reason we
  4179      should run them?  */
  4180   if (!samebuf && !MINI_WINDOW_P (w) && !WINDOW_PSEUDO_P (w))
  4181     FRAME_WINDOW_CHANGE (XFRAME (w->frame)) = true;
  4182 
  4183   unbind_to (count, Qnil);
  4184 }
  4185 
  4186 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
  4187        doc: /* Make WINDOW display BUFFER-OR-NAME.
  4188 WINDOW must be a live window and defaults to the selected one.
  4189 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
  4190 
  4191 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
  4192 display margins, fringe widths, and scroll bar settings are preserved;
  4193 the default is to reset these from the local settings for BUFFER-OR-NAME
  4194 or the frame defaults.  Return nil.
  4195 
  4196 This function throws an error when WINDOW is strongly dedicated to its
  4197 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
  4198 already display BUFFER-OR-NAME.
  4199 
  4200 This function runs `window-scroll-functions' before running
  4201 `window-configuration-change-hook'.  */)
  4202   (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
  4203 {
  4204   register Lisp_Object tem, buffer;
  4205   register struct window *w = decode_live_window (window);
  4206 
  4207   XSETWINDOW (window, w);
  4208   buffer = Fget_buffer (buffer_or_name);
  4209   CHECK_BUFFER (buffer);
  4210   if (!BUFFER_LIVE_P (XBUFFER (buffer)))
  4211     error ("Attempt to display deleted buffer");
  4212 
  4213   tem = w->contents;
  4214   if (NILP (tem))
  4215     error ("Window is deleted");
  4216   else
  4217     {
  4218       if (!EQ (tem, buffer))
  4219         {
  4220           if (EQ (w->dedicated, Qt))
  4221             /* WINDOW is strongly dedicated to its buffer, signal an
  4222                error.  */
  4223             error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
  4224           else
  4225             /* WINDOW is weakly dedicated to its buffer, reset
  4226                dedication.  */
  4227             wset_dedicated (w, Qnil);
  4228 
  4229           call1 (Qrecord_window_buffer, window);
  4230         }
  4231 
  4232       unshow_buffer (w);
  4233     }
  4234 
  4235   set_window_buffer (window, buffer, true, !NILP (keep_margins));
  4236 
  4237   return Qnil;
  4238 }
  4239 
  4240 static Lisp_Object
  4241 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
  4242 {
  4243   return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
  4244 }
  4245 
  4246 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
  4247        0, 1, 0,
  4248        doc: /* Force all windows to be updated on next redisplay.
  4249 If optional arg OBJECT is a window, force redisplay of that window only.
  4250 If OBJECT is a buffer or buffer name, force redisplay of all windows
  4251 displaying that buffer.  */)
  4252   (Lisp_Object object)
  4253 {
  4254   if (NILP (object))
  4255     {
  4256       windows_or_buffers_changed = 29;
  4257       update_mode_lines = 28;
  4258       return Qt;
  4259     }
  4260 
  4261   if (WINDOW_LIVE_P (object))
  4262     {
  4263       struct window *w = XWINDOW (object);
  4264       mark_window_display_accurate (object, false);
  4265       w->update_mode_line = true;
  4266       if (BUFFERP (w->contents))
  4267         XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
  4268       update_mode_lines = 29;
  4269       return Qt;
  4270     }
  4271 
  4272   if (STRINGP (object))
  4273     object = Fget_buffer (object);
  4274   if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))
  4275       && buffer_window_count (XBUFFER (object)))
  4276     {
  4277       /* If buffer is live and shown in at least one window, find
  4278          all windows showing this buffer and force update of them.  */
  4279       object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, false, Qvisible);
  4280       return NILP (object) ? Qnil : Qt;
  4281     }
  4282 
  4283   /* If nothing suitable was found, just return.
  4284      We could signal an error, but this feature will typically be used
  4285      asynchronously in timers or process sentinels, so we don't.  */
  4286   return Qnil;
  4287 }
  4288 
  4289 /* Obsolete since 24.3.  */
  4290 void
  4291 temp_output_buffer_show (register Lisp_Object buf)
  4292 {
  4293   register struct buffer *old = current_buffer;
  4294   register Lisp_Object window;
  4295   register struct window *w;
  4296 
  4297   bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
  4298 
  4299   Fset_buffer (buf);
  4300   BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
  4301   BEGV = BEG;
  4302   ZV = Z;
  4303   SET_PT (BEG);
  4304   set_buffer_internal (old);
  4305 
  4306   if (!NILP (Vtemp_buffer_show_function))
  4307     call1 (Vtemp_buffer_show_function, buf);
  4308   else if (WINDOW_LIVE_P (window = display_buffer (buf, Qnil, Qnil)))
  4309     {
  4310       if (!EQ (XWINDOW (window)->frame, selected_frame))
  4311         Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
  4312       Vminibuf_scroll_window = window;
  4313       w = XWINDOW (window);
  4314       w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
  4315       w->suspend_auto_hscroll = false;
  4316       set_marker_restricted_both (w->start, buf, BEG, BEG);
  4317       set_marker_restricted_both (w->pointm, buf, BEG, BEG);
  4318       set_marker_restricted_both (w->old_pointm, buf, BEG, BEG);
  4319 
  4320       /* Run temp-buffer-show-hook, with the chosen window selected
  4321          and its buffer current.  */
  4322       {
  4323         specpdl_ref count = SPECPDL_INDEX ();
  4324         Lisp_Object prev_window, prev_buffer;
  4325         prev_window = selected_window;
  4326         XSETBUFFER (prev_buffer, old);
  4327 
  4328         /* Select the window that was chosen, for running the hook.
  4329            Note: Both Fselect_window and select_window_norecord may
  4330            set-buffer to the buffer displayed in the window,
  4331            so we need to save the current buffer.  --stef  */
  4332         record_unwind_protect (restore_buffer, prev_buffer);
  4333         record_unwind_protect (select_window_norecord, prev_window);
  4334         Fselect_window (window, Qt);
  4335         Fset_buffer (w->contents);
  4336         run_hook (Qtemp_buffer_show_hook);
  4337         unbind_to (count, Qnil);
  4338       }
  4339     }
  4340 }
  4341 
  4342 /* Allocate basically initialized window.  */
  4343 
  4344 static struct window *
  4345 allocate_window (void)
  4346 {
  4347   return ALLOCATE_ZEROED_PSEUDOVECTOR (struct window, mode_line_help_echo,
  4348                                        PVEC_WINDOW);
  4349 }
  4350 
  4351 /* Make new window, have it replace WINDOW in window-tree, and make
  4352    WINDOW its only vertical child (HORFLAG means make WINDOW its only
  4353    horizontal child).   */
  4354 static void
  4355 make_parent_window (Lisp_Object window, bool horflag)
  4356 {
  4357   Lisp_Object parent;
  4358   register struct window *o, *p;
  4359 
  4360   o = XWINDOW (window);
  4361   p = allocate_window ();
  4362   memcpy ((char *) p + sizeof (union vectorlike_header),
  4363           (char *) o + sizeof (union vectorlike_header),
  4364           word_size * VECSIZE (struct window));
  4365   /* P's buffer slot may change from nil to a buffer...  */
  4366   adjust_window_count (p, 1);
  4367   XSETWINDOW (parent, p);
  4368 
  4369   p->sequence_number = ++sequence_number;
  4370 
  4371   replace_window (window, parent, true);
  4372 
  4373   wset_next (o, Qnil);
  4374   wset_prev (o, Qnil);
  4375   wset_parent (o, parent);
  4376   /* ...but now P becomes an internal window.  */
  4377   wset_start (p, Qnil);
  4378   wset_pointm (p, Qnil);
  4379   wset_old_pointm (p, Qnil);
  4380   wset_buffer (p, Qnil);
  4381   wset_combination (p, horflag, window);
  4382   wset_combination_limit (p, Qnil);
  4383   wset_window_parameters (p, Qnil);
  4384 }
  4385 
  4386 /* Make new window from scratch.  */
  4387 Lisp_Object
  4388 make_window (void)
  4389 {
  4390   Lisp_Object window;
  4391   register struct window *w;
  4392 
  4393   w = allocate_window ();
  4394   /* Initialize Lisp data.  Note that allocate_window initializes all
  4395      Lisp data to nil, so do it only for slots which should not be nil.  */
  4396   wset_normal_lines (w, make_float (1.0));
  4397   wset_normal_cols (w, make_float (1.0));
  4398   wset_new_total (w, make_fixnum (0));
  4399   wset_new_normal (w, make_fixnum (0));
  4400   wset_new_pixel (w, make_fixnum (0));
  4401   wset_start (w, Fmake_marker ());
  4402   wset_pointm (w, Fmake_marker ());
  4403   wset_old_pointm (w, Fmake_marker ());
  4404   wset_vertical_scroll_bar_type (w, Qt);
  4405   wset_horizontal_scroll_bar_type (w, Qt);
  4406   /* These Lisp fields are marked specially so they're not set to nil by
  4407      allocate_window.  */
  4408   wset_prev_buffers (w, Qnil);
  4409   wset_next_buffers (w, Qnil);
  4410 
  4411   /* Initialize non-Lisp data.  Note that allocate_window zeroes out all
  4412      non-Lisp data, so do it only for slots which should not be zero.  */
  4413   w->nrows_scale_factor = w->ncols_scale_factor = 1;
  4414   w->left_fringe_width = w->right_fringe_width = -1;
  4415   w->mode_line_height = w->tab_line_height = w->header_line_height = -1;
  4416 #ifdef HAVE_WINDOW_SYSTEM
  4417   w->phys_cursor_type = NO_CURSOR;
  4418   w->phys_cursor_width = -1;
  4419 #endif
  4420   w->sequence_number = ++sequence_number;
  4421   w->scroll_bar_width = -1;
  4422   w->scroll_bar_height = -1;
  4423   w->column_number_displayed = -1;
  4424   /* Reset window_list.  */
  4425   Vwindow_list = Qnil;
  4426   /* Return window.  */
  4427   XSETWINDOW (window, w);
  4428   return window;
  4429 }
  4430 
  4431 DEFUN ("set-window-new-pixel", Fset_window_new_pixel, Sset_window_new_pixel, 2, 3, 0,
  4432        doc: /* Set new pixel size of WINDOW to SIZE.
  4433 WINDOW must be a valid window and defaults to the selected one.
  4434 Return SIZE.
  4435 
  4436 Optional argument ADD non-nil means add SIZE to the new pixel size of
  4437 WINDOW and return the sum.
  4438 
  4439 The new pixel size of WINDOW, if valid, will be shortly installed as
  4440 WINDOW's pixel height (see `window-pixel-height') or pixel width (see
  4441 `window-pixel-width').
  4442 
  4443 Note: This function does not operate on any child windows of WINDOW.  */)
  4444   (Lisp_Object window, Lisp_Object size, Lisp_Object add)
  4445 {
  4446   struct window *w = decode_valid_window (window);
  4447   EMACS_INT size_min = NILP (add) ? 0 : - XFIXNUM (w->new_pixel);
  4448   EMACS_INT size_max = size_min + min (INT_MAX, MOST_POSITIVE_FIXNUM);
  4449 
  4450   int checked_size = check_integer_range (size, size_min, size_max);
  4451   if (NILP (add))
  4452     wset_new_pixel (w, size);
  4453   else
  4454     wset_new_pixel (w, make_fixnum (XFIXNUM (w->new_pixel) + checked_size));
  4455 
  4456   return w->new_pixel;
  4457 }
  4458 
  4459 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
  4460        doc: /* Set new total size of WINDOW to SIZE.
  4461 WINDOW must be a valid window and defaults to the selected one.
  4462 Return SIZE.
  4463 
  4464 Optional argument ADD non-nil means add SIZE to the new total size of
  4465 WINDOW and return the sum.
  4466 
  4467 The new total size of WINDOW, if valid, will be shortly installed as
  4468 WINDOW's total height (see `window-total-height') or total width (see
  4469 `window-total-width').
  4470 
  4471 Note: This function does not operate on any child windows of WINDOW.  */)
  4472      (Lisp_Object window, Lisp_Object size, Lisp_Object add)
  4473 {
  4474   struct window *w = decode_valid_window (window);
  4475 
  4476   CHECK_FIXNUM (size);
  4477   if (NILP (add))
  4478     wset_new_total (w, size);
  4479   else
  4480     wset_new_total (w, make_fixnum (XFIXNUM (w->new_total) + XFIXNUM (size)));
  4481 
  4482   return w->new_total;
  4483 }
  4484 
  4485 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
  4486        doc: /* Set new normal size of WINDOW to SIZE.
  4487 WINDOW must be a valid window and defaults to the selected one.
  4488 Return SIZE.
  4489 
  4490 The new normal size of WINDOW, if valid, will be shortly installed as
  4491 WINDOW's normal size (see `window-normal-size').
  4492 
  4493 Note: This function does not operate on any child windows of WINDOW.  */)
  4494      (Lisp_Object window, Lisp_Object size)
  4495 {
  4496   wset_new_normal (decode_valid_window (window), size);
  4497   return size;
  4498 }
  4499 
  4500 /* Return true if setting w->pixel_height (w->pixel_width if HORFLAG)
  4501    to w->new_pixel would result in correct heights (widths)
  4502    for window W and recursively all child windows of W.
  4503 
  4504    Note: This function does not check any of `window-fixed-size-p',
  4505    `window-min-height' or `window-min-width'.  It does check that window
  4506    sizes do not drop below one line (two columns). */
  4507 static bool
  4508 window_resize_check (struct window *w, bool horflag)
  4509 {
  4510   struct frame *f = XFRAME (w->frame);
  4511   struct window *c;
  4512 
  4513   if (WINDOW_VERTICAL_COMBINATION_P (w))
  4514     /* W is a vertical combination.  */
  4515     {
  4516       c = XWINDOW (w->contents);
  4517       if (horflag)
  4518         /* All child windows of W must have the same width as W.  */
  4519         {
  4520           while (c)
  4521             {
  4522               if (XFIXNUM (c->new_pixel) != XFIXNUM (w->new_pixel)
  4523                   || !window_resize_check (c, horflag))
  4524                 return false;
  4525 
  4526               c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4527             }
  4528 
  4529           return true;
  4530         }
  4531       else
  4532         /* The sum of the heights of the child windows of W must equal
  4533            W's height.  */
  4534         {
  4535           int remaining_pixels = XFIXNUM (w->new_pixel);
  4536 
  4537           while (c)
  4538             {
  4539               if (!window_resize_check (c, horflag))
  4540                 return false;
  4541 
  4542               remaining_pixels -= XFIXNUM (c->new_pixel);
  4543               if (remaining_pixels < 0)
  4544                 return false;
  4545               c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4546             }
  4547 
  4548           return remaining_pixels == 0;
  4549         }
  4550     }
  4551   else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
  4552     /* W is a horizontal combination.  */
  4553     {
  4554       c = XWINDOW (w->contents);
  4555       if (horflag)
  4556         /* The sum of the widths of the child windows of W must equal W's
  4557            width.  */
  4558         {
  4559           int remaining_pixels = XFIXNUM (w->new_pixel);
  4560 
  4561           while (c)
  4562             {
  4563               if (!window_resize_check (c, horflag))
  4564                 return false;
  4565 
  4566               remaining_pixels -= XFIXNUM (c->new_pixel);
  4567               if (remaining_pixels < 0)
  4568                 return false;
  4569               c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4570             }
  4571 
  4572           return remaining_pixels == 0;
  4573         }
  4574       else
  4575         /* All child windows of W must have the same height as W.  */
  4576         {
  4577           while (c)
  4578             {
  4579               if (XFIXNUM (c->new_pixel) != XFIXNUM (w->new_pixel)
  4580                   || !window_resize_check (c, horflag))
  4581                 return false;
  4582 
  4583               c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4584             }
  4585 
  4586           return true;
  4587         }
  4588     }
  4589   else
  4590     /* A leaf window.  Make sure it's not too small.  The following
  4591        hardcodes the values of `window-safe-min-width' (2) and
  4592        `window-safe-min-height' (1) which are defined in window.el.  */
  4593     return (XFIXNUM (w->new_pixel) >= (horflag
  4594                                        ? 2 * FRAME_COLUMN_WIDTH (f)
  4595                                        : FRAME_LINE_HEIGHT (f)));
  4596 }
  4597 
  4598 
  4599 /* Set w->pixel_height (w->pixel_width if HORFLAG) to
  4600    w->new_pixel for window W and recursively all child windows of W.
  4601    Also calculate and assign the new vertical (horizontal) pixel start
  4602    positions of each of these windows.
  4603 
  4604    This function does not perform any error checks.  Make sure you have
  4605    run window_resize_check on W before applying this function.  */
  4606 static void
  4607 window_resize_apply (struct window *w, bool horflag)
  4608 {
  4609   struct window *c;
  4610   int edge;
  4611   int unit = (horflag
  4612               ? FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w))
  4613               : FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
  4614 
  4615   /* Note: Assigning new_normal requires that the new total size of the
  4616      parent window has been set *before*.  */
  4617   if (horflag)
  4618     {
  4619       w->pixel_width = XFIXNAT (w->new_pixel);
  4620       w->total_cols = w->pixel_width / unit;
  4621       if (NUMBERP (w->new_normal))
  4622         wset_normal_cols (w, w->new_normal);
  4623 
  4624       edge = w->pixel_left;
  4625     }
  4626   else
  4627     {
  4628       w->pixel_height = XFIXNAT (w->new_pixel);
  4629       w->total_lines = w->pixel_height / unit;
  4630       if (NUMBERP (w->new_normal))
  4631         wset_normal_lines (w, w->new_normal);
  4632 
  4633       edge = w->pixel_top;
  4634     }
  4635 
  4636   if (WINDOW_VERTICAL_COMBINATION_P (w))
  4637     /* W is a vertical combination.  */
  4638     {
  4639       c = XWINDOW (w->contents);
  4640       while (c)
  4641         {
  4642           if (horflag)
  4643             {
  4644               c->pixel_left = edge;
  4645               c->left_col = edge / unit;
  4646             }
  4647           else
  4648             {
  4649               c->pixel_top = edge;
  4650               c->top_line = edge / unit;
  4651             }
  4652           window_resize_apply (c, horflag);
  4653           if (!horflag)
  4654             edge = edge + c->pixel_height;
  4655 
  4656           c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4657         }
  4658     }
  4659   else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
  4660     /* W is a horizontal combination.  */
  4661     {
  4662       c = XWINDOW (w->contents);
  4663       while (c)
  4664         {
  4665           if (horflag)
  4666             {
  4667               c->pixel_left = edge;
  4668               c->left_col = edge / unit;
  4669             }
  4670           else
  4671             {
  4672               c->pixel_top = edge;
  4673               c->top_line = edge / unit;
  4674             }
  4675 
  4676           window_resize_apply (c, horflag);
  4677           if (horflag)
  4678             edge = edge + c->pixel_width;
  4679 
  4680           c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4681         }
  4682     }
  4683   else
  4684     /* Bug#15957.  */
  4685     w->window_end_valid = false;
  4686 
  4687   if (!WINDOW_PSEUDO_P (w))
  4688     FRAME_WINDOW_CHANGE (WINDOW_XFRAME (w)) = true;
  4689 }
  4690 
  4691 
  4692 /* Set w->total_lines (w->total_cols if HORFLAG) to
  4693    w->new_total for window W and recursively all child windows of W.
  4694    Also calculate and assign the new vertical (horizontal) start
  4695    positions of each of these windows.  */
  4696 static void
  4697 window_resize_apply_total (struct window *w, bool horflag)
  4698 {
  4699   struct window *c;
  4700   int edge;
  4701 
  4702   /* Note: Assigning new_normal requires that the new total size of the
  4703      parent window has been set *before*.  */
  4704   if (horflag)
  4705     {
  4706       w->total_cols = XFIXNAT (w->new_total);
  4707       edge = w->left_col;
  4708     }
  4709   else
  4710     {
  4711       w->total_lines = XFIXNAT (w->new_total);
  4712       edge = w->top_line;
  4713     }
  4714 
  4715   if (WINDOW_VERTICAL_COMBINATION_P (w))
  4716     /* W is a vertical combination.  */
  4717     {
  4718       c = XWINDOW (w->contents);
  4719       while (c)
  4720         {
  4721           if (horflag)
  4722             c->left_col = edge;
  4723           else
  4724             c->top_line = edge;
  4725 
  4726           window_resize_apply_total (c, horflag);
  4727           if (!horflag)
  4728             edge = edge + c->total_lines;
  4729 
  4730           c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4731         }
  4732     }
  4733   else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
  4734     /* W is a horizontal combination.  */
  4735     {
  4736       c = XWINDOW (w->contents);
  4737       while (c)
  4738         {
  4739           if (horflag)
  4740             c->left_col = edge;
  4741           else
  4742             c->top_line = edge;
  4743 
  4744           window_resize_apply_total (c, horflag);
  4745           if (horflag)
  4746             edge = edge + c->total_cols;
  4747 
  4748           c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4749         }
  4750     }
  4751 }
  4752 
  4753 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
  4754        doc: /* Apply requested size values for window-tree of FRAME.
  4755 If FRAME is omitted or nil, it defaults to the selected frame.
  4756 
  4757 Optional argument HORIZONTAL omitted or nil means apply requested
  4758 height values.  HORIZONTAL non-nil means apply requested width values.
  4759 
  4760 The requested size values are those set by `set-window-new-pixel' and
  4761 `set-window-new-normal'.  This function checks whether the requested
  4762 values sum up to a valid window layout, recursively assigns the new
  4763 sizes of all child windows and calculates and assigns the new start
  4764 positions of these windows.
  4765 
  4766 Return t if the requested values have been applied correctly, nil
  4767 otherwise.
  4768 
  4769 Note: This function does not check any of `window-fixed-size-p',
  4770 `window-min-height' or `window-min-width'.  All these checks have to
  4771 be applied on the Elisp level.  */)
  4772      (Lisp_Object frame, Lisp_Object horizontal)
  4773 {
  4774   struct frame *f = decode_live_frame (frame);
  4775   struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
  4776   bool horflag = !NILP (horizontal);
  4777 
  4778   if (!window_resize_check (r, horflag)
  4779       || (XFIXNUM (r->new_pixel)
  4780           != (horflag ? r->pixel_width : r->pixel_height)))
  4781     return Qnil;
  4782 
  4783   block_input ();
  4784   window_resize_apply (r, horflag);
  4785 
  4786   fset_redisplay (f);
  4787 
  4788   adjust_frame_glyphs (f);
  4789   unblock_input ();
  4790 
  4791   return Qt;
  4792 }
  4793 
  4794 
  4795 DEFUN ("window-resize-apply-total", Fwindow_resize_apply_total, Swindow_resize_apply_total, 0, 2, 0,
  4796        doc: /* Apply requested total size values for window-tree of FRAME.
  4797 If FRAME is omitted or nil, it defaults to the selected frame.
  4798 
  4799 This function does not assign pixel or normal size values.  You should
  4800 have run `window-resize-apply' before running this.
  4801 
  4802 Optional argument HORIZONTAL omitted or nil means apply requested
  4803 height values.  HORIZONTAL non-nil means apply requested width
  4804 values.  */)
  4805      (Lisp_Object frame, Lisp_Object horizontal)
  4806 {
  4807   struct frame *f = decode_live_frame (frame);
  4808   struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
  4809 
  4810   block_input ();
  4811   /* Necessary when deleting the top-/or leftmost window.  */
  4812   r->left_col = 0;
  4813   r->top_line = FRAME_TOP_MARGIN (f);
  4814   window_resize_apply_total (r, !NILP (horizontal));
  4815   /* Handle the mini window.  */
  4816   if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
  4817     {
  4818       struct window *m = XWINDOW (f->minibuffer_window);
  4819 
  4820       if (NILP (horizontal))
  4821         {
  4822           m->top_line = r->top_line + r->total_lines;
  4823           m->total_lines = XFIXNAT (m->new_total);
  4824         }
  4825       else
  4826         m->total_cols = XFIXNAT (m->new_total);
  4827     }
  4828 
  4829   unblock_input ();
  4830 
  4831   return Qt;
  4832 }
  4833 
  4834 /* Resize frame F's windows when F's inner height (inner width if
  4835    HORFLAG is true) has been set to SIZE pixels.  */
  4836 
  4837 void
  4838 resize_frame_windows (struct frame *f, int size, bool horflag)
  4839 {
  4840   Lisp_Object root = f->root_window;
  4841   struct window *r = XWINDOW (root);
  4842   int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
  4843   int new_size, new_pixel_size;
  4844   int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
  4845   Lisp_Object mini = f->minibuffer_window;
  4846   struct window *m = WINDOWP (mini) ? XWINDOW (mini) : NULL;
  4847   int mini_height = ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
  4848                      ? (unit + m->pixel_height
  4849                         - window_body_height (m, WINDOW_BODY_IN_PIXELS))
  4850                      : 0);
  4851 
  4852   new_pixel_size = max (horflag ? size : size - mini_height, unit);
  4853   new_size = new_pixel_size / unit;
  4854 
  4855   if (new_pixel_size == old_pixel_size
  4856       && (horflag || r->pixel_top == FRAME_TOP_MARGIN_HEIGHT (f)))
  4857     ;
  4858   else if (WINDOW_LEAF_P (r))
  4859     {
  4860       /* For a leaf root window just set the size.  */
  4861       if (horflag)
  4862         {
  4863           r->total_cols = new_size;
  4864           r->pixel_width = new_pixel_size;
  4865         }
  4866       else
  4867         {
  4868           r->top_line = FRAME_TOP_MARGIN (f);
  4869           r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
  4870 
  4871           r->total_lines = new_size;
  4872           r->pixel_height = new_pixel_size;
  4873         }
  4874 
  4875       FRAME_WINDOW_CHANGE (f)
  4876         = !WINDOW_PSEUDO_P (r) && new_pixel_size != old_pixel_size;
  4877     }
  4878   else
  4879     {
  4880       Lisp_Object delta;
  4881 
  4882       if (!horflag)
  4883         {
  4884           r->top_line = FRAME_TOP_MARGIN (f);
  4885           r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
  4886         }
  4887 
  4888       XSETINT (delta, new_pixel_size - old_pixel_size);
  4889 
  4890       /* Try a "normal" resize first.  */
  4891       resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil, Qt);
  4892       if (window_resize_check (r, horflag)
  4893           && new_pixel_size == XFIXNUM (r->new_pixel))
  4894         {
  4895           window_resize_apply (r, horflag);
  4896           window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
  4897         }
  4898       else
  4899         {
  4900           /* Try with "reasonable" minimum sizes next.  */
  4901           resize_root_window (root, delta, horflag ? Qt : Qnil, Qt, Qt);
  4902           if (window_resize_check (r, horflag)
  4903               && new_pixel_size == XFIXNUM (r->new_pixel))
  4904             {
  4905               window_resize_apply (r, horflag);
  4906               window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
  4907             }
  4908         }
  4909     }
  4910 
  4911   if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
  4912     {
  4913       m = XWINDOW (mini);
  4914       if (horflag)
  4915         {
  4916           m->total_cols = new_size;
  4917           m->pixel_width = new_pixel_size;
  4918         }
  4919       else
  4920         {
  4921           m->total_lines = mini_height / unit;
  4922           m->pixel_height = mini_height;
  4923           m->top_line = r->top_line + r->total_lines;
  4924           m->pixel_top = r->pixel_top + r->pixel_height;
  4925         }
  4926     }
  4927 
  4928   fset_redisplay (f);
  4929 }
  4930 
  4931 
  4932 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
  4933        doc: /* Split window OLD.
  4934 Second argument PIXEL-SIZE specifies the number of pixels of the
  4935 new window.  It must be a positive integer.
  4936 
  4937 Third argument SIDE nil (or `below') specifies that the new window shall
  4938 be located below WINDOW.  SIDE `above' means the new window shall be
  4939 located above WINDOW.  In both cases PIXEL-SIZE specifies the pixel
  4940 height of the new window including space reserved for the mode and/or
  4941 header/tab line.
  4942 
  4943 SIDE t (or `right') specifies that the new window shall be located on
  4944 the right side of WINDOW.  SIDE `left' means the new window shall be
  4945 located on the left of WINDOW.  In both cases PIXEL-SIZE specifies the
  4946 width of the new window including space reserved for fringes and the
  4947 scrollbar or a divider column.
  4948 
  4949 Fourth argument NORMAL-SIZE specifies the normal size of the new window
  4950 according to the SIDE argument.
  4951 
  4952 The new pixel and normal sizes of all involved windows must have been
  4953 set correctly.  See the code of `split-window' for how this is done.  */)
  4954   (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side, Lisp_Object normal_size)
  4955 {
  4956   /* OLD (*o) is the window we have to split.  (*p) is either OLD's
  4957      parent window or an internal window we have to install as OLD's new
  4958      parent.  REFERENCE (*r) must denote a live window, or is set to OLD
  4959      provided OLD is a leaf window, or to the frame's selected window.
  4960      NEW (*n) is the new window created with some parameters taken from
  4961      REFERENCE (*r).  */
  4962   Lisp_Object new, frame, reference;
  4963   struct window *o, *p, *n, *r, *c;
  4964   struct frame *f;
  4965   bool horflag
  4966     /* HORFLAG is true when we split side-by-side, false otherwise.  */
  4967     = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
  4968 
  4969   CHECK_WINDOW (old);
  4970   o = XWINDOW (old);
  4971   frame = WINDOW_FRAME (o);
  4972   f = XFRAME (frame);
  4973 
  4974   CHECK_FIXNUM (pixel_size);
  4975   EMACS_INT total_size
  4976     = XFIXNUM (pixel_size) / (horflag
  4977                            ? FRAME_COLUMN_WIDTH (f)
  4978                            : FRAME_LINE_HEIGHT (f));
  4979 
  4980   /* Set combination_limit if we have to make a new parent window.
  4981      We do that if either `window-combination-limit' is t, or OLD has no
  4982      parent, or OLD is ortho-combined.  */
  4983   bool combination_limit
  4984     = (EQ (Vwindow_combination_limit, Qt)
  4985        || NILP (o->parent)
  4986        || (horflag
  4987            ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
  4988            : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent))));
  4989 
  4990   /* We need a live reference window to initialize some parameters.  */
  4991   if (WINDOW_LIVE_P (old))
  4992     /* OLD is live, use it as reference window.  */
  4993     reference = old;
  4994   else
  4995     /* Use the frame's selected window as reference window.  */
  4996     reference = FRAME_SELECTED_WINDOW (f);
  4997   r = XWINDOW (reference);
  4998 
  4999   /* The following bugs are caught by `split-window'.  */
  5000   if (MINI_WINDOW_P (o))
  5001     error ("Attempt to split minibuffer window");
  5002   else if (total_size < (horflag ? 2 : 1))
  5003     error ("Size of new window too small (after split)");
  5004   else if (!combination_limit && !NILP (Vwindow_combination_resize))
  5005     /* `window-combination-resize' non-nil means try to resize OLD's siblings
  5006        proportionally.  */
  5007     {
  5008       p = XWINDOW (o->parent);
  5009       /* Temporarily pretend we split the parent window.  */
  5010       wset_new_pixel
  5011         (p, make_fixnum ((horflag ? p->pixel_width : p->pixel_height)
  5012                          - XFIXNUM (pixel_size)));
  5013       if (!window_resize_check (p, horflag))
  5014         error ("Window sizes don't fit");
  5015       else
  5016         /* Undo the temporary pretension.  */
  5017         wset_new_pixel (p, make_fixnum (horflag ? p->pixel_width : p->pixel_height));
  5018     }
  5019   else
  5020     {
  5021       if (!window_resize_check (o, horflag))
  5022         error ("Resizing old window failed");
  5023       else if (XFIXNUM (pixel_size) + XFIXNUM (o->new_pixel)
  5024                != (horflag ? o->pixel_width : o->pixel_height))
  5025         error ("Sum of sizes of old and new window don't fit");
  5026     }
  5027 
  5028   /* This is our point of no return.  */
  5029   if (combination_limit)
  5030     {
  5031       /* Save the old value of o->normal_cols/lines.  It gets corrupted
  5032          by make_parent_window and we need it below for assigning it to
  5033          p->new_normal.  */
  5034       Lisp_Object new_normal
  5035         = horflag ? o->normal_cols : o->normal_lines;
  5036 
  5037       make_parent_window (old, horflag);
  5038       p = XWINDOW (o->parent);
  5039       if (EQ (Vwindow_combination_limit, Qt))
  5040         /* Store t in the new parent's combination_limit slot to avoid
  5041            that its children get merged into another window.  */
  5042         wset_combination_limit (p, Qt);
  5043       /* These get applied below.  */
  5044       wset_new_pixel
  5045         (p, make_fixnum (horflag ? o->pixel_width : o->pixel_height));
  5046       wset_new_total
  5047         (p, make_fixnum (horflag ? o->total_cols : o->total_lines));
  5048       wset_new_normal (p, new_normal);
  5049     }
  5050   else
  5051     p = XWINDOW (o->parent);
  5052 
  5053   fset_redisplay (f);
  5054   new = make_window ();
  5055   n = XWINDOW (new);
  5056   wset_frame (n, frame);
  5057   wset_parent (n, o->parent);
  5058 
  5059   if (EQ (side, Qabove) || EQ (side, Qleft))
  5060     {
  5061       wset_prev (n, o->prev);
  5062       if (NILP (n->prev))
  5063         wset_combination (p, horflag, new);
  5064       else
  5065         wset_next (XWINDOW (n->prev), new);
  5066       wset_next (n, old);
  5067       wset_prev (o, new);
  5068     }
  5069   else
  5070     {
  5071       wset_next (n, o->next);
  5072       if (!NILP (n->next))
  5073         wset_prev (XWINDOW (n->next), new);
  5074       wset_prev (n, old);
  5075       wset_next (o, new);
  5076     }
  5077 
  5078   n->window_end_valid = false;
  5079   n->last_cursor_vpos = 0;
  5080 
  5081   /* Get special geometry settings from reference window.  */
  5082   n->left_margin_cols = r->left_margin_cols;
  5083   n->right_margin_cols = r->right_margin_cols;
  5084   n->left_fringe_width = r->left_fringe_width;
  5085   n->right_fringe_width = r->right_fringe_width;
  5086   n->fringes_outside_margins = r->fringes_outside_margins;
  5087   n->scroll_bar_width = r->scroll_bar_width;
  5088   n->scroll_bar_height = r->scroll_bar_height;
  5089   wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
  5090   wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
  5091 
  5092   /* Directly assign orthogonal coordinates and sizes.  */
  5093   if (horflag)
  5094     {
  5095       n->pixel_top = o->pixel_top;
  5096       n->top_line = o->top_line;
  5097       n->pixel_height = o->pixel_height;
  5098       n->total_lines = o->total_lines;
  5099     }
  5100   else
  5101     {
  5102       n->pixel_left = o->pixel_left;
  5103       n->left_col = o->left_col;
  5104       n->pixel_width = o->pixel_width;
  5105       n->total_cols = o->total_cols;
  5106     }
  5107 
  5108   /* Iso-coordinates and sizes are assigned by window_resize_apply,
  5109      get them ready here.  */
  5110   wset_new_pixel (n, pixel_size);
  5111   EMACS_INT sum = 0;
  5112   c = XWINDOW (p->contents);
  5113   while (c)
  5114     {
  5115       if (c != n)
  5116         sum = sum + XFIXNUM (c->new_total);
  5117       c = NILP (c->next) ? 0 : XWINDOW (c->next);
  5118     }
  5119   wset_new_total (n, make_fixnum ((horflag
  5120                                    ? p->total_cols
  5121                                    : p->total_lines)
  5122                                   - sum));
  5123   wset_new_normal (n, normal_size);
  5124 
  5125   block_input ();
  5126   window_resize_apply (p, horflag);
  5127   adjust_frame_glyphs (f);
  5128   /* Set buffer of NEW to buffer of reference window.  */
  5129   set_window_buffer (new, r->contents, true, true);
  5130   FRAME_WINDOW_CHANGE (f) = true;
  5131   unblock_input ();
  5132 
  5133   return new;
  5134 }
  5135 
  5136 
  5137 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
  5138        doc: /* Remove WINDOW from its frame.
  5139 WINDOW defaults to the selected window.  Return nil.
  5140 Signal an error when WINDOW is the only window on its frame.  */)
  5141      (Lisp_Object window)
  5142 {
  5143   Lisp_Object parent, sibling, frame, root;
  5144   struct window *w, *p, *s, *r;
  5145   struct frame *f;
  5146   bool horflag, before_sibling = false;
  5147 
  5148   w = decode_any_window (window);
  5149   XSETWINDOW (window, w);
  5150   if (NILP (w->contents))
  5151     /* It's a no-op to delete an already deleted window.  */
  5152     return Qnil;
  5153 
  5154   parent = w->parent;
  5155   if (NILP (parent))
  5156     /* Never delete a minibuffer or frame root window.  */
  5157     error ("Attempt to delete minibuffer or sole ordinary window");
  5158   else if (NILP (w->prev) && NILP (w->next))
  5159     /* Rather bow out here, this case should be handled on the Elisp
  5160        level.  */
  5161     error ("Attempt to delete sole window of parent");
  5162 
  5163   p = XWINDOW (parent);
  5164   horflag = WINDOW_HORIZONTAL_COMBINATION_P (p);
  5165 
  5166   frame = WINDOW_FRAME (w);
  5167   f = XFRAME (frame);
  5168 
  5169   root = FRAME_ROOT_WINDOW (f);
  5170   r = XWINDOW (root);
  5171 
  5172   /* Unlink WINDOW from window tree.  */
  5173   if (NILP (w->prev))
  5174     /* Get SIBLING below (on the right of) WINDOW.  */
  5175     {
  5176       /* before_sibling means WINDOW is the first child of its
  5177          parent and thus before the sibling.  */
  5178       before_sibling = true;
  5179       sibling = w->next;
  5180       s = XWINDOW (sibling);
  5181       wset_prev (s, Qnil);
  5182       wset_combination (p, horflag, sibling);
  5183     }
  5184   else
  5185     /* Get SIBLING above (on the left of) WINDOW.  */
  5186     {
  5187       sibling = w->prev;
  5188       s = XWINDOW (sibling);
  5189       wset_next (s, w->next);
  5190       if (!NILP (s->next))
  5191         wset_prev (XWINDOW (s->next), sibling);
  5192     }
  5193 
  5194   if (window_resize_check (r, horflag)
  5195       && (XFIXNUM (r->new_pixel)
  5196           == (horflag ? r->pixel_width : r->pixel_height)))
  5197     /* We can delete WINDOW now.  */
  5198     {
  5199 
  5200       /* Block input.  */
  5201       block_input ();
  5202       xwidget_view_delete_all_in_window (w);
  5203       window_resize_apply (p, horflag);
  5204       /* If this window is referred to by the dpyinfo's mouse
  5205          highlight, invalidate that slot to be safe (Bug#9904).  */
  5206       if (!FRAME_INITIAL_P (f))
  5207         {
  5208           Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
  5209 
  5210           if (EQ (hlinfo->mouse_face_window, window))
  5211             hlinfo->mouse_face_window = Qnil;
  5212         }
  5213 
  5214       fset_redisplay (f);
  5215       Vwindow_list = Qnil;
  5216 
  5217       wset_next (w, Qnil);  /* Don't delete w->next too.  */
  5218       free_window_matrices (w);
  5219 
  5220       if (WINDOWP (w->contents))
  5221         {
  5222           delete_all_child_windows (w->contents);
  5223           wset_combination (w, false, Qnil);
  5224         }
  5225       else
  5226         {
  5227           unshow_buffer (w);
  5228           unchain_marker (XMARKER (w->pointm));
  5229           unchain_marker (XMARKER (w->old_pointm));
  5230           unchain_marker (XMARKER (w->start));
  5231           wset_buffer (w, Qnil);
  5232         }
  5233 
  5234       if (NILP (s->prev) && NILP (s->next))
  5235           /* A matrjoshka where SIBLING has become the only child of
  5236              PARENT.  */
  5237         {
  5238           /* Put SIBLING into PARENT's place.  */
  5239           replace_window (parent, sibling, false);
  5240           /* Have SIBLING inherit the following three slot values from
  5241              PARENT (the combination_limit slot is not inherited).  */
  5242           wset_normal_cols (s, p->normal_cols);
  5243           wset_normal_lines (s, p->normal_lines);
  5244           /* Mark PARENT as deleted.  */
  5245           wset_combination (p, false, Qnil);
  5246           /* Try to merge SIBLING into its new parent.  */
  5247           recombine_windows (sibling);
  5248         }
  5249 
  5250       adjust_frame_glyphs (f);
  5251 
  5252       if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
  5253         /* We apparently deleted the frame's selected window; use the
  5254            frame's first window as substitute but don't record it yet.
  5255            `delete-window' may have something better up its sleeves.  */
  5256         {
  5257           /* Use the frame's first window as fallback ...  */
  5258           Lisp_Object new_selected_window = Fframe_first_window (frame);
  5259 
  5260           if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
  5261             Fselect_window (new_selected_window, Qt);
  5262           else
  5263             /* Do not clear f->select_mini_window_flag here.  If the
  5264                last selected window on F was an active minibuffer, we
  5265                want to return to it on a later Fselect_frame.  */
  5266             fset_selected_window (f, new_selected_window);
  5267         }
  5268 
  5269       unblock_input ();
  5270       FRAME_WINDOW_CHANGE (f) = true;
  5271     }
  5272   else
  5273     /* We failed: Relink WINDOW into window tree.  */
  5274     {
  5275       if (before_sibling)
  5276         {
  5277           wset_prev (s, window);
  5278           wset_combination (p, horflag, window);
  5279         }
  5280       else
  5281         {
  5282           wset_next (s, window);
  5283           if (!NILP (w->next))
  5284             wset_prev (XWINDOW (w->next), window);
  5285         }
  5286       error ("Deletion failed");
  5287     }
  5288 
  5289   return Qnil;
  5290 }
  5291 
  5292 /***********************************************************************
  5293                         Resizing Mini-Windows
  5294  ***********************************************************************/
  5295 
  5296 /**
  5297  * resize_mini_window_apply:
  5298  *
  5299  * Assign new window sizes after resizing a mini window W by DELTA
  5300  * pixels.  No error checking performed.
  5301   */
  5302 static void
  5303 resize_mini_window_apply (struct window *w, int delta)
  5304 {
  5305   struct frame *f = XFRAME (w->frame);
  5306   Lisp_Object root = FRAME_ROOT_WINDOW (f);
  5307   struct window *r = XWINDOW (root);
  5308 
  5309   block_input ();
  5310   w->pixel_height = w->pixel_height + delta;
  5311   w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
  5312 
  5313   window_resize_apply (r, false);
  5314 
  5315   w->pixel_top = r->pixel_top + r->pixel_height;
  5316   w->top_line = r->top_line + r->total_lines;
  5317 
  5318   /* Enforce full redisplay of the frame.  */
  5319   /* FIXME: Shouldn't some of the caller do it?  */
  5320   fset_redisplay (f);
  5321   adjust_frame_glyphs (f);
  5322   unblock_input ();
  5323 }
  5324 
  5325 /**
  5326  * grow_mini_window:
  5327  *
  5328  * Grow mini-window W by DELTA pixels.  If DELTA is negative, this may
  5329  * shrink the minibuffer window to the minimum height to display one
  5330  * line of text.
  5331  */
  5332 void
  5333 grow_mini_window (struct window *w, int delta)
  5334 {
  5335   struct frame *f = XFRAME (w->frame);
  5336   int old_height = window_body_height (w, WINDOW_BODY_IN_PIXELS);
  5337   int min_height = FRAME_LINE_HEIGHT (f);
  5338 
  5339   eassert (MINI_WINDOW_P (w));
  5340 
  5341   /* Never shrink mini-window to less than its minimum height.  */
  5342   if (old_height + delta < min_height)
  5343     delta = old_height > min_height ? min_height - old_height : 0;
  5344 
  5345   if (delta != 0)
  5346     {
  5347       Lisp_Object root = FRAME_ROOT_WINDOW (f);
  5348       struct window *r = XWINDOW (root);
  5349       Lisp_Object grow;
  5350 
  5351       FRAME_WINDOWS_FROZEN (f) = true;
  5352       grow = call3 (Qwindow__resize_root_window_vertically,
  5353                     root, make_fixnum (- delta), Qt);
  5354 
  5355       if (FIXNUMP (grow) && window_resize_check (r, false))
  5356         resize_mini_window_apply (w, -XFIXNUM (grow));
  5357     }
  5358 }
  5359 
  5360 /**
  5361  * shrink_mini_window:
  5362  *
  5363  * Shrink mini-window W to the minimum height needed to display one
  5364  * line of text.
  5365  */
  5366 void
  5367 shrink_mini_window (struct window *w)
  5368 {
  5369   struct frame *f = XFRAME (w->frame);
  5370   int delta = (window_body_height (w, WINDOW_BODY_IN_PIXELS)
  5371                - FRAME_LINE_HEIGHT (f));
  5372 
  5373   eassert (MINI_WINDOW_P (w));
  5374 
  5375   if (delta > 0)
  5376     {
  5377       Lisp_Object root = FRAME_ROOT_WINDOW (f);
  5378       struct window *r = XWINDOW (root);
  5379       Lisp_Object grow;
  5380 
  5381       FRAME_WINDOWS_FROZEN (f) = false;
  5382       grow = call3 (Qwindow__resize_root_window_vertically,
  5383                     root, make_fixnum (delta), Qt);
  5384 
  5385       if (FIXNUMP (grow) && window_resize_check (r, false))
  5386         resize_mini_window_apply (w, -XFIXNUM (grow));
  5387     }
  5388   else if (delta < 0)
  5389     /* delta can be less than zero after adding horizontal scroll
  5390        bar.  */
  5391     grow_mini_window (w, -delta);
  5392 
  5393 }
  5394 
  5395 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal,
  5396        Sresize_mini_window_internal, 1, 1, 0,
  5397        doc: /* Resize mini window WINDOW.  */)
  5398      (Lisp_Object window)
  5399 {
  5400   struct window *w = XWINDOW (window);
  5401   struct window *r;
  5402   struct frame *f;
  5403   int old_height, delta;
  5404 
  5405   CHECK_LIVE_WINDOW (window);
  5406   f = XFRAME (w->frame);
  5407 
  5408   if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
  5409     error ("Not a valid minibuffer window");
  5410   else if (FRAME_MINIBUF_ONLY_P (f))
  5411     error ("Cannot resize a minibuffer-only frame");
  5412 
  5413   r = XWINDOW (FRAME_ROOT_WINDOW (f));
  5414   old_height = r->pixel_height + w->pixel_height;
  5415   delta = XFIXNUM (w->new_pixel) - w->pixel_height;
  5416   if (window_resize_check (r, false)
  5417       && XFIXNUM (w->new_pixel) > 0
  5418       && old_height == XFIXNUM (r->new_pixel) + XFIXNUM (w->new_pixel))
  5419     {
  5420       resize_mini_window_apply (w, delta);
  5421 
  5422       return Qt;
  5423     }
  5424   else
  5425     error ("Cannot resize mini window");
  5426 }
  5427 
  5428 /* Mark window cursors off for all windows in the window tree rooted
  5429    at W by setting their phys_cursor_on_p flag to zero.  Called from
  5430    xterm.c, e.g. when a frame is cleared and thereby all cursors on
  5431    the frame are cleared.  */
  5432 
  5433 void
  5434 mark_window_cursors_off (struct window *w)
  5435 {
  5436   while (w)
  5437     {
  5438       if (WINDOWP (w->contents))
  5439         mark_window_cursors_off (XWINDOW (w->contents));
  5440       else
  5441         w->phys_cursor_on_p = false;
  5442 
  5443       w = NILP (w->next) ? 0 : XWINDOW (w->next);
  5444     }
  5445 }
  5446 
  5447 
  5448 /**
  5449  * window_wants_mode_line:
  5450  *
  5451  * Return 1 if window W wants a mode line and is high enough to
  5452  * accommodate it, 0 otherwise.
  5453  *
  5454  * W wants a mode line if it's a leaf window and neither a minibuffer
  5455  * nor a pseudo window.  Moreover, its 'window-mode-line-format'
  5456  * parameter must not be 'none' and either that parameter or W's
  5457  * buffer's 'mode-line-format' value must be non-nil.  Finally, W must
  5458  * be higher than its frame's canonical character height.
  5459  */
  5460 bool
  5461 window_wants_mode_line (struct window *w)
  5462 {
  5463   Lisp_Object window_mode_line_format =
  5464     window_parameter (w, Qmode_line_format);
  5465 
  5466   return (WINDOW_LEAF_P (w)
  5467           && !MINI_WINDOW_P (w)
  5468           && !WINDOW_PSEUDO_P (w)
  5469           && !EQ (window_mode_line_format, Qnone)
  5470           && (!NILP (window_mode_line_format)
  5471               || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), mode_line_format)))
  5472           && WINDOW_PIXEL_HEIGHT (w) > WINDOW_FRAME_LINE_HEIGHT (w));
  5473 }
  5474 
  5475 
  5476 /**
  5477  * window_wants_header_line:
  5478  *
  5479  * Return 1 if window W wants a header line and is high enough to
  5480  * accommodate it, 0 otherwise.
  5481  *
  5482  * W wants a header line if it's a leaf window and neither a
  5483  * minibuffer nor a pseudo window.  Moreover, its
  5484  * 'window-header-line-format' parameter must not be 'none' and either
  5485  * that parameter or W's buffer's 'header-line-format' value must be
  5486  * non-nil.  Finally, W must be higher than its frame's canonical
  5487  * character height and be able to accommodate a mode line too if
  5488  * necessary (the mode line prevails).
  5489  */
  5490 bool
  5491 window_wants_header_line (struct window *w)
  5492 {
  5493   Lisp_Object window_header_line_format =
  5494     window_parameter (w, Qheader_line_format);
  5495 
  5496   return (WINDOW_LEAF_P (w)
  5497           && !MINI_WINDOW_P (w)
  5498           && !WINDOW_PSEUDO_P (w)
  5499           && !EQ (window_header_line_format, Qnone)
  5500           && (!NILP (window_header_line_format)
  5501               || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
  5502           && (WINDOW_PIXEL_HEIGHT (w)
  5503               > (window_wants_mode_line (w)
  5504                  ? 2 * WINDOW_FRAME_LINE_HEIGHT (w)
  5505                  : WINDOW_FRAME_LINE_HEIGHT (w))));
  5506 }
  5507 
  5508 
  5509 /**
  5510  * window_wants_tab_line:
  5511  *
  5512  * Return 1 if window W wants a tab line and is high enough to
  5513  * accommodate it, 0 otherwise.
  5514  *
  5515  * W wants a tab line if it's a leaf window and neither a minibuffer
  5516  * nor a pseudo window.  Moreover, its 'window-tab-line-format'
  5517  * parameter must not be 'none' and either that parameter or W's
  5518  * buffer's 'tab-line-format' value must be non-nil.  Finally, W must
  5519  * be higher than its frame's canonical character height and be able
  5520  * to accommodate a mode line and a header line too if necessary (the
  5521  * mode line and a header line prevail).
  5522  */
  5523 
  5524 bool
  5525 window_wants_tab_line (struct window *w)
  5526 {
  5527   Lisp_Object window_tab_line_format =
  5528     window_parameter (w, Qtab_line_format);
  5529 
  5530   return (WINDOW_LEAF_P (w)
  5531           && !MINI_WINDOW_P (w)
  5532           && !WINDOW_PSEUDO_P (w)
  5533           && !EQ (window_tab_line_format, Qnone)
  5534           && (!NILP (window_tab_line_format)
  5535               || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), tab_line_format)))
  5536           && (WINDOW_PIXEL_HEIGHT (w)
  5537               > (((window_wants_mode_line (w) ? 1 : 0)
  5538                   + (window_wants_header_line (w) ? 1 : 0)
  5539                   + 1) * WINDOW_FRAME_LINE_HEIGHT (w))));
  5540 }
  5541 
  5542 /* Return number of lines of text in window W, not counting the mode
  5543    line and header line, if any.  Do NOT use this for windows on GUI
  5544    frames; use window_body_height instead.  This function is only for
  5545    windows on TTY frames, where it is much more efficient.  */
  5546 
  5547 int
  5548 window_internal_height (struct window *w)
  5549 {
  5550   int ht = w->total_lines;
  5551 
  5552   if (window_wants_mode_line (w))
  5553     --ht;
  5554 
  5555   if (window_wants_header_line (w))
  5556     --ht;
  5557 
  5558   if (window_wants_tab_line (w))
  5559     --ht;
  5560 
  5561   return ht;
  5562 }
  5563 
  5564 
  5565 /************************************************************************
  5566                            Window Scrolling
  5567  ***********************************************************************/
  5568 
  5569 /* Scroll contents of window WINDOW up.  If WHOLE, scroll
  5570    N screen-fulls, which is defined as the height of the window minus
  5571    next_screen_context_lines.  If WHOLE is zero, scroll up N lines
  5572    instead.  Negative values of N mean scroll down.  NOERROR
  5573    means don't signal an error if we try to move over BEGV or ZV,
  5574    respectively.  */
  5575 
  5576 static void
  5577 window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
  5578 {
  5579   struct window *w = XWINDOW (window);
  5580   struct buffer *b = XBUFFER (w->contents);
  5581   bool long_lines_truncated =
  5582     b->long_line_optimizations_p && !NILP (BVAR (b, truncate_lines));
  5583   specpdl_ref count = SPECPDL_INDEX ();
  5584 
  5585   n = clip_to_bounds (INT_MIN, n, INT_MAX);
  5586 
  5587   wset_redisplay (w);
  5588 
  5589   /* Does this window's buffer have very long and truncated lines?  */
  5590   if (b->long_line_optimizations_p
  5591       && !long_lines_truncated
  5592       && !NILP (Vtruncate_partial_width_windows)
  5593       && w->total_cols < FRAME_COLS (XFRAME (WINDOW_FRAME (w))))
  5594     {
  5595       if (FIXNUMP (Vtruncate_partial_width_windows))
  5596         long_lines_truncated =
  5597           w->total_cols < XFIXNAT (Vtruncate_partial_width_windows);
  5598       else
  5599         long_lines_truncated = true;
  5600     }
  5601 
  5602   if (whole && (fast_but_imprecise_scrolling || long_lines_truncated))
  5603     specbind (Qfontification_functions, Qnil);
  5604 
  5605   if (whole && long_lines_truncated)
  5606     window_scroll_for_long_lines (w, n, noerror);
  5607   else if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
  5608     {
  5609 
  5610       /* On GUI frames, use the pixel-based version which is much
  5611          slower than the line-based one, but can handle varying
  5612          line heights.  */
  5613       record_unwind_protect_void (unwind_display_working_on_window);
  5614       display_working_on_window_p = true;
  5615       window_scroll_pixel_based (window, n, whole, noerror);
  5616     }
  5617   else
  5618     window_scroll_line_based (window, n, whole, noerror);
  5619 
  5620   unbind_to (count, Qnil);
  5621 
  5622   /* Bug#15957.  */
  5623   XWINDOW (window)->window_end_valid = false;
  5624 }
  5625 
  5626 /* Compute scroll margin for WINDOW.
  5627    We scroll when point is within this distance from the top or bottom
  5628    of the window.  The result is measured in lines or in pixels
  5629    depending on the second parameter.  */
  5630 int
  5631 window_scroll_margin (struct window *window, enum margin_unit unit)
  5632 {
  5633   if (scroll_margin > 0)
  5634     {
  5635       int frame_line_height = default_line_pixel_height (window);
  5636       int window_lines = window_box_height (window) / frame_line_height;
  5637 
  5638       double ratio = 0.25;
  5639       if (FLOATP (Vmaximum_scroll_margin))
  5640         {
  5641           ratio = XFLOAT_DATA (Vmaximum_scroll_margin);
  5642           ratio = max (0.0, ratio);
  5643           ratio = min (ratio, 0.5);
  5644         }
  5645       int max_margin = min ((window_lines - 1)/2,
  5646                             (int) (window_lines * ratio));
  5647       int margin = clip_to_bounds (0, scroll_margin, max_margin);
  5648       return (unit == MARGIN_IN_PIXELS)
  5649         ? margin * frame_line_height
  5650         : margin;
  5651     }
  5652   else
  5653     return 0;
  5654 }
  5655 
  5656 static int
  5657 sanitize_next_screen_context_lines (void)
  5658 {
  5659   return clip_to_bounds (0, next_screen_context_lines, 1000000);
  5660 }
  5661 
  5662 /* Implementation of window_scroll for very long and truncated lines.
  5663    This is a simplified version, it only handles WHOLE window scrolls,
  5664    and doesn't honor scroll-preserve-screen-position nor scroll-margin.  */
  5665 static void
  5666 window_scroll_for_long_lines (struct window *w, int n, bool noerror)
  5667 {
  5668   ptrdiff_t startpos = marker_position (w->start);
  5669   ptrdiff_t startbyte = marker_byte_position (w->start);
  5670   int nscls = sanitize_next_screen_context_lines ();
  5671   register int ht = window_internal_height (w);
  5672 
  5673   n *= max (1, ht - nscls);
  5674 
  5675   /* If point is not visible in window, bring it inside window.  */
  5676   struct position pos;
  5677   int rtop, rbot, dummy_rowh, dummy_vpos, dummy_x, dummy_y;
  5678   if (!(PT >= startpos
  5679         && PT <= ZV
  5680         && startpos <= ZV
  5681         && pos_visible_p (w, PT, &dummy_x, &dummy_y, &rtop, &rbot, &dummy_rowh,
  5682                           &dummy_vpos)
  5683         && !rtop && !rbot))
  5684     {
  5685       pos = *vmotion (PT, PT_BYTE, - (ht / 2), w);
  5686       startpos = pos.bufpos;
  5687       startbyte = pos.bytepos;
  5688     }
  5689   SET_PT_BOTH (startpos, startbyte);
  5690 
  5691   bool lose = n < 0 && PT == BEGV;
  5692   pos = *vmotion (PT, PT_BYTE, n, w);
  5693   if (lose)
  5694     {
  5695       if (noerror)
  5696         return;
  5697       else
  5698         xsignal0 (Qbeginning_of_buffer);
  5699     }
  5700 
  5701   bool bolp = pos.bufpos == BEGV || FETCH_BYTE (pos.bytepos - 1) == '\n';
  5702   if (pos.bufpos < ZV)
  5703     {
  5704       set_marker_restricted_both (w->start, w->contents,
  5705                                   pos.bufpos, pos.bytepos);
  5706       w->start_at_line_beg = bolp;
  5707       wset_update_mode_line (w);
  5708       /* Set force_start so that redisplay_window will run
  5709          the window-scroll-functions.  */
  5710       w->force_start = true;
  5711       SET_PT_BOTH (pos.bufpos, pos.bytepos);
  5712       if (n > 0)
  5713         pos = *vmotion (PT, PT_BYTE, ht / 2, w);
  5714       else if (n < 0)
  5715         pos = *vmotion (PT, PT_BYTE, - (ht / 2), w);
  5716       SET_PT_BOTH (pos.bufpos, pos.bytepos);
  5717     }
  5718   else
  5719     {
  5720       if (noerror)
  5721         return;
  5722       else
  5723         xsignal0 (Qend_of_buffer);
  5724     }
  5725 }
  5726 
  5727 /* Implementation of window_scroll that works based on pixel line
  5728    heights.  See the comment of window_scroll for parameter
  5729    descriptions.  */
  5730 
  5731 static void
  5732 window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
  5733 {
  5734   struct it it;
  5735   struct window *w = XWINDOW (window);
  5736   struct text_pos start;
  5737   int this_scroll_margin;
  5738   /* True if we fiddled the window vscroll field without really scrolling.  */
  5739   bool vscrolled = false;
  5740   int x, y, rtop, rbot, rowh, vpos;
  5741   void *itdata = NULL;
  5742   int frame_line_height = default_line_pixel_height (w);
  5743   bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
  5744                                           Fwindow_old_point (window)));
  5745 
  5746   SET_TEXT_POS_FROM_MARKER (start, w->start);
  5747   /* Scrolling a minibuffer window via scroll bar when the echo area
  5748      shows long text sometimes resets the minibuffer contents behind
  5749      our backs.  Also, someone might narrow-to-region and immediately
  5750      call a scroll function.  */
  5751   if (CHARPOS (start) > ZV || CHARPOS (start) < BEGV)
  5752     SET_TEXT_POS (start, BEGV, BEGV_BYTE);
  5753 
  5754   /* If PT is not visible in WINDOW, move back one half of
  5755      the screen.  Allow PT to be partially visible, otherwise
  5756      something like (scroll-down 1) with PT in the line before
  5757      the partially visible one would recenter.  */
  5758 
  5759   if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
  5760     {
  5761       itdata = bidi_shelve_cache ();
  5762       /* Move backward half the height of the window.  Performance note:
  5763          vmotion used here is about 10% faster, but would give wrong
  5764          results for variable height lines.  */
  5765       init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
  5766       it.current_y = it.last_visible_y;
  5767       move_it_vertically_backward (&it, window_box_height (w) / 2);
  5768 
  5769       /* The function move_iterator_vertically may move over more than
  5770          the specified y-distance.  If it->w is small, e.g. a
  5771          mini-buffer window, we may end up in front of the window's
  5772          display area.  Start displaying at the start of the line
  5773          containing PT in this case.  */
  5774       if (it.current_y <= 0)
  5775         {
  5776           init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
  5777           move_it_vertically_backward (&it, 0);
  5778           it.current_y = 0;
  5779         }
  5780 
  5781       start = it.current.pos;
  5782       bidi_unshelve_cache (itdata, false);
  5783     }
  5784   else if (auto_window_vscroll_p)
  5785     {
  5786       if (rtop || rbot)         /* Partially visible.  */
  5787         {
  5788           int px;
  5789           int dy = frame_line_height;
  5790           /* In the below we divide the window box height by the
  5791              frame's line height to make the result predictable when
  5792              the window box is not an integral multiple of the line
  5793              height.  This is important to ensure we get back to the
  5794              same position when scrolling up, then down.  */
  5795           if (whole)
  5796             {
  5797               int ht = window_box_height (w);
  5798               int nscls = sanitize_next_screen_context_lines ();
  5799               dy = max (dy, (ht / dy - nscls) * dy);
  5800             }
  5801           dy *= n;
  5802 
  5803           if (n < 0)
  5804             {
  5805               /* Only vscroll backwards if already vscrolled forwards.  */
  5806               if (w->vscroll < 0 && rtop > 0)
  5807                 {
  5808                   px = max (0, -w->vscroll - min (rtop, -dy));
  5809                   Fset_window_vscroll (window, make_fixnum (px), Qt,
  5810                                        Qnil);
  5811                   return;
  5812                 }
  5813             }
  5814           if (n > 0)
  5815             {
  5816               /* Do vscroll if already vscrolled or only display line.  */
  5817               if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
  5818                 {
  5819                   px = max (0, -w->vscroll + min (rbot, dy));
  5820                   Fset_window_vscroll (window, make_fixnum (px), Qt,
  5821                                        Qnil);
  5822                   return;
  5823                 }
  5824 
  5825               /* Maybe modify window start instead of scrolling.  */
  5826               if (rbot > 0 || w->vscroll < 0)
  5827                 {
  5828                   ptrdiff_t spos;
  5829 
  5830                   Fset_window_vscroll (window, make_fixnum (0), Qt,
  5831                                        Qnil);
  5832                   /* If there are other text lines above the current row,
  5833                      move window start to current row.  Else to next row. */
  5834                   if (rbot > 0)
  5835                     spos = XFIXNUM (Fline_beginning_position (Qnil));
  5836                   else
  5837                     spos = min (XFIXNUM (Fline_end_position (Qnil)) + 1, ZV);
  5838                   set_marker_restricted (w->start, make_fixnum (spos),
  5839                                          w->contents);
  5840                   w->start_at_line_beg = true;
  5841                   wset_update_mode_line (w);
  5842                   /* Set force_start so that redisplay_window will run the
  5843                      window-scroll-functions.  */
  5844                   w->force_start = true;
  5845                   return;
  5846                 }
  5847             }
  5848         }
  5849       /* Cancel previous vscroll.  */
  5850       Fset_window_vscroll (window, make_fixnum (0), Qt, Qnil);
  5851     }
  5852 
  5853   itdata = bidi_shelve_cache ();
  5854   /* If scroll_preserve_screen_position is non-nil, we try to set
  5855      point in the same window line as it is now, so get that line.  */
  5856   if (!NILP (Vscroll_preserve_screen_position))
  5857     {
  5858       /* We preserve the goal pixel coordinate across consecutive
  5859          calls to scroll-up, scroll-down and other commands that
  5860          have the `scroll-command' property.  This avoids the
  5861          possibility of point becoming "stuck" on a tall line when
  5862          scrolling by one line.  */
  5863       if (window_scroll_pixel_based_preserve_y < 0
  5864           || !SYMBOLP (KVAR (current_kboard, Vlast_command))
  5865           || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
  5866         {
  5867           start_display (&it, w, start);
  5868           move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
  5869           window_scroll_pixel_based_preserve_y = it.current_y;
  5870           window_scroll_pixel_based_preserve_x = it.current_x;
  5871         }
  5872     }
  5873   else
  5874     window_scroll_pixel_based_preserve_y
  5875       = window_scroll_pixel_based_preserve_x = -1;
  5876 
  5877   /* Move iterator it from start the specified distance forward or
  5878      backward.  The result is the new window start.  */
  5879   start_display (&it, w, start);
  5880   if (whole)
  5881     {
  5882       ptrdiff_t start_pos = IT_CHARPOS (it);
  5883       int flh = frame_line_height;
  5884       int ht = window_box_height (w);
  5885       int nscls = sanitize_next_screen_context_lines ();
  5886       /* In the below we divide the window box height by the frame's
  5887          line height to make the result predictable when the window
  5888          box is not an integral multiple of the line height.  This is
  5889          important to ensure we get back to the same position when
  5890          scrolling up, then down.  */
  5891       int dy = n * max (flh, (ht / flh - nscls) * flh);
  5892       int goal_y;
  5893       void *it_data;
  5894 
  5895       /* Note that move_it_vertically always moves the iterator to the
  5896          start of a line.  So, if the last line doesn't have a newline,
  5897          we would end up at the start of the line ending at ZV.  */
  5898       if (dy <= 0)
  5899         {
  5900           goal_y = it.current_y + dy;
  5901           move_it_vertically_backward (&it, -dy);
  5902           /* move_it_vertically_backward above always overshoots if DY
  5903              cannot be reached exactly, i.e. if it falls in the middle
  5904              of a screen line.  But if that screen line is large
  5905              (e.g., a tall image), it might make more sense to
  5906              undershoot instead.  */
  5907           if (goal_y - it.current_y > 0.5 * flh)
  5908             {
  5909               it_data = bidi_shelve_cache ();
  5910               struct it it1 = it;
  5911               if (line_bottom_y (&it1) - goal_y < goal_y - it.current_y)
  5912                 move_it_by_lines (&it, 1);
  5913               bidi_unshelve_cache (it_data, true);
  5914             }
  5915           /* Ensure we actually do move, e.g. in case we are currently
  5916              looking at an image that is taller that the window height.  */
  5917           while (start_pos == IT_CHARPOS (it)
  5918                  && start_pos > BEGV)
  5919             move_it_by_lines (&it, -1);
  5920         }
  5921       else if (dy > 0)
  5922         {
  5923           goal_y = it.current_y + dy;
  5924           move_it_to (&it, ZV, -1, goal_y, -1, MOVE_TO_POS | MOVE_TO_Y);
  5925           /* Extra precision for people who want us to preserve the
  5926              screen position of the cursor: effectively round DY to the
  5927              nearest screen line, instead of rounding to zero; the latter
  5928              causes point to move by one line after C-v followed by M-v,
  5929              if the buffer has lines of different height.  */
  5930           if (!NILP (Vscroll_preserve_screen_position)
  5931               && goal_y - it.current_y  > 0.5 * flh)
  5932             {
  5933               it_data = bidi_shelve_cache ();
  5934               struct it it2 = it;
  5935 
  5936               move_it_by_lines (&it, 1);
  5937               if (it.current_y > goal_y + 0.5 * flh)
  5938                 {
  5939                   it = it2;
  5940                   bidi_unshelve_cache (it_data, false);
  5941                 }
  5942               else
  5943                 bidi_unshelve_cache (it_data, true);
  5944             }
  5945           /* Ensure we actually do move, e.g. in case we are currently
  5946              looking at an image that is taller that the window height.  */
  5947           while (start_pos == IT_CHARPOS (it)
  5948                  && start_pos < ZV)
  5949             move_it_by_lines (&it, 1);
  5950         }
  5951     }
  5952   else
  5953     move_it_by_lines (&it, n);
  5954 
  5955   /* We failed if we find ZV is already on the screen (scrolling up,
  5956      means there's nothing past the end), or if we can't start any
  5957      earlier (scrolling down, means there's nothing past the top).  */
  5958   if ((n > 0 && IT_CHARPOS (it) == ZV)
  5959       || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
  5960     {
  5961       if (IT_CHARPOS (it) == ZV)
  5962         {
  5963           if (it.current_y < it.last_visible_y
  5964               && (it.current_y + it.max_ascent + it.max_descent
  5965                   > it.last_visible_y))
  5966             {
  5967               /* The last line was only partially visible, make it fully
  5968                  visible.  */
  5969               w->vscroll = (it.last_visible_y
  5970                             - it.current_y + it.max_ascent + it.max_descent);
  5971               adjust_frame_glyphs (it.f);
  5972             }
  5973           else
  5974             {
  5975               bidi_unshelve_cache (itdata, false);
  5976               if (noerror)
  5977                 return;
  5978               else if (n < 0)   /* could happen with empty buffers */
  5979                 xsignal0 (Qbeginning_of_buffer);
  5980               else
  5981                 xsignal0 (Qend_of_buffer);
  5982             }
  5983         }
  5984       else
  5985         {
  5986           if (w->vscroll != 0)
  5987             /* The first line was only partially visible, make it fully
  5988                visible. */
  5989             w->vscroll = 0;
  5990           else
  5991             {
  5992               bidi_unshelve_cache (itdata, false);
  5993               if (noerror)
  5994                 return;
  5995               else
  5996                 xsignal0 (Qbeginning_of_buffer);
  5997             }
  5998         }
  5999 
  6000       /* If control gets here, then we vscrolled.  */
  6001 
  6002       XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
  6003 
  6004       /* Don't try to change the window start below.  */
  6005       vscrolled = true;
  6006     }
  6007 
  6008   if (! vscrolled)
  6009     {
  6010       ptrdiff_t pos = IT_CHARPOS (it);
  6011       ptrdiff_t bytepos;
  6012 
  6013       /* If in the middle of a multi-glyph character move forward to
  6014          the next character.  */
  6015       if (in_display_vector_p (&it))
  6016         {
  6017           ++pos;
  6018           move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
  6019         }
  6020 
  6021       /* Set the window start, and set up the window for redisplay.  */
  6022       set_marker_restricted_both (w->start, w->contents, IT_CHARPOS (it),
  6023                                   IT_BYTEPOS (it));
  6024       bytepos = marker_byte_position (w->start);
  6025       w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
  6026       wset_update_mode_line (w);
  6027       /* Set force_start so that redisplay_window will run the
  6028          window-scroll-functions.  */
  6029       w->force_start = true;
  6030     }
  6031 
  6032   /* The rest of this function uses current_y in a nonstandard way,
  6033      not including the height of the header line if any.  */
  6034   it.current_y = it.vpos = 0;
  6035 
  6036   /* Move PT out of scroll margins.
  6037      This code wants current_y to be zero at the window start position
  6038      even if there is a header line.  */
  6039   this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
  6040 
  6041   if (n > 0)
  6042     {
  6043       int last_y = it.last_visible_y - this_scroll_margin - 1;
  6044 
  6045       /* We moved the window start towards ZV, so PT may be now
  6046          in the scroll margin at the top.  */
  6047       if (IT_CHARPOS (it) < PT)
  6048         move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
  6049       if (IT_CHARPOS (it) == PT
  6050           && it.current_y >= this_scroll_margin
  6051           && it.current_y <= last_y - WINDOW_TAB_LINE_HEIGHT (w)
  6052                                     - WINDOW_HEADER_LINE_HEIGHT (w)
  6053           && (NILP (Vscroll_preserve_screen_position)
  6054               || EQ (Vscroll_preserve_screen_position, Qt)))
  6055         /* We found PT at a legitimate height.  Leave it alone.  */
  6056         ;
  6057       else
  6058         {
  6059           if (window_scroll_pixel_based_preserve_y >= 0)
  6060             {
  6061               /* Don't enter the scroll margin at the end of the window.  */
  6062               int goal_y = min (last_y, window_scroll_pixel_based_preserve_y);
  6063 
  6064               /* If we have a header line, take account of it.  This
  6065                  is necessary because we set it.current_y to 0, above.  */
  6066               move_it_to (&it, -1,
  6067                           window_scroll_pixel_based_preserve_x,
  6068                           goal_y - WINDOW_TAB_LINE_HEIGHT (w)
  6069                                  - WINDOW_HEADER_LINE_HEIGHT (w),
  6070                           -1, MOVE_TO_Y | MOVE_TO_X);
  6071             }
  6072 
  6073           /* Get out of the scroll margin at the top of the window.  */
  6074           while (it.current_y < this_scroll_margin)
  6075             {
  6076               int prev = it.current_y;
  6077               move_it_by_lines (&it, 1);
  6078               if (prev == it.current_y)
  6079                 break;
  6080             }
  6081           SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
  6082           /* Fix up the Y position to preserve, if it is inside the
  6083              scroll margin at the window top.  */
  6084           if (window_scroll_pixel_based_preserve_y >= 0
  6085               && window_scroll_pixel_based_preserve_y < this_scroll_margin)
  6086             window_scroll_pixel_based_preserve_y = this_scroll_margin;
  6087         }
  6088     }
  6089   else if (n < 0)
  6090     {
  6091       ptrdiff_t charpos, bytepos;
  6092       bool partial_p;
  6093 
  6094       /* Save our position, for the
  6095          window_scroll_pixel_based_preserve_y case.  */
  6096       charpos = IT_CHARPOS (it);
  6097       bytepos = IT_BYTEPOS (it);
  6098 
  6099       /* We moved the window start towards BEGV, so PT may be now
  6100          in the scroll margin at the bottom.  */
  6101       move_it_to (&it, PT, -1,
  6102                   /* We subtract WINDOW_HEADER_LINE_HEIGHT because
  6103                      it.y is relative to the bottom of the header
  6104                      line, see above.  */
  6105                   (it.last_visible_y - WINDOW_TAB_LINE_HEIGHT (w)
  6106                                      - WINDOW_HEADER_LINE_HEIGHT (w)
  6107                    - partial_line_height (&it) - this_scroll_margin - 1),
  6108                   -1,
  6109                   MOVE_TO_POS | MOVE_TO_Y);
  6110 
  6111       /* Save our position, in case it's correct.  */
  6112       charpos = IT_CHARPOS (it);
  6113       bytepos = IT_BYTEPOS (it);
  6114 
  6115       /* If PT is in the screen line at the last fully visible line,
  6116          move_it_to will stop at X = 0 in that line, because the
  6117          required Y coordinate is reached there.  See if we can get to
  6118          PT without descending lower in Y, and if we can, it means we
  6119          reached PT before the scroll margin.  */
  6120       if (charpos != PT)
  6121         {
  6122           struct it it2;
  6123           void *it_data;
  6124 
  6125           it2 = it;
  6126           it_data = bidi_shelve_cache ();
  6127           move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
  6128           if (IT_CHARPOS (it) == PT && it.current_y == it2.current_y)
  6129             {
  6130               charpos = IT_CHARPOS (it);
  6131               bytepos = IT_BYTEPOS (it);
  6132               bidi_unshelve_cache (it_data, true);
  6133             }
  6134           else
  6135             {
  6136               it = it2;
  6137               bidi_unshelve_cache (it_data, false);
  6138             }
  6139         }
  6140 
  6141       /* See if point is on a partially visible line at the end.  */
  6142       if (it.what == IT_EOB)
  6143         partial_p =
  6144           it.current_y + it.ascent + it.descent
  6145           > it.last_visible_y - this_scroll_margin
  6146           - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w);
  6147       else
  6148         {
  6149           move_it_by_lines (&it, 1);
  6150           partial_p =
  6151             it.current_y
  6152             > it.last_visible_y - this_scroll_margin
  6153               - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w);
  6154         }
  6155 
  6156       if (charpos == PT && !partial_p
  6157           && (NILP (Vscroll_preserve_screen_position)
  6158               || EQ (Vscroll_preserve_screen_position, Qt)))
  6159         /* We found PT before we found the display margin, so PT is ok.  */
  6160         ;
  6161       else if (window_scroll_pixel_based_preserve_y >= 0)
  6162         {
  6163           int goal_y = min (it.last_visible_y - this_scroll_margin - 1,
  6164                             window_scroll_pixel_based_preserve_y);
  6165 
  6166           /* Don't let the preserved screen Y coordinate put us inside
  6167              any of the two margins.  */
  6168           if (goal_y < this_scroll_margin)
  6169             goal_y = this_scroll_margin;
  6170           SET_TEXT_POS_FROM_MARKER (start, w->start);
  6171           start_display (&it, w, start);
  6172           /* It would be wrong to subtract WINDOW_HEADER_LINE_HEIGHT
  6173              here because we called start_display again and did not
  6174              alter it.current_y this time.  */
  6175           move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
  6176                       goal_y, -1, MOVE_TO_Y | MOVE_TO_X);
  6177           SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
  6178         }
  6179       else
  6180         {
  6181           if (partial_p)
  6182             /* The last line was only partially visible, so back up two
  6183                lines to make sure we're on a fully visible line.  */
  6184             {
  6185               move_it_by_lines (&it, -2);
  6186               SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
  6187             }
  6188           else
  6189             /* No, the position we saved is OK, so use it.  */
  6190             SET_PT_BOTH (charpos, bytepos);
  6191         }
  6192     }
  6193   bidi_unshelve_cache (itdata, false);
  6194 
  6195   if (adjust_old_pointm)
  6196     Fset_marker (w->old_pointm,
  6197                  ((w == XWINDOW (selected_window))
  6198                   ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
  6199                   : Fmarker_position (w->pointm)),
  6200                  w->contents);
  6201 }
  6202 
  6203 
  6204 /* Implementation of window_scroll that works based on screen lines.
  6205    See the comment of window_scroll for parameter descriptions.  */
  6206 
  6207 static void
  6208 window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
  6209 {
  6210   struct window *w = XWINDOW (window);
  6211   /* Fvertical_motion enters redisplay, which can trigger
  6212      fontification, which in turn can modify buffer text (e.g., if the
  6213      fontification functions replace escape sequences with faces, as
  6214      in `grep-mode-font-lock-keywords').  So we use a marker to record
  6215      the old point position, to prevent crashes in SET_PT_BOTH.  */
  6216   Lisp_Object opoint_marker = Fpoint_marker ();
  6217   register ptrdiff_t pos, pos_byte;
  6218   register int ht = window_internal_height (w);
  6219   register Lisp_Object tem;
  6220   bool lose;
  6221   Lisp_Object bolp;
  6222   ptrdiff_t startpos = marker_position (w->start);
  6223   ptrdiff_t startbyte = marker_byte_position (w->start);
  6224   Lisp_Object original_pos = Qnil;
  6225   bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
  6226                                           Fwindow_old_point (window)));
  6227 
  6228   /* If scrolling screen-fulls, compute the number of lines to
  6229      scroll from the window's height.  */
  6230   if (whole)
  6231     {
  6232       int nscls = sanitize_next_screen_context_lines ();
  6233       n *= max (1, ht - nscls);
  6234     }
  6235 
  6236   if (!NILP (Vscroll_preserve_screen_position))
  6237     {
  6238       if (window_scroll_preserve_vpos <= 0
  6239           || !SYMBOLP (KVAR (current_kboard, Vlast_command))
  6240           || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
  6241         {
  6242           struct position posit
  6243             = *compute_motion (startpos, startbyte, 0, 0, false,
  6244                                PT, ht, 0, -1, w->hscroll, 0, w);
  6245 
  6246           window_scroll_preserve_vpos = posit.vpos;
  6247           window_scroll_preserve_hpos = posit.hpos + w->hscroll;
  6248         }
  6249 
  6250       original_pos = Fcons (make_fixnum (window_scroll_preserve_hpos),
  6251                             make_fixnum (window_scroll_preserve_vpos));
  6252     }
  6253 
  6254   XSETFASTINT (tem, PT);
  6255   tem = Fpos_visible_in_window_p (tem, window, Qnil);
  6256 
  6257   if (NILP (tem))
  6258     {
  6259       Fvertical_motion (make_fixnum (- (ht / 2)), window, Qnil);
  6260       startpos = PT;
  6261       startbyte = PT_BYTE;
  6262     }
  6263 
  6264   SET_PT_BOTH (startpos, startbyte);
  6265   lose = n < 0 && PT == BEGV;
  6266   Fvertical_motion (make_fixnum (n), window, Qnil);
  6267   pos = PT;
  6268   pos_byte = PT_BYTE;
  6269   bolp = Fbolp ();
  6270   SET_PT_BOTH (marker_position (opoint_marker),
  6271                marker_byte_position (opoint_marker));
  6272 
  6273   if (lose)
  6274     {
  6275       if (noerror)
  6276         return;
  6277       else
  6278         xsignal0 (Qbeginning_of_buffer);
  6279     }
  6280 
  6281   if (pos < ZV)
  6282     {
  6283       int this_scroll_margin = window_scroll_margin (w, MARGIN_IN_LINES);
  6284 
  6285       set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
  6286       w->start_at_line_beg = !NILP (bolp);
  6287       wset_update_mode_line (w);
  6288       /* Set force_start so that redisplay_window will run
  6289          the window-scroll-functions.  */
  6290       w->force_start = true;
  6291 
  6292       if (!NILP (Vscroll_preserve_screen_position)
  6293           && this_scroll_margin == 0
  6294           && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
  6295         {
  6296           SET_PT_BOTH (pos, pos_byte);
  6297           Fvertical_motion (original_pos, window, Qnil);
  6298         }
  6299       /* If we scrolled forward, put point enough lines down
  6300          that it is outside the scroll margin.  */
  6301       else if (n > 0)
  6302         {
  6303           int top_margin;
  6304 
  6305           if (this_scroll_margin > 0)
  6306             {
  6307               SET_PT_BOTH (pos, pos_byte);
  6308               Fvertical_motion (make_fixnum (this_scroll_margin), window, Qnil);
  6309               top_margin = PT;
  6310             }
  6311           else
  6312             top_margin = pos;
  6313 
  6314           if (top_margin <= marker_position (opoint_marker))
  6315             SET_PT_BOTH (marker_position (opoint_marker),
  6316                          marker_byte_position (opoint_marker));
  6317           else if (!NILP (Vscroll_preserve_screen_position))
  6318             {
  6319               int nlines = window_scroll_preserve_vpos;
  6320 
  6321               SET_PT_BOTH (pos, pos_byte);
  6322               if (window_scroll_preserve_vpos < this_scroll_margin)
  6323                 nlines = this_scroll_margin;
  6324               else if (window_scroll_preserve_vpos
  6325                        >= w->total_lines - this_scroll_margin)
  6326                 nlines = w->total_lines - this_scroll_margin - 1;
  6327               Fvertical_motion (Fcons (make_fixnum (window_scroll_preserve_hpos),
  6328                                        make_fixnum (nlines)), window, Qnil);
  6329             }
  6330           else
  6331             SET_PT (top_margin);
  6332         }
  6333       else if (n < 0)
  6334         {
  6335           int bottom_margin;
  6336 
  6337           /* If we scrolled backward, put point near the end of the window
  6338              but not within the scroll margin.  */
  6339           SET_PT_BOTH (pos, pos_byte);
  6340           tem = Fvertical_motion (make_fixnum (ht - this_scroll_margin), window,
  6341                                   Qnil);
  6342           if (XFIXNAT (tem) == ht - this_scroll_margin)
  6343             bottom_margin = PT;
  6344           else
  6345             bottom_margin = PT + 1;
  6346 
  6347           if (bottom_margin > marker_position (opoint_marker))
  6348             SET_PT_BOTH (marker_position (opoint_marker),
  6349                          marker_byte_position (opoint_marker));
  6350           else
  6351             {
  6352               if (!NILP (Vscroll_preserve_screen_position))
  6353                 {
  6354                   int nlines = window_scroll_preserve_vpos;
  6355 
  6356                   SET_PT_BOTH (pos, pos_byte);
  6357                   if (window_scroll_preserve_vpos < this_scroll_margin)
  6358                     nlines = this_scroll_margin;
  6359                   else if (window_scroll_preserve_vpos
  6360                            >= ht - this_scroll_margin)
  6361                     nlines = ht - this_scroll_margin - 1;
  6362                   Fvertical_motion (Fcons (make_fixnum (window_scroll_preserve_hpos),
  6363                                            make_fixnum (nlines)), window, Qnil);
  6364                 }
  6365               else
  6366                 Fvertical_motion (make_fixnum (-1), window, Qnil);
  6367             }
  6368         }
  6369     }
  6370   else
  6371     {
  6372       if (noerror)
  6373         return;
  6374       else
  6375         xsignal0 (Qend_of_buffer);
  6376     }
  6377 
  6378   if (adjust_old_pointm)
  6379     Fset_marker (w->old_pointm,
  6380                  ((w == XWINDOW (selected_window))
  6381                   ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
  6382                   : Fmarker_position (w->pointm)),
  6383                  w->contents);
  6384 }
  6385 
  6386 
  6387 /* Scroll WINDOW up or down.  If N is nil, scroll upward by a
  6388    screen-full which is defined as the height of the window minus
  6389    next_screen_context_lines.  If N is the symbol `-', scroll downward
  6390    by a screen-full.  DIRECTION may be 1 meaning to scroll down, or -1
  6391    meaning to scroll up.  */
  6392 
  6393 static void
  6394 scroll_command (Lisp_Object window, Lisp_Object n, int direction)
  6395 {
  6396   struct window *w;
  6397   bool other_window;
  6398   specpdl_ref count = SPECPDL_INDEX ();
  6399 
  6400   eassert (eabs (direction) == 1);
  6401 
  6402   w = XWINDOW (window);
  6403   other_window = ! EQ (window, selected_window);
  6404 
  6405   /* If given window's buffer isn't current, make it current for the
  6406      moment.  If the window's buffer is the same, but it is not the
  6407      selected window, we need to save-excursion to avoid affecting
  6408      point in the selected window (which would cause the selected
  6409      window to scroll).  Don't screw up if window_scroll gets an
  6410      error.  */
  6411   if (other_window || XBUFFER (w->contents) != current_buffer)
  6412     {
  6413       record_unwind_protect_excursion ();
  6414       if (XBUFFER (w->contents) != current_buffer)
  6415         Fset_buffer (w->contents);
  6416     }
  6417 
  6418   if (other_window)
  6419     {
  6420       SET_PT_BOTH (marker_position (w->pointm),
  6421                    marker_byte_position (w->pointm));
  6422       SET_PT_BOTH (marker_position (w->old_pointm),
  6423                    marker_byte_position (w->old_pointm));
  6424     }
  6425 
  6426   if (NILP (n))
  6427     window_scroll (window, direction, true, false);
  6428   else if (EQ (n, Qminus))
  6429     window_scroll (window, -direction, true, false);
  6430   else
  6431     {
  6432       n = Fprefix_numeric_value (n);
  6433       window_scroll (window, XFIXNUM (n) * direction, false, false);
  6434     }
  6435 
  6436   if (other_window)
  6437     {
  6438       set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
  6439       set_marker_both (w->old_pointm, Qnil, PT, PT_BYTE);
  6440     }
  6441 
  6442   unbind_to (count, Qnil);
  6443 }
  6444 
  6445 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
  6446        doc: /* Scroll text of selected window upward ARG lines.
  6447 If ARG is omitted or nil, scroll upward by a near full screen.
  6448 A near full screen is `next-screen-context-lines' less than a full screen.
  6449 Negative ARG means scroll downward.
  6450 If ARG is the atom `-', scroll downward by nearly full screen.
  6451 When calling from a program, supply as argument a number, nil, or `-'.  */)
  6452   (Lisp_Object arg)
  6453 {
  6454   scroll_command (selected_window, arg, 1);
  6455   return Qnil;
  6456 }
  6457 
  6458 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
  6459        doc: /* Scroll text of selected window down ARG lines.
  6460 If ARG is omitted or nil, scroll down by a near full screen.
  6461 A near full screen is `next-screen-context-lines' less than a full screen.
  6462 Negative ARG means scroll upward.
  6463 If ARG is the atom `-', scroll upward by nearly full screen.
  6464 When calling from a program, supply as argument a number, nil, or `-'.  */)
  6465   (Lisp_Object arg)
  6466 {
  6467   scroll_command (selected_window, arg, -1);
  6468   return Qnil;
  6469 }
  6470 
  6471 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
  6472        doc: /* Return the other window for \"other window scroll\" commands.
  6473 If in the minibuffer, `minibuffer-scroll-window' if non-nil
  6474 specifies the window.
  6475 Otherwise, if `other-window-scroll-buffer' is non-nil, a window
  6476 showing that buffer is used, popping the buffer up if necessary.
  6477 Finally, look for a neighboring window on the selected frame,
  6478 followed by all visible frames on the current terminal.  */)
  6479   (void)
  6480 {
  6481   Lisp_Object window;
  6482 
  6483   if (MINI_WINDOW_P (XWINDOW (selected_window))
  6484       && !NILP (Vminibuf_scroll_window))
  6485     window = Vminibuf_scroll_window;
  6486   /* If buffer is specified and live, scroll that buffer.  */
  6487   else if (BUFFERP (Vother_window_scroll_buffer)
  6488            && BUFFER_LIVE_P (XBUFFER (Vother_window_scroll_buffer)))
  6489     {
  6490       window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
  6491       if (NILP (window))
  6492         window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
  6493     }
  6494   else if (FUNCTIONP (Vother_window_scroll_default))
  6495     /* Nothing specified; try to get a window from the function.  */
  6496     window = call0 (Vother_window_scroll_default);
  6497   else
  6498     {
  6499       /* Otherwise, look for a neighboring window on the same frame.  */
  6500       window = Fnext_window (selected_window, Qlambda, Qnil);
  6501 
  6502       if (EQ (window, selected_window))
  6503         /* That didn't get us anywhere; look for a window on another
  6504            visible frame on the current terminal.  */
  6505         window = Fnext_window (window, Qlambda, Qvisible);
  6506     }
  6507 
  6508   CHECK_LIVE_WINDOW (window);
  6509 
  6510   if (EQ (window, selected_window))
  6511     error ("There is no other window");
  6512 
  6513   return window;
  6514 }
  6515 
  6516 
  6517 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
  6518        doc: /* Scroll selected window display ARG columns left.
  6519 Default for ARG is window width minus 2.
  6520 Value is the total amount of leftward horizontal scrolling in
  6521 effect after the change.
  6522 If SET-MINIMUM is non-nil, the new scroll amount becomes the
  6523 lower bound for automatic scrolling, i.e. automatic scrolling
  6524 will not scroll a window to a column less than the value returned
  6525 by this function.  This happens in an interactive call.  */)
  6526   (register Lisp_Object arg, Lisp_Object set_minimum)
  6527 {
  6528   struct window *w = XWINDOW (selected_window);
  6529   EMACS_INT requested_arg =
  6530     (NILP (arg)
  6531      ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2
  6532      : XFIXNUM (Fprefix_numeric_value (arg)));
  6533   Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
  6534 
  6535   if (!NILP (set_minimum))
  6536     w->min_hscroll = w->hscroll;
  6537 
  6538   w->suspend_auto_hscroll = true;
  6539 
  6540   return result;
  6541 }
  6542 
  6543 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
  6544        doc: /* Scroll selected window display ARG columns right.
  6545 Default for ARG is window width minus 2.
  6546 Value is the total amount of leftward horizontal scrolling in
  6547 effect after the change.
  6548 If SET-MINIMUM is non-nil, the new scroll amount becomes the
  6549 lower bound for automatic scrolling, i.e. automatic scrolling
  6550 will not scroll a window to a column less than the value returned
  6551 by this function.  This happens in an interactive call.  */)
  6552   (register Lisp_Object arg, Lisp_Object set_minimum)
  6553 {
  6554   struct window *w = XWINDOW (selected_window);
  6555   EMACS_INT requested_arg =
  6556     (NILP (arg)
  6557      ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2
  6558      : XFIXNUM (Fprefix_numeric_value (arg)));
  6559   Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
  6560 
  6561   if (!NILP (set_minimum))
  6562     w->min_hscroll = w->hscroll;
  6563 
  6564   w->suspend_auto_hscroll = true;
  6565 
  6566   return result;
  6567 }
  6568 
  6569 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
  6570        doc: /* Return window selected just before minibuffer window was selected.
  6571 Return nil if the selected window is not a minibuffer window.  */)
  6572   (void)
  6573 {
  6574   if (minibuf_level > 0
  6575       && MINI_WINDOW_P (XWINDOW (selected_window))
  6576       && WINDOW_LIVE_P (minibuf_selected_window))
  6577     return minibuf_selected_window;
  6578 
  6579   return Qnil;
  6580 }
  6581 
  6582 /* Value is the number of lines actually displayed in window W,
  6583    as opposed to its height.  */
  6584 
  6585 static int
  6586 displayed_window_lines (struct window *w)
  6587 {
  6588   struct it it;
  6589   struct text_pos start;
  6590   int height = window_box_height (w);
  6591   struct buffer *old_buffer;
  6592   int bottom_y;
  6593   void *itdata = NULL;
  6594 
  6595   if (XBUFFER (w->contents) != current_buffer)
  6596     {
  6597       old_buffer = current_buffer;
  6598       set_buffer_internal (XBUFFER (w->contents));
  6599     }
  6600   else
  6601     old_buffer = NULL;
  6602 
  6603   /* In case W->start is out of the accessible range, do something
  6604      reasonable.  This happens in Info mode when Info-scroll-down
  6605      calls (recenter -1) while W->start is 1.  */
  6606   CLIP_TEXT_POS_FROM_MARKER (start, w->start);
  6607 
  6608   itdata = bidi_shelve_cache ();
  6609 
  6610   specpdl_ref count = SPECPDL_INDEX ();
  6611   record_unwind_protect_void (unwind_display_working_on_window);
  6612   display_working_on_window_p = true;
  6613   start_display (&it, w, start);
  6614   move_it_vertically (&it, height);
  6615   bottom_y = line_bottom_y (&it);
  6616   unbind_to (count, Qnil);
  6617   bidi_unshelve_cache (itdata, false);
  6618 
  6619   /* Add in empty lines at the bottom of the window.  */
  6620   if (bottom_y < height)
  6621     {
  6622       int uy = FRAME_LINE_HEIGHT (it.f);
  6623       it.vpos += (height - bottom_y + uy - 1) / uy;
  6624     }
  6625   else if (bottom_y == height)
  6626     it.vpos++;
  6627 
  6628   if (old_buffer)
  6629     set_buffer_internal (old_buffer);
  6630 
  6631   return it.vpos;
  6632 }
  6633 
  6634 
  6635 DEFUN ("recenter", Frecenter, Srecenter, 0, 2, "P\np",
  6636        doc: /* Center point in selected window and maybe redisplay frame.
  6637 With a numeric prefix argument ARG, recenter putting point on screen line ARG
  6638 relative to the selected window.  If ARG is negative, it counts up from the
  6639 bottom of the window.  (ARG should be less than the height of the window.)
  6640 
  6641 If ARG is omitted or nil, then recenter with point on the middle line
  6642 of the selected window; if REDISPLAY & `recenter-redisplay' are
  6643 non-nil, also erase the entire frame and redraw it (when
  6644 `auto-resize-tool-bars' is set to `grow-only', this resets the
  6645 tool-bar's height to the minimum height needed); if
  6646 `recenter-redisplay' has the special value `tty', then only tty frames
  6647 are redrawn.  Interactively, REDISPLAY is always non-nil.
  6648 
  6649 Just C-u as prefix means put point in the center of the window
  6650 and redisplay normally--don't erase and redraw the frame.  */)
  6651   (Lisp_Object arg, Lisp_Object redisplay)
  6652 {
  6653   struct window *w = XWINDOW (selected_window);
  6654   struct buffer *buf = XBUFFER (w->contents);
  6655   bool center_p = false;
  6656   ptrdiff_t charpos, bytepos;
  6657   EMACS_INT iarg UNINIT;
  6658   int this_scroll_margin;
  6659 
  6660   /* For reasons why we signal an error here, see
  6661      https://lists.gnu.org/r/emacs-devel/2014-06/msg00053.html,
  6662      https://lists.gnu.org/r/emacs-devel/2014-06/msg00094.html.  */
  6663   if (buf != current_buffer)
  6664     error ("`recenter'ing a window that does not display current-buffer.");
  6665 
  6666   /* If redisplay is suppressed due to an error, try again.  */
  6667   buf->display_error_modiff = 0;
  6668 
  6669   if (NILP (arg))
  6670     {
  6671       if (!NILP (redisplay)
  6672           && !NILP (Vrecenter_redisplay)
  6673           && (!EQ (Vrecenter_redisplay, Qtty)
  6674               || !NILP (Ftty_type (selected_frame))))
  6675         {
  6676           ptrdiff_t i;
  6677 
  6678           /* Invalidate pixel data calculated for all compositions.  */
  6679           for (i = 0; i < n_compositions; i++)
  6680             composition_table[i]->font = NULL;
  6681 #if defined (HAVE_WINDOW_SYSTEM)
  6682           WINDOW_XFRAME (w)->minimize_tab_bar_window_p = 1;
  6683 #endif
  6684 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
  6685           WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
  6686 #endif
  6687           Fredraw_frame (WINDOW_FRAME (w));
  6688           SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
  6689         }
  6690 
  6691       center_p = true;
  6692     }
  6693   else if (CONSP (arg)) /* Just C-u.  */
  6694     center_p = true;
  6695   else
  6696     {
  6697       arg = Fprefix_numeric_value (arg);
  6698       CHECK_FIXNUM (arg);
  6699       iarg = XFIXNUM (arg);
  6700     }
  6701 
  6702   /* Do this after making BUF current
  6703      in case scroll_margin is buffer-local.  */
  6704   this_scroll_margin = window_scroll_margin (w, MARGIN_IN_LINES);
  6705 
  6706   /* Don't use the display code for initial frames, as the necessary
  6707      data structures might not be set up yet then.  Also don't use it
  6708      for buffers with very long lines, as it tremdously slows down
  6709      redisplay, especially when lines are truncated.  */
  6710   if (!FRAME_INITIAL_P (XFRAME (w->frame))
  6711       && !current_buffer->long_line_optimizations_p)
  6712     {
  6713       specpdl_ref count = SPECPDL_INDEX ();
  6714 
  6715       record_unwind_protect_void (unwind_display_working_on_window);
  6716       display_working_on_window_p = true;
  6717       if (center_p)
  6718         {
  6719           struct it it;
  6720           struct text_pos pt;
  6721           void *itdata = bidi_shelve_cache ();
  6722 
  6723           SET_TEXT_POS (pt, PT, PT_BYTE);
  6724           start_display (&it, w, pt);
  6725           move_it_vertically_backward (&it, window_box_height (w) / 2);
  6726           charpos = IT_CHARPOS (it);
  6727           bytepos = IT_BYTEPOS (it);
  6728           bidi_unshelve_cache (itdata, false);
  6729         }
  6730       else if (iarg < 0)
  6731         {
  6732           struct it it;
  6733           struct text_pos pt;
  6734           ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
  6735           int extra_line_spacing;
  6736           int h = window_box_height (w);
  6737           int ht = window_internal_height (w);
  6738           void *itdata = bidi_shelve_cache ();
  6739 
  6740           nlines = clip_to_bounds (this_scroll_margin + 1, nlines,
  6741                                    ht - this_scroll_margin);
  6742 
  6743           SET_TEXT_POS (pt, PT, PT_BYTE);
  6744           start_display (&it, w, pt);
  6745 
  6746           /* Be sure we have the exact height of the full line containing PT.  */
  6747           move_it_by_lines (&it, 0);
  6748 
  6749           /* The amount of pixels we have to move back is the window
  6750              height minus what's displayed in the line containing PT,
  6751              and the lines below.  */
  6752           it.current_y = 0;
  6753           it.vpos = 0;
  6754           move_it_by_lines (&it, nlines);
  6755 
  6756           if (it.vpos == nlines)
  6757             h -= it.current_y;
  6758           else
  6759             {
  6760               /* Last line has no newline.  */
  6761               h -= line_bottom_y (&it);
  6762               it.vpos++;
  6763             }
  6764 
  6765           /* Don't reserve space for extra line spacing of last line.  */
  6766           extra_line_spacing = it.max_extra_line_spacing;
  6767 
  6768           /* If we can't move down NLINES lines because we hit
  6769              the end of the buffer, count in some empty lines.  */
  6770           if (it.vpos < nlines)
  6771             {
  6772               nlines -= it.vpos;
  6773               extra_line_spacing = it.extra_line_spacing;
  6774               h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
  6775             }
  6776           if (h <= 0)
  6777             {
  6778               bidi_unshelve_cache (itdata, false);
  6779               unbind_to (count, Qnil);
  6780               return Qnil;
  6781             }
  6782 
  6783           /* Now find the new top line (starting position) of the window.  */
  6784           start_display (&it, w, pt);
  6785           it.current_y = 0;
  6786           move_it_vertically_backward (&it, h);
  6787 
  6788           /* If extra line spacing is present, we may move too far
  6789              back.  This causes the last line to be only partially
  6790              visible (which triggers redisplay to recenter that line
  6791              in the middle), so move forward.
  6792              But ignore extra line spacing on last line, as it is not
  6793              considered to be part of the visible height of the line.
  6794           */
  6795           h += extra_line_spacing;
  6796           while (-it.current_y > h && it.what != IT_EOB)
  6797             move_it_by_lines (&it, 1);
  6798 
  6799           charpos = IT_CHARPOS (it);
  6800           bytepos = IT_BYTEPOS (it);
  6801 
  6802           bidi_unshelve_cache (itdata, false);
  6803         }
  6804       else
  6805         {
  6806           struct it it;
  6807           struct text_pos pt;
  6808           ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
  6809           int ht = window_internal_height (w);
  6810           void *itdata = bidi_shelve_cache ();
  6811 
  6812           nlines = clip_to_bounds (this_scroll_margin, nlines,
  6813                                    ht - this_scroll_margin - 1);
  6814 
  6815           SET_TEXT_POS (pt, PT, PT_BYTE);
  6816           start_display (&it, w, pt);
  6817 
  6818           /* Move to the beginning of screen line containing PT.  */
  6819           move_it_by_lines (&it, 0);
  6820 
  6821           /* Move back to find the point which is ARG screen lines above PT.  */
  6822           if (nlines > 0)
  6823             {
  6824               it.current_y = 0;
  6825               it.vpos = 0;
  6826               move_it_by_lines (&it, -nlines);
  6827             }
  6828 
  6829           charpos = IT_CHARPOS (it);
  6830           bytepos = IT_BYTEPOS (it);
  6831 
  6832           bidi_unshelve_cache (itdata, false);
  6833         }
  6834       unbind_to (count, Qnil);
  6835     }
  6836   else
  6837     {
  6838       struct position pos;
  6839       int ht = window_internal_height (w);
  6840 
  6841       if (center_p)
  6842         iarg = ht / 2;
  6843       else if (iarg < 0)
  6844         iarg += ht;
  6845 
  6846       /* Don't let it get into the margin at either top or bottom.  */
  6847       iarg = clip_to_bounds (this_scroll_margin, iarg,
  6848                              ht - this_scroll_margin - 1);
  6849 
  6850       pos = *vmotion (PT, PT_BYTE, - iarg, w);
  6851       charpos = pos.bufpos;
  6852       bytepos = pos.bytepos;
  6853     }
  6854 
  6855   /* Set the new window start.  */
  6856   set_marker_both (w->start, w->contents, charpos, bytepos);
  6857   w->window_end_valid = false;
  6858 
  6859   w->optional_new_start = true;
  6860 
  6861   w->start_at_line_beg = (bytepos == BEGV_BYTE
  6862                           || FETCH_BYTE (bytepos - 1) == '\n');
  6863 
  6864   wset_redisplay (w);
  6865 
  6866   return Qnil;
  6867 }
  6868 
  6869 DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
  6870        0, 2, 0,
  6871        doc: /* Return the width in columns of the text display area of WINDOW.
  6872 WINDOW must be a live window and defaults to the selected one.
  6873 
  6874 The returned width does not include dividers, scrollbars, margins,
  6875 fringes, nor any partial-width columns at the right of the text
  6876 area.
  6877 
  6878 Optional argument PIXELWISE non-nil, means to return the width in
  6879 pixels.  */)
  6880   (Lisp_Object window, Lisp_Object pixelwise)
  6881 {
  6882   struct window *w = decode_live_window (window);
  6883 
  6884   if (NILP (pixelwise))
  6885     return make_fixnum (window_box_width (w, TEXT_AREA)
  6886                         / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
  6887   else
  6888     return make_fixnum (window_box_width (w, TEXT_AREA));
  6889 }
  6890 
  6891 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
  6892        0, 2, 0,
  6893        doc: /* Return the height in lines of the text display area of WINDOW.
  6894 WINDOW must be a live window and defaults to the selected one.
  6895 
  6896 The returned height does not include dividers, the mode line, any header
  6897 line, nor any partial-height lines at the bottom of the text area.
  6898 
  6899 Optional argument PIXELWISE non-nil, means to return the height in
  6900 pixels.  */)
  6901   (Lisp_Object window, Lisp_Object pixelwise)
  6902 {
  6903   struct window *w = decode_live_window (window);
  6904 
  6905   if (NILP (pixelwise))
  6906     return make_fixnum (window_box_height (w)
  6907                         / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
  6908   else
  6909     return make_fixnum (window_box_height (w));
  6910 }
  6911 
  6912 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
  6913        1, 1, "P",
  6914        doc: /* Position point relative to window.
  6915 ARG nil means position point at center of window.
  6916 Else, ARG specifies vertical position within the window;
  6917 zero means top of window, negative means relative to bottom
  6918 of window, -1 meaning the last fully visible display line
  6919 of the window.
  6920 
  6921 Value is the screen line of the window point moved to, counting
  6922 from the top of the window.  */)
  6923   (Lisp_Object arg)
  6924 {
  6925   struct window *w = XWINDOW (selected_window);
  6926   int lines, start;
  6927   Lisp_Object window;
  6928 #if false
  6929   int this_scroll_margin;
  6930 #endif
  6931 
  6932   if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
  6933     /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
  6934        when passed below to set_marker_both.  */
  6935     error ("move-to-window-line called from unrelated buffer");
  6936 
  6937   window = selected_window;
  6938   start = marker_position (w->start);
  6939   if (start < BEGV || start > ZV)
  6940     {
  6941       int height = window_internal_height (w);
  6942       Fvertical_motion (make_fixnum (- (height / 2)), window, Qnil);
  6943       set_marker_both (w->start, w->contents, PT, PT_BYTE);
  6944       w->start_at_line_beg = !NILP (Fbolp ());
  6945       w->force_start = true;
  6946     }
  6947   else
  6948     Fgoto_char (w->start);
  6949 
  6950   lines = displayed_window_lines (w);
  6951 
  6952   if (NILP (arg))
  6953     XSETFASTINT (arg, lines / 2);
  6954   else
  6955     {
  6956       EMACS_INT iarg = XFIXNUM (Fprefix_numeric_value (arg));
  6957 
  6958       if (iarg < 0)
  6959         iarg = iarg + lines;
  6960 
  6961 #if false /* This code would prevent move-to-window-line from moving point
  6962              to a place inside the scroll margins (which would cause the
  6963              next redisplay to scroll).  I wrote this code, but then concluded
  6964              it is probably better not to install it.  However, it is here
  6965              inside #if false so as not to lose it.  -- rms.  */
  6966 
  6967       this_scroll_margin = window_scroll_margin (w, MARGIN_IN_LINES);
  6968 
  6969       /* Don't let it get into the margin at either top or bottom.  */
  6970       iarg = max (iarg, this_scroll_margin);
  6971       iarg = min (iarg, lines - this_scroll_margin - 1);
  6972 #endif
  6973 
  6974       arg = make_fixnum (iarg);
  6975     }
  6976 
  6977   /* Skip past a partially visible first line.  */
  6978   if (w->vscroll)
  6979     XSETINT (arg, XFIXNUM (arg) + 1);
  6980 
  6981   return Fvertical_motion (arg, window, Qnil);
  6982 }
  6983 
  6984 
  6985 
  6986 /***********************************************************************
  6987                          Window Configuration
  6988  ***********************************************************************/
  6989 
  6990 struct save_window_data
  6991   {
  6992     union vectorlike_header header;
  6993     Lisp_Object selected_frame;
  6994     Lisp_Object current_window;
  6995     Lisp_Object f_current_buffer;
  6996     Lisp_Object minibuf_scroll_window;
  6997     Lisp_Object minibuf_selected_window;
  6998     Lisp_Object root_window;
  6999     Lisp_Object focus_frame;
  7000     /* A vector, each of whose elements is a struct saved_window
  7001        for one window.  */
  7002     Lisp_Object saved_windows;
  7003 
  7004     /* All fields above are traced by the GC.
  7005        After saved_windows, the fields are ignored by the GC.  */
  7006 
  7007     /* We should be able to do without the following two.  */
  7008     int frame_cols, frame_lines;
  7009     /* These three should get eventually replaced by their pixel
  7010        counterparts.  */
  7011     int frame_menu_bar_lines, frame_tab_bar_lines, frame_tool_bar_lines;
  7012     int frame_text_width, frame_text_height;
  7013     /* These are currently unused.  We need them as soon as we convert
  7014        to pixels.  */
  7015     int frame_menu_bar_height, frame_tab_bar_height, frame_tool_bar_height;
  7016   } GCALIGNED_STRUCT;
  7017 
  7018 /* This is saved as a Lisp_Vector.  */
  7019 struct saved_window
  7020 {
  7021   union vectorlike_header header;
  7022 
  7023   Lisp_Object window, buffer, start, pointm, old_pointm;
  7024   Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
  7025   Lisp_Object left_col, top_line, total_cols, total_lines;
  7026   Lisp_Object normal_cols, normal_lines;
  7027   Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
  7028   Lisp_Object vscroll;
  7029   Lisp_Object parent, prev;
  7030   Lisp_Object start_at_line_beg;
  7031   Lisp_Object display_table;
  7032   Lisp_Object left_margin_cols, right_margin_cols;
  7033   Lisp_Object left_fringe_width, right_fringe_width;
  7034   Lisp_Object fringes_outside_margins, fringes_persistent;
  7035   Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
  7036   Lisp_Object scroll_bar_height, horizontal_scroll_bar_type;
  7037   Lisp_Object scroll_bars_persistent, dedicated;
  7038   Lisp_Object combination_limit, window_parameters;
  7039 };
  7040 
  7041 #define SAVED_WINDOW_N(swv,n) \
  7042   ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
  7043 
  7044 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
  7045        doc: /* Return t if OBJECT is a window-configuration object.  */)
  7046   (Lisp_Object object)
  7047 {
  7048   return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
  7049 }
  7050 
  7051 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
  7052        doc: /* Return the frame that CONFIG, a window-configuration object, is about.  */)
  7053   (Lisp_Object config)
  7054 {
  7055   register struct save_window_data *data;
  7056   struct Lisp_Vector *saved_windows;
  7057 
  7058   CHECK_WINDOW_CONFIGURATION (config);
  7059 
  7060   data = (struct save_window_data *) XVECTOR (config);
  7061   saved_windows = XVECTOR (data->saved_windows);
  7062   return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
  7063 }
  7064 
  7065 DEFUN ("set-window-configuration", Fset_window_configuration,
  7066        Sset_window_configuration, 1, 3, 0,
  7067        doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
  7068 CONFIGURATION must be a value previously returned
  7069 by `current-window-configuration' (which see).
  7070 
  7071 Normally, this function selects the frame of the CONFIGURATION, but if
  7072 DONT-SET-FRAME is non-nil, it leaves selected the frame which was
  7073 current at the start of the function.  If DONT-SET-MINIWINDOW is non-nil,
  7074 the mini-window of the frame doesn't get set to the corresponding element
  7075 of CONFIGURATION.
  7076 
  7077 If CONFIGURATION was made from a frame that is now deleted,
  7078 only frame-independent values can be restored.  In this case,
  7079 the return value is nil.  Otherwise the value is t.  */)
  7080   (Lisp_Object configuration, Lisp_Object dont_set_frame,
  7081    Lisp_Object dont_set_miniwindow)
  7082 {
  7083   register struct save_window_data *data;
  7084   struct Lisp_Vector *saved_windows;
  7085   Lisp_Object new_current_buffer;
  7086   Lisp_Object frame;
  7087   Lisp_Object old_frame = selected_frame;
  7088   struct frame *f;
  7089   ptrdiff_t old_point = -1;
  7090   USE_SAFE_ALLOCA;
  7091 
  7092   CHECK_WINDOW_CONFIGURATION (configuration);
  7093 
  7094   data = (struct save_window_data *) XVECTOR (configuration);
  7095   saved_windows = XVECTOR (data->saved_windows);
  7096 
  7097   new_current_buffer = data->f_current_buffer;
  7098   if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
  7099     new_current_buffer = Qnil;
  7100   else
  7101     {
  7102       if (XBUFFER (new_current_buffer) == current_buffer)
  7103         /* The code further down "preserves point" by saving here PT in
  7104            old_point and then setting it later back into PT.  When the
  7105            current-selected-window and the final-selected-window both show
  7106            the current buffer, this suffers from the problem that the
  7107            current PT is the window-point of the current-selected-window,
  7108            while the final PT is the point of the final-selected-window, so
  7109            this copy from one PT to the other would end up moving the
  7110            window-point of the final-selected-window to the window-point of
  7111            the current-selected-window.  So we have to be careful which
  7112            point of the current-buffer we copy into old_point.  */
  7113         if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
  7114             && WINDOWP (selected_window)
  7115             && EQ (XWINDOW (selected_window)->contents, new_current_buffer)
  7116             && !EQ (selected_window, data->current_window))
  7117           old_point = marker_position (XWINDOW (data->current_window)->pointm);
  7118         else
  7119           old_point = PT;
  7120       else
  7121         /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
  7122            point in new_current_buffer as of the last time this buffer was
  7123            used.  This can be non-deterministic since it can be changed by
  7124            things like jit-lock by mere temporary selection of some random
  7125            window that happens to show this buffer.
  7126            So if possible we want this arbitrary choice of "which point" to
  7127            be the one from the to-be-selected-window so as to prevent this
  7128            window's cursor from being copied from another window.  */
  7129         if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
  7130             /* If current_window = selected_window, its point is in BUF_PT.  */
  7131             && !EQ (selected_window, data->current_window))
  7132           old_point = marker_position (XWINDOW (data->current_window)->pointm);
  7133         else
  7134           old_point = BUF_PT (XBUFFER (new_current_buffer));
  7135     }
  7136 
  7137   frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
  7138   f = XFRAME (frame);
  7139 
  7140   /* If f is a dead frame, don't bother rebuilding its window tree.
  7141      However, there is other stuff we should still try to do below.  */
  7142   if (FRAME_LIVE_P (f))
  7143     {
  7144       Lisp_Object window;
  7145       Lisp_Object dead_windows = Qnil;
  7146       Lisp_Object tem, par, pers;
  7147       struct window *w;
  7148       struct saved_window *p;
  7149       struct window *root_window;
  7150       struct window **leaf_windows;
  7151       ptrdiff_t i, k, n_leaf_windows;
  7152 
  7153       /* Don't do this within the main loop below: This may call Lisp
  7154          code and is thus potentially unsafe while input is blocked.  */
  7155       for (k = 0; k < saved_windows->header.size; k++)
  7156         {
  7157           p = SAVED_WINDOW_N (saved_windows, k);
  7158           window = p->window;
  7159           w = XWINDOW (window);
  7160 
  7161           if (BUFFERP (w->contents)
  7162               && !EQ (w->contents, p->buffer)
  7163               && BUFFER_LIVE_P (XBUFFER (p->buffer))
  7164               && (NILP (Fminibufferp (p->buffer, Qnil))))
  7165             /* If a window we restore gets another buffer, record the
  7166                window's old buffer.  */
  7167             call1 (Qrecord_window_buffer, window);
  7168         }
  7169 
  7170       /* Disallow set_window_size_hook, temporarily.  */
  7171       f->can_set_window_size = false;
  7172       /* The mouse highlighting code could get screwed up
  7173          if it runs during this.  */
  7174       block_input ();
  7175 
  7176       /* "Swap out" point from the selected window's buffer
  7177          into the window itself.  (Normally the pointm of the selected
  7178          window holds garbage.)  We do this now, before
  7179          restoring the window contents, and prevent it from
  7180          being done later on when we select a new window.  */
  7181       if (! NILP (XWINDOW (selected_window)->contents))
  7182         {
  7183           w = XWINDOW (selected_window);
  7184           set_marker_both (w->pointm,
  7185                            w->contents,
  7186                            BUF_PT (XBUFFER (w->contents)),
  7187                            BUF_PT_BYTE (XBUFFER (w->contents)));
  7188         }
  7189 
  7190       fset_redisplay (f);
  7191 
  7192       /* Problem: Freeing all matrices and later allocating them again
  7193          is a serious redisplay flickering problem.  What we would
  7194          really like to do is to free only those matrices not reused
  7195          below.  */
  7196       root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
  7197       ptrdiff_t nwindows = count_windows (root_window);
  7198       SAFE_NALLOCA (leaf_windows, 1, nwindows);
  7199       n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
  7200 
  7201       /* Kludge Alert!
  7202          Mark all windows now on frame as "deleted".
  7203          Restoring the new configuration "undeletes" any that are in it.
  7204 
  7205          Save their current buffers in their height fields, since we may
  7206          need it later, if a buffer saved in the configuration is now
  7207          dead.  */
  7208       delete_all_child_windows (FRAME_ROOT_WINDOW (f));
  7209 
  7210       for (k = 0; k < saved_windows->header.size; k++)
  7211         {
  7212           p = SAVED_WINDOW_N (saved_windows, k);
  7213           window = p->window;
  7214           w = XWINDOW (window);
  7215           wset_next (w, Qnil);
  7216 
  7217           if (!NILP (p->parent))
  7218             wset_parent
  7219               (w, SAVED_WINDOW_N (saved_windows, XFIXNAT (p->parent))->window);
  7220           else
  7221             wset_parent (w, Qnil);
  7222 
  7223           if (!NILP (p->prev))
  7224             {
  7225               wset_prev
  7226                 (w, SAVED_WINDOW_N (saved_windows, XFIXNAT (p->prev))->window);
  7227               wset_next (XWINDOW (w->prev), p->window);
  7228             }
  7229           else
  7230             {
  7231               wset_prev (w, Qnil);
  7232               if (!NILP (w->parent))
  7233                 wset_combination (XWINDOW (w->parent),
  7234                                   (XFIXNUM (p->total_cols)
  7235                                    != XWINDOW (w->parent)->total_cols),
  7236                                   p->window);
  7237             }
  7238 
  7239           /* If we squirreled away the buffer, restore it now.  */
  7240           if (BUFFERP (w->combination_limit))
  7241             wset_buffer (w, w->combination_limit);
  7242           w->pixel_left = XFIXNAT (p->pixel_left);
  7243           w->pixel_top = XFIXNAT (p->pixel_top);
  7244           w->pixel_width = XFIXNAT (p->pixel_width);
  7245           w->pixel_height = XFIXNAT (p->pixel_height);
  7246           w->left_col = XFIXNAT (p->left_col);
  7247           w->top_line = XFIXNAT (p->top_line);
  7248           w->total_cols = XFIXNAT (p->total_cols);
  7249           w->total_lines = XFIXNAT (p->total_lines);
  7250           wset_normal_cols (w, p->normal_cols);
  7251           wset_normal_lines (w, p->normal_lines);
  7252           w->hscroll = XFIXNAT (p->hscroll);
  7253           w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll);
  7254           w->min_hscroll = XFIXNAT (p->min_hscroll);
  7255           w->hscroll_whole = XFIXNAT (p->hscroll_whole);
  7256           w->vscroll = -XFIXNAT (p->vscroll);
  7257           wset_display_table (w, p->display_table);
  7258           w->left_margin_cols = XFIXNUM (p->left_margin_cols);
  7259           w->right_margin_cols = XFIXNUM (p->right_margin_cols);
  7260           w->left_fringe_width = XFIXNUM (p->left_fringe_width);
  7261           w->right_fringe_width = XFIXNUM (p->right_fringe_width);
  7262           w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
  7263           w->fringes_persistent = !NILP (p->fringes_persistent);
  7264           w->scroll_bar_width = XFIXNUM (p->scroll_bar_width);
  7265           w->scroll_bar_height = XFIXNUM (p->scroll_bar_height);
  7266           w->scroll_bars_persistent = !NILP (p->scroll_bars_persistent);
  7267           wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
  7268           wset_horizontal_scroll_bar_type (w, p->horizontal_scroll_bar_type);
  7269           wset_dedicated (w, p->dedicated);
  7270           wset_combination_limit (w, p->combination_limit);
  7271           /* Restore any window parameters that have been saved.
  7272              Parameters that have not been saved are left alone.  */
  7273           for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
  7274             {
  7275               pers = XCAR (tem);
  7276               if (CONSP (pers))
  7277                 {
  7278                   if (NILP (XCDR (pers)))
  7279                     {
  7280                       par = Fassq (XCAR (pers), w->window_parameters);
  7281                       if (CONSP (par) && !NILP (XCDR (par)))
  7282                         /* Reset a parameter to nil if and only if it
  7283                            has a non-nil association.  Don't make new
  7284                            associations.  */
  7285                         Fsetcdr (par, Qnil);
  7286                     }
  7287                   else
  7288                     /* Always restore a non-nil value.  */
  7289                     Fset_window_parameter (window, XCAR (pers), XCDR (pers));
  7290                 }
  7291             }
  7292 
  7293           if ((NILP (dont_set_miniwindow) || !MINI_WINDOW_P (w))
  7294               && BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
  7295             /* If saved buffer is alive, install it, unless it's a
  7296                minibuffer we explicitly prohibit.  */
  7297             {
  7298               wset_buffer (w, p->buffer);
  7299               w->start_at_line_beg = !NILP (p->start_at_line_beg);
  7300               set_marker_restricted (w->start, p->start, w->contents);
  7301               set_marker_restricted (w->pointm, p->pointm, w->contents);
  7302               set_marker_restricted (w->old_pointm, p->old_pointm, w->contents);
  7303               /* As documented in Fcurrent_window_configuration, don't
  7304                  restore the location of point in the buffer which was
  7305                  current when the window configuration was recorded.  */
  7306               if (!EQ (p->buffer, new_current_buffer)
  7307                   && XBUFFER (p->buffer) == current_buffer)
  7308                 Fgoto_char (w->pointm);
  7309             }
  7310           else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
  7311             /* Keep window's old buffer; make sure the markers are real.  */
  7312             {
  7313               /* Set window markers at start of visible range.  */
  7314               if (XMARKER (w->start)->buffer == 0)
  7315                 set_marker_restricted_both (w->start, w->contents, 0, 0);
  7316               if (XMARKER (w->pointm)->buffer == 0)
  7317                 set_marker_restricted_both
  7318                   (w->pointm, w->contents,
  7319                    BUF_PT (XBUFFER (w->contents)),
  7320                    BUF_PT_BYTE (XBUFFER (w->contents)));
  7321               if (XMARKER (w->old_pointm)->buffer == 0)
  7322                 set_marker_restricted_both
  7323                   (w->old_pointm, w->contents,
  7324                    BUF_PT (XBUFFER (w->contents)),
  7325                    BUF_PT_BYTE (XBUFFER (w->contents)));
  7326               w->start_at_line_beg = true;
  7327             }
  7328           else if (!NILP (w->start))
  7329             /* Leaf window has no live buffer, get one.  */
  7330             {
  7331               /* Get the buffer via other_buffer_safely in order to
  7332                  avoid showing an unimportant buffer and, if necessary, to
  7333                  recreate *scratch* in the course (part of Juanma's bs-show
  7334                  scenario from March 2011).  */
  7335               wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
  7336               /* This will set the markers to beginning of visible
  7337                  range.  */
  7338               set_marker_restricted_both (w->start, w->contents, 0, 0);
  7339               set_marker_restricted_both (w->pointm, w->contents, 0, 0);
  7340               set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
  7341               w->start_at_line_beg = true;
  7342               if (!NILP (w->dedicated))
  7343                 /* Record this window as dead.  */
  7344                 dead_windows = Fcons (window, dead_windows);
  7345               /* Make sure window is no more dedicated.  */
  7346               wset_dedicated (w, Qnil);
  7347             }
  7348         }
  7349 
  7350       fset_root_window (f, data->root_window);
  7351       /* Arrange *not* to restore point in the buffer that was
  7352          current when the window configuration was saved.  */
  7353       if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
  7354         set_marker_restricted (XWINDOW (data->current_window)->pointm,
  7355                                make_fixnum (old_point),
  7356                                XWINDOW (data->current_window)->contents);
  7357 
  7358       /* In the following call to select_window, prevent "swapping out
  7359          point" in the old selected window using the buffer that has
  7360          been restored into it.  We already swapped out that point
  7361          from that window's old buffer.
  7362 
  7363          Do not record the buffer here.  We do that in a separate call
  7364          to select_window below.  See also Bug#16207.  */
  7365       select_window (data->current_window, Qt, true);
  7366       BVAR (XBUFFER (XWINDOW (selected_window)->contents),
  7367             last_selected_window)
  7368         = selected_window;
  7369 
  7370       /* We may have deleted windows above.  Then again, maybe we
  7371          haven't: the functions we call to maybe delete windows can
  7372          decide a window cannot be deleted.  Force recalculation of
  7373          Vwindow_list next time it is needed, to make sure stale
  7374          windows with no buffers don't escape into the wild, which
  7375          will cause crashes elsewhere.  */
  7376       Vwindow_list = Qnil;
  7377 
  7378       if (NILP (data->focus_frame)
  7379           || (FRAMEP (data->focus_frame)
  7380               && FRAME_LIVE_P (XFRAME (data->focus_frame))))
  7381         Fredirect_frame_focus (frame, data->focus_frame);
  7382 
  7383       /* Now, free glyph matrices in windows that were not reused.  */
  7384       for (i = 0; i < n_leaf_windows; i++)
  7385         if (NILP (leaf_windows[i]->contents))
  7386           free_window_matrices (leaf_windows[i]);
  7387 
  7388       /* Allow set_window_size_hook again and resize frame's windows
  7389          if necessary.  But change frame size only to preserve window
  7390          minimum sizes.  */
  7391       f->can_set_window_size = true;
  7392       adjust_frame_size (f, -1, -1, 4, false, Qset_window_configuration);
  7393 
  7394       adjust_frame_glyphs (f);
  7395       unblock_input ();
  7396 
  7397       /* Scan dead buffer windows.  */
  7398       for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
  7399         {
  7400           window = XCAR (dead_windows);
  7401           if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
  7402             delete_deletable_window (window);
  7403         }
  7404 
  7405       /* Record the selected window's buffer here.  The window should
  7406          already be the selected one from the call above.  */
  7407       if (WINDOW_LIVE_P (data->current_window))
  7408         select_window (data->current_window, Qnil, false);
  7409 
  7410       /* select_window will have made f the selected frame, so we
  7411          reselect the proper frame here.  do_switch_frame will change
  7412          the selected window too, but that doesn't make the call to
  7413          select_window above totally superfluous; it still sets f's
  7414          selected window.  */
  7415       if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
  7416         do_switch_frame (NILP (dont_set_frame)
  7417                          ? data->selected_frame
  7418                          : old_frame
  7419                          , 0, 0, Qnil);
  7420     }
  7421 
  7422   FRAME_WINDOW_CHANGE (f) = true;
  7423 
  7424   if (!NILP (new_current_buffer))
  7425     {
  7426       Fset_buffer (new_current_buffer);
  7427       /* If the new current buffer doesn't appear in the selected
  7428          window, go to its old point (Bug#12208).
  7429 
  7430          The original fix used data->current_window below which caused
  7431          false positives (compare Bug#31695) when data->current_window
  7432          is not on data->selected_frame.  This happens, for example,
  7433          when read_minibuf restores the configuration of a stand-alone
  7434          minibuffer frame: After switching to the previously selected
  7435          "normal" frame, point of that frame's selected window jumped
  7436          unexpectedly because new_current_buffer is usually *not*
  7437          shown in data->current_window - the minibuffer frame's
  7438          selected window.  Using selected_window instead fixes this
  7439          because do_switch_frame has set up selected_window already to
  7440          the "normal" frame's selected window and that window *does*
  7441          show new_current_buffer.  */
  7442       if (!EQ (XWINDOW (selected_window)->contents, new_current_buffer))
  7443         Fgoto_char (make_fixnum (old_point));
  7444     }
  7445 
  7446   Vminibuf_scroll_window = data->minibuf_scroll_window;
  7447   minibuf_selected_window = data->minibuf_selected_window;
  7448 
  7449   SAFE_FREE ();
  7450   return FRAME_LIVE_P (f) ? Qt : Qnil;
  7451 }
  7452 
  7453 void
  7454 restore_window_configuration (Lisp_Object configuration)
  7455 {
  7456   if (CONSP (configuration))
  7457     Fset_window_configuration (XCAR (configuration),
  7458                                Fcar_safe (XCDR (configuration)),
  7459                                Fcar_safe (Fcdr_safe (XCDR (configuration))));
  7460   else
  7461     Fset_window_configuration (configuration, Qnil, Qnil);
  7462 }
  7463 
  7464 
  7465 /* If WINDOW is an internal window, recursively delete all child windows
  7466    reachable via the next and contents slots of WINDOW.  Otherwise setup
  7467    WINDOW to not show any buffer.  */
  7468 
  7469 void
  7470 delete_all_child_windows (Lisp_Object window)
  7471 {
  7472   register struct window *w;
  7473 
  7474   w = XWINDOW (window);
  7475 
  7476   if (!NILP (w->next))
  7477     /* Delete WINDOW's siblings (we traverse postorderly).  */
  7478     delete_all_child_windows (w->next);
  7479 
  7480   if (WINDOWP (w->contents))
  7481     {
  7482       delete_all_child_windows (w->contents);
  7483       wset_combination (w, false, Qnil);
  7484     }
  7485   else if (BUFFERP (w->contents))
  7486     {
  7487       unshow_buffer (w);
  7488       unchain_marker (XMARKER (w->pointm));
  7489       unchain_marker (XMARKER (w->old_pointm));
  7490       unchain_marker (XMARKER (w->start));
  7491       /* Since combination limit makes sense for an internal windows
  7492          only, we use this slot to save the buffer for the sake of
  7493          possible resurrection in Fset_window_configuration.  */
  7494       wset_combination_limit (w, w->contents);
  7495       wset_buffer (w, Qnil);
  7496     }
  7497 
  7498   Vwindow_list = Qnil;
  7499 }
  7500 
  7501 static ptrdiff_t
  7502 count_windows (struct window *window)
  7503 {
  7504   ptrdiff_t count = 1;
  7505   if (!NILP (window->next))
  7506     count += count_windows (XWINDOW (window->next));
  7507   if (WINDOWP (window->contents))
  7508     count += count_windows (XWINDOW (window->contents));
  7509   return count;
  7510 }
  7511 
  7512 
  7513 /* Fill vector FLAT with leaf windows under W, starting at index I.
  7514    Value is last index + 1.  */
  7515 static ptrdiff_t
  7516 get_leaf_windows (struct window *w, struct window **flat, ptrdiff_t i)
  7517 {
  7518   while (w)
  7519     {
  7520       if (WINDOWP (w->contents))
  7521         i = get_leaf_windows (XWINDOW (w->contents), flat, i);
  7522       else
  7523         flat[i++] = w;
  7524 
  7525       w = NILP (w->next) ? 0 : XWINDOW (w->next);
  7526     }
  7527 
  7528   return i;
  7529 }
  7530 
  7531 
  7532 /* Return a pointer to the glyph W's physical cursor is on.  Value is
  7533    null if W's current matrix is invalid, so that no meaningful glyph
  7534    can be returned.  */
  7535 struct glyph *
  7536 get_phys_cursor_glyph (struct window *w)
  7537 {
  7538   struct glyph_row *row;
  7539   struct glyph *glyph;
  7540   int hpos = w->phys_cursor.hpos;
  7541 
  7542   if (!(w->phys_cursor.vpos >= 0
  7543         && w->phys_cursor.vpos < w->current_matrix->nrows))
  7544     return NULL;
  7545 
  7546   row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
  7547   if (!row->enabled_p)
  7548     return NULL;
  7549 
  7550   if (w->hscroll)
  7551     {
  7552       /* When the window is hscrolled, cursor hpos can legitimately be
  7553          out of bounds, but we draw the cursor at the corresponding
  7554          window margin in that case.  */
  7555       if (!row->reversed_p && hpos < 0)
  7556         hpos = 0;
  7557       if (row->reversed_p && hpos >= row->used[TEXT_AREA])
  7558         hpos = row->used[TEXT_AREA] - 1;
  7559     }
  7560 
  7561   if (0 <= hpos && hpos < row->used[TEXT_AREA])
  7562     glyph = row->glyphs[TEXT_AREA] + hpos;
  7563   else
  7564     glyph = NULL;
  7565 
  7566   return glyph;
  7567 }
  7568 
  7569 
  7570 static ptrdiff_t
  7571 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i)
  7572 {
  7573   struct saved_window *p;
  7574   struct window *w;
  7575   Lisp_Object tem, pers, par;
  7576 
  7577   for (; !NILP (window); window = w->next)
  7578     {
  7579       p = SAVED_WINDOW_N (vector, i);
  7580       w = XWINDOW (window);
  7581 
  7582       wset_temslot (w, make_fixnum (i)); i++;
  7583       p->window = window;
  7584       p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil);
  7585       p->pixel_left = make_fixnum (w->pixel_left);
  7586       p->pixel_top = make_fixnum (w->pixel_top);
  7587       p->pixel_width = make_fixnum (w->pixel_width);
  7588       p->pixel_height = make_fixnum (w->pixel_height);
  7589       p->left_col = make_fixnum (w->left_col);
  7590       p->top_line = make_fixnum (w->top_line);
  7591       p->total_cols = make_fixnum (w->total_cols);
  7592       p->total_lines = make_fixnum (w->total_lines);
  7593       p->normal_cols = w->normal_cols;
  7594       p->normal_lines = w->normal_lines;
  7595       XSETFASTINT (p->hscroll, w->hscroll);
  7596       p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil;
  7597       XSETFASTINT (p->min_hscroll, w->min_hscroll);
  7598       XSETFASTINT (p->hscroll_whole, w->hscroll_whole);
  7599       XSETFASTINT (p->vscroll, -w->vscroll);
  7600       p->display_table = w->display_table;
  7601       p->left_margin_cols = make_fixnum (w->left_margin_cols);
  7602       p->right_margin_cols = make_fixnum (w->right_margin_cols);
  7603       p->left_fringe_width = make_fixnum (w->left_fringe_width);
  7604       p->right_fringe_width = make_fixnum (w->right_fringe_width);
  7605       p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
  7606       p->fringes_persistent = w->fringes_persistent ? Qt : Qnil;
  7607       p->scroll_bar_width = make_fixnum (w->scroll_bar_width);
  7608       p->scroll_bar_height = make_fixnum (w->scroll_bar_height);
  7609       p->scroll_bars_persistent = w->scroll_bars_persistent ? Qt : Qnil;
  7610       p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
  7611       p->horizontal_scroll_bar_type = w->horizontal_scroll_bar_type;
  7612       p->dedicated = w->dedicated;
  7613       p->combination_limit = w->combination_limit;
  7614       p->window_parameters = Qnil;
  7615 
  7616       if (!NILP (Vwindow_persistent_parameters))
  7617         {
  7618           /* Run cycle detection on Vwindow_persistent_parameters.  */
  7619           Lisp_Object tortoise, hare;
  7620 
  7621           hare = tortoise = Vwindow_persistent_parameters;
  7622           while (CONSP (hare))
  7623             {
  7624               hare = XCDR (hare);
  7625               if (!CONSP (hare))
  7626                 break;
  7627 
  7628               hare = XCDR (hare);
  7629               tortoise = XCDR (tortoise);
  7630 
  7631               if (BASE_EQ (hare, tortoise))
  7632                 /* Reset Vwindow_persistent_parameters to Qnil.  */
  7633                 {
  7634                   Vwindow_persistent_parameters = Qnil;
  7635                   break;
  7636                 }
  7637             }
  7638 
  7639           for (tem = Vwindow_persistent_parameters; CONSP (tem);
  7640                tem = XCDR (tem))
  7641             {
  7642               pers = XCAR (tem);
  7643               /* Save values for persistent window parameters. */
  7644               if (CONSP (pers) && !NILP (XCDR (pers)))
  7645                 {
  7646                   par = Fassq (XCAR (pers), w->window_parameters);
  7647                   if (NILP (par))
  7648                     /* If the window has no value for the parameter,
  7649                        make one.  */
  7650                     p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
  7651                                                   p->window_parameters);
  7652                   else
  7653                     /* If the window has a value for the parameter,
  7654                        save it.  */
  7655                     p->window_parameters = Fcons (Fcons (XCAR (par),
  7656                                                          XCDR (par)),
  7657                                                   p->window_parameters);
  7658                 }
  7659             }
  7660         }
  7661 
  7662       if (BUFFERP (w->contents))
  7663         {
  7664           bool window_point_insertion_type
  7665             = !NILP (buffer_local_value
  7666                       (Qwindow_point_insertion_type, w->contents));
  7667 
  7668           /* Save w's value of point in the window configuration.  If w
  7669              is the selected window, then get the value of point from
  7670              the buffer; pointm is garbage in the selected window.  */
  7671           if (EQ (window, selected_window))
  7672             p->pointm = build_marker (XBUFFER (w->contents),
  7673                                       BUF_PT (XBUFFER (w->contents)),
  7674                                       BUF_PT_BYTE (XBUFFER (w->contents)));
  7675           else
  7676             p->pointm = Fcopy_marker (w->pointm, Qnil);
  7677           p->old_pointm = Fcopy_marker (w->old_pointm, Qnil);
  7678           XMARKER (p->pointm)->insertion_type = window_point_insertion_type;
  7679           XMARKER (p->old_pointm)->insertion_type = window_point_insertion_type;
  7680 
  7681           p->start = Fcopy_marker (w->start, Qnil);
  7682           p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
  7683         }
  7684       else
  7685         {
  7686           p->pointm = Qnil;
  7687           p->old_pointm = Qnil;
  7688           p->start = Qnil;
  7689           p->start_at_line_beg = Qnil;
  7690         }
  7691 
  7692       p->parent = NILP (w->parent) ? Qnil : XWINDOW (w->parent)->temslot;
  7693       p->prev = NILP (w->prev) ? Qnil : XWINDOW (w->prev)->temslot;
  7694 
  7695       if (WINDOWP (w->contents))
  7696         i = save_window_save (w->contents, vector, i);
  7697     }
  7698 
  7699   return i;
  7700 }
  7701 
  7702 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
  7703        Scurrent_window_configuration, 0, 1, 0,
  7704        doc: /* Return an object representing the current window configuration of FRAME.
  7705 If FRAME is nil or omitted, use the selected frame.
  7706 This describes the number of windows, their sizes and current buffers,
  7707 and for each displayed buffer, where display starts, and the position of
  7708 point.  An exception is made for point in the current buffer:
  7709 its value is -not- saved.
  7710 This also records the currently selected frame, and FRAME's focus
  7711 redirection (see `redirect-frame-focus').  The variable
  7712 `window-persistent-parameters' specifies which window parameters are
  7713 saved by this function.  */)
  7714   (Lisp_Object frame)
  7715 {
  7716   struct frame *f = decode_live_frame (frame);
  7717   ptrdiff_t n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
  7718   struct save_window_data *data
  7719     = ALLOCATE_PSEUDOVECTOR (struct save_window_data, saved_windows,
  7720                              PVEC_WINDOW_CONFIGURATION);
  7721   data->frame_cols = FRAME_COLS (f);
  7722   data->frame_lines = FRAME_LINES (f);
  7723   data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
  7724   data->frame_tab_bar_lines = FRAME_TAB_BAR_LINES (f);
  7725   data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
  7726   data->frame_text_width = FRAME_TEXT_WIDTH (f);
  7727   data->frame_text_height = FRAME_TEXT_HEIGHT (f);
  7728   data->frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
  7729   data->frame_tab_bar_height = FRAME_TAB_BAR_HEIGHT (f);
  7730   data->frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
  7731   data->selected_frame = selected_frame;
  7732   data->current_window = FRAME_SELECTED_WINDOW (f);
  7733   XSETBUFFER (data->f_current_buffer, current_buffer);
  7734   data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
  7735   data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
  7736   data->root_window = FRAME_ROOT_WINDOW (f);
  7737   data->focus_frame = FRAME_FOCUS_FRAME (f);
  7738   Lisp_Object tem = make_nil_vector (n_windows);
  7739   data->saved_windows = tem;
  7740   for (ptrdiff_t i = 0; i < n_windows; i++)
  7741     ASET (tem, i, make_nil_vector (VECSIZE (struct saved_window)));
  7742   save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
  7743   XSETWINDOW_CONFIGURATION (tem, data);
  7744   return tem;
  7745 }
  7746 
  7747 /* Called after W's margins, fringes or scroll bars was adjusted.  */
  7748 
  7749 static void
  7750 apply_window_adjustment (struct window *w)
  7751 {
  7752   eassert (w);
  7753   clear_glyph_matrix (w->current_matrix);
  7754   w->window_end_valid = false;
  7755   wset_redisplay (w);
  7756   adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
  7757 }
  7758 
  7759 
  7760 /***********************************************************************
  7761                             Marginal Areas
  7762  ***********************************************************************/
  7763 
  7764 static int
  7765 extract_dimension (Lisp_Object dimension)
  7766 {
  7767   if (NILP (dimension))
  7768     return -1;
  7769   return check_integer_range (dimension, 0, INT_MAX);
  7770 }
  7771 
  7772 static struct window *
  7773 set_window_margins (struct window *w, Lisp_Object left_width,
  7774                     Lisp_Object right_width)
  7775 {
  7776   int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
  7777   int left = NILP (left_width) ? 0 : extract_dimension (left_width);
  7778   int right = NILP (right_width) ? 0 : extract_dimension (right_width);
  7779 
  7780   if (w->left_margin_cols != left || w->right_margin_cols != right)
  7781     {
  7782       /* Don't change anything if new margins won't fit.  */
  7783       if ((WINDOW_PIXEL_WIDTH (w)
  7784            - WINDOW_FRINGES_WIDTH (w)
  7785            - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
  7786            - (left + right) * unit)
  7787           >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
  7788         {
  7789           w->left_margin_cols = left;
  7790           w->right_margin_cols = right;
  7791 
  7792           return w;
  7793         }
  7794       else
  7795         return NULL;
  7796     }
  7797   else
  7798     return NULL;
  7799 }
  7800 
  7801 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
  7802        2, 3, 0,
  7803        doc: /* Set width of marginal areas of window WINDOW.
  7804 WINDOW must be a live window and defaults to the selected one.
  7805 
  7806 Second arg LEFT-WIDTH specifies the number of character cells to
  7807 reserve for the left marginal area.  Optional third arg RIGHT-WIDTH
  7808 does the same for the right marginal area.  A nil width parameter
  7809 means no margin.
  7810 
  7811 Leave margins unchanged if WINDOW is not large enough to accommodate
  7812 margins of the desired width.  Return t if any margin was actually
  7813 changed and nil otherwise.  */)
  7814   (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
  7815 {
  7816   struct window *w = set_window_margins (decode_live_window (window),
  7817                                          left_width, right_width);
  7818   return w ? (apply_window_adjustment (w), Qt) : Qnil;
  7819 }
  7820 
  7821 
  7822 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
  7823        0, 1, 0,
  7824        doc: /* Get width of marginal areas of window WINDOW.
  7825 WINDOW must be a live window and defaults to the selected one.
  7826 
  7827 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
  7828 If a marginal area does not exist, its width will be returned
  7829 as nil.  */)
  7830   (Lisp_Object window)
  7831 {
  7832   struct window *w = decode_live_window (window);
  7833   return Fcons (w->left_margin_cols
  7834                 ? make_fixnum (w->left_margin_cols) : Qnil,
  7835                 w->right_margin_cols
  7836                 ? make_fixnum (w->right_margin_cols) : Qnil);
  7837 }
  7838 
  7839 
  7840 
  7841 /***********************************************************************
  7842                             Fringes
  7843  ***********************************************************************/
  7844 
  7845 static struct window *
  7846 set_window_fringes (struct window *w,
  7847                     Lisp_Object left_width, Lisp_Object right_width,
  7848                     Lisp_Object outside_margins, Lisp_Object persistent)
  7849 {
  7850   /* Do nothing on a tty.  */
  7851   if (!FRAME_WINDOW_P (WINDOW_XFRAME (w)))
  7852     return NULL;
  7853   else
  7854     {
  7855       struct frame *f = XFRAME (WINDOW_FRAME (w));
  7856       int old_left = WINDOW_LEFT_FRINGE_WIDTH (w);
  7857       int old_right = WINDOW_RIGHT_FRINGE_WIDTH (w);
  7858       int new_left = extract_dimension (left_width);
  7859       int new_right = extract_dimension (right_width);
  7860       bool outside = !NILP (outside_margins);
  7861       bool changed = false;
  7862       bool failed = false;
  7863 
  7864       /* Check dimensions of new fringes.  Make changes only if they
  7865          fit the window's dimensions.  */
  7866       if ((WINDOW_PIXEL_WIDTH (w)
  7867            - WINDOW_MARGINS_WIDTH (w)
  7868            - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
  7869            - WINDOW_RIGHT_DIVIDER_WIDTH (w)
  7870            - (new_left == -1 ? FRAME_LEFT_FRINGE_WIDTH (f) : new_left)
  7871            - (new_right == -1 ? FRAME_RIGHT_FRINGE_WIDTH (f) : new_right))
  7872           >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
  7873         {
  7874           w->left_fringe_width = new_left;
  7875           w->right_fringe_width = new_right;
  7876           changed = new_left != old_left || new_right != old_right;
  7877         }
  7878       else
  7879         failed = true;
  7880 
  7881       /* Placing fringes outside margins.  */
  7882       if (outside != w->fringes_outside_margins)
  7883         {
  7884           w->fringes_outside_margins = outside;
  7885           changed = true;
  7886         }
  7887 
  7888       /* Make settings persistent unless we failed to apply some
  7889          changes.  */
  7890       if (!failed)
  7891         w->fringes_persistent = !NILP (persistent);
  7892 
  7893       /* This is needed to trigger immediate redisplay of the window
  7894          when its fringes are changed, because fringes are redrawn
  7895          only if update_window is called, so we must trigger that even
  7896          if the window's glyph matrices did not change at all.  */
  7897       if (changed)
  7898         {
  7899           windows_or_buffers_changed = 35;
  7900           return w;
  7901         }
  7902       else
  7903         return NULL;
  7904     }
  7905 }
  7906 
  7907 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
  7908        2, 5, 0,
  7909        doc: /* Set fringes of specified WINDOW.
  7910 WINDOW must specify a live window and defaults to the selected one.
  7911 
  7912 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
  7913 the left fringe.  Optional third arg RIGHT-WIDTH specifies the right
  7914 fringe width.  If a fringe width arg is nil, that means to use the
  7915 frame's default fringe width.  Default fringe widths can be set with
  7916 the command `set-fringe-style'.
  7917 
  7918 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
  7919 outside of the display margins.  By default, fringes are drawn between
  7920 display marginal areas and the text area.
  7921 
  7922 Optional fifth argument PERSISTENT non-nil means that fringe settings
  7923 for WINDOW are persistent, i.e., remain unchanged when another buffer
  7924 is shown in WINDOW.  PERSISTENT nil means that fringes are reset from
  7925 buffer local values when `set-window-buffer' is called on WINDOW with
  7926 the argument KEEP-MARGINS nil.
  7927 
  7928 Leave fringes unchanged if WINDOW is not large enough to accommodate
  7929 fringes of the desired width.  Return t if any fringe was actually
  7930 changed and nil otherwise.  */)
  7931   (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width,
  7932    Lisp_Object outside_margins, Lisp_Object persistent)
  7933 {
  7934   struct window *w
  7935     = set_window_fringes (decode_live_window (window), left_width,
  7936                           right_width, outside_margins, persistent);
  7937   return w ? (apply_window_adjustment (w), Qt) : Qnil;
  7938 }
  7939 
  7940 
  7941 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
  7942        0, 1, 0,
  7943        doc: /* Return fringe settings for specified WINDOW.
  7944 WINDOW must be a live window and defaults to the selected one.
  7945 
  7946 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS
  7947 PERSISTENT), see `set-window-fringes'.  */)
  7948   (Lisp_Object window)
  7949 {
  7950   struct window *w = decode_live_window (window);
  7951 
  7952   return list4 (make_fixnum (WINDOW_LEFT_FRINGE_WIDTH (w)),
  7953                 make_fixnum (WINDOW_RIGHT_FRINGE_WIDTH (w)),
  7954                 WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil,
  7955                 w->fringes_persistent ? Qt : Qnil);
  7956 }
  7957 
  7958 
  7959 
  7960 /***********************************************************************
  7961                             Scroll bars
  7962  ***********************************************************************/
  7963 
  7964 static struct window *
  7965 set_window_scroll_bars (struct window *w, Lisp_Object width,
  7966                         Lisp_Object vertical_type, Lisp_Object height,
  7967                         Lisp_Object horizontal_type, Lisp_Object persistent)
  7968 {
  7969   /* Do nothing on a tty.  */
  7970   if (!FRAME_WINDOW_P (WINDOW_XFRAME (w)))
  7971     return NULL;
  7972   else
  7973     {
  7974       struct frame *f = XFRAME (WINDOW_FRAME (w));
  7975       int new_width = extract_dimension (width);
  7976       bool changed = false;
  7977       bool failed = false;
  7978 
  7979       if (new_width == 0)
  7980         vertical_type = Qnil;
  7981       else if (!(NILP (vertical_type)
  7982                  || EQ (vertical_type, Qleft)
  7983                  || EQ (vertical_type, Qright)
  7984                  || EQ (vertical_type, Qt)))
  7985         error ("Invalid type of vertical scroll bar");
  7986 
  7987       /* Check dimension of new scroll bar.  Make changes only if it
  7988          fit the window's dimensions.  */
  7989       if ((WINDOW_PIXEL_WIDTH (w)
  7990            - WINDOW_MARGINS_WIDTH (w)
  7991            - WINDOW_FRINGES_WIDTH (w)
  7992            - WINDOW_RIGHT_DIVIDER_WIDTH (w)
  7993            - (new_width == -1 ? FRAME_SCROLL_BAR_AREA_WIDTH (f) : new_width))
  7994           >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
  7995         {
  7996           changed = (!EQ (vertical_type, w->vertical_scroll_bar_type)
  7997                      || new_width != WINDOW_SCROLL_BAR_AREA_WIDTH (w));
  7998           wset_vertical_scroll_bar_type (w, vertical_type);
  7999           w->scroll_bar_width = new_width;
  8000         }
  8001       else
  8002         failed = true;
  8003 
  8004 #if USE_HORIZONTAL_SCROLL_BARS
  8005       int new_height = extract_dimension (height);
  8006 
  8007       if ((MINI_WINDOW_P (w) && !EQ (horizontal_type, Qbottom))
  8008           || new_height == 0)
  8009         horizontal_type = Qnil;
  8010 
  8011       if (!(NILP (horizontal_type)
  8012             || EQ (horizontal_type, Qbottom)
  8013             || EQ (horizontal_type, Qt)))
  8014         error ("Invalid type of horizontal scroll bar");
  8015 
  8016       /* Don't change anything if new scroll bar won't fit.  */
  8017       if ((WINDOW_PIXEL_HEIGHT (w)
  8018            - WINDOW_TAB_LINE_HEIGHT (w)
  8019            - WINDOW_HEADER_LINE_HEIGHT (w)
  8020            - WINDOW_MODE_LINE_HEIGHT (w)
  8021            - (new_height == -1 ? FRAME_SCROLL_BAR_AREA_HEIGHT (f) : new_height))
  8022           >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
  8023         {
  8024           changed = (changed
  8025                      || !EQ (horizontal_type, w->horizontal_scroll_bar_type)
  8026                      || new_height != WINDOW_SCROLL_BAR_AREA_HEIGHT (w));
  8027           wset_horizontal_scroll_bar_type (w, horizontal_type);
  8028           w->scroll_bar_height = new_height;
  8029         }
  8030       else
  8031         failed = true;
  8032 #else
  8033       wset_horizontal_scroll_bar_type (w, Qnil);
  8034 #endif
  8035 
  8036       /* Make settings persistent unless we failed to apply some
  8037          changes.  */
  8038       if (!failed)
  8039         w->scroll_bars_persistent = !NILP (persistent);
  8040 
  8041       /* This is needed to trigger immediate redisplay of the window when
  8042          scroll bars are changed, because scroll bars are redisplayed only
  8043          if more than a single window needs to be considered, see
  8044          redisplay_internal.  */
  8045       if (changed)
  8046         wset_redisplay (w);
  8047 
  8048       return changed ? w : NULL;
  8049     }
  8050 }
  8051 
  8052 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
  8053        Sset_window_scroll_bars, 1, 6, 0,
  8054        doc: /* Set width and type of scroll bars of specified WINDOW.
  8055 WINDOW must specify a live window and defaults to the selected one.
  8056 
  8057 Second argument WIDTH specifies the pixel width for the vertical scroll
  8058 bar.  If WIDTH is nil, use the scroll bar width of WINDOW's frame.
  8059 Third argument VERTICAL-TYPE specifies the type of the vertical scroll
  8060 bar: left, right, nil or t where nil means to not display a vertical
  8061 scroll bar on WINDOW and t means to use WINDOW frame's vertical scroll
  8062 bar type.
  8063 
  8064 Fourth argument HEIGHT specifies the pixel height for the horizontal
  8065 scroll bar.  If HEIGHT is nil, use the scroll bar height of WINDOW's
  8066 frame.  Fifth argument HORIZONTAL-TYPE specifies the type of the
  8067 horizontal scroll bar: bottom, nil, or t where nil means to not
  8068 display a horizontal scroll bar on WINDOW and t means to use WINDOW
  8069 frame's horizontal scroll bar type.  If WINDOW is a mini window, t
  8070 effectively behaves like nil.  HORIZONTAL-TYPE must equal bottom in
  8071 order to show a scroll bar for mini windows.
  8072 
  8073 Optional sixth argument PERSISTENT non-nil means that scroll bar
  8074 settings for WINDOW are persistent, i.e., remain unchanged when
  8075 another buffer is shown in WINDOW.  PERSISTENT nil means that scroll
  8076 bars are reset from buffer local values when `set-window-buffer' is
  8077 called on WINDOW with the argument KEEP-MARGINS nil.
  8078 
  8079 If WINDOW is not large enough to accommodate a scroll bar of the
  8080 desired dimension, leave the corresponding scroll bar unchanged.
  8081 Return t if scroll bars were actually changed and nil otherwise.  */)
  8082   (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type,
  8083    Lisp_Object height, Lisp_Object horizontal_type, Lisp_Object persistent)
  8084 {
  8085   struct window *w
  8086     = set_window_scroll_bars (decode_live_window (window),
  8087                               width, vertical_type, height,
  8088                               horizontal_type, persistent);
  8089   return w ? (apply_window_adjustment (w), Qt) : Qnil;
  8090 }
  8091 
  8092 
  8093 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
  8094        0, 1, 0,
  8095        doc: /* Get width and type of scroll bars of window WINDOW.
  8096 WINDOW must be a live window and defaults to the selected one.
  8097 
  8098 Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES
  8099 HORIZONTAL-TYPE PERSISTENT), see `set-window-scroll-bars'.  If WIDTH
  8100 or HEIGHT is nil or VERTICAL-TYPE or HORIZONTAL-TYPE is t, WINDOW is
  8101 using the frame's corresponding value.  */)
  8102   (Lisp_Object window)
  8103 {
  8104   struct window *w = decode_live_window (window);
  8105 
  8106   return Fcons (((w->scroll_bar_width >= 0)
  8107                  ? make_fixnum (w->scroll_bar_width)
  8108                  : Qnil),
  8109                 Fcons (make_fixnum (WINDOW_SCROLL_BAR_COLS (w)),
  8110                        list5 (w->vertical_scroll_bar_type,
  8111                               ((w->scroll_bar_height >= 0)
  8112                                ? make_fixnum (w->scroll_bar_height)
  8113                                : Qnil),
  8114                               make_fixnum (WINDOW_SCROLL_BAR_LINES (w)),
  8115                               w->horizontal_scroll_bar_type,
  8116                               w->scroll_bars_persistent ? Qt : Qnil)));
  8117 }
  8118 
  8119 /***********************************************************************
  8120                            Smooth scrolling
  8121  ***********************************************************************/
  8122 
  8123 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
  8124        doc: /* Return the amount by which WINDOW is scrolled vertically.
  8125 This takes effect when displaying tall lines or images.
  8126 
  8127 If WINDOW is omitted or nil, it defaults to the selected window.
  8128 Normally, value is a multiple of the canonical character height of WINDOW;
  8129 optional second arg PIXELS-P means value is measured in pixels.  */)
  8130   (Lisp_Object window, Lisp_Object pixels_p)
  8131 {
  8132   Lisp_Object result;
  8133   struct window *w = decode_live_window (window);
  8134   struct frame *f = XFRAME (w->frame);
  8135 
  8136   if (FRAME_WINDOW_P (f))
  8137     result = (NILP (pixels_p)
  8138               ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
  8139               : make_fixnum (-w->vscroll));
  8140   else
  8141     result = make_fixnum (0);
  8142   return result;
  8143 }
  8144 
  8145 
  8146 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
  8147        2, 4, 0,
  8148        doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
  8149 This takes effect when displaying tall lines or images.
  8150 
  8151 WINDOW nil means use the selected window.  Normally, VSCROLL is a
  8152 non-negative multiple of the canonical character height of WINDOW;
  8153 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
  8154 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
  8155 corresponds to an integral number of pixels.  The return value is the
  8156 result of this rounding.
  8157 If PIXELS-P is non-nil, the return value is VSCROLL.
  8158 
  8159 PRESERVE-VSCROLL-P makes setting the start of WINDOW preserve the
  8160 vscroll if its start is "frozen" due to a resized mini-window.  */)
  8161   (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p,
  8162    Lisp_Object preserve_vscroll_p)
  8163 {
  8164   struct window *w = decode_live_window (window);
  8165   struct frame *f = XFRAME (w->frame);
  8166 
  8167   CHECK_NUMBER (vscroll);
  8168 
  8169   if (FRAME_WINDOW_P (f))
  8170     {
  8171       int old_dy = w->vscroll;
  8172 
  8173       w->vscroll = - (NILP (pixels_p)
  8174                       ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
  8175                       : XFLOATINT (vscroll));
  8176       w->vscroll = min (w->vscroll, 0);
  8177 
  8178       if (w->vscroll != old_dy)
  8179         {
  8180           /* Adjust glyph matrix of the frame if the virtual display
  8181              area becomes larger than before.  */
  8182           if (w->vscroll < 0 && w->vscroll < old_dy)
  8183             adjust_frame_glyphs (f);
  8184 
  8185           /* Prevent redisplay shortcuts.  */
  8186           XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
  8187 
  8188           /* Mark W for redisplay.  (bug#55299) */
  8189           wset_redisplay (w);
  8190         }
  8191 
  8192       w->preserve_vscroll_p = !NILP (preserve_vscroll_p);
  8193     }
  8194 
  8195   return Fwindow_vscroll (window, pixels_p);
  8196 }
  8197 
  8198 
  8199 /* Call FN for all leaf windows on frame F.  FN is called with the
  8200    first argument being a pointer to the leaf window, and with
  8201    additional argument USER_DATA.  Stops when FN returns 0.  */
  8202 
  8203 static void
  8204 foreach_window (struct frame *f, bool (*fn) (struct window *, void *),
  8205                 void *user_data)
  8206 {
  8207   /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil.  */
  8208   if (WINDOWP (FRAME_ROOT_WINDOW (f)))
  8209     foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
  8210 }
  8211 
  8212 
  8213 /* Helper function for foreach_window.  Call FN for all leaf windows
  8214    reachable from W.  FN is called with the first argument being a
  8215    pointer to the leaf window, and with additional argument USER_DATA.
  8216    Stop when FN returns false.  Value is false if stopped by FN.  */
  8217 
  8218 static bool
  8219 foreach_window_1 (struct window *w, bool (*fn) (struct window *, void *),
  8220                   void *user_data)
  8221 {
  8222   bool cont;
  8223 
  8224   for (cont = true; w && cont;)
  8225     {
  8226       if (WINDOWP (w->contents))
  8227         cont = foreach_window_1 (XWINDOW (w->contents), fn, user_data);
  8228       else
  8229         cont = fn (w, user_data);
  8230 
  8231       w = NILP (w->next) ? 0 : XWINDOW (w->next);
  8232     }
  8233 
  8234   return cont;
  8235 }
  8236 
  8237 /***********************************************************************
  8238                             Initialization
  8239  ***********************************************************************/
  8240 
  8241 /* Return true if window configurations CONFIGURATION1 and CONFIGURATION2
  8242    describe the same state of affairs.  This is used by Fequal.
  8243 
  8244    Ignore non-matching scroll positions and the like.
  8245 
  8246    This ignores a couple of things like the dedication status of
  8247    window, combination_limit and the like.  This might have to be
  8248    fixed.  */
  8249 
  8250 static bool
  8251 compare_window_configurations (Lisp_Object configuration1,
  8252                                Lisp_Object configuration2)
  8253 {
  8254   struct save_window_data *d1, *d2;
  8255   struct Lisp_Vector *sws1, *sws2;
  8256   ptrdiff_t i;
  8257 
  8258   CHECK_WINDOW_CONFIGURATION (configuration1);
  8259   CHECK_WINDOW_CONFIGURATION (configuration2);
  8260 
  8261   d1 = (struct save_window_data *) XVECTOR (configuration1);
  8262   d2 = (struct save_window_data *) XVECTOR (configuration2);
  8263   sws1 = XVECTOR (d1->saved_windows);
  8264   sws2 = XVECTOR (d2->saved_windows);
  8265 
  8266   /* Frame settings must match.  */
  8267   if (d1->frame_cols != d2->frame_cols
  8268       || d1->frame_lines != d2->frame_lines
  8269       || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
  8270       || !EQ (d1->selected_frame, d2->selected_frame)
  8271       || !EQ (d1->f_current_buffer, d2->f_current_buffer)
  8272       || !EQ (d1->focus_frame, d2->focus_frame)
  8273       /* Verify that the two configurations have the same number of windows.  */
  8274       || sws1->header.size != sws2->header.size)
  8275     return false;
  8276 
  8277   for (i = 0; i < sws1->header.size; i++)
  8278     {
  8279       struct saved_window *sw1, *sw2;
  8280 
  8281       sw1 = SAVED_WINDOW_N (sws1, i);
  8282       sw2 = SAVED_WINDOW_N (sws2, i);
  8283 
  8284       if (
  8285            /* The "current" windows in the two configurations must
  8286               correspond to each other.  */
  8287           EQ (d1->current_window, sw1->window)
  8288           != EQ (d2->current_window, sw2->window)
  8289           /* Windows' buffers must match.  */
  8290           || !EQ (sw1->buffer, sw2->buffer)
  8291           || !EQ (sw1->pixel_left, sw2->pixel_left)
  8292           || !EQ (sw1->pixel_top, sw2->pixel_top)
  8293           || !EQ (sw1->pixel_height, sw2->pixel_height)
  8294           || !EQ (sw1->pixel_width, sw2->pixel_width)
  8295           || !EQ (sw1->left_col, sw2->left_col)
  8296           || !EQ (sw1->top_line, sw2->top_line)
  8297           || !EQ (sw1->total_cols, sw2->total_cols)
  8298           || !EQ (sw1->total_lines, sw2->total_lines)
  8299           || !EQ (sw1->display_table, sw2->display_table)
  8300           /* The next two disjuncts check the window structure for
  8301              equality.  */
  8302           || !EQ (sw1->parent, sw2->parent)
  8303           || !EQ (sw1->prev, sw2->prev)
  8304           || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
  8305           || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
  8306           || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
  8307           || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
  8308           || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
  8309           || !EQ (sw1->fringes_persistent, sw2->fringes_persistent)
  8310           || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
  8311           || !EQ (sw1->scroll_bar_height, sw2->scroll_bar_height)
  8312           || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type)
  8313           || !EQ (sw1->horizontal_scroll_bar_type, sw2->horizontal_scroll_bar_type)
  8314           || !EQ (sw1->scroll_bars_persistent, sw2->scroll_bars_persistent))
  8315         return false;
  8316     }
  8317 
  8318   return true;
  8319 }
  8320 
  8321 DEFUN ("window-configuration-equal-p", Fwindow_configuration_equal_p,
  8322        Swindow_configuration_equal_p, 2, 2, 0,
  8323        doc: /* Say whether two window configurations have the same window layout.
  8324 This function ignores details such as the values of point and
  8325 scrolling positions.  */)
  8326   (Lisp_Object x, Lisp_Object y)
  8327 {
  8328   if (compare_window_configurations (x, y))
  8329     return Qt;
  8330   return Qnil;
  8331 }
  8332 
  8333 
  8334 static void init_window_once_for_pdumper (void);
  8335 
  8336 void
  8337 init_window_once (void)
  8338 {
  8339   minibuf_window = Qnil;
  8340   staticpro (&minibuf_window);
  8341 
  8342   selected_window = Qnil;
  8343   staticpro (&selected_window);
  8344 
  8345   Vwindow_list = Qnil;
  8346   staticpro (&Vwindow_list);
  8347 
  8348   minibuf_selected_window = Qnil;
  8349   staticpro (&minibuf_selected_window);
  8350   old_selected_window = Qnil;
  8351   staticpro (&old_selected_window);
  8352 
  8353   pdumper_do_now_and_after_late_load (init_window_once_for_pdumper);
  8354 }
  8355 
  8356 static void init_window_once_for_pdumper (void)
  8357 {
  8358   window_scroll_pixel_based_preserve_x = -1;
  8359   window_scroll_pixel_based_preserve_y = -1;
  8360   window_scroll_preserve_hpos = -1;
  8361   window_scroll_preserve_vpos = -1;
  8362   PDUMPER_IGNORE (sequence_number);
  8363 
  8364   PDUMPER_RESET_LV (minibuf_window, Qnil);
  8365   PDUMPER_RESET_LV (selected_window, Qnil);
  8366   PDUMPER_RESET_LV (Vwindow_list, Qnil);
  8367   PDUMPER_RESET_LV (minibuf_selected_window, Qnil);
  8368 
  8369   /* Hack: if mode_line_in_non_selected_windows is true (which it may
  8370      be, if we're restoring from a dump) the guts of
  8371      make_initial_frame will try to access selected_window, which is
  8372      invalid at this point, and lose.  For the purposes of creating
  8373      the initial frame and window, this variable must be false.  */
  8374   bool old_mode_line_in_non_selected_windows;
  8375 
  8376   /* Snapshot dumped_with_pdumper to suppress compiler warning.  */
  8377   bool saved_dumped_with_pdumper = dumped_with_pdumper_p ();
  8378   if (saved_dumped_with_pdumper)
  8379     {
  8380       old_mode_line_in_non_selected_windows
  8381         = mode_line_in_non_selected_windows;
  8382       mode_line_in_non_selected_windows = false;
  8383     }
  8384   struct frame *f = make_initial_frame ();
  8385   if (saved_dumped_with_pdumper)
  8386     mode_line_in_non_selected_windows =
  8387       old_mode_line_in_non_selected_windows;
  8388   XSETFRAME (selected_frame, f);
  8389   old_selected_frame = Vterminal_frame = selected_frame;
  8390   minibuf_window = f->minibuffer_window;
  8391   old_selected_window = selected_window = f->selected_window;
  8392 }
  8393 
  8394 void
  8395 init_window (void)
  8396 {
  8397   Vwindow_list = Qnil;
  8398 }
  8399 
  8400 void
  8401 syms_of_window (void)
  8402 {
  8403   DEFSYM (Qscroll_up, "scroll-up");
  8404   DEFSYM (Qscroll_down, "scroll-down");
  8405   DEFSYM (Qscroll_command, "scroll-command");
  8406 
  8407   Fput (Qscroll_up, Qscroll_command, Qt);
  8408   Fput (Qscroll_down, Qscroll_command, Qt);
  8409 
  8410   DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
  8411   DEFSYM (Qwindow_state_change_hook, "window-state-change-hook");
  8412   DEFSYM (Qwindow_state_change_functions, "window-state-change-functions");
  8413   DEFSYM (Qwindow_size_change_functions, "window-size-change-functions");
  8414   DEFSYM (Qwindow_buffer_change_functions, "window-buffer-change-functions");
  8415   DEFSYM (Qwindow_selection_change_functions, "window-selection-change-functions");
  8416   DEFSYM (Qwindowp, "windowp");
  8417   DEFSYM (Qwindow_configuration_p, "window-configuration-p");
  8418   DEFSYM (Qwindow_live_p, "window-live-p");
  8419   DEFSYM (Qwindow_valid_p, "window-valid-p");
  8420   DEFSYM (Qwindow_deletable_p, "window-deletable-p");
  8421   DEFSYM (Qdelete_window, "delete-window");
  8422   DEFSYM (Qwindow__resize_root_window, "window--resize-root-window");
  8423   DEFSYM (Qwindow__resize_root_window_vertically,
  8424           "window--resize-root-window-vertically");
  8425   DEFSYM (Qwindow__resize_mini_frame, "window--resize-mini-frame");
  8426   DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
  8427   DEFSYM (Qsafe, "safe");
  8428   DEFSYM (Qdisplay_buffer, "display-buffer");
  8429   DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
  8430   DEFSYM (Qrecord_window_buffer, "record-window-buffer");
  8431   DEFSYM (Qget_mru_window, "get-mru-window");
  8432   DEFSYM (Qwindow_size, "window-size");
  8433   DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
  8434   DEFSYM (Qabove, "above");
  8435   DEFSYM (Qclone_of, "clone-of");
  8436   DEFSYM (Qfloor, "floor");
  8437   DEFSYM (Qceiling, "ceiling");
  8438   DEFSYM (Qmark_for_redisplay, "mark-for-redisplay");
  8439   DEFSYM (Qmode_line_format, "mode-line-format");
  8440   DEFSYM (Qheader_line_format, "header-line-format");
  8441   DEFSYM (Qtab_line_format, "tab-line-format");
  8442   DEFSYM (Qno_other_window, "no-other-window");
  8443 
  8444   DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
  8445                doc: /* Non-nil means call as function to display a help buffer.
  8446 The function is called with one argument, the buffer to be displayed.
  8447 Used by `with-output-to-temp-buffer'.
  8448 If this function is used, then it must do the entire job of showing
  8449 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.  */);
  8450   Vtemp_buffer_show_function = Qnil;
  8451 
  8452   DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
  8453                doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll.  */);
  8454   Vminibuf_scroll_window = Qnil;
  8455 
  8456   DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
  8457                doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
  8458 If the minibuffer is active, the `minibuffer-scroll-window' mode line
  8459 is displayed in the `mode-line' face.  */);
  8460   mode_line_in_non_selected_windows = true;
  8461 
  8462   DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
  8463                doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window.  */);
  8464   Vother_window_scroll_buffer = Qnil;
  8465 
  8466   DEFVAR_LISP ("other-window-scroll-default", Vother_window_scroll_default,
  8467                doc: /* Function that provides the window to scroll by \\[scroll-other-window].
  8468 The function `other-window-for-scrolling' first tries to use
  8469 `minibuffer-scroll-window' and `other-window-scroll-buffer'.
  8470 But when both are nil, then by default it uses a neighboring window.
  8471 This variable is intended to get another default instead of `next-window'.  */);
  8472   Vother_window_scroll_default = Qnil;
  8473 
  8474   DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
  8475                doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines.  */);
  8476   auto_window_vscroll_p = true;
  8477 
  8478   DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
  8479               doc: /* Number of lines of continuity when scrolling by screenfuls.  */);
  8480   next_screen_context_lines = 2;
  8481 
  8482   DEFVAR_LISP ("scroll-preserve-screen-position",
  8483                Vscroll_preserve_screen_position,
  8484                doc: /* Controls if scroll commands move point to keep its screen position unchanged.
  8485 
  8486 A value of nil means point does not keep its screen position except
  8487 at the scroll margin or window boundary respectively.
  8488 
  8489 A value of t means point keeps its screen position if the scroll
  8490 command moved it vertically out of the window, e.g. when scrolling
  8491 by full screens.  If point is within `next-screen-context-lines' lines
  8492 from the edges of the window, point will typically not keep its screen
  8493 position when doing commands like `scroll-up-command'/`scroll-down-command'
  8494 and the like.
  8495 
  8496 Any other value means point always keeps its screen position.
  8497 Scroll commands should have the `scroll-command' property
  8498 on their symbols to be controlled by this variable.  */);
  8499   Vscroll_preserve_screen_position = Qnil;
  8500 
  8501   DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
  8502                doc: /* Insertion type of marker to use for `window-point'.
  8503 See `marker-insertion-type' for the meaning of the possible values.  */);
  8504   Vwindow_point_insertion_type = Qnil;
  8505   DEFSYM (Qwindow_point_insertion_type, "window-point-insertion-type");
  8506 
  8507   DEFVAR_LISP ("window-buffer-change-functions", Vwindow_buffer_change_functions,
  8508                doc: /* Functions called during redisplay when window buffers have changed.
  8509 The value should be a list of functions that take one argument.
  8510 
  8511 Functions specified buffer-locally are called for each window showing
  8512 the corresponding buffer if and only if that window has been added or
  8513 changed its buffer since the last redisplay.  In this case the window
  8514 is passed as argument.
  8515 
  8516 Functions specified by the default value are called for each frame if
  8517 at least one window on that frame has been added, deleted or changed
  8518 its buffer since the last redisplay.  In this case the frame is passed
  8519 as argument.  */);
  8520   Vwindow_buffer_change_functions = Qnil;
  8521 
  8522   DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions,
  8523                doc: /* Functions called during redisplay when window sizes have changed.
  8524 The value should be a list of functions that take one argument.
  8525 
  8526 Functions specified buffer-locally are called for each window showing
  8527 the corresponding buffer if and only if that window has been added or
  8528 changed its buffer or its total or body size since the last redisplay.
  8529 In this case the window is passed as argument.
  8530 
  8531 Functions specified by the default value are called for each frame if
  8532 at least one window on that frame has been added or changed its buffer
  8533 or its total or body size since the last redisplay.  In this case the
  8534 frame is passed as argument.
  8535 
  8536 For instance, to hide the title bar when the frame is maximized, you
  8537 can add `frame-hide-title-bar-when-maximized' to this variable.  */);
  8538   Vwindow_size_change_functions = Qnil;
  8539 
  8540   DEFVAR_LISP ("window-selection-change-functions", Vwindow_selection_change_functions,
  8541                doc: /* Functions called during redisplay when the selected window has changed.
  8542 The value should be a list of functions that take one argument.
  8543 
  8544 Functions specified buffer-locally are called for each window showing
  8545 the corresponding buffer if and only if that window has been selected
  8546 or deselected since the last redisplay.  In this case the window is
  8547 passed as argument.
  8548 
  8549 Functions specified by the default value are called for each frame if
  8550 the frame's selected window has changed since the last redisplay.  In
  8551 this case the frame is passed as argument.  */);
  8552   Vwindow_selection_change_functions = Qnil;
  8553 
  8554   DEFVAR_LISP ("window-state-change-functions", Vwindow_state_change_functions,
  8555                doc: /* Functions called during redisplay when the window state changed.
  8556 The value should be a list of functions that take one argument.
  8557 
  8558 Functions specified buffer-locally are called for each window showing
  8559 the corresponding buffer if and only if that window has been added,
  8560 resized, changed its buffer or has been (de-)selected since the last
  8561 redisplay.  In this case the window is passed as argument.
  8562 
  8563 Functions specified by the default value are called for each frame if
  8564 at least one window on that frame has been added, deleted, changed its
  8565 buffer or its total or body size or the frame has been (de-)selected,
  8566 its selected window has changed or the window state change flag has
  8567 been set for this frame since the last redisplay.  In this case the
  8568 frame is passed as argument.  */);
  8569   Vwindow_state_change_functions = Qnil;
  8570 
  8571   DEFVAR_LISP ("window-state-change-hook", Vwindow_state_change_hook,
  8572                doc: /* Functions called during redisplay when the window state changed.
  8573 The value should be a list of functions that take no argument.
  8574 
  8575 This hook is called during redisplay when at least one window has been
  8576 added, deleted, (de-)selected, changed its buffer or its total or body
  8577 size or the window state change flag has been set for at least one
  8578 frame.  This hook is called after all other window change functions
  8579 have been run and should be used only if a function should react to
  8580 changes that happened on at least two frames since last redisplay or
  8581 the function intends to change the window configuration.  */);
  8582   Vwindow_state_change_hook = Qnil;
  8583 
  8584   DEFVAR_LISP ("window-configuration-change-hook", Vwindow_configuration_change_hook,
  8585                doc: /* Functions called during redisplay when window configuration has changed.
  8586 The value should be a list of functions that take no argument.
  8587 
  8588 Functions specified buffer-locally are called for each window showing
  8589 the corresponding buffer if at least one window on that frame has been
  8590 added, deleted or changed its buffer or its total or body size since
  8591 the last redisplay.  Each call is performed with the window showing
  8592 the buffer temporarily selected.
  8593 
  8594 Functions specified by the default value are called for each frame if
  8595 at least one window on that frame has been added, deleted or changed
  8596 its buffer or its total or body size since the last redisplay.  Each
  8597 call is performed with the frame temporarily selected.  */);
  8598   Vwindow_configuration_change_hook = Qnil;
  8599 
  8600   DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
  8601                doc: /* Non-nil means `recenter' redraws entire frame.
  8602 If this option is non-nil, then the `recenter' command with a nil
  8603 argument will redraw the entire frame; the special value `tty' causes
  8604 the frame to be redrawn only if it is a tty frame.  */);
  8605   Vrecenter_redisplay = Qtty;
  8606 
  8607   DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
  8608                doc: /* If t, resize window combinations proportionally.
  8609 If this variable is nil, splitting a window gets the entire screen space
  8610 for displaying the new window from the window to split.  Deleting and
  8611 resizing a window preferably resizes one adjacent window only.
  8612 
  8613 If this variable is t, splitting a window tries to get the space
  8614 proportionally from all windows in the same combination.  This also
  8615 allows splitting a window that is otherwise too small or of fixed size.
  8616 Resizing and deleting a window proportionally resize all windows in the
  8617 same combination.
  8618 
  8619 Other values are reserved for future use.
  8620 
  8621 A specific split operation may ignore the value of this variable if it
  8622 is affected by a non-nil value of `window-combination-limit'.  */);
  8623   Vwindow_combination_resize = Qnil;
  8624 
  8625   DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
  8626                doc: /* If non-nil, splitting a window makes a new parent window.
  8627 The following values are recognized:
  8628 
  8629 nil means splitting a window will create a new parent window only if the
  8630     window has no parent window or the window shall become part of a
  8631     combination orthogonal to the one it is part of.
  8632 
  8633 `window-size' means that splitting a window for displaying a buffer
  8634     makes a new parent window provided `display-buffer' is supposed to
  8635     explicitly set the window's size due to the presence of a
  8636     `window-height' or `window-width' entry in the alist used by
  8637     `display-buffer'.  Otherwise, this value is handled like nil.
  8638 
  8639 `temp-buffer-resize' means that splitting a window for displaying a
  8640     temporary buffer via `with-temp-buffer-window' makes a new parent
  8641     window only if `temp-buffer-resize-mode' is enabled.  Otherwise,
  8642     this value is handled like nil.
  8643 
  8644 `temp-buffer' means that splitting a window for displaying a temporary
  8645     buffer via `with-temp-buffer-window' always makes a new parent
  8646     window.  Otherwise, this value is handled like nil.
  8647 
  8648 `display-buffer' means that splitting a window for displaying a buffer
  8649     always makes a new parent window.  Since temporary buffers are
  8650     displayed by the function `display-buffer', this value is stronger
  8651     than `temp-buffer'.  Splitting a window for other purpose makes a
  8652     new parent window only if needed.
  8653 
  8654 t means that splitting a window always creates a new parent window.  If
  8655     all splits behave this way, each frame's window tree is a binary
  8656     tree and every window but the frame's root window has exactly one
  8657     sibling.
  8658 
  8659 The default value is `window-size'.  Other values are reserved for
  8660 future use.  */);
  8661   Vwindow_combination_limit = Qwindow_size;
  8662 
  8663   DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
  8664                doc: /* Alist of persistent window parameters.
  8665 This alist specifies which window parameters shall get saved by
  8666 `current-window-configuration' and `window-state-get' and subsequently
  8667 restored to their previous values by `set-window-configuration' and
  8668 `window-state-put'.
  8669 
  8670 The car of each entry of this alist is the symbol specifying the
  8671 parameter.  The cdr is one of the following:
  8672 
  8673 nil means the parameter is neither saved by `window-state-get' nor by
  8674 `current-window-configuration'.
  8675 
  8676 t means the parameter is saved by `current-window-configuration' and,
  8677 provided its WRITABLE argument is nil, by `window-state-get'.
  8678 
  8679 The symbol `writable' means the parameter is saved unconditionally by
  8680 both `current-window-configuration' and `window-state-get'.  Do not use
  8681 this value for parameters without read syntax (like windows or frames).
  8682 
  8683 Parameters not saved by `current-window-configuration' or
  8684 `window-state-get' are left alone by `set-window-configuration'
  8685 respectively are not installed by `window-state-put'.  */);
  8686   Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
  8687 
  8688   DEFVAR_BOOL ("window-resize-pixelwise", window_resize_pixelwise,
  8689                doc: /*  Non-nil means resize windows pixelwise.
  8690 This currently affects the functions: `split-window', `maximize-window',
  8691 `minimize-window', `fit-window-to-buffer' and `fit-frame-to-buffer', and
  8692 all functions that symmetrically resize a parent window.
  8693 
  8694 Note that when a frame's pixel size is not a multiple of the
  8695 frame's character size, at least one window may get resized
  8696 pixelwise even if this option is nil.  */);
  8697   window_resize_pixelwise = false;
  8698 
  8699   DEFVAR_BOOL ("fast-but-imprecise-scrolling",
  8700                fast_but_imprecise_scrolling,
  8701                doc: /* When non-nil, accelerate scrolling operations.
  8702 This comes into play when scrolling rapidly over previously
  8703 unfontified buffer regions.  Only those portions of the buffer which
  8704 are actually going to be displayed get fontified.
  8705 
  8706 Note that this optimization can cause the portion of the buffer
  8707 displayed after a scrolling operation to be somewhat inaccurate.  */);
  8708   fast_but_imprecise_scrolling = false;
  8709 
  8710   defsubr (&Sselected_window);
  8711   defsubr (&Sold_selected_window);
  8712   defsubr (&Sminibuffer_window);
  8713   defsubr (&Swindow_minibuffer_p);
  8714   defsubr (&Swindowp);
  8715   defsubr (&Swindow_valid_p);
  8716   defsubr (&Swindow_live_p);
  8717   defsubr (&Swindow_frame);
  8718   defsubr (&Sframe_root_window);
  8719   defsubr (&Sframe_first_window);
  8720   defsubr (&Sframe_selected_window);
  8721   defsubr (&Sframe_old_selected_window);
  8722   defsubr (&Sset_frame_selected_window);
  8723   defsubr (&Spos_visible_in_window_p);
  8724   defsubr (&Swindow_line_height);
  8725   defsubr (&Swindow_buffer);
  8726   defsubr (&Swindow_old_buffer);
  8727   defsubr (&Swindow_parent);
  8728   defsubr (&Swindow_top_child);
  8729   defsubr (&Swindow_left_child);
  8730   defsubr (&Swindow_next_sibling);
  8731   defsubr (&Swindow_prev_sibling);
  8732   defsubr (&Swindow_combination_limit);
  8733   defsubr (&Sset_window_combination_limit);
  8734   defsubr (&Swindow_use_time);
  8735   defsubr (&Swindow_pixel_width);
  8736   defsubr (&Swindow_pixel_height);
  8737   defsubr (&Swindow_old_pixel_width);
  8738   defsubr (&Swindow_old_pixel_height);
  8739   defsubr (&Swindow_old_body_pixel_width);
  8740   defsubr (&Swindow_old_body_pixel_height);
  8741   defsubr (&Swindow_total_width);
  8742   defsubr (&Swindow_total_height);
  8743   defsubr (&Swindow_normal_size);
  8744   defsubr (&Swindow_new_pixel);
  8745   defsubr (&Swindow_new_total);
  8746   defsubr (&Swindow_new_normal);
  8747   defsubr (&Swindow_pixel_left);
  8748   defsubr (&Swindow_pixel_top);
  8749   defsubr (&Swindow_left_column);
  8750   defsubr (&Swindow_top_line);
  8751   defsubr (&Sset_window_new_pixel);
  8752   defsubr (&Sset_window_new_total);
  8753   defsubr (&Sset_window_new_normal);
  8754   defsubr (&Swindow_resize_apply);
  8755   defsubr (&Swindow_resize_apply_total);
  8756   defsubr (&Swindow_body_height);
  8757   defsubr (&Swindow_body_width);
  8758   defsubr (&Swindow_hscroll);
  8759   defsubr (&Sset_window_hscroll);
  8760   defsubr (&Swindow_mode_line_height);
  8761   defsubr (&Swindow_header_line_height);
  8762   defsubr (&Swindow_tab_line_height);
  8763   defsubr (&Swindow_right_divider_width);
  8764   defsubr (&Swindow_bottom_divider_width);
  8765   defsubr (&Swindow_scroll_bar_width);
  8766   defsubr (&Swindow_scroll_bar_height);
  8767   defsubr (&Scoordinates_in_window_p);
  8768   defsubr (&Swindow_at);
  8769   defsubr (&Swindow_point);
  8770   defsubr (&Swindow_old_point);
  8771   defsubr (&Swindow_start);
  8772   defsubr (&Swindow_end);
  8773   defsubr (&Sset_window_point);
  8774   defsubr (&Sset_window_start);
  8775   defsubr (&Swindow_dedicated_p);
  8776   defsubr (&Swindow_lines_pixel_dimensions);
  8777   defsubr (&Sset_window_dedicated_p);
  8778   defsubr (&Swindow_display_table);
  8779   defsubr (&Sset_window_display_table);
  8780   defsubr (&Snext_window);
  8781   defsubr (&Sprevious_window);
  8782   defsubr (&Sget_buffer_window);
  8783   defsubr (&Sdelete_other_windows_internal);
  8784   defsubr (&Sdelete_window_internal);
  8785   defsubr (&Sresize_mini_window_internal);
  8786   defsubr (&Sset_window_buffer);
  8787   defsubr (&Srun_window_configuration_change_hook);
  8788   defsubr (&Srun_window_scroll_functions);
  8789   defsubr (&Sselect_window);
  8790   defsubr (&Sforce_window_update);
  8791   defsubr (&Ssplit_window_internal);
  8792   defsubr (&Sscroll_up);
  8793   defsubr (&Sscroll_down);
  8794   defsubr (&Sscroll_left);
  8795   defsubr (&Sscroll_right);
  8796   defsubr (&Sother_window_for_scrolling);
  8797   defsubr (&Sminibuffer_selected_window);
  8798   defsubr (&Srecenter);
  8799   defsubr (&Swindow_text_width);
  8800   defsubr (&Swindow_text_height);
  8801   defsubr (&Smove_to_window_line);
  8802   defsubr (&Swindow_configuration_p);
  8803   defsubr (&Swindow_configuration_frame);
  8804   defsubr (&Sset_window_configuration);
  8805   defsubr (&Scurrent_window_configuration);
  8806   defsubr (&Sset_window_margins);
  8807   defsubr (&Swindow_margins);
  8808   defsubr (&Sset_window_fringes);
  8809   defsubr (&Swindow_fringes);
  8810   defsubr (&Sset_window_scroll_bars);
  8811   defsubr (&Swindow_scroll_bars);
  8812   defsubr (&Swindow_vscroll);
  8813   defsubr (&Sset_window_vscroll);
  8814   defsubr (&Swindow_configuration_equal_p);
  8815   defsubr (&Swindow_bump_use_time);
  8816   defsubr (&Swindow_list);
  8817   defsubr (&Swindow_list_1);
  8818   defsubr (&Swindow_prev_buffers);
  8819   defsubr (&Sset_window_prev_buffers);
  8820   defsubr (&Swindow_next_buffers);
  8821   defsubr (&Sset_window_next_buffers);
  8822   defsubr (&Swindow_parameters);
  8823   defsubr (&Swindow_parameter);
  8824   defsubr (&Sset_window_parameter);
  8825 }

/* [<][>][^][v][top][bottom][index][help] */