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   call1 (Qreplace_buffer_in_windows, buffer);
  3518 }
  3519 
  3520 /* If BUFFER is shown in a window, safely replace it with some other
  3521    buffer in all windows of all frames, even those on other keyboards.  */
  3522 
  3523 void
  3524 replace_buffer_in_windows_safely (Lisp_Object buffer)
  3525 {
  3526   if (buffer_window_count (XBUFFER (buffer)))
  3527     {
  3528       Lisp_Object tail, frame;
  3529 
  3530       /* A single call to window_loop won't do the job because it only
  3531          considers frames on the current keyboard.  So loop manually over
  3532          frames, and handle each one.  */
  3533       FOR_EACH_FRAME (tail, frame)
  3534         window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, true, frame);
  3535     }
  3536 }
  3537 
  3538 /* The following three routines are needed for running a window's
  3539    configuration change hook.  */
  3540 static void
  3541 run_funs (Lisp_Object funs)
  3542 {
  3543   for (; CONSP (funs); funs = XCDR (funs))
  3544     if (!EQ (XCAR (funs), Qt))
  3545       call0 (XCAR (funs));
  3546 }
  3547 
  3548 static void
  3549 select_window_norecord (Lisp_Object window)
  3550 {
  3551   if (WINDOW_LIVE_P (window))
  3552     Fselect_window (window, Qt);
  3553 }
  3554 
  3555 static void
  3556 select_frame_norecord (Lisp_Object frame)
  3557 {
  3558   if (FRAME_LIVE_P (XFRAME (frame)))
  3559     Fselect_frame (frame, Qt);
  3560 }
  3561 
  3562 /**
  3563  * run_window_configuration_change_hook:
  3564  *
  3565  * Run any functions on 'window-configuration-change-hook' for the
  3566  * frame specified by F.  The buffer-local values are run with the
  3567  * window showing the buffer selected.  The default value is run with
  3568  * the frame specified by F selected.  All functions are called with
  3569  * the selected window's buffer current.
  3570  */
  3571 static void
  3572 run_window_configuration_change_hook (struct frame *f)
  3573 {
  3574   specpdl_ref count = SPECPDL_INDEX ();
  3575   Lisp_Object frame, global_wcch
  3576     = Fdefault_value (Qwindow_configuration_change_hook);
  3577   XSETFRAME (frame, f);
  3578 
  3579   if (NILP (Vrun_hooks)
  3580       || !f->can_set_window_size
  3581       || !f->after_make_frame)
  3582     return;
  3583 
  3584   /* Use the right buffer.  Matters when running the local hooks.  */
  3585   if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
  3586     {
  3587       record_unwind_current_buffer ();
  3588       Fset_buffer (Fwindow_buffer (Qnil));
  3589     }
  3590 
  3591   if (SELECTED_FRAME () != f)
  3592     {
  3593       record_unwind_protect (select_frame_norecord, selected_frame);
  3594       select_frame_norecord (frame);
  3595     }
  3596 
  3597   /* Look for buffer-local values.  */
  3598   {
  3599     Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
  3600     for (; CONSP (windows); windows = XCDR (windows))
  3601       {
  3602         Lisp_Object window = XCAR (windows);
  3603         Lisp_Object buffer = Fwindow_buffer (window);
  3604         if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
  3605                                       buffer)))
  3606           {
  3607             specpdl_ref inner_count = SPECPDL_INDEX ();
  3608             record_unwind_protect (select_window_norecord, selected_window);
  3609             select_window_norecord (window);
  3610             run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
  3611                                            buffer));
  3612             unbind_to (inner_count, Qnil);
  3613           }
  3614       }
  3615   }
  3616 
  3617   run_funs (global_wcch);
  3618   unbind_to (count, Qnil);
  3619 }
  3620 
  3621 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
  3622        Srun_window_configuration_change_hook, 0, 1, 0,
  3623        doc: /* Run `window-configuration-change-hook' for FRAME.
  3624 If FRAME is omitted or nil, it defaults to the selected frame.
  3625 
  3626 This function should not be needed any more and will be therefore
  3627 considered obsolete.  */)
  3628   (Lisp_Object frame)
  3629 {
  3630   run_window_configuration_change_hook (decode_live_frame (frame));
  3631   return Qnil;
  3632 }
  3633 
  3634 DEFUN ("run-window-scroll-functions", Frun_window_scroll_functions,
  3635        Srun_window_scroll_functions, 0, 1, 0,
  3636        doc: /* Run `window-scroll-functions' for WINDOW.
  3637 If WINDOW is omitted or nil, it defaults to the selected window.
  3638 
  3639 This function is called by `split-window' for the new window, after it
  3640 has established the size of the new window.  */)
  3641   (Lisp_Object window)
  3642 {
  3643   struct window *w = decode_live_window (window);
  3644   specpdl_ref count = SPECPDL_INDEX ();
  3645 
  3646   record_unwind_current_buffer ();
  3647   Fset_buffer (w->contents);
  3648   if (!NILP (Vwindow_scroll_functions))
  3649     run_hook_with_args_2 (Qwindow_scroll_functions, window,
  3650                           Fmarker_position (w->start));
  3651   unbind_to (count, Qnil);
  3652 
  3653   return Qnil;
  3654 }
  3655 
  3656 
  3657 /**
  3658  * window_sub_list:
  3659  *
  3660  * Return list of live windows constructed by traversing any window
  3661  * sub-tree rooted at WINDOW in preorder followed by right siblings of
  3662  * WINDOW.  Called from outside with second argument WINDOWS nil.  The
  3663  * returned list is in reverse order.
  3664  */
  3665 static Lisp_Object
  3666 window_sub_list (Lisp_Object window, Lisp_Object windows)
  3667 {
  3668 
  3669   struct window *w = XWINDOW (window);
  3670 
  3671   while (w)
  3672     {
  3673       if (WINDOW_INTERNAL_P (w))
  3674         windows = window_sub_list (w->contents, windows);
  3675       else
  3676         windows = Fcons (window, windows);
  3677 
  3678       window = w->next;
  3679       w = NILP (window) ? 0 : XWINDOW (window);
  3680     }
  3681 
  3682   return windows;
  3683 }
  3684 
  3685 
  3686 /**
  3687  * window_change_record_windows:
  3688  *
  3689  * Record changes for all live windows found by traversing any window
  3690  * sub-tree rooted at WINDOW in preorder followed by any right
  3691  * siblings of WINDOW.  This sets the old buffer, old pixel and old
  3692  * body pixel sizes of each live window found to the respective
  3693  * current values.  It also sets the change stamp of each window found
  3694  * to STAMP.  Return the number of live windows found.
  3695  *
  3696  * When not called by itself recursively, WINDOW is its frame's root
  3697  * window, STAMP is the current change stamp of WINDOW's frame and
  3698  * NUMBER is 0.
  3699  */
  3700 static ptrdiff_t
  3701 window_change_record_windows (Lisp_Object window, int stamp, ptrdiff_t number)
  3702 {
  3703   struct window *w = XWINDOW (window);
  3704 
  3705   while (w)
  3706     {
  3707       if (WINDOW_INTERNAL_P (w))
  3708         number = window_change_record_windows (w->contents, stamp, number);
  3709       else
  3710         {
  3711           number += 1;
  3712           w->change_stamp = stamp;
  3713           wset_old_buffer (w, w->contents);
  3714           w->old_pixel_width = w->pixel_width;
  3715           w->old_pixel_height = w->pixel_height;
  3716           w->old_body_pixel_width
  3717             = window_body_width (w, WINDOW_BODY_IN_PIXELS);
  3718           w->old_body_pixel_height
  3719             = window_body_height (w, WINDOW_BODY_IN_PIXELS);
  3720         }
  3721 
  3722       w = NILP (w->next) ? 0 : XWINDOW (w->next);
  3723     }
  3724 
  3725   return number;
  3726 }
  3727 
  3728 
  3729 /**
  3730  * window_change_record:
  3731  *
  3732  * For each frame that has recorded changes, record its selected
  3733  * window, update Fchange stamp, record the states of all its live
  3734  * windows via window_change_record_windows and reset its
  3735  * window_change and window_state_change flags.
  3736  *
  3737  * Record selected window in old_selected_window and selected frame in
  3738  * old_selected_frame.
  3739  */
  3740 static void
  3741 window_change_record (void)
  3742 {
  3743   if (window_change_record_frames)
  3744     {
  3745       Lisp_Object tail, frame;
  3746 
  3747       FOR_EACH_FRAME (tail, frame)
  3748         {
  3749           struct frame *f = XFRAME (frame);
  3750 
  3751           /* Record FRAME's selected window.  */
  3752           fset_old_selected_window (f, FRAME_SELECTED_WINDOW (f));
  3753 
  3754           /* Bump up FRAME's change stamp.  If this wraps, make it 1 to avoid
  3755              that a new window (whose change stamp is always set to 0) gets
  3756              reported as "existing before".  */
  3757           f->change_stamp += 1;
  3758           if (f->change_stamp == 0)
  3759             f->change_stamp = 1;
  3760 
  3761           /* Bump up the change stamps of all live windows on this frame so
  3762              the next call of this function can tell whether any of them
  3763              "existed before" and record state for each of these windows.  */
  3764           f->number_of_windows
  3765             = window_change_record_windows (f->root_window, f->change_stamp, 0);
  3766 
  3767           /* Reset our flags.  */
  3768           FRAME_WINDOW_CHANGE (f) = false;
  3769           FRAME_WINDOW_STATE_CHANGE (f) = false;
  3770         }
  3771     }
  3772 
  3773   /* Strictly spoken we don't need old_selected_window at all - its
  3774      value is the old selected window of old_selected_frame.  */
  3775   old_selected_window = selected_window;
  3776   old_selected_frame = selected_frame;
  3777 }
  3778 
  3779 
  3780 /**
  3781  * run_window_change_functions_1:
  3782  *
  3783  * Run window change functions specified by SYMBOL with argument
  3784  * WINDOW_OR_FRAME.  If BUFFER is nil, WINDOW_OR_FRAME specifies a
  3785  * frame.  In this case, run the default value of SYMBOL.  Otherwise,
  3786  * WINDOW_OR_FRAME denotes a window showing BUFFER.  In this case, run
  3787  * the buffer local value of SYMBOL in BUFFER, if any.
  3788  */
  3789 static void
  3790 run_window_change_functions_1 (Lisp_Object symbol, Lisp_Object buffer,
  3791                                Lisp_Object window_or_frame)
  3792 {
  3793   Lisp_Object funs = Qnil;
  3794 
  3795   if (NILP (buffer))
  3796     funs = Fdefault_value (symbol);
  3797   else if (!NILP (Fassoc (symbol, BVAR (XBUFFER (buffer), local_var_alist),
  3798                           Qnil)))
  3799     /* Don't run global value buffer-locally.  */
  3800     funs = buffer_local_value (symbol, buffer);
  3801 
  3802   while (CONSP (funs))
  3803     {
  3804       if (!EQ (XCAR (funs), Qt)
  3805           && (NILP (buffer)
  3806               ? FRAME_LIVE_P (XFRAME (window_or_frame))
  3807               : WINDOW_LIVE_P (window_or_frame)))
  3808         {
  3809           /* Any function called here may change the state of any
  3810              frame.  Make sure to record changes for each live frame
  3811              in window_change_record later.  */
  3812           window_change_record_frames = true;
  3813           safe_call1 (XCAR (funs), window_or_frame);
  3814         }
  3815 
  3816       funs = XCDR (funs);
  3817     }
  3818 }
  3819 
  3820 
  3821 /**
  3822  * run_window_change_functions:
  3823  *
  3824  * Run window change functions for each live frame.  This function
  3825  * must be called from a "safe" position in redisplay_internal.
  3826  *
  3827  * Do not run any functions for a frame whose window_change flag is
  3828  * nil, where no window selection happened and whose window state
  3829  * change flag was not set since the last time this function was
  3830  * called.  Never run any functions for tooltip frames.
  3831  *
  3832  * The change functions run are, in this order:
  3833  *
  3834  * 'window-buffer-change-functions' which are run for a window that
  3835  * changed its buffer or that was not shown the last time window
  3836  * change functions were run.  The default value is also run when a
  3837  * window was deleted since the last time window change functions were
  3838  * run.
  3839  *
  3840  * `window-size-change-functions' run for a window that changed its
  3841  * body or total size, a window that changed its buffer or a window
  3842  * that was not shown the last time window change functions were run.
  3843  *
  3844  * `window-selected-change-functions' run for a window that was
  3845  * (de-)selected since the last time window change functions were run.
  3846  *
  3847  * `window-state-change-functions' run for a window for which any of
  3848  * the above three changes occurred.
  3849  *
  3850  * A buffer-local value of these functions is run if and only if the
  3851  * window for which the functions are run currently shows the buffer.
  3852  * Each call gets one argument - the window showing the buffer.  This
  3853  * means that the buffer-local value of these functions may be called
  3854  * as many times as the buffer is shown on the frame.
  3855  *
  3856  * The default values of these functions are called only after all
  3857  * buffer-local values for all of these functions have been run.  Each
  3858  * such call receives one argument - the frame for which a change
  3859  * occurred.  Functions on `window-state-change-functions' are run
  3860  * also if the corresponding frame's window state change flag has been
  3861  * set.
  3862  *
  3863  * After the four change functions cited above have been run in the
  3864  * indicated way, functions on 'window-configuration-change-hook' are
  3865  * run.  A buffer-local value is run if a window shows that buffer and
  3866  * has either changed its buffer or its body or total size or did not
  3867  * appear on this frame since the last time window change functions
  3868  * were run.  The functions are called without argument and with the
  3869  * buffer's window selected.  The default value is run without
  3870  * argument and with the frame for which the function is run selected.
  3871  *
  3872  * In a final step, functions on `window-state-change-hook' are run
  3873  * provided a window state change has occurred or the window state
  3874  * change flag has been set on at least one frame.  Each of these
  3875  * functions is called without argument.
  3876  *
  3877  * This function does not save and restore match data.  Any functions
  3878  * it calls are responsible for doing that themselves.
  3879  */
  3880 void
  3881 run_window_change_functions (void)
  3882 {
  3883   Lisp_Object tail, frame;
  3884   bool selected_frame_change = !EQ (selected_frame, old_selected_frame);
  3885   bool run_window_state_change_hook = false;
  3886   specpdl_ref count = SPECPDL_INDEX ();
  3887 
  3888   window_change_record_frames = false;
  3889   record_unwind_protect_void (window_change_record);
  3890   specbind (Qinhibit_redisplay, Qt);
  3891 
  3892   FOR_EACH_FRAME (tail, frame)
  3893     {
  3894       struct frame *f = XFRAME (frame);
  3895       Lisp_Object root = FRAME_ROOT_WINDOW (f);
  3896       bool frame_window_change = FRAME_WINDOW_CHANGE (f);
  3897       bool window_buffer_change, window_size_change;
  3898       bool frame_buffer_change = false, frame_size_change = false;
  3899       bool frame_selected_change
  3900         = (selected_frame_change
  3901            && (EQ (frame, old_selected_frame)
  3902                || EQ (frame, selected_frame)));
  3903       bool frame_selected_window_change
  3904         = !EQ (FRAME_OLD_SELECTED_WINDOW (f), FRAME_SELECTED_WINDOW (f));
  3905       bool frame_window_state_change = FRAME_WINDOW_STATE_CHANGE (f);
  3906       bool window_deleted = false;
  3907       Lisp_Object windows;
  3908       ptrdiff_t number_of_windows;
  3909 
  3910       if (!FRAME_LIVE_P (f)
  3911           || !f->can_set_window_size
  3912           || !f->after_make_frame
  3913           || FRAME_TOOLTIP_P (f)
  3914           || !(frame_window_change
  3915                || frame_selected_change
  3916                || frame_selected_window_change
  3917                || frame_window_state_change))
  3918         /* Either we are not allowed to run hooks for this frame or no
  3919            window change has been reported for it since the last time
  3920            we ran window change functions on it.  */
  3921         continue;
  3922 
  3923       /* Analyze windows and run buffer locals hooks in pre-order.  */
  3924       windows = Fnreverse (window_sub_list (root, Qnil));
  3925       number_of_windows = 0;
  3926 
  3927       /* The following loop collects all data needed to tell whether
  3928          the default value of a hook shall be run and runs any buffer
  3929          local hooks right away.  */
  3930       for (; CONSP (windows); windows = XCDR (windows))
  3931         {
  3932           Lisp_Object window = XCAR (windows);
  3933           struct window *w = XWINDOW (window);
  3934           Lisp_Object buffer = WINDOW_BUFFER (w);
  3935 
  3936           /* Count this window even if it has been deleted while
  3937              running a hook.  */
  3938           number_of_windows += 1;
  3939 
  3940           if (!WINDOW_LIVE_P (window))
  3941             continue;
  3942 
  3943           /* A "buffer change" means either the window's buffer
  3944              changed or the window was not part of this frame the last
  3945              time window change functions were run for it.  */
  3946           window_buffer_change =
  3947             (frame_window_change
  3948              && (!EQ (buffer, w->old_buffer)
  3949                  || w->change_stamp != f->change_stamp));
  3950           /* A "size change" means either a buffer change or that the
  3951              total or body size of the window has changed.
  3952 
  3953              Note: A buffer change implies a size change because either
  3954              this window didn't show the buffer before or this window
  3955              didn't show the buffer the last time the window change
  3956              functions were run.  In either case, an application
  3957              tracing size changes in a buffer-locally fashion might
  3958              want to be informed about that change.  */
  3959           window_size_change =
  3960             (frame_window_change
  3961              && (window_buffer_change
  3962                  || w->pixel_width != w->old_pixel_width
  3963                  || w->pixel_height != w->old_pixel_height
  3964                  || (window_body_width (w, WINDOW_BODY_IN_PIXELS)
  3965                      != w->old_body_pixel_width)
  3966                  || (window_body_height (w, WINDOW_BODY_IN_PIXELS)
  3967                      != w->old_body_pixel_height)));
  3968 
  3969           /* The following two are needed when running the default
  3970              values for this frame below.  */
  3971           frame_buffer_change = frame_buffer_change || window_buffer_change;
  3972           frame_size_change = frame_size_change || window_size_change;
  3973 
  3974           if (window_buffer_change)
  3975             run_window_change_functions_1
  3976               (Qwindow_buffer_change_functions, buffer, window);
  3977 
  3978           if (window_size_change && WINDOW_LIVE_P (window))
  3979             run_window_change_functions_1
  3980               (Qwindow_size_change_functions, buffer, window);
  3981 
  3982           /* This window's selection has changed when it was
  3983              (de-)selected as its frame's or the globally selected
  3984              window.  */
  3985           if (((frame_selected_change
  3986                 && (EQ (window, old_selected_window)
  3987                     || EQ (window, selected_window)))
  3988                || (frame_selected_window_change
  3989                    && (EQ (window, FRAME_OLD_SELECTED_WINDOW (f))
  3990                        || EQ (window, FRAME_SELECTED_WINDOW (f)))))
  3991               && WINDOW_LIVE_P (window))
  3992             run_window_change_functions_1
  3993               (Qwindow_selection_change_functions, buffer, window);
  3994 
  3995           /* This window's state has changed when its buffer or size
  3996              changed or it was (de-)selected as its frame's or the
  3997              globally selected window.  */
  3998           if ((window_buffer_change
  3999                || window_size_change
  4000                || ((frame_selected_change
  4001                     && (EQ (window, old_selected_window)
  4002                         || EQ (window, selected_window)))
  4003                    || (frame_selected_window_change
  4004                        && (EQ (window, FRAME_OLD_SELECTED_WINDOW (f))
  4005                            || EQ (window, FRAME_SELECTED_WINDOW (f))))))
  4006               && WINDOW_LIVE_P (window))
  4007             run_window_change_functions_1
  4008               (Qwindow_state_change_functions, buffer, window);
  4009         }
  4010 
  4011       /* When the number of windows on a frame has decreased, at least
  4012          one window of that frame was deleted.  In that case, we want
  4013          to run the default buffer and configuration change hooks.  The
  4014          default size change hook is not necessarily run in that case,
  4015          but usually will be unless the deletion was "compensated" by
  4016          a reduction of the frame size or an increase of a minibuffer
  4017          window size.  */
  4018       window_deleted = number_of_windows < f->number_of_windows;
  4019       /* A frame changed buffers when one of its windows has changed
  4020          its buffer or at least one window was deleted.  */
  4021       if ((frame_buffer_change || window_deleted) && FRAME_LIVE_P (f))
  4022         run_window_change_functions_1
  4023           (Qwindow_buffer_change_functions, Qnil, frame);
  4024 
  4025       /* A size change occurred when at least one of the frame's
  4026          windows has changed size.  */
  4027       if (frame_size_change && FRAME_LIVE_P (f))
  4028         run_window_change_functions_1
  4029           (Qwindow_size_change_functions, Qnil, frame);
  4030 
  4031       /* A frame has changed its window selection when its selected
  4032          window has changed or when it was (de-)selected.  */
  4033       if ((frame_selected_change || frame_selected_window_change)
  4034           && FRAME_LIVE_P (f))
  4035         run_window_change_functions_1
  4036           (Qwindow_selection_change_functions, Qnil, frame);
  4037 
  4038       /* A frame has changed state when a size or buffer change
  4039          occurred, its selected window has changed, when it was
  4040          (de-)selected or its window state change flag was set.  */
  4041       if ((frame_selected_change || frame_selected_window_change
  4042            || frame_buffer_change || window_deleted
  4043            || frame_size_change || frame_window_state_change)
  4044           && FRAME_LIVE_P (f))
  4045         {
  4046           run_window_change_functions_1
  4047             (Qwindow_state_change_functions, Qnil, frame);
  4048           /* Make sure to run 'window-state-change-hook' later.  */
  4049           run_window_state_change_hook = true;
  4050           /*  Make sure to record changes for each live frame in
  4051              window_change_record later.  */
  4052           window_change_record_frames = true;
  4053         }
  4054 
  4055       /* A frame's configuration changed when one of its windows has
  4056          changed buffer or size or at least one window was deleted.  */
  4057       if ((frame_size_change || window_deleted) && FRAME_LIVE_P (f))
  4058         /* This will run any buffer local window configuration change
  4059            hook as well.  */
  4060         run_window_configuration_change_hook (f);
  4061     }
  4062 
  4063   /* Run 'window-state-change-hook' if at least one frame has changed
  4064      state.  */
  4065   if (run_window_state_change_hook && !NILP (Vwindow_state_change_hook))
  4066     safe_run_hooks (Qwindow_state_change_hook);
  4067 
  4068   /* Record changes for all frames (if asked for), selected window and
  4069      frame.  */
  4070   unbind_to (count, Qnil);
  4071 }
  4072 
  4073 /* Make WINDOW display BUFFER.  RUN_HOOKS_P means it's allowed
  4074    to run hooks.  See make_frame for a case where it's not allowed.
  4075    KEEP_MARGINS_P means that the current margins, fringes, and
  4076    scroll bar settings of the window are not reset from the buffer's
  4077    local settings.  */
  4078 
  4079 void
  4080 set_window_buffer (Lisp_Object window, Lisp_Object buffer,
  4081                    bool run_hooks_p, bool keep_margins_p)
  4082 {
  4083   struct window *w = XWINDOW (window);
  4084   struct buffer *b = XBUFFER (buffer);
  4085   specpdl_ref count = SPECPDL_INDEX ();
  4086   bool samebuf = EQ (buffer, w->contents);
  4087 
  4088   wset_buffer (w, buffer);
  4089 
  4090   if (EQ (window, selected_window))
  4091     bset_last_selected_window (b, window);
  4092 
  4093   /* Let redisplay errors through.  */
  4094   b->display_error_modiff = 0;
  4095 
  4096   /* Update time stamps of buffer display.  */
  4097   if (INTEGERP (BVAR (b, display_count)))
  4098     bset_display_count (b, Fadd1 (BVAR (b, display_count)));
  4099   bset_display_time (b, Fcurrent_time ());
  4100 
  4101   w->window_end_pos = 0;
  4102   w->window_end_vpos = 0;
  4103   w->last_cursor_vpos = 0;
  4104 
  4105   if (!(keep_margins_p && samebuf))
  4106     { /* If we're not actually changing the buffer, don't reset hscroll
  4107          and vscroll.  Resetting hscroll and vscroll here is problematic
  4108          for things like image-mode and doc-view-mode since it resets
  4109          the image's position whenever we resize the frame.  */
  4110       w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
  4111       w->suspend_auto_hscroll = false;
  4112       w->vscroll = 0;
  4113       set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
  4114       set_marker_both (w->old_pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
  4115       set_marker_restricted (w->start,
  4116                              make_fixnum (b->last_window_start),
  4117                              buffer);
  4118       w->start_at_line_beg = false;
  4119       w->force_start = false;
  4120     }
  4121 
  4122   wset_redisplay (w);
  4123   wset_update_mode_line (w);
  4124 
  4125   /* We must select BUFFER to run the window-scroll-functions and to look up
  4126      the buffer-local value of Vwindow_point_insertion_type.  */
  4127   record_unwind_current_buffer ();
  4128   Fset_buffer (buffer);
  4129 
  4130   XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
  4131   XMARKER (w->old_pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
  4132 
  4133   if (!keep_margins_p)
  4134     {
  4135       /* Set fringes and scroll bars from buffer unless they have been
  4136          declared as persistent.  */
  4137       if (!w->fringes_persistent)
  4138         set_window_fringes (w, BVAR (b, left_fringe_width),
  4139                             BVAR (b, right_fringe_width),
  4140                             BVAR (b, fringes_outside_margins), Qnil);
  4141       if (!w->scroll_bars_persistent)
  4142         set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
  4143                                 BVAR (b, vertical_scroll_bar_type),
  4144                                 BVAR (b, scroll_bar_height),
  4145                                 BVAR (b, horizontal_scroll_bar_type), Qnil);
  4146       /* Set left and right marginal area width from buffer.  */
  4147       set_window_margins (w, BVAR (b, left_margin_cols),
  4148                           BVAR (b, right_margin_cols));
  4149       apply_window_adjustment (w);
  4150     }
  4151 
  4152   if (run_hooks_p && !NILP (Vwindow_scroll_functions))
  4153     run_hook_with_args_2 (Qwindow_scroll_functions, window,
  4154                           Fmarker_position (w->start));
  4155 
  4156   /* Ensure that window change functions are run later if the buffer
  4157      differs and the window is neither a mini nor a pseudo window.
  4158 
  4159      Note: Running window change functions for the minibuffer is noisy
  4160      and was generally suppressed in the past.  Is there any reason we
  4161      should run them?  */
  4162   if (!samebuf && !MINI_WINDOW_P (w) && !WINDOW_PSEUDO_P (w))
  4163     FRAME_WINDOW_CHANGE (XFRAME (w->frame)) = true;
  4164 
  4165   unbind_to (count, Qnil);
  4166 }
  4167 
  4168 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
  4169        doc: /* Make WINDOW display BUFFER-OR-NAME.
  4170 WINDOW must be a live window and defaults to the selected one.
  4171 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
  4172 
  4173 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
  4174 display margins, fringe widths, and scroll bar settings are preserved;
  4175 the default is to reset these from the local settings for BUFFER-OR-NAME
  4176 or the frame defaults.  Return nil.
  4177 
  4178 This function throws an error when WINDOW is strongly dedicated to its
  4179 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
  4180 already display BUFFER-OR-NAME.
  4181 
  4182 This function runs `window-scroll-functions' before running
  4183 `window-configuration-change-hook'.  */)
  4184   (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
  4185 {
  4186   register Lisp_Object tem, buffer;
  4187   register struct window *w = decode_live_window (window);
  4188 
  4189   XSETWINDOW (window, w);
  4190   buffer = Fget_buffer (buffer_or_name);
  4191   CHECK_BUFFER (buffer);
  4192   if (!BUFFER_LIVE_P (XBUFFER (buffer)))
  4193     error ("Attempt to display deleted buffer");
  4194 
  4195   tem = w->contents;
  4196   if (NILP (tem))
  4197     error ("Window is deleted");
  4198   else
  4199     {
  4200       if (!EQ (tem, buffer))
  4201         {
  4202           if (EQ (w->dedicated, Qt))
  4203             /* WINDOW is strongly dedicated to its buffer, signal an
  4204                error.  */
  4205             error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
  4206           else
  4207             /* WINDOW is weakly dedicated to its buffer, reset
  4208                dedication.  */
  4209             wset_dedicated (w, Qnil);
  4210 
  4211           call1 (Qrecord_window_buffer, window);
  4212         }
  4213 
  4214       unshow_buffer (w);
  4215     }
  4216 
  4217   set_window_buffer (window, buffer, true, !NILP (keep_margins));
  4218 
  4219   return Qnil;
  4220 }
  4221 
  4222 static Lisp_Object
  4223 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
  4224 {
  4225   return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
  4226 }
  4227 
  4228 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
  4229        0, 1, 0,
  4230        doc: /* Force all windows to be updated on next redisplay.
  4231 If optional arg OBJECT is a window, force redisplay of that window only.
  4232 If OBJECT is a buffer or buffer name, force redisplay of all windows
  4233 displaying that buffer.  */)
  4234   (Lisp_Object object)
  4235 {
  4236   if (NILP (object))
  4237     {
  4238       windows_or_buffers_changed = 29;
  4239       update_mode_lines = 28;
  4240       return Qt;
  4241     }
  4242 
  4243   if (WINDOW_LIVE_P (object))
  4244     {
  4245       struct window *w = XWINDOW (object);
  4246       mark_window_display_accurate (object, false);
  4247       w->update_mode_line = true;
  4248       if (BUFFERP (w->contents))
  4249         XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
  4250       update_mode_lines = 29;
  4251       return Qt;
  4252     }
  4253 
  4254   if (STRINGP (object))
  4255     object = Fget_buffer (object);
  4256   if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))
  4257       && buffer_window_count (XBUFFER (object)))
  4258     {
  4259       /* If buffer is live and shown in at least one window, find
  4260          all windows showing this buffer and force update of them.  */
  4261       object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, false, Qvisible);
  4262       return NILP (object) ? Qnil : Qt;
  4263     }
  4264 
  4265   /* If nothing suitable was found, just return.
  4266      We could signal an error, but this feature will typically be used
  4267      asynchronously in timers or process sentinels, so we don't.  */
  4268   return Qnil;
  4269 }
  4270 
  4271 /* Obsolete since 24.3.  */
  4272 void
  4273 temp_output_buffer_show (register Lisp_Object buf)
  4274 {
  4275   register struct buffer *old = current_buffer;
  4276   register Lisp_Object window;
  4277   register struct window *w;
  4278 
  4279   bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
  4280 
  4281   Fset_buffer (buf);
  4282   BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
  4283   BEGV = BEG;
  4284   ZV = Z;
  4285   SET_PT (BEG);
  4286   set_buffer_internal (old);
  4287 
  4288   if (!NILP (Vtemp_buffer_show_function))
  4289     call1 (Vtemp_buffer_show_function, buf);
  4290   else if (WINDOW_LIVE_P (window = display_buffer (buf, Qnil, Qnil)))
  4291     {
  4292       if (!EQ (XWINDOW (window)->frame, selected_frame))
  4293         Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
  4294       Vminibuf_scroll_window = window;
  4295       w = XWINDOW (window);
  4296       w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
  4297       w->suspend_auto_hscroll = false;
  4298       set_marker_restricted_both (w->start, buf, BEG, BEG);
  4299       set_marker_restricted_both (w->pointm, buf, BEG, BEG);
  4300       set_marker_restricted_both (w->old_pointm, buf, BEG, BEG);
  4301 
  4302       /* Run temp-buffer-show-hook, with the chosen window selected
  4303          and its buffer current.  */
  4304       {
  4305         specpdl_ref count = SPECPDL_INDEX ();
  4306         Lisp_Object prev_window, prev_buffer;
  4307         prev_window = selected_window;
  4308         XSETBUFFER (prev_buffer, old);
  4309 
  4310         /* Select the window that was chosen, for running the hook.
  4311            Note: Both Fselect_window and select_window_norecord may
  4312            set-buffer to the buffer displayed in the window,
  4313            so we need to save the current buffer.  --stef  */
  4314         record_unwind_protect (restore_buffer, prev_buffer);
  4315         record_unwind_protect (select_window_norecord, prev_window);
  4316         Fselect_window (window, Qt);
  4317         Fset_buffer (w->contents);
  4318         run_hook (Qtemp_buffer_show_hook);
  4319         unbind_to (count, Qnil);
  4320       }
  4321     }
  4322 }
  4323 
  4324 /* Allocate basically initialized window.  */
  4325 
  4326 static struct window *
  4327 allocate_window (void)
  4328 {
  4329   return ALLOCATE_ZEROED_PSEUDOVECTOR (struct window, mode_line_help_echo,
  4330                                        PVEC_WINDOW);
  4331 }
  4332 
  4333 /* Make new window, have it replace WINDOW in window-tree, and make
  4334    WINDOW its only vertical child (HORFLAG means make WINDOW its only
  4335    horizontal child).   */
  4336 static void
  4337 make_parent_window (Lisp_Object window, bool horflag)
  4338 {
  4339   Lisp_Object parent;
  4340   register struct window *o, *p;
  4341 
  4342   o = XWINDOW (window);
  4343   p = allocate_window ();
  4344   memcpy ((char *) p + sizeof (union vectorlike_header),
  4345           (char *) o + sizeof (union vectorlike_header),
  4346           word_size * VECSIZE (struct window));
  4347   /* P's buffer slot may change from nil to a buffer...  */
  4348   adjust_window_count (p, 1);
  4349   XSETWINDOW (parent, p);
  4350 
  4351   p->sequence_number = ++sequence_number;
  4352 
  4353   replace_window (window, parent, true);
  4354 
  4355   wset_next (o, Qnil);
  4356   wset_prev (o, Qnil);
  4357   wset_parent (o, parent);
  4358   /* ...but now P becomes an internal window.  */
  4359   wset_start (p, Qnil);
  4360   wset_pointm (p, Qnil);
  4361   wset_old_pointm (p, Qnil);
  4362   wset_buffer (p, Qnil);
  4363   wset_combination (p, horflag, window);
  4364   wset_combination_limit (p, Qnil);
  4365   wset_window_parameters (p, Qnil);
  4366 }
  4367 
  4368 /* Make new window from scratch.  */
  4369 Lisp_Object
  4370 make_window (void)
  4371 {
  4372   Lisp_Object window;
  4373   register struct window *w;
  4374 
  4375   w = allocate_window ();
  4376   /* Initialize Lisp data.  Note that allocate_window initializes all
  4377      Lisp data to nil, so do it only for slots which should not be nil.  */
  4378   wset_normal_lines (w, make_float (1.0));
  4379   wset_normal_cols (w, make_float (1.0));
  4380   wset_new_total (w, make_fixnum (0));
  4381   wset_new_normal (w, make_fixnum (0));
  4382   wset_new_pixel (w, make_fixnum (0));
  4383   wset_start (w, Fmake_marker ());
  4384   wset_pointm (w, Fmake_marker ());
  4385   wset_old_pointm (w, Fmake_marker ());
  4386   wset_vertical_scroll_bar_type (w, Qt);
  4387   wset_horizontal_scroll_bar_type (w, Qt);
  4388   /* These Lisp fields are marked specially so they're not set to nil by
  4389      allocate_window.  */
  4390   wset_prev_buffers (w, Qnil);
  4391   wset_next_buffers (w, Qnil);
  4392 
  4393   /* Initialize non-Lisp data.  Note that allocate_window zeroes out all
  4394      non-Lisp data, so do it only for slots which should not be zero.  */
  4395   w->nrows_scale_factor = w->ncols_scale_factor = 1;
  4396   w->left_fringe_width = w->right_fringe_width = -1;
  4397   w->mode_line_height = w->tab_line_height = w->header_line_height = -1;
  4398 #ifdef HAVE_WINDOW_SYSTEM
  4399   w->phys_cursor_type = NO_CURSOR;
  4400   w->phys_cursor_width = -1;
  4401 #endif
  4402   w->sequence_number = ++sequence_number;
  4403   w->scroll_bar_width = -1;
  4404   w->scroll_bar_height = -1;
  4405   w->column_number_displayed = -1;
  4406   /* Reset window_list.  */
  4407   Vwindow_list = Qnil;
  4408   /* Return window.  */
  4409   XSETWINDOW (window, w);
  4410   return window;
  4411 }
  4412 
  4413 DEFUN ("set-window-new-pixel", Fset_window_new_pixel, Sset_window_new_pixel, 2, 3, 0,
  4414        doc: /* Set new pixel size of WINDOW to SIZE.
  4415 WINDOW must be a valid window and defaults to the selected one.
  4416 Return SIZE.
  4417 
  4418 Optional argument ADD non-nil means add SIZE to the new pixel size of
  4419 WINDOW and return the sum.
  4420 
  4421 The new pixel size of WINDOW, if valid, will be shortly installed as
  4422 WINDOW's pixel height (see `window-pixel-height') or pixel width (see
  4423 `window-pixel-width').
  4424 
  4425 Note: This function does not operate on any child windows of WINDOW.  */)
  4426   (Lisp_Object window, Lisp_Object size, Lisp_Object add)
  4427 {
  4428   struct window *w = decode_valid_window (window);
  4429   EMACS_INT size_min = NILP (add) ? 0 : - XFIXNUM (w->new_pixel);
  4430   EMACS_INT size_max = size_min + min (INT_MAX, MOST_POSITIVE_FIXNUM);
  4431 
  4432   int checked_size = check_integer_range (size, size_min, size_max);
  4433   if (NILP (add))
  4434     wset_new_pixel (w, size);
  4435   else
  4436     wset_new_pixel (w, make_fixnum (XFIXNUM (w->new_pixel) + checked_size));
  4437 
  4438   return w->new_pixel;
  4439 }
  4440 
  4441 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
  4442        doc: /* Set new total size of WINDOW to SIZE.
  4443 WINDOW must be a valid window and defaults to the selected one.
  4444 Return SIZE.
  4445 
  4446 Optional argument ADD non-nil means add SIZE to the new total size of
  4447 WINDOW and return the sum.
  4448 
  4449 The new total size of WINDOW, if valid, will be shortly installed as
  4450 WINDOW's total height (see `window-total-height') or total width (see
  4451 `window-total-width').
  4452 
  4453 Note: This function does not operate on any child windows of WINDOW.  */)
  4454      (Lisp_Object window, Lisp_Object size, Lisp_Object add)
  4455 {
  4456   struct window *w = decode_valid_window (window);
  4457 
  4458   CHECK_FIXNUM (size);
  4459   if (NILP (add))
  4460     wset_new_total (w, size);
  4461   else
  4462     wset_new_total (w, make_fixnum (XFIXNUM (w->new_total) + XFIXNUM (size)));
  4463 
  4464   return w->new_total;
  4465 }
  4466 
  4467 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
  4468        doc: /* Set new normal size of WINDOW to SIZE.
  4469 WINDOW must be a valid window and defaults to the selected one.
  4470 Return SIZE.
  4471 
  4472 The new normal size of WINDOW, if valid, will be shortly installed as
  4473 WINDOW's normal size (see `window-normal-size').
  4474 
  4475 Note: This function does not operate on any child windows of WINDOW.  */)
  4476      (Lisp_Object window, Lisp_Object size)
  4477 {
  4478   wset_new_normal (decode_valid_window (window), size);
  4479   return size;
  4480 }
  4481 
  4482 /* Return true if setting w->pixel_height (w->pixel_width if HORFLAG)
  4483    to w->new_pixel would result in correct heights (widths)
  4484    for window W and recursively all child windows of W.
  4485 
  4486    Note: This function does not check any of `window-fixed-size-p',
  4487    `window-min-height' or `window-min-width'.  It does check that window
  4488    sizes do not drop below one line (two columns). */
  4489 static bool
  4490 window_resize_check (struct window *w, bool horflag)
  4491 {
  4492   struct frame *f = XFRAME (w->frame);
  4493   struct window *c;
  4494 
  4495   if (WINDOW_VERTICAL_COMBINATION_P (w))
  4496     /* W is a vertical combination.  */
  4497     {
  4498       c = XWINDOW (w->contents);
  4499       if (horflag)
  4500         /* All child windows of W must have the same width as W.  */
  4501         {
  4502           while (c)
  4503             {
  4504               if (XFIXNUM (c->new_pixel) != XFIXNUM (w->new_pixel)
  4505                   || !window_resize_check (c, horflag))
  4506                 return false;
  4507 
  4508               c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4509             }
  4510 
  4511           return true;
  4512         }
  4513       else
  4514         /* The sum of the heights of the child windows of W must equal
  4515            W's height.  */
  4516         {
  4517           int remaining_pixels = XFIXNUM (w->new_pixel);
  4518 
  4519           while (c)
  4520             {
  4521               if (!window_resize_check (c, horflag))
  4522                 return false;
  4523 
  4524               remaining_pixels -= XFIXNUM (c->new_pixel);
  4525               if (remaining_pixels < 0)
  4526                 return false;
  4527               c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4528             }
  4529 
  4530           return remaining_pixels == 0;
  4531         }
  4532     }
  4533   else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
  4534     /* W is a horizontal combination.  */
  4535     {
  4536       c = XWINDOW (w->contents);
  4537       if (horflag)
  4538         /* The sum of the widths of the child windows of W must equal W's
  4539            width.  */
  4540         {
  4541           int remaining_pixels = XFIXNUM (w->new_pixel);
  4542 
  4543           while (c)
  4544             {
  4545               if (!window_resize_check (c, horflag))
  4546                 return false;
  4547 
  4548               remaining_pixels -= XFIXNUM (c->new_pixel);
  4549               if (remaining_pixels < 0)
  4550                 return false;
  4551               c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4552             }
  4553 
  4554           return remaining_pixels == 0;
  4555         }
  4556       else
  4557         /* All child windows of W must have the same height as W.  */
  4558         {
  4559           while (c)
  4560             {
  4561               if (XFIXNUM (c->new_pixel) != XFIXNUM (w->new_pixel)
  4562                   || !window_resize_check (c, horflag))
  4563                 return false;
  4564 
  4565               c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4566             }
  4567 
  4568           return true;
  4569         }
  4570     }
  4571   else
  4572     /* A leaf window.  Make sure it's not too small.  The following
  4573        hardcodes the values of `window-safe-min-width' (2) and
  4574        `window-safe-min-height' (1) which are defined in window.el.  */
  4575     return (XFIXNUM (w->new_pixel) >= (horflag
  4576                                        ? 2 * FRAME_COLUMN_WIDTH (f)
  4577                                        : FRAME_LINE_HEIGHT (f)));
  4578 }
  4579 
  4580 
  4581 /* Set w->pixel_height (w->pixel_width if HORFLAG) to
  4582    w->new_pixel for window W and recursively all child windows of W.
  4583    Also calculate and assign the new vertical (horizontal) pixel start
  4584    positions of each of these windows.
  4585 
  4586    This function does not perform any error checks.  Make sure you have
  4587    run window_resize_check on W before applying this function.  */
  4588 static void
  4589 window_resize_apply (struct window *w, bool horflag)
  4590 {
  4591   struct window *c;
  4592   int edge;
  4593   int unit = (horflag
  4594               ? FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w))
  4595               : FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
  4596 
  4597   /* Note: Assigning new_normal requires that the new total size of the
  4598      parent window has been set *before*.  */
  4599   if (horflag)
  4600     {
  4601       w->pixel_width = XFIXNAT (w->new_pixel);
  4602       w->total_cols = w->pixel_width / unit;
  4603       if (NUMBERP (w->new_normal))
  4604         wset_normal_cols (w, w->new_normal);
  4605 
  4606       edge = w->pixel_left;
  4607     }
  4608   else
  4609     {
  4610       w->pixel_height = XFIXNAT (w->new_pixel);
  4611       w->total_lines = w->pixel_height / unit;
  4612       if (NUMBERP (w->new_normal))
  4613         wset_normal_lines (w, w->new_normal);
  4614 
  4615       edge = w->pixel_top;
  4616     }
  4617 
  4618   if (WINDOW_VERTICAL_COMBINATION_P (w))
  4619     /* W is a vertical combination.  */
  4620     {
  4621       c = XWINDOW (w->contents);
  4622       while (c)
  4623         {
  4624           if (horflag)
  4625             {
  4626               c->pixel_left = edge;
  4627               c->left_col = edge / unit;
  4628             }
  4629           else
  4630             {
  4631               c->pixel_top = edge;
  4632               c->top_line = edge / unit;
  4633             }
  4634           window_resize_apply (c, horflag);
  4635           if (!horflag)
  4636             edge = edge + c->pixel_height;
  4637 
  4638           c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4639         }
  4640     }
  4641   else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
  4642     /* W is a horizontal combination.  */
  4643     {
  4644       c = XWINDOW (w->contents);
  4645       while (c)
  4646         {
  4647           if (horflag)
  4648             {
  4649               c->pixel_left = edge;
  4650               c->left_col = edge / unit;
  4651             }
  4652           else
  4653             {
  4654               c->pixel_top = edge;
  4655               c->top_line = edge / unit;
  4656             }
  4657 
  4658           window_resize_apply (c, horflag);
  4659           if (horflag)
  4660             edge = edge + c->pixel_width;
  4661 
  4662           c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4663         }
  4664     }
  4665   else
  4666     /* Bug#15957.  */
  4667     w->window_end_valid = false;
  4668 
  4669   if (!WINDOW_PSEUDO_P (w))
  4670     FRAME_WINDOW_CHANGE (WINDOW_XFRAME (w)) = true;
  4671 }
  4672 
  4673 
  4674 /* Set w->total_lines (w->total_cols if HORFLAG) to
  4675    w->new_total for window W and recursively all child windows of W.
  4676    Also calculate and assign the new vertical (horizontal) start
  4677    positions of each of these windows.  */
  4678 static void
  4679 window_resize_apply_total (struct window *w, bool horflag)
  4680 {
  4681   struct window *c;
  4682   int edge;
  4683 
  4684   /* Note: Assigning new_normal requires that the new total size of the
  4685      parent window has been set *before*.  */
  4686   if (horflag)
  4687     {
  4688       w->total_cols = XFIXNAT (w->new_total);
  4689       edge = w->left_col;
  4690     }
  4691   else
  4692     {
  4693       w->total_lines = XFIXNAT (w->new_total);
  4694       edge = w->top_line;
  4695     }
  4696 
  4697   if (WINDOW_VERTICAL_COMBINATION_P (w))
  4698     /* W is a vertical combination.  */
  4699     {
  4700       c = XWINDOW (w->contents);
  4701       while (c)
  4702         {
  4703           if (horflag)
  4704             c->left_col = edge;
  4705           else
  4706             c->top_line = edge;
  4707 
  4708           window_resize_apply_total (c, horflag);
  4709           if (!horflag)
  4710             edge = edge + c->total_lines;
  4711 
  4712           c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4713         }
  4714     }
  4715   else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
  4716     /* W is a horizontal 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_cols;
  4729 
  4730           c = NILP (c->next) ? 0 : XWINDOW (c->next);
  4731         }
  4732     }
  4733 }
  4734 
  4735 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
  4736        doc: /* Apply requested size values for window-tree of FRAME.
  4737 If FRAME is omitted or nil, it defaults to the selected frame.
  4738 
  4739 Optional argument HORIZONTAL omitted or nil means apply requested
  4740 height values.  HORIZONTAL non-nil means apply requested width values.
  4741 
  4742 The requested size values are those set by `set-window-new-pixel' and
  4743 `set-window-new-normal'.  This function checks whether the requested
  4744 values sum up to a valid window layout, recursively assigns the new
  4745 sizes of all child windows and calculates and assigns the new start
  4746 positions of these windows.
  4747 
  4748 Return t if the requested values have been applied correctly, nil
  4749 otherwise.
  4750 
  4751 Note: This function does not check any of `window-fixed-size-p',
  4752 `window-min-height' or `window-min-width'.  All these checks have to
  4753 be applied on the Elisp level.  */)
  4754      (Lisp_Object frame, Lisp_Object horizontal)
  4755 {
  4756   struct frame *f = decode_live_frame (frame);
  4757   struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
  4758   bool horflag = !NILP (horizontal);
  4759 
  4760   if (!window_resize_check (r, horflag)
  4761       || (XFIXNUM (r->new_pixel)
  4762           != (horflag ? r->pixel_width : r->pixel_height)))
  4763     return Qnil;
  4764 
  4765   block_input ();
  4766   window_resize_apply (r, horflag);
  4767 
  4768   fset_redisplay (f);
  4769 
  4770   adjust_frame_glyphs (f);
  4771   unblock_input ();
  4772 
  4773   return Qt;
  4774 }
  4775 
  4776 
  4777 DEFUN ("window-resize-apply-total", Fwindow_resize_apply_total, Swindow_resize_apply_total, 0, 2, 0,
  4778        doc: /* Apply requested total size values for window-tree of FRAME.
  4779 If FRAME is omitted or nil, it defaults to the selected frame.
  4780 
  4781 This function does not assign pixel or normal size values.  You should
  4782 have run `window-resize-apply' before running this.
  4783 
  4784 Optional argument HORIZONTAL omitted or nil means apply requested
  4785 height values.  HORIZONTAL non-nil means apply requested width
  4786 values.  */)
  4787      (Lisp_Object frame, Lisp_Object horizontal)
  4788 {
  4789   struct frame *f = decode_live_frame (frame);
  4790   struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
  4791 
  4792   block_input ();
  4793   /* Necessary when deleting the top-/or leftmost window.  */
  4794   r->left_col = 0;
  4795   r->top_line = FRAME_TOP_MARGIN (f);
  4796   window_resize_apply_total (r, !NILP (horizontal));
  4797   /* Handle the mini window.  */
  4798   if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
  4799     {
  4800       struct window *m = XWINDOW (f->minibuffer_window);
  4801 
  4802       if (NILP (horizontal))
  4803         {
  4804           m->top_line = r->top_line + r->total_lines;
  4805           m->total_lines = XFIXNAT (m->new_total);
  4806         }
  4807       else
  4808         m->total_cols = XFIXNAT (m->new_total);
  4809     }
  4810 
  4811   unblock_input ();
  4812 
  4813   return Qt;
  4814 }
  4815 
  4816 
  4817 /**
  4818 Resize frame F's windows when F's inner height (inner width if HORFLAG
  4819 is true) has been set to SIZE pixels.  */
  4820 void
  4821 resize_frame_windows (struct frame *f, int size, bool horflag)
  4822 {
  4823   Lisp_Object root = f->root_window;
  4824   struct window *r = XWINDOW (root);
  4825   int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
  4826   int new_size, new_pixel_size;
  4827   int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
  4828   Lisp_Object mini = f->minibuffer_window;
  4829   struct window *m = WINDOWP (mini) ? XWINDOW (mini) : NULL;
  4830   int mini_height = ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
  4831                      ? (unit + m->pixel_height
  4832                         - window_body_height (m, WINDOW_BODY_IN_PIXELS))
  4833                      : 0);
  4834 
  4835   new_pixel_size = max (horflag ? size : size - mini_height, unit);
  4836   new_size = new_pixel_size / unit;
  4837 
  4838   if (new_pixel_size == old_pixel_size
  4839       && (horflag || r->pixel_top == FRAME_TOP_MARGIN_HEIGHT (f)))
  4840     ;
  4841   else if (WINDOW_LEAF_P (r))
  4842     {
  4843       /* For a leaf root window just set the size.  */
  4844       if (horflag)
  4845         {
  4846           r->total_cols = new_size;
  4847           r->pixel_width = new_pixel_size;
  4848         }
  4849       else
  4850         {
  4851           r->top_line = FRAME_TOP_MARGIN (f);
  4852           r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
  4853 
  4854           r->total_lines = new_size;
  4855           r->pixel_height = new_pixel_size;
  4856         }
  4857 
  4858       FRAME_WINDOW_CHANGE (f)
  4859         = !WINDOW_PSEUDO_P (r) && new_pixel_size != old_pixel_size;
  4860     }
  4861   else
  4862     {
  4863       Lisp_Object delta;
  4864 
  4865       if (!horflag)
  4866         {
  4867           r->top_line = FRAME_TOP_MARGIN (f);
  4868           r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
  4869         }
  4870 
  4871       XSETINT (delta, new_pixel_size - old_pixel_size);
  4872 
  4873       /* Try a "normal" resize first.  */
  4874       resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil, Qt);
  4875       if (window_resize_check (r, horflag)
  4876           && new_pixel_size == XFIXNUM (r->new_pixel))
  4877         {
  4878           window_resize_apply (r, horflag);
  4879           window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
  4880         }
  4881       else
  4882         {
  4883           /* Try with "reasonable" minimum sizes next.  */
  4884           resize_root_window (root, delta, horflag ? Qt : Qnil, Qt, Qt);
  4885           if (window_resize_check (r, horflag)
  4886               && new_pixel_size == XFIXNUM (r->new_pixel))
  4887             {
  4888               window_resize_apply (r, horflag);
  4889               window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
  4890             }
  4891         }
  4892     }
  4893 
  4894   if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
  4895     {
  4896       m = XWINDOW (mini);
  4897       if (horflag)
  4898         {
  4899           m->total_cols = new_size;
  4900           m->pixel_width = new_pixel_size;
  4901         }
  4902       else
  4903         {
  4904           m->total_lines = mini_height / unit;
  4905           m->pixel_height = mini_height;
  4906           m->top_line = r->top_line + r->total_lines;
  4907           m->pixel_top = r->pixel_top + r->pixel_height;
  4908         }
  4909     }
  4910 
  4911   fset_redisplay (f);
  4912 }
  4913 
  4914 
  4915 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
  4916        doc: /* Split window OLD.
  4917 Second argument PIXEL-SIZE specifies the number of pixels of the
  4918 new window.  It must be a positive integer.
  4919 
  4920 Third argument SIDE nil (or `below') specifies that the new window shall
  4921 be located below WINDOW.  SIDE `above' means the new window shall be
  4922 located above WINDOW.  In both cases PIXEL-SIZE specifies the pixel
  4923 height of the new window including space reserved for the mode and/or
  4924 header/tab line.
  4925 
  4926 SIDE t (or `right') specifies that the new window shall be located on
  4927 the right side of WINDOW.  SIDE `left' means the new window shall be
  4928 located on the left of WINDOW.  In both cases PIXEL-SIZE specifies the
  4929 width of the new window including space reserved for fringes and the
  4930 scrollbar or a divider column.
  4931 
  4932 Fourth argument NORMAL-SIZE specifies the normal size of the new window
  4933 according to the SIDE argument.
  4934 
  4935 The new pixel and normal sizes of all involved windows must have been
  4936 set correctly.  See the code of `split-window' for how this is done.  */)
  4937   (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side, Lisp_Object normal_size)
  4938 {
  4939   /* OLD (*o) is the window we have to split.  (*p) is either OLD's
  4940      parent window or an internal window we have to install as OLD's new
  4941      parent.  REFERENCE (*r) must denote a live window, or is set to OLD
  4942      provided OLD is a leaf window, or to the frame's selected window.
  4943      NEW (*n) is the new window created with some parameters taken from
  4944      REFERENCE (*r).  */
  4945   Lisp_Object new, frame, reference;
  4946   struct window *o, *p, *n, *r, *c;
  4947   struct frame *f;
  4948   bool horflag
  4949     /* HORFLAG is true when we split side-by-side, false otherwise.  */
  4950     = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
  4951 
  4952   CHECK_WINDOW (old);
  4953   o = XWINDOW (old);
  4954   frame = WINDOW_FRAME (o);
  4955   f = XFRAME (frame);
  4956 
  4957   CHECK_FIXNUM (pixel_size);
  4958   EMACS_INT total_size
  4959     = XFIXNUM (pixel_size) / (horflag
  4960                            ? FRAME_COLUMN_WIDTH (f)
  4961                            : FRAME_LINE_HEIGHT (f));
  4962 
  4963   /* Set combination_limit if we have to make a new parent window.
  4964      We do that if either `window-combination-limit' is t, or OLD has no
  4965      parent, or OLD is ortho-combined.  */
  4966   bool combination_limit
  4967     = (EQ (Vwindow_combination_limit, Qt)
  4968        || NILP (o->parent)
  4969        || (horflag
  4970            ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
  4971            : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent))));
  4972 
  4973   /* We need a live reference window to initialize some parameters.  */
  4974   if (WINDOW_LIVE_P (old))
  4975     /* OLD is live, use it as reference window.  */
  4976     reference = old;
  4977   else
  4978     /* Use the frame's selected window as reference window.  */
  4979     reference = FRAME_SELECTED_WINDOW (f);
  4980   r = XWINDOW (reference);
  4981 
  4982   /* The following bugs are caught by `split-window'.  */
  4983   if (MINI_WINDOW_P (o))
  4984     error ("Attempt to split minibuffer window");
  4985   else if (total_size < (horflag ? 2 : 1))
  4986     error ("Size of new window too small (after split)");
  4987   else if (!combination_limit && !NILP (Vwindow_combination_resize))
  4988     /* `window-combination-resize' non-nil means try to resize OLD's siblings
  4989        proportionally.  */
  4990     {
  4991       p = XWINDOW (o->parent);
  4992       /* Temporarily pretend we split the parent window.  */
  4993       wset_new_pixel
  4994         (p, make_fixnum ((horflag ? p->pixel_width : p->pixel_height)
  4995                          - XFIXNUM (pixel_size)));
  4996       if (!window_resize_check (p, horflag))
  4997         error ("Window sizes don't fit");
  4998       else
  4999         /* Undo the temporary pretension.  */
  5000         wset_new_pixel (p, make_fixnum (horflag ? p->pixel_width : p->pixel_height));
  5001     }
  5002   else
  5003     {
  5004       if (!window_resize_check (o, horflag))
  5005         error ("Resizing old window failed");
  5006       else if (XFIXNUM (pixel_size) + XFIXNUM (o->new_pixel)
  5007                != (horflag ? o->pixel_width : o->pixel_height))
  5008         error ("Sum of sizes of old and new window don't fit");
  5009     }
  5010 
  5011   /* This is our point of no return.  */
  5012   if (combination_limit)
  5013     {
  5014       /* Save the old value of o->normal_cols/lines.  It gets corrupted
  5015          by make_parent_window and we need it below for assigning it to
  5016          p->new_normal.  */
  5017       Lisp_Object new_normal
  5018         = horflag ? o->normal_cols : o->normal_lines;
  5019 
  5020       make_parent_window (old, horflag);
  5021       p = XWINDOW (o->parent);
  5022       if (EQ (Vwindow_combination_limit, Qt))
  5023         /* Store t in the new parent's combination_limit slot to avoid
  5024            that its children get merged into another window.  */
  5025         wset_combination_limit (p, Qt);
  5026       /* These get applied below.  */
  5027       wset_new_pixel
  5028         (p, make_fixnum (horflag ? o->pixel_width : o->pixel_height));
  5029       wset_new_total
  5030         (p, make_fixnum (horflag ? o->total_cols : o->total_lines));
  5031       wset_new_normal (p, new_normal);
  5032     }
  5033   else
  5034     p = XWINDOW (o->parent);
  5035 
  5036   fset_redisplay (f);
  5037   new = make_window ();
  5038   n = XWINDOW (new);
  5039   wset_frame (n, frame);
  5040   wset_parent (n, o->parent);
  5041 
  5042   if (EQ (side, Qabove) || EQ (side, Qleft))
  5043     {
  5044       wset_prev (n, o->prev);
  5045       if (NILP (n->prev))
  5046         wset_combination (p, horflag, new);
  5047       else
  5048         wset_next (XWINDOW (n->prev), new);
  5049       wset_next (n, old);
  5050       wset_prev (o, new);
  5051     }
  5052   else
  5053     {
  5054       wset_next (n, o->next);
  5055       if (!NILP (n->next))
  5056         wset_prev (XWINDOW (n->next), new);
  5057       wset_prev (n, old);
  5058       wset_next (o, new);
  5059     }
  5060 
  5061   n->window_end_valid = false;
  5062   n->last_cursor_vpos = 0;
  5063 
  5064   /* Get special geometry settings from reference window.  */
  5065   n->left_margin_cols = r->left_margin_cols;
  5066   n->right_margin_cols = r->right_margin_cols;
  5067   n->left_fringe_width = r->left_fringe_width;
  5068   n->right_fringe_width = r->right_fringe_width;
  5069   n->fringes_outside_margins = r->fringes_outside_margins;
  5070   n->scroll_bar_width = r->scroll_bar_width;
  5071   n->scroll_bar_height = r->scroll_bar_height;
  5072   wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
  5073   wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
  5074 
  5075   /* Directly assign orthogonal coordinates and sizes.  */
  5076   if (horflag)
  5077     {
  5078       n->pixel_top = o->pixel_top;
  5079       n->top_line = o->top_line;
  5080       n->pixel_height = o->pixel_height;
  5081       n->total_lines = o->total_lines;
  5082     }
  5083   else
  5084     {
  5085       n->pixel_left = o->pixel_left;
  5086       n->left_col = o->left_col;
  5087       n->pixel_width = o->pixel_width;
  5088       n->total_cols = o->total_cols;
  5089     }
  5090 
  5091   /* Iso-coordinates and sizes are assigned by window_resize_apply,
  5092      get them ready here.  */
  5093   wset_new_pixel (n, pixel_size);
  5094   EMACS_INT sum = 0;
  5095   c = XWINDOW (p->contents);
  5096   while (c)
  5097     {
  5098       if (c != n)
  5099         sum = sum + XFIXNUM (c->new_total);
  5100       c = NILP (c->next) ? 0 : XWINDOW (c->next);
  5101     }
  5102   wset_new_total (n, make_fixnum ((horflag
  5103                                    ? p->total_cols
  5104                                    : p->total_lines)
  5105                                   - sum));
  5106   wset_new_normal (n, normal_size);
  5107 
  5108   block_input ();
  5109   window_resize_apply (p, horflag);
  5110   adjust_frame_glyphs (f);
  5111   /* Set buffer of NEW to buffer of reference window.  */
  5112   set_window_buffer (new, r->contents, true, true);
  5113   FRAME_WINDOW_CHANGE (f) = true;
  5114   unblock_input ();
  5115 
  5116   return new;
  5117 }
  5118 
  5119 
  5120 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
  5121        doc: /* Remove WINDOW from its frame.
  5122 WINDOW defaults to the selected window.  Return nil.
  5123 Signal an error when WINDOW is the only window on its frame.  */)
  5124      (Lisp_Object window)
  5125 {
  5126   Lisp_Object parent, sibling, frame, root;
  5127   struct window *w, *p, *s, *r;
  5128   struct frame *f;
  5129   bool horflag, before_sibling = false;
  5130 
  5131   w = decode_any_window (window);
  5132   XSETWINDOW (window, w);
  5133   if (NILP (w->contents))
  5134     /* It's a no-op to delete an already deleted window.  */
  5135     return Qnil;
  5136 
  5137   parent = w->parent;
  5138   if (NILP (parent))
  5139     /* Never delete a minibuffer or frame root window.  */
  5140     error ("Attempt to delete minibuffer or sole ordinary window");
  5141   else if (NILP (w->prev) && NILP (w->next))
  5142     /* Rather bow out here, this case should be handled on the Elisp
  5143        level.  */
  5144     error ("Attempt to delete sole window of parent");
  5145 
  5146   p = XWINDOW (parent);
  5147   horflag = WINDOW_HORIZONTAL_COMBINATION_P (p);
  5148 
  5149   frame = WINDOW_FRAME (w);
  5150   f = XFRAME (frame);
  5151 
  5152   root = FRAME_ROOT_WINDOW (f);
  5153   r = XWINDOW (root);
  5154 
  5155   /* Unlink WINDOW from window tree.  */
  5156   if (NILP (w->prev))
  5157     /* Get SIBLING below (on the right of) WINDOW.  */
  5158     {
  5159       /* before_sibling means WINDOW is the first child of its
  5160          parent and thus before the sibling.  */
  5161       before_sibling = true;
  5162       sibling = w->next;
  5163       s = XWINDOW (sibling);
  5164       wset_prev (s, Qnil);
  5165       wset_combination (p, horflag, sibling);
  5166     }
  5167   else
  5168     /* Get SIBLING above (on the left of) WINDOW.  */
  5169     {
  5170       sibling = w->prev;
  5171       s = XWINDOW (sibling);
  5172       wset_next (s, w->next);
  5173       if (!NILP (s->next))
  5174         wset_prev (XWINDOW (s->next), sibling);
  5175     }
  5176 
  5177   if (window_resize_check (r, horflag)
  5178       && (XFIXNUM (r->new_pixel)
  5179           == (horflag ? r->pixel_width : r->pixel_height)))
  5180     /* We can delete WINDOW now.  */
  5181     {
  5182 
  5183       /* Block input.  */
  5184       block_input ();
  5185       xwidget_view_delete_all_in_window (w);
  5186       window_resize_apply (p, horflag);
  5187       /* If this window is referred to by the dpyinfo's mouse
  5188          highlight, invalidate that slot to be safe (Bug#9904).  */
  5189       if (!FRAME_INITIAL_P (f))
  5190         {
  5191           Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
  5192 
  5193           if (EQ (hlinfo->mouse_face_window, window))
  5194             hlinfo->mouse_face_window = Qnil;
  5195         }
  5196 
  5197       fset_redisplay (f);
  5198       Vwindow_list = Qnil;
  5199 
  5200       wset_next (w, Qnil);  /* Don't delete w->next too.  */
  5201       free_window_matrices (w);
  5202 
  5203       if (WINDOWP (w->contents))
  5204         {
  5205           delete_all_child_windows (w->contents);
  5206           wset_combination (w, false, Qnil);
  5207         }
  5208       else
  5209         {
  5210           unshow_buffer (w);
  5211           unchain_marker (XMARKER (w->pointm));
  5212           unchain_marker (XMARKER (w->old_pointm));
  5213           unchain_marker (XMARKER (w->start));
  5214           wset_buffer (w, Qnil);
  5215         }
  5216 
  5217       if (NILP (s->prev) && NILP (s->next))
  5218           /* A matrjoshka where SIBLING has become the only child of
  5219              PARENT.  */
  5220         {
  5221           /* Put SIBLING into PARENT's place.  */
  5222           replace_window (parent, sibling, false);
  5223           /* Have SIBLING inherit the following three slot values from
  5224              PARENT (the combination_limit slot is not inherited).  */
  5225           wset_normal_cols (s, p->normal_cols);
  5226           wset_normal_lines (s, p->normal_lines);
  5227           /* Mark PARENT as deleted.  */
  5228           wset_combination (p, false, Qnil);
  5229           /* Try to merge SIBLING into its new parent.  */
  5230           recombine_windows (sibling);
  5231         }
  5232 
  5233       adjust_frame_glyphs (f);
  5234 
  5235       if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
  5236         /* We apparently deleted the frame's selected window; use the
  5237            frame's first window as substitute but don't record it yet.
  5238            `delete-window' may have something better up its sleeves.  */
  5239         {
  5240           /* Use the frame's first window as fallback ...  */
  5241           Lisp_Object new_selected_window = Fframe_first_window (frame);
  5242 
  5243           if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
  5244             Fselect_window (new_selected_window, Qt);
  5245           else
  5246             /* Do not clear f->select_mini_window_flag here.  If the
  5247                last selected window on F was an active minibuffer, we
  5248                want to return to it on a later Fselect_frame.  */
  5249             fset_selected_window (f, new_selected_window);
  5250         }
  5251 
  5252       unblock_input ();
  5253       FRAME_WINDOW_CHANGE (f) = true;
  5254     }
  5255   else
  5256     /* We failed: Relink WINDOW into window tree.  */
  5257     {
  5258       if (before_sibling)
  5259         {
  5260           wset_prev (s, window);
  5261           wset_combination (p, horflag, window);
  5262         }
  5263       else
  5264         {
  5265           wset_next (s, window);
  5266           if (!NILP (w->next))
  5267             wset_prev (XWINDOW (w->next), window);
  5268         }
  5269       error ("Deletion failed");
  5270     }
  5271 
  5272   return Qnil;
  5273 }
  5274 
  5275 /***********************************************************************
  5276                         Resizing Mini-Windows
  5277  ***********************************************************************/
  5278 
  5279 /**
  5280  * resize_mini_window_apply:
  5281  *
  5282  * Assign new window sizes after resizing a mini window W by DELTA
  5283  * pixels.  No error checking performed.
  5284   */
  5285 static void
  5286 resize_mini_window_apply (struct window *w, int delta)
  5287 {
  5288   struct frame *f = XFRAME (w->frame);
  5289   Lisp_Object root = FRAME_ROOT_WINDOW (f);
  5290   struct window *r = XWINDOW (root);
  5291 
  5292   block_input ();
  5293   w->pixel_height = w->pixel_height + delta;
  5294   w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
  5295 
  5296   window_resize_apply (r, false);
  5297 
  5298   w->pixel_top = r->pixel_top + r->pixel_height;
  5299   w->top_line = r->top_line + r->total_lines;
  5300 
  5301   /* Enforce full redisplay of the frame.  */
  5302   /* FIXME: Shouldn't some of the caller do it?  */
  5303   fset_redisplay (f);
  5304   adjust_frame_glyphs (f);
  5305   unblock_input ();
  5306 }
  5307 
  5308 /**
  5309  * grow_mini_window:
  5310  *
  5311  * Grow mini-window W by DELTA pixels.  If DELTA is negative, this may
  5312  * shrink the minibuffer window to the minimum height to display one
  5313  * line of text.
  5314  */
  5315 void
  5316 grow_mini_window (struct window *w, int delta)
  5317 {
  5318   struct frame *f = XFRAME (w->frame);
  5319   int old_height = window_body_height (w, WINDOW_BODY_IN_PIXELS);
  5320   int min_height = FRAME_LINE_HEIGHT (f);
  5321 
  5322   eassert (MINI_WINDOW_P (w));
  5323 
  5324   /* Never shrink mini-window to less than its minimum height.  */
  5325   if (old_height + delta < min_height)
  5326     delta = old_height > min_height ? min_height - old_height : 0;
  5327 
  5328   if (delta != 0)
  5329     {
  5330       Lisp_Object root = FRAME_ROOT_WINDOW (f);
  5331       struct window *r = XWINDOW (root);
  5332       Lisp_Object grow;
  5333 
  5334       FRAME_WINDOWS_FROZEN (f) = true;
  5335       grow = call3 (Qwindow__resize_root_window_vertically,
  5336                     root, make_fixnum (- delta), Qt);
  5337 
  5338       if (FIXNUMP (grow) && window_resize_check (r, false))
  5339         resize_mini_window_apply (w, -XFIXNUM (grow));
  5340     }
  5341 }
  5342 
  5343 /**
  5344  * shrink_mini_window:
  5345  *
  5346  * Shrink mini-window W to the minimum height needed to display one
  5347  * line of text.
  5348  */
  5349 void
  5350 shrink_mini_window (struct window *w)
  5351 {
  5352   struct frame *f = XFRAME (w->frame);
  5353   int delta = (window_body_height (w, WINDOW_BODY_IN_PIXELS)
  5354                - FRAME_LINE_HEIGHT (f));
  5355 
  5356   eassert (MINI_WINDOW_P (w));
  5357 
  5358   if (delta > 0)
  5359     {
  5360       Lisp_Object root = FRAME_ROOT_WINDOW (f);
  5361       struct window *r = XWINDOW (root);
  5362       Lisp_Object grow;
  5363 
  5364       FRAME_WINDOWS_FROZEN (f) = false;
  5365       grow = call3 (Qwindow__resize_root_window_vertically,
  5366                     root, make_fixnum (delta), Qt);
  5367 
  5368       if (FIXNUMP (grow) && window_resize_check (r, false))
  5369         resize_mini_window_apply (w, -XFIXNUM (grow));
  5370     }
  5371   else if (delta < 0)
  5372     /* delta can be less than zero after adding horizontal scroll
  5373        bar.  */
  5374     grow_mini_window (w, -delta);
  5375 
  5376 }
  5377 
  5378 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal,
  5379        Sresize_mini_window_internal, 1, 1, 0,
  5380        doc: /* Resize mini window WINDOW.  */)
  5381      (Lisp_Object window)
  5382 {
  5383   struct window *w = XWINDOW (window);
  5384   struct window *r;
  5385   struct frame *f;
  5386   int old_height, delta;
  5387 
  5388   CHECK_LIVE_WINDOW (window);
  5389   f = XFRAME (w->frame);
  5390 
  5391   if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
  5392     error ("Not a valid minibuffer window");
  5393   else if (FRAME_MINIBUF_ONLY_P (f))
  5394     error ("Cannot resize a minibuffer-only frame");
  5395 
  5396   r = XWINDOW (FRAME_ROOT_WINDOW (f));
  5397   old_height = r->pixel_height + w->pixel_height;
  5398   delta = XFIXNUM (w->new_pixel) - w->pixel_height;
  5399   if (window_resize_check (r, false)
  5400       && XFIXNUM (w->new_pixel) > 0
  5401       && old_height == XFIXNUM (r->new_pixel) + XFIXNUM (w->new_pixel))
  5402     {
  5403       resize_mini_window_apply (w, delta);
  5404 
  5405       return Qt;
  5406     }
  5407   else
  5408     error ("Cannot resize mini window");
  5409 }
  5410 
  5411 /* Mark window cursors off for all windows in the window tree rooted
  5412    at W by setting their phys_cursor_on_p flag to zero.  Called from
  5413    xterm.c, e.g. when a frame is cleared and thereby all cursors on
  5414    the frame are cleared.  */
  5415 
  5416 void
  5417 mark_window_cursors_off (struct window *w)
  5418 {
  5419   while (w)
  5420     {
  5421       if (WINDOWP (w->contents))
  5422         mark_window_cursors_off (XWINDOW (w->contents));
  5423       else
  5424         w->phys_cursor_on_p = false;
  5425 
  5426       w = NILP (w->next) ? 0 : XWINDOW (w->next);
  5427     }
  5428 }
  5429 
  5430 
  5431 /**
  5432  * window_wants_mode_line:
  5433  *
  5434  * Return 1 if window W wants a mode line and is high enough to
  5435  * accommodate it, 0 otherwise.
  5436  *
  5437  * W wants a mode line if it's a leaf window and neither a minibuffer
  5438  * nor a pseudo window.  Moreover, its 'window-mode-line-format'
  5439  * parameter must not be 'none' and either that parameter or W's
  5440  * buffer's 'mode-line-format' value must be non-nil.  Finally, W must
  5441  * be higher than its frame's canonical character height.
  5442  */
  5443 bool
  5444 window_wants_mode_line (struct window *w)
  5445 {
  5446   Lisp_Object window_mode_line_format =
  5447     window_parameter (w, Qmode_line_format);
  5448 
  5449   return (WINDOW_LEAF_P (w)
  5450           && !MINI_WINDOW_P (w)
  5451           && !WINDOW_PSEUDO_P (w)
  5452           && !EQ (window_mode_line_format, Qnone)
  5453           && (!NILP (window_mode_line_format)
  5454               || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), mode_line_format)))
  5455           && WINDOW_PIXEL_HEIGHT (w) > WINDOW_FRAME_LINE_HEIGHT (w));
  5456 }
  5457 
  5458 
  5459 /**
  5460  * window_wants_header_line:
  5461  *
  5462  * Return 1 if window W wants a header line and is high enough to
  5463  * accommodate it, 0 otherwise.
  5464  *
  5465  * W wants a header line if it's a leaf window and neither a
  5466  * minibuffer nor a pseudo window.  Moreover, its
  5467  * 'window-header-line-format' parameter must not be 'none' and either
  5468  * that parameter or W's buffer's 'header-line-format' value must be
  5469  * non-nil.  Finally, W must be higher than its frame's canonical
  5470  * character height and be able to accommodate a mode line too if
  5471  * necessary (the mode line prevails).
  5472  */
  5473 bool
  5474 window_wants_header_line (struct window *w)
  5475 {
  5476   Lisp_Object window_header_line_format =
  5477     window_parameter (w, Qheader_line_format);
  5478 
  5479   return (WINDOW_LEAF_P (w)
  5480           && !MINI_WINDOW_P (w)
  5481           && !WINDOW_PSEUDO_P (w)
  5482           && !EQ (window_header_line_format, Qnone)
  5483           && (!NILP (window_header_line_format)
  5484               || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
  5485           && (WINDOW_PIXEL_HEIGHT (w)
  5486               > (window_wants_mode_line (w)
  5487                  ? 2 * WINDOW_FRAME_LINE_HEIGHT (w)
  5488                  : WINDOW_FRAME_LINE_HEIGHT (w))));
  5489 }
  5490 
  5491 
  5492 /**
  5493  * window_wants_tab_line:
  5494  *
  5495  * Return 1 if window W wants a tab line and is high enough to
  5496  * accommodate it, 0 otherwise.
  5497  *
  5498  * W wants a tab line if it's a leaf window and neither a minibuffer
  5499  * nor a pseudo window.  Moreover, its 'window-tab-line-format'
  5500  * parameter must not be 'none' and either that parameter or W's
  5501  * buffer's 'tab-line-format' value must be non-nil.  Finally, W must
  5502  * be higher than its frame's canonical character height and be able
  5503  * to accommodate a mode line and a header line too if necessary (the
  5504  * mode line and a header line prevail).
  5505  */
  5506 
  5507 bool
  5508 window_wants_tab_line (struct window *w)
  5509 {
  5510   Lisp_Object window_tab_line_format =
  5511     window_parameter (w, Qtab_line_format);
  5512 
  5513   return (WINDOW_LEAF_P (w)
  5514           && !MINI_WINDOW_P (w)
  5515           && !WINDOW_PSEUDO_P (w)
  5516           && !EQ (window_tab_line_format, Qnone)
  5517           && (!NILP (window_tab_line_format)
  5518               || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), tab_line_format)))
  5519           && (WINDOW_PIXEL_HEIGHT (w)
  5520               > (((window_wants_mode_line (w) ? 1 : 0)
  5521                   + (window_wants_header_line (w) ? 1 : 0)
  5522                   + 1) * WINDOW_FRAME_LINE_HEIGHT (w))));
  5523 }
  5524 
  5525 /* Return number of lines of text in window W, not counting the mode
  5526    line and header line, if any.  Do NOT use this for windows on GUI
  5527    frames; use window_body_height instead.  This function is only for
  5528    windows on TTY frames, where it is much more efficient.  */
  5529 
  5530 int
  5531 window_internal_height (struct window *w)
  5532 {
  5533   int ht = w->total_lines;
  5534 
  5535   if (window_wants_mode_line (w))
  5536     --ht;
  5537 
  5538   if (window_wants_header_line (w))
  5539     --ht;
  5540 
  5541   if (window_wants_tab_line (w))
  5542     --ht;
  5543 
  5544   return ht;
  5545 }
  5546 
  5547 
  5548 /************************************************************************
  5549                            Window Scrolling
  5550  ***********************************************************************/
  5551 
  5552 /* Scroll contents of window WINDOW up.  If WHOLE, scroll
  5553    N screen-fulls, which is defined as the height of the window minus
  5554    next_screen_context_lines.  If WHOLE is zero, scroll up N lines
  5555    instead.  Negative values of N mean scroll down.  NOERROR
  5556    means don't signal an error if we try to move over BEGV or ZV,
  5557    respectively.  */
  5558 
  5559 static void
  5560 window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
  5561 {
  5562   struct window *w = XWINDOW (window);
  5563   struct buffer *b = XBUFFER (w->contents);
  5564   bool long_lines_truncated =
  5565     b->long_line_optimizations_p && !NILP (BVAR (b, truncate_lines));
  5566   specpdl_ref count = SPECPDL_INDEX ();
  5567 
  5568   n = clip_to_bounds (INT_MIN, n, INT_MAX);
  5569 
  5570   wset_redisplay (w);
  5571 
  5572   /* Does this window's buffer have very long and truncated lines?  */
  5573   if (b->long_line_optimizations_p
  5574       && !long_lines_truncated
  5575       && !NILP (Vtruncate_partial_width_windows)
  5576       && w->total_cols < FRAME_COLS (XFRAME (WINDOW_FRAME (w))))
  5577     {
  5578       if (FIXNUMP (Vtruncate_partial_width_windows))
  5579         long_lines_truncated =
  5580           w->total_cols < XFIXNAT (Vtruncate_partial_width_windows);
  5581       else
  5582         long_lines_truncated = true;
  5583     }
  5584 
  5585   if (whole && (fast_but_imprecise_scrolling || long_lines_truncated))
  5586     specbind (Qfontification_functions, Qnil);
  5587 
  5588   if (whole && long_lines_truncated)
  5589     window_scroll_for_long_lines (w, n, noerror);
  5590   else if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
  5591     {
  5592 
  5593       /* On GUI frames, use the pixel-based version which is much
  5594          slower than the line-based one, but can handle varying
  5595          line heights.  */
  5596       record_unwind_protect_void (unwind_display_working_on_window);
  5597       display_working_on_window_p = true;
  5598       window_scroll_pixel_based (window, n, whole, noerror);
  5599     }
  5600   else
  5601     window_scroll_line_based (window, n, whole, noerror);
  5602 
  5603   unbind_to (count, Qnil);
  5604 
  5605   /* Bug#15957.  */
  5606   XWINDOW (window)->window_end_valid = false;
  5607 }
  5608 
  5609 /* Compute scroll margin for WINDOW.
  5610    We scroll when point is within this distance from the top or bottom
  5611    of the window.  The result is measured in lines or in pixels
  5612    depending on the second parameter.  */
  5613 int
  5614 window_scroll_margin (struct window *window, enum margin_unit unit)
  5615 {
  5616   if (scroll_margin > 0)
  5617     {
  5618       int frame_line_height = default_line_pixel_height (window);
  5619       int window_lines = window_box_height (window) / frame_line_height;
  5620 
  5621       double ratio = 0.25;
  5622       if (FLOATP (Vmaximum_scroll_margin))
  5623         {
  5624           ratio = XFLOAT_DATA (Vmaximum_scroll_margin);
  5625           ratio = max (0.0, ratio);
  5626           ratio = min (ratio, 0.5);
  5627         }
  5628       int max_margin = min ((window_lines - 1)/2,
  5629                             (int) (window_lines * ratio));
  5630       int margin = clip_to_bounds (0, scroll_margin, max_margin);
  5631       return (unit == MARGIN_IN_PIXELS)
  5632         ? margin * frame_line_height
  5633         : margin;
  5634     }
  5635   else
  5636     return 0;
  5637 }
  5638 
  5639 static int
  5640 sanitize_next_screen_context_lines (void)
  5641 {
  5642   return clip_to_bounds (0, next_screen_context_lines, 1000000);
  5643 }
  5644 
  5645 /* Implementation of window_scroll for very long and truncated lines.
  5646    This is a simplified version, it only handles WHOLE window scrolls,
  5647    and doesn't honor scroll-preserve-screen-position nor scroll-margin.  */
  5648 static void
  5649 window_scroll_for_long_lines (struct window *w, int n, bool noerror)
  5650 {
  5651   ptrdiff_t startpos = marker_position (w->start);
  5652   ptrdiff_t startbyte = marker_byte_position (w->start);
  5653   int nscls = sanitize_next_screen_context_lines ();
  5654   register int ht = window_internal_height (w);
  5655 
  5656   n *= max (1, ht - nscls);
  5657 
  5658   /* If point is not visible in window, bring it inside window.  */
  5659   struct position pos;
  5660   int rtop, rbot, dummy_rowh, dummy_vpos, dummy_x, dummy_y;
  5661   if (!(PT >= startpos
  5662         && PT <= ZV
  5663         && startpos <= ZV
  5664         && pos_visible_p (w, PT, &dummy_x, &dummy_y, &rtop, &rbot, &dummy_rowh,
  5665                           &dummy_vpos)
  5666         && !rtop && !rbot))
  5667     {
  5668       pos = *vmotion (PT, PT_BYTE, - (ht / 2), w);
  5669       startpos = pos.bufpos;
  5670       startbyte = pos.bytepos;
  5671     }
  5672   SET_PT_BOTH (startpos, startbyte);
  5673 
  5674   bool lose = n < 0 && PT == BEGV;
  5675   pos = *vmotion (PT, PT_BYTE, n, w);
  5676   if (lose)
  5677     {
  5678       if (noerror)
  5679         return;
  5680       else
  5681         xsignal0 (Qbeginning_of_buffer);
  5682     }
  5683 
  5684   bool bolp = pos.bufpos == BEGV || FETCH_BYTE (pos.bytepos - 1) == '\n';
  5685   if (pos.bufpos < ZV)
  5686     {
  5687       set_marker_restricted_both (w->start, w->contents,
  5688                                   pos.bufpos, pos.bytepos);
  5689       w->start_at_line_beg = bolp;
  5690       wset_update_mode_line (w);
  5691       /* Set force_start so that redisplay_window will run
  5692          the window-scroll-functions.  */
  5693       w->force_start = true;
  5694       SET_PT_BOTH (pos.bufpos, pos.bytepos);
  5695       if (n > 0)
  5696         pos = *vmotion (PT, PT_BYTE, ht / 2, w);
  5697       else if (n < 0)
  5698         pos = *vmotion (PT, PT_BYTE, - (ht / 2), w);
  5699       SET_PT_BOTH (pos.bufpos, pos.bytepos);
  5700     }
  5701   else
  5702     {
  5703       if (noerror)
  5704         return;
  5705       else
  5706         xsignal0 (Qend_of_buffer);
  5707     }
  5708 }
  5709 
  5710 /* Implementation of window_scroll that works based on pixel line
  5711    heights.  See the comment of window_scroll for parameter
  5712    descriptions.  */
  5713 
  5714 static void
  5715 window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
  5716 {
  5717   struct it it;
  5718   struct window *w = XWINDOW (window);
  5719   struct text_pos start;
  5720   int this_scroll_margin;
  5721   /* True if we fiddled the window vscroll field without really scrolling.  */
  5722   bool vscrolled = false;
  5723   int x, y, rtop, rbot, rowh, vpos;
  5724   void *itdata = NULL;
  5725   int frame_line_height = default_line_pixel_height (w);
  5726   bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
  5727                                           Fwindow_old_point (window)));
  5728 
  5729   SET_TEXT_POS_FROM_MARKER (start, w->start);
  5730   /* Scrolling a minibuffer window via scroll bar when the echo area
  5731      shows long text sometimes resets the minibuffer contents behind
  5732      our backs.  Also, someone might narrow-to-region and immediately
  5733      call a scroll function.  */
  5734   if (CHARPOS (start) > ZV || CHARPOS (start) < BEGV)
  5735     SET_TEXT_POS (start, BEGV, BEGV_BYTE);
  5736 
  5737   /* If PT is not visible in WINDOW, move back one half of
  5738      the screen.  Allow PT to be partially visible, otherwise
  5739      something like (scroll-down 1) with PT in the line before
  5740      the partially visible one would recenter.  */
  5741 
  5742   if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
  5743     {
  5744       itdata = bidi_shelve_cache ();
  5745       /* Move backward half the height of the window.  Performance note:
  5746          vmotion used here is about 10% faster, but would give wrong
  5747          results for variable height lines.  */
  5748       init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
  5749       it.current_y = it.last_visible_y;
  5750       move_it_vertically_backward (&it, window_box_height (w) / 2);
  5751 
  5752       /* The function move_iterator_vertically may move over more than
  5753          the specified y-distance.  If it->w is small, e.g. a
  5754          mini-buffer window, we may end up in front of the window's
  5755          display area.  Start displaying at the start of the line
  5756          containing PT in this case.  */
  5757       if (it.current_y <= 0)
  5758         {
  5759           init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
  5760           move_it_vertically_backward (&it, 0);
  5761           it.current_y = 0;
  5762         }
  5763 
  5764       start = it.current.pos;
  5765       bidi_unshelve_cache (itdata, false);
  5766     }
  5767   else if (auto_window_vscroll_p)
  5768     {
  5769       if (rtop || rbot)         /* Partially visible.  */
  5770         {
  5771           int px;
  5772           int dy = frame_line_height;
  5773           /* In the below we divide the window box height by the
  5774              frame's line height to make the result predictable when
  5775              the window box is not an integral multiple of the line
  5776              height.  This is important to ensure we get back to the
  5777              same position when scrolling up, then down.  */
  5778           if (whole)
  5779             {
  5780               int ht = window_box_height (w);
  5781               int nscls = sanitize_next_screen_context_lines ();
  5782               dy = max (dy, (ht / dy - nscls) * dy);
  5783             }
  5784           dy *= n;
  5785 
  5786           if (n < 0)
  5787             {
  5788               /* Only vscroll backwards if already vscrolled forwards.  */
  5789               if (w->vscroll < 0 && rtop > 0)
  5790                 {
  5791                   px = max (0, -w->vscroll - min (rtop, -dy));
  5792                   Fset_window_vscroll (window, make_fixnum (px), Qt,
  5793                                        Qnil);
  5794                   return;
  5795                 }
  5796             }
  5797           if (n > 0)
  5798             {
  5799               /* Do vscroll if already vscrolled or only display line.  */
  5800               if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
  5801                 {
  5802                   px = max (0, -w->vscroll + min (rbot, dy));
  5803                   Fset_window_vscroll (window, make_fixnum (px), Qt,
  5804                                        Qnil);
  5805                   return;
  5806                 }
  5807 
  5808               /* Maybe modify window start instead of scrolling.  */
  5809               if (rbot > 0 || w->vscroll < 0)
  5810                 {
  5811                   ptrdiff_t spos;
  5812 
  5813                   Fset_window_vscroll (window, make_fixnum (0), Qt,
  5814                                        Qnil);
  5815                   /* If there are other text lines above the current row,
  5816                      move window start to current row.  Else to next row. */
  5817                   if (rbot > 0)
  5818                     spos = XFIXNUM (Fline_beginning_position (Qnil));
  5819                   else
  5820                     spos = min (XFIXNUM (Fline_end_position (Qnil)) + 1, ZV);
  5821                   set_marker_restricted (w->start, make_fixnum (spos),
  5822                                          w->contents);
  5823                   w->start_at_line_beg = true;
  5824                   wset_update_mode_line (w);
  5825                   /* Set force_start so that redisplay_window will run the
  5826                      window-scroll-functions.  */
  5827                   w->force_start = true;
  5828                   return;
  5829                 }
  5830             }
  5831         }
  5832       /* Cancel previous vscroll.  */
  5833       Fset_window_vscroll (window, make_fixnum (0), Qt, Qnil);
  5834     }
  5835 
  5836   itdata = bidi_shelve_cache ();
  5837   /* If scroll_preserve_screen_position is non-nil, we try to set
  5838      point in the same window line as it is now, so get that line.  */
  5839   if (!NILP (Vscroll_preserve_screen_position))
  5840     {
  5841       /* We preserve the goal pixel coordinate across consecutive
  5842          calls to scroll-up, scroll-down and other commands that
  5843          have the `scroll-command' property.  This avoids the
  5844          possibility of point becoming "stuck" on a tall line when
  5845          scrolling by one line.  */
  5846       if (window_scroll_pixel_based_preserve_y < 0
  5847           || !SYMBOLP (KVAR (current_kboard, Vlast_command))
  5848           || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
  5849         {
  5850           start_display (&it, w, start);
  5851           move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
  5852           window_scroll_pixel_based_preserve_y = it.current_y;
  5853           window_scroll_pixel_based_preserve_x = it.current_x;
  5854         }
  5855     }
  5856   else
  5857     window_scroll_pixel_based_preserve_y
  5858       = window_scroll_pixel_based_preserve_x = -1;
  5859 
  5860   /* Move iterator it from start the specified distance forward or
  5861      backward.  The result is the new window start.  */
  5862   start_display (&it, w, start);
  5863   if (whole)
  5864     {
  5865       ptrdiff_t start_pos = IT_CHARPOS (it);
  5866       int flh = frame_line_height;
  5867       int ht = window_box_height (w);
  5868       int nscls = sanitize_next_screen_context_lines ();
  5869       /* In the below we divide the window box height by the frame's
  5870          line height to make the result predictable when the window
  5871          box is not an integral multiple of the line height.  This is
  5872          important to ensure we get back to the same position when
  5873          scrolling up, then down.  */
  5874       int dy = n * max (flh, (ht / flh - nscls) * flh);
  5875       int goal_y;
  5876       void *it_data;
  5877 
  5878       /* Note that move_it_vertically always moves the iterator to the
  5879          start of a line.  So, if the last line doesn't have a newline,
  5880          we would end up at the start of the line ending at ZV.  */
  5881       if (dy <= 0)
  5882         {
  5883           goal_y = it.current_y + dy;
  5884           move_it_vertically_backward (&it, -dy);
  5885           /* move_it_vertically_backward above always overshoots if DY
  5886              cannot be reached exactly, i.e. if it falls in the middle
  5887              of a screen line.  But if that screen line is large
  5888              (e.g., a tall image), it might make more sense to
  5889              undershoot instead.  */
  5890           if (goal_y - it.current_y > 0.5 * flh)
  5891             {
  5892               it_data = bidi_shelve_cache ();
  5893               struct it it1 = it;
  5894               if (line_bottom_y (&it1) - goal_y < goal_y - it.current_y)
  5895                 move_it_by_lines (&it, 1);
  5896               bidi_unshelve_cache (it_data, true);
  5897             }
  5898           /* Ensure we actually do move, e.g. in case we are currently
  5899              looking at an image that is taller that the window height.  */
  5900           while (start_pos == IT_CHARPOS (it)
  5901                  && start_pos > BEGV)
  5902             move_it_by_lines (&it, -1);
  5903         }
  5904       else if (dy > 0)
  5905         {
  5906           goal_y = it.current_y + dy;
  5907           move_it_to (&it, ZV, -1, goal_y, -1, MOVE_TO_POS | MOVE_TO_Y);
  5908           /* Extra precision for people who want us to preserve the
  5909              screen position of the cursor: effectively round DY to the
  5910              nearest screen line, instead of rounding to zero; the latter
  5911              causes point to move by one line after C-v followed by M-v,
  5912              if the buffer has lines of different height.  */
  5913           if (!NILP (Vscroll_preserve_screen_position)
  5914               && goal_y - it.current_y  > 0.5 * flh)
  5915             {
  5916               it_data = bidi_shelve_cache ();
  5917               struct it it2 = it;
  5918 
  5919               move_it_by_lines (&it, 1);
  5920               if (it.current_y > goal_y + 0.5 * flh)
  5921                 {
  5922                   it = it2;
  5923                   bidi_unshelve_cache (it_data, false);
  5924                 }
  5925               else
  5926                 bidi_unshelve_cache (it_data, true);
  5927             }
  5928           /* Ensure we actually do move, e.g. in case we are currently
  5929              looking at an image that is taller that the window height.  */
  5930           while (start_pos == IT_CHARPOS (it)
  5931                  && start_pos < ZV)
  5932             move_it_by_lines (&it, 1);
  5933         }
  5934     }
  5935   else
  5936     move_it_by_lines (&it, n);
  5937 
  5938   /* We failed if we find ZV is already on the screen (scrolling up,
  5939      means there's nothing past the end), or if we can't start any
  5940      earlier (scrolling down, means there's nothing past the top).  */
  5941   if ((n > 0 && IT_CHARPOS (it) == ZV)
  5942       || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
  5943     {
  5944       if (IT_CHARPOS (it) == ZV)
  5945         {
  5946           if (it.current_y < it.last_visible_y
  5947               && (it.current_y + it.max_ascent + it.max_descent
  5948                   > it.last_visible_y))
  5949             {
  5950               /* The last line was only partially visible, make it fully
  5951                  visible.  */
  5952               w->vscroll = (it.last_visible_y
  5953                             - it.current_y + it.max_ascent + it.max_descent);
  5954               adjust_frame_glyphs (it.f);
  5955             }
  5956           else
  5957             {
  5958               bidi_unshelve_cache (itdata, false);
  5959               if (noerror)
  5960                 return;
  5961               else if (n < 0)   /* could happen with empty buffers */
  5962                 xsignal0 (Qbeginning_of_buffer);
  5963               else
  5964                 xsignal0 (Qend_of_buffer);
  5965             }
  5966         }
  5967       else
  5968         {
  5969           if (w->vscroll != 0)
  5970             /* The first line was only partially visible, make it fully
  5971                visible. */
  5972             w->vscroll = 0;
  5973           else
  5974             {
  5975               bidi_unshelve_cache (itdata, false);
  5976               if (noerror)
  5977                 return;
  5978               else
  5979                 xsignal0 (Qbeginning_of_buffer);
  5980             }
  5981         }
  5982 
  5983       /* If control gets here, then we vscrolled.  */
  5984 
  5985       XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
  5986 
  5987       /* Don't try to change the window start below.  */
  5988       vscrolled = true;
  5989     }
  5990 
  5991   if (! vscrolled)
  5992     {
  5993       ptrdiff_t pos = IT_CHARPOS (it);
  5994       ptrdiff_t bytepos;
  5995 
  5996       /* If in the middle of a multi-glyph character move forward to
  5997          the next character.  */
  5998       if (in_display_vector_p (&it))
  5999         {
  6000           ++pos;
  6001           move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
  6002         }
  6003 
  6004       /* Set the window start, and set up the window for redisplay.  */
  6005       set_marker_restricted_both (w->start, w->contents, IT_CHARPOS (it),
  6006                                   IT_BYTEPOS (it));
  6007       bytepos = marker_byte_position (w->start);
  6008       w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
  6009       wset_update_mode_line (w);
  6010       /* Set force_start so that redisplay_window will run the
  6011          window-scroll-functions.  */
  6012       w->force_start = true;
  6013     }
  6014 
  6015   /* The rest of this function uses current_y in a nonstandard way,
  6016      not including the height of the header line if any.  */
  6017   it.current_y = it.vpos = 0;
  6018 
  6019   /* Move PT out of scroll margins.
  6020      This code wants current_y to be zero at the window start position
  6021      even if there is a header line.  */
  6022   this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
  6023 
  6024   if (n > 0)
  6025     {
  6026       int last_y = it.last_visible_y - this_scroll_margin - 1;
  6027 
  6028       /* We moved the window start towards ZV, so PT may be now
  6029          in the scroll margin at the top.  */
  6030       if (IT_CHARPOS (it) < PT)
  6031         move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
  6032       if (IT_CHARPOS (it) == PT
  6033           && it.current_y >= this_scroll_margin
  6034           && it.current_y <= last_y - WINDOW_TAB_LINE_HEIGHT (w)
  6035                                     - WINDOW_HEADER_LINE_HEIGHT (w)
  6036           && (NILP (Vscroll_preserve_screen_position)
  6037               || EQ (Vscroll_preserve_screen_position, Qt)))
  6038         /* We found PT at a legitimate height.  Leave it alone.  */
  6039         ;
  6040       else
  6041         {
  6042           if (window_scroll_pixel_based_preserve_y >= 0)
  6043             {
  6044               /* Don't enter the scroll margin at the end of the window.  */
  6045               int goal_y = min (last_y, window_scroll_pixel_based_preserve_y);
  6046 
  6047               /* If we have a header line, take account of it.  This
  6048                  is necessary because we set it.current_y to 0, above.  */
  6049               move_it_to (&it, -1,
  6050                           window_scroll_pixel_based_preserve_x,
  6051                           goal_y - WINDOW_TAB_LINE_HEIGHT (w)
  6052                                  - WINDOW_HEADER_LINE_HEIGHT (w),
  6053                           -1, MOVE_TO_Y | MOVE_TO_X);
  6054             }
  6055 
  6056           /* Get out of the scroll margin at the top of the window.  */
  6057           while (it.current_y < this_scroll_margin)
  6058             {
  6059               int prev = it.current_y;
  6060               move_it_by_lines (&it, 1);
  6061               if (prev == it.current_y)
  6062                 break;
  6063             }
  6064           SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
  6065           /* Fix up the Y position to preserve, if it is inside the
  6066              scroll margin at the window top.  */
  6067           if (window_scroll_pixel_based_preserve_y >= 0
  6068               && window_scroll_pixel_based_preserve_y < this_scroll_margin)
  6069             window_scroll_pixel_based_preserve_y = this_scroll_margin;
  6070         }
  6071     }
  6072   else if (n < 0)
  6073     {
  6074       ptrdiff_t charpos, bytepos;
  6075       bool partial_p;
  6076 
  6077       /* Save our position, for the
  6078          window_scroll_pixel_based_preserve_y case.  */
  6079       charpos = IT_CHARPOS (it);
  6080       bytepos = IT_BYTEPOS (it);
  6081 
  6082       /* We moved the window start towards BEGV, so PT may be now
  6083          in the scroll margin at the bottom.  */
  6084       move_it_to (&it, PT, -1,
  6085                   /* We subtract WINDOW_HEADER_LINE_HEIGHT because
  6086                      it.y is relative to the bottom of the header
  6087                      line, see above.  */
  6088                   (it.last_visible_y - WINDOW_TAB_LINE_HEIGHT (w)
  6089                                      - WINDOW_HEADER_LINE_HEIGHT (w)
  6090                    - partial_line_height (&it) - this_scroll_margin - 1),
  6091                   -1,
  6092                   MOVE_TO_POS | MOVE_TO_Y);
  6093 
  6094       /* Save our position, in case it's correct.  */
  6095       charpos = IT_CHARPOS (it);
  6096       bytepos = IT_BYTEPOS (it);
  6097 
  6098       /* If PT is in the screen line at the last fully visible line,
  6099          move_it_to will stop at X = 0 in that line, because the
  6100          required Y coordinate is reached there.  See if we can get to
  6101          PT without descending lower in Y, and if we can, it means we
  6102          reached PT before the scroll margin.  */
  6103       if (charpos != PT)
  6104         {
  6105           struct it it2;
  6106           void *it_data;
  6107 
  6108           it2 = it;
  6109           it_data = bidi_shelve_cache ();
  6110           move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
  6111           if (IT_CHARPOS (it) == PT && it.current_y == it2.current_y)
  6112             {
  6113               charpos = IT_CHARPOS (it);
  6114               bytepos = IT_BYTEPOS (it);
  6115               bidi_unshelve_cache (it_data, true);
  6116             }
  6117           else
  6118             {
  6119               it = it2;
  6120               bidi_unshelve_cache (it_data, false);
  6121             }
  6122         }
  6123 
  6124       /* See if point is on a partially visible line at the end.  */
  6125       if (it.what == IT_EOB)
  6126         partial_p =
  6127           it.current_y + it.ascent + it.descent
  6128           > it.last_visible_y - this_scroll_margin
  6129           - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w);
  6130       else
  6131         {
  6132           move_it_by_lines (&it, 1);
  6133           partial_p =
  6134             it.current_y
  6135             > it.last_visible_y - this_scroll_margin
  6136               - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w);
  6137         }
  6138 
  6139       if (charpos == PT && !partial_p
  6140           && (NILP (Vscroll_preserve_screen_position)
  6141               || EQ (Vscroll_preserve_screen_position, Qt)))
  6142         /* We found PT before we found the display margin, so PT is ok.  */
  6143         ;
  6144       else if (window_scroll_pixel_based_preserve_y >= 0)
  6145         {
  6146           int goal_y = min (it.last_visible_y - this_scroll_margin - 1,
  6147                             window_scroll_pixel_based_preserve_y);
  6148 
  6149           /* Don't let the preserved screen Y coordinate put us inside
  6150              any of the two margins.  */
  6151           if (goal_y < this_scroll_margin)
  6152             goal_y = this_scroll_margin;
  6153           SET_TEXT_POS_FROM_MARKER (start, w->start);
  6154           start_display (&it, w, start);
  6155           /* It would be wrong to subtract WINDOW_HEADER_LINE_HEIGHT
  6156              here because we called start_display again and did not
  6157              alter it.current_y this time.  */
  6158           move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
  6159                       goal_y, -1, MOVE_TO_Y | MOVE_TO_X);
  6160           SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
  6161         }
  6162       else
  6163         {
  6164           if (partial_p)
  6165             /* The last line was only partially visible, so back up two
  6166                lines to make sure we're on a fully visible line.  */
  6167             {
  6168               move_it_by_lines (&it, -2);
  6169               SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
  6170             }
  6171           else
  6172             /* No, the position we saved is OK, so use it.  */
  6173             SET_PT_BOTH (charpos, bytepos);
  6174         }
  6175     }
  6176   bidi_unshelve_cache (itdata, false);
  6177 
  6178   if (adjust_old_pointm)
  6179     Fset_marker (w->old_pointm,
  6180                  ((w == XWINDOW (selected_window))
  6181                   ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
  6182                   : Fmarker_position (w->pointm)),
  6183                  w->contents);
  6184 }
  6185 
  6186 
  6187 /* Implementation of window_scroll that works based on screen lines.
  6188    See the comment of window_scroll for parameter descriptions.  */
  6189 
  6190 static void
  6191 window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
  6192 {
  6193   struct window *w = XWINDOW (window);
  6194   /* Fvertical_motion enters redisplay, which can trigger
  6195      fontification, which in turn can modify buffer text (e.g., if the
  6196      fontification functions replace escape sequences with faces, as
  6197      in `grep-mode-font-lock-keywords').  So we use a marker to record
  6198      the old point position, to prevent crashes in SET_PT_BOTH.  */
  6199   Lisp_Object opoint_marker = Fpoint_marker ();
  6200   register ptrdiff_t pos, pos_byte;
  6201   register int ht = window_internal_height (w);
  6202   register Lisp_Object tem;
  6203   bool lose;
  6204   Lisp_Object bolp;
  6205   ptrdiff_t startpos = marker_position (w->start);
  6206   ptrdiff_t startbyte = marker_byte_position (w->start);
  6207   Lisp_Object original_pos = Qnil;
  6208   bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
  6209                                           Fwindow_old_point (window)));
  6210 
  6211   /* If scrolling screen-fulls, compute the number of lines to
  6212      scroll from the window's height.  */
  6213   if (whole)
  6214     {
  6215       int nscls = sanitize_next_screen_context_lines ();
  6216       n *= max (1, ht - nscls);
  6217     }
  6218 
  6219   if (!NILP (Vscroll_preserve_screen_position))
  6220     {
  6221       if (window_scroll_preserve_vpos <= 0
  6222           || !SYMBOLP (KVAR (current_kboard, Vlast_command))
  6223           || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
  6224         {
  6225           struct position posit
  6226             = *compute_motion (startpos, startbyte, 0, 0, false,
  6227                                PT, ht, 0, -1, w->hscroll, 0, w);
  6228 
  6229           window_scroll_preserve_vpos = posit.vpos;
  6230           window_scroll_preserve_hpos = posit.hpos + w->hscroll;
  6231         }
  6232 
  6233       original_pos = Fcons (make_fixnum (window_scroll_preserve_hpos),
  6234                             make_fixnum (window_scroll_preserve_vpos));
  6235     }
  6236 
  6237   XSETFASTINT (tem, PT);
  6238   tem = Fpos_visible_in_window_p (tem, window, Qnil);
  6239 
  6240   if (NILP (tem))
  6241     {
  6242       Fvertical_motion (make_fixnum (- (ht / 2)), window, Qnil);
  6243       startpos = PT;
  6244       startbyte = PT_BYTE;
  6245     }
  6246 
  6247   SET_PT_BOTH (startpos, startbyte);
  6248   lose = n < 0 && PT == BEGV;
  6249   Fvertical_motion (make_fixnum (n), window, Qnil);
  6250   pos = PT;
  6251   pos_byte = PT_BYTE;
  6252   bolp = Fbolp ();
  6253   SET_PT_BOTH (marker_position (opoint_marker),
  6254                marker_byte_position (opoint_marker));
  6255 
  6256   if (lose)
  6257     {
  6258       if (noerror)
  6259         return;
  6260       else
  6261         xsignal0 (Qbeginning_of_buffer);
  6262     }
  6263 
  6264   if (pos < ZV)
  6265     {
  6266       int this_scroll_margin = window_scroll_margin (w, MARGIN_IN_LINES);
  6267 
  6268       set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
  6269       w->start_at_line_beg = !NILP (bolp);
  6270       wset_update_mode_line (w);
  6271       /* Set force_start so that redisplay_window will run
  6272          the window-scroll-functions.  */
  6273       w->force_start = true;
  6274 
  6275       if (!NILP (Vscroll_preserve_screen_position)
  6276           && this_scroll_margin == 0
  6277           && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
  6278         {
  6279           SET_PT_BOTH (pos, pos_byte);
  6280           Fvertical_motion (original_pos, window, Qnil);
  6281         }
  6282       /* If we scrolled forward, put point enough lines down
  6283          that it is outside the scroll margin.  */
  6284       else if (n > 0)
  6285         {
  6286           int top_margin;
  6287 
  6288           if (this_scroll_margin > 0)
  6289             {
  6290               SET_PT_BOTH (pos, pos_byte);
  6291               Fvertical_motion (make_fixnum (this_scroll_margin), window, Qnil);
  6292               top_margin = PT;
  6293             }
  6294           else
  6295             top_margin = pos;
  6296 
  6297           if (top_margin <= marker_position (opoint_marker))
  6298             SET_PT_BOTH (marker_position (opoint_marker),
  6299                          marker_byte_position (opoint_marker));
  6300           else if (!NILP (Vscroll_preserve_screen_position))
  6301             {
  6302               int nlines = window_scroll_preserve_vpos;
  6303 
  6304               SET_PT_BOTH (pos, pos_byte);
  6305               if (window_scroll_preserve_vpos < this_scroll_margin)
  6306                 nlines = this_scroll_margin;
  6307               else if (window_scroll_preserve_vpos
  6308                        >= w->total_lines - this_scroll_margin)
  6309                 nlines = w->total_lines - this_scroll_margin - 1;
  6310               Fvertical_motion (Fcons (make_fixnum (window_scroll_preserve_hpos),
  6311                                        make_fixnum (nlines)), window, Qnil);
  6312             }
  6313           else
  6314             SET_PT (top_margin);
  6315         }
  6316       else if (n < 0)
  6317         {
  6318           int bottom_margin;
  6319 
  6320           /* If we scrolled backward, put point near the end of the window
  6321              but not within the scroll margin.  */
  6322           SET_PT_BOTH (pos, pos_byte);
  6323           tem = Fvertical_motion (make_fixnum (ht - this_scroll_margin), window,
  6324                                   Qnil);
  6325           if (XFIXNAT (tem) == ht - this_scroll_margin)
  6326             bottom_margin = PT;
  6327           else
  6328             bottom_margin = PT + 1;
  6329 
  6330           if (bottom_margin > marker_position (opoint_marker))
  6331             SET_PT_BOTH (marker_position (opoint_marker),
  6332                          marker_byte_position (opoint_marker));
  6333           else
  6334             {
  6335               if (!NILP (Vscroll_preserve_screen_position))
  6336                 {
  6337                   int nlines = window_scroll_preserve_vpos;
  6338 
  6339                   SET_PT_BOTH (pos, pos_byte);
  6340                   if (window_scroll_preserve_vpos < this_scroll_margin)
  6341                     nlines = this_scroll_margin;
  6342                   else if (window_scroll_preserve_vpos
  6343                            >= ht - this_scroll_margin)
  6344                     nlines = ht - this_scroll_margin - 1;
  6345                   Fvertical_motion (Fcons (make_fixnum (window_scroll_preserve_hpos),
  6346                                            make_fixnum (nlines)), window, Qnil);
  6347                 }
  6348               else
  6349                 Fvertical_motion (make_fixnum (-1), window, Qnil);
  6350             }
  6351         }
  6352     }
  6353   else
  6354     {
  6355       if (noerror)
  6356         return;
  6357       else
  6358         xsignal0 (Qend_of_buffer);
  6359     }
  6360 
  6361   if (adjust_old_pointm)
  6362     Fset_marker (w->old_pointm,
  6363                  ((w == XWINDOW (selected_window))
  6364                   ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
  6365                   : Fmarker_position (w->pointm)),
  6366                  w->contents);
  6367 }
  6368 
  6369 
  6370 /* Scroll WINDOW up or down.  If N is nil, scroll upward by a
  6371    screen-full which is defined as the height of the window minus
  6372    next_screen_context_lines.  If N is the symbol `-', scroll downward
  6373    by a screen-full.  DIRECTION may be 1 meaning to scroll down, or -1
  6374    meaning to scroll up.  */
  6375 
  6376 static void
  6377 scroll_command (Lisp_Object window, Lisp_Object n, int direction)
  6378 {
  6379   struct window *w;
  6380   bool other_window;
  6381   specpdl_ref count = SPECPDL_INDEX ();
  6382 
  6383   eassert (eabs (direction) == 1);
  6384 
  6385   w = XWINDOW (window);
  6386   other_window = ! EQ (window, selected_window);
  6387 
  6388   /* If given window's buffer isn't current, make it current for the
  6389      moment.  If the window's buffer is the same, but it is not the
  6390      selected window, we need to save-excursion to avoid affecting
  6391      point in the selected window (which would cause the selected
  6392      window to scroll).  Don't screw up if window_scroll gets an
  6393      error.  */
  6394   if (other_window || XBUFFER (w->contents) != current_buffer)
  6395     {
  6396       record_unwind_protect_excursion ();
  6397       if (XBUFFER (w->contents) != current_buffer)
  6398         Fset_buffer (w->contents);
  6399     }
  6400 
  6401   if (other_window)
  6402     {
  6403       SET_PT_BOTH (marker_position (w->pointm),
  6404                    marker_byte_position (w->pointm));
  6405       SET_PT_BOTH (marker_position (w->old_pointm),
  6406                    marker_byte_position (w->old_pointm));
  6407     }
  6408 
  6409   if (NILP (n))
  6410     window_scroll (window, direction, true, false);
  6411   else if (EQ (n, Qminus))
  6412     window_scroll (window, -direction, true, false);
  6413   else
  6414     {
  6415       n = Fprefix_numeric_value (n);
  6416       window_scroll (window, XFIXNUM (n) * direction, false, false);
  6417     }
  6418 
  6419   if (other_window)
  6420     {
  6421       set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
  6422       set_marker_both (w->old_pointm, Qnil, PT, PT_BYTE);
  6423     }
  6424 
  6425   unbind_to (count, Qnil);
  6426 }
  6427 
  6428 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
  6429        doc: /* Scroll text of selected window upward ARG lines.
  6430 If ARG is omitted or nil, scroll upward by a near full screen.
  6431 A near full screen is `next-screen-context-lines' less than a full screen.
  6432 Negative ARG means scroll downward.
  6433 If ARG is the atom `-', scroll downward by nearly full screen.
  6434 When calling from a program, supply as argument a number, nil, or `-'.  */)
  6435   (Lisp_Object arg)
  6436 {
  6437   scroll_command (selected_window, arg, 1);
  6438   return Qnil;
  6439 }
  6440 
  6441 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
  6442        doc: /* Scroll text of selected window down ARG lines.
  6443 If ARG is omitted or nil, scroll down by a near full screen.
  6444 A near full screen is `next-screen-context-lines' less than a full screen.
  6445 Negative ARG means scroll upward.
  6446 If ARG is the atom `-', scroll upward by nearly full screen.
  6447 When calling from a program, supply as argument a number, nil, or `-'.  */)
  6448   (Lisp_Object arg)
  6449 {
  6450   scroll_command (selected_window, arg, -1);
  6451   return Qnil;
  6452 }
  6453 
  6454 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
  6455        doc: /* Return the other window for \"other window scroll\" commands.
  6456 If in the minibuffer, `minibuffer-scroll-window' if non-nil
  6457 specifies the window.
  6458 Otherwise, if `other-window-scroll-buffer' is non-nil, a window
  6459 showing that buffer is used, popping the buffer up if necessary.
  6460 Finally, look for a neighboring window on the selected frame,
  6461 followed by all visible frames on the current terminal.  */)
  6462   (void)
  6463 {
  6464   Lisp_Object window;
  6465 
  6466   if (MINI_WINDOW_P (XWINDOW (selected_window))
  6467       && !NILP (Vminibuf_scroll_window))
  6468     window = Vminibuf_scroll_window;
  6469   /* If buffer is specified and live, scroll that buffer.  */
  6470   else if (BUFFERP (Vother_window_scroll_buffer)
  6471            && BUFFER_LIVE_P (XBUFFER (Vother_window_scroll_buffer)))
  6472     {
  6473       window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
  6474       if (NILP (window))
  6475         window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
  6476     }
  6477   else if (FUNCTIONP (Vother_window_scroll_default))
  6478     /* Nothing specified; try to get a window from the function.  */
  6479     window = call0 (Vother_window_scroll_default);
  6480   else
  6481     {
  6482       /* Otherwise, look for a neighboring window on the same frame.  */
  6483       window = Fnext_window (selected_window, Qlambda, Qnil);
  6484 
  6485       if (EQ (window, selected_window))
  6486         /* That didn't get us anywhere; look for a window on another
  6487            visible frame on the current terminal.  */
  6488         window = Fnext_window (window, Qlambda, Qvisible);
  6489     }
  6490 
  6491   CHECK_LIVE_WINDOW (window);
  6492 
  6493   if (EQ (window, selected_window))
  6494     error ("There is no other window");
  6495 
  6496   return window;
  6497 }
  6498 
  6499 
  6500 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
  6501        doc: /* Scroll selected window display ARG columns left.
  6502 Default for ARG is window width minus 2.
  6503 Value is the total amount of leftward horizontal scrolling in
  6504 effect after the change.
  6505 If SET-MINIMUM is non-nil, the new scroll amount becomes the
  6506 lower bound for automatic scrolling, i.e. automatic scrolling
  6507 will not scroll a window to a column less than the value returned
  6508 by this function.  This happens in an interactive call.  */)
  6509   (register Lisp_Object arg, Lisp_Object set_minimum)
  6510 {
  6511   struct window *w = XWINDOW (selected_window);
  6512   EMACS_INT requested_arg =
  6513     (NILP (arg)
  6514      ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2
  6515      : XFIXNUM (Fprefix_numeric_value (arg)));
  6516   Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
  6517 
  6518   if (!NILP (set_minimum))
  6519     w->min_hscroll = w->hscroll;
  6520 
  6521   w->suspend_auto_hscroll = true;
  6522 
  6523   return result;
  6524 }
  6525 
  6526 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
  6527        doc: /* Scroll selected window display ARG columns right.
  6528 Default for ARG is window width minus 2.
  6529 Value is the total amount of leftward horizontal scrolling in
  6530 effect after the change.
  6531 If SET-MINIMUM is non-nil, the new scroll amount becomes the
  6532 lower bound for automatic scrolling, i.e. automatic scrolling
  6533 will not scroll a window to a column less than the value returned
  6534 by this function.  This happens in an interactive call.  */)
  6535   (register Lisp_Object arg, Lisp_Object set_minimum)
  6536 {
  6537   struct window *w = XWINDOW (selected_window);
  6538   EMACS_INT requested_arg =
  6539     (NILP (arg)
  6540      ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2
  6541      : XFIXNUM (Fprefix_numeric_value (arg)));
  6542   Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
  6543 
  6544   if (!NILP (set_minimum))
  6545     w->min_hscroll = w->hscroll;
  6546 
  6547   w->suspend_auto_hscroll = true;
  6548 
  6549   return result;
  6550 }
  6551 
  6552 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
  6553        doc: /* Return window selected just before minibuffer window was selected.
  6554 Return nil if the selected window is not a minibuffer window.  */)
  6555   (void)
  6556 {
  6557   if (minibuf_level > 0
  6558       && MINI_WINDOW_P (XWINDOW (selected_window))
  6559       && WINDOW_LIVE_P (minibuf_selected_window))
  6560     return minibuf_selected_window;
  6561 
  6562   return Qnil;
  6563 }
  6564 
  6565 /* Value is the number of lines actually displayed in window W,
  6566    as opposed to its height.  */
  6567 
  6568 static int
  6569 displayed_window_lines (struct window *w)
  6570 {
  6571   struct it it;
  6572   struct text_pos start;
  6573   int height = window_box_height (w);
  6574   struct buffer *old_buffer;
  6575   int bottom_y;
  6576   void *itdata = NULL;
  6577 
  6578   if (XBUFFER (w->contents) != current_buffer)
  6579     {
  6580       old_buffer = current_buffer;
  6581       set_buffer_internal (XBUFFER (w->contents));
  6582     }
  6583   else
  6584     old_buffer = NULL;
  6585 
  6586   /* In case W->start is out of the accessible range, do something
  6587      reasonable.  This happens in Info mode when Info-scroll-down
  6588      calls (recenter -1) while W->start is 1.  */
  6589   CLIP_TEXT_POS_FROM_MARKER (start, w->start);
  6590 
  6591   itdata = bidi_shelve_cache ();
  6592 
  6593   specpdl_ref count = SPECPDL_INDEX ();
  6594   record_unwind_protect_void (unwind_display_working_on_window);
  6595   display_working_on_window_p = true;
  6596   start_display (&it, w, start);
  6597   move_it_vertically (&it, height);
  6598   bottom_y = line_bottom_y (&it);
  6599   unbind_to (count, Qnil);
  6600   bidi_unshelve_cache (itdata, false);
  6601 
  6602   /* Add in empty lines at the bottom of the window.  */
  6603   if (bottom_y < height)
  6604     {
  6605       int uy = FRAME_LINE_HEIGHT (it.f);
  6606       it.vpos += (height - bottom_y + uy - 1) / uy;
  6607     }
  6608   else if (bottom_y == height)
  6609     it.vpos++;
  6610 
  6611   if (old_buffer)
  6612     set_buffer_internal (old_buffer);
  6613 
  6614   return it.vpos;
  6615 }
  6616 
  6617 
  6618 DEFUN ("recenter", Frecenter, Srecenter, 0, 2, "P\np",
  6619        doc: /* Center point in selected window and maybe redisplay frame.
  6620 With a numeric prefix argument ARG, recenter putting point on screen line ARG
  6621 relative to the selected window.  If ARG is negative, it counts up from the
  6622 bottom of the window.  (ARG should be less than the height of the window.)
  6623 
  6624 If ARG is omitted or nil, then recenter with point on the middle line
  6625 of the selected window; if REDISPLAY & `recenter-redisplay' are
  6626 non-nil, also erase the entire frame and redraw it (when
  6627 `auto-resize-tool-bars' is set to `grow-only', this resets the
  6628 tool-bar's height to the minimum height needed); if
  6629 `recenter-redisplay' has the special value `tty', then only tty frames
  6630 are redrawn.  Interactively, REDISPLAY is always non-nil.
  6631 
  6632 Just C-u as prefix means put point in the center of the window
  6633 and redisplay normally--don't erase and redraw the frame.  */)
  6634   (Lisp_Object arg, Lisp_Object redisplay)
  6635 {
  6636   struct window *w = XWINDOW (selected_window);
  6637   struct buffer *buf = XBUFFER (w->contents);
  6638   bool center_p = false;
  6639   ptrdiff_t charpos, bytepos;
  6640   EMACS_INT iarg UNINIT;
  6641   int this_scroll_margin;
  6642 
  6643   /* For reasons why we signal an error here, see
  6644      https://lists.gnu.org/r/emacs-devel/2014-06/msg00053.html,
  6645      https://lists.gnu.org/r/emacs-devel/2014-06/msg00094.html.  */
  6646   if (buf != current_buffer)
  6647     error ("`recenter'ing a window that does not display current-buffer.");
  6648 
  6649   /* If redisplay is suppressed due to an error, try again.  */
  6650   buf->display_error_modiff = 0;
  6651 
  6652   if (NILP (arg))
  6653     {
  6654       if (!NILP (redisplay)
  6655           && !NILP (Vrecenter_redisplay)
  6656           && (!EQ (Vrecenter_redisplay, Qtty)
  6657               || !NILP (Ftty_type (selected_frame))))
  6658         {
  6659           ptrdiff_t i;
  6660 
  6661           /* Invalidate pixel data calculated for all compositions.  */
  6662           for (i = 0; i < n_compositions; i++)
  6663             composition_table[i]->font = NULL;
  6664 #if defined (HAVE_WINDOW_SYSTEM)
  6665           WINDOW_XFRAME (w)->minimize_tab_bar_window_p = 1;
  6666 #endif
  6667 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
  6668           WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
  6669 #endif
  6670           Fredraw_frame (WINDOW_FRAME (w));
  6671           SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
  6672         }
  6673 
  6674       center_p = true;
  6675     }
  6676   else if (CONSP (arg)) /* Just C-u.  */
  6677     center_p = true;
  6678   else
  6679     {
  6680       arg = Fprefix_numeric_value (arg);
  6681       CHECK_FIXNUM (arg);
  6682       iarg = XFIXNUM (arg);
  6683     }
  6684 
  6685   /* Do this after making BUF current
  6686      in case scroll_margin is buffer-local.  */
  6687   this_scroll_margin = window_scroll_margin (w, MARGIN_IN_LINES);
  6688 
  6689   /* Don't use the display code for initial frames, as the necessary
  6690      data structures might not be set up yet then.  Also don't use it
  6691      for buffers with very long lines, as it tremdously slows down
  6692      redisplay, especially when lines are truncated.  */
  6693   if (!FRAME_INITIAL_P (XFRAME (w->frame))
  6694       && !current_buffer->long_line_optimizations_p)
  6695     {
  6696       specpdl_ref count = SPECPDL_INDEX ();
  6697 
  6698       record_unwind_protect_void (unwind_display_working_on_window);
  6699       display_working_on_window_p = true;
  6700       if (center_p)
  6701         {
  6702           struct it it;
  6703           struct text_pos pt;
  6704           void *itdata = bidi_shelve_cache ();
  6705 
  6706           SET_TEXT_POS (pt, PT, PT_BYTE);
  6707           start_display (&it, w, pt);
  6708           move_it_vertically_backward (&it, window_box_height (w) / 2);
  6709           charpos = IT_CHARPOS (it);
  6710           bytepos = IT_BYTEPOS (it);
  6711           bidi_unshelve_cache (itdata, false);
  6712         }
  6713       else if (iarg < 0)
  6714         {
  6715           struct it it;
  6716           struct text_pos pt;
  6717           ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
  6718           int extra_line_spacing;
  6719           int h = window_box_height (w);
  6720           int ht = window_internal_height (w);
  6721           void *itdata = bidi_shelve_cache ();
  6722 
  6723           nlines = clip_to_bounds (this_scroll_margin + 1, nlines,
  6724                                    ht - this_scroll_margin);
  6725 
  6726           SET_TEXT_POS (pt, PT, PT_BYTE);
  6727           start_display (&it, w, pt);
  6728 
  6729           /* Be sure we have the exact height of the full line containing PT.  */
  6730           move_it_by_lines (&it, 0);
  6731 
  6732           /* The amount of pixels we have to move back is the window
  6733              height minus what's displayed in the line containing PT,
  6734              and the lines below.  */
  6735           it.current_y = 0;
  6736           it.vpos = 0;
  6737           move_it_by_lines (&it, nlines);
  6738 
  6739           if (it.vpos == nlines)
  6740             h -= it.current_y;
  6741           else
  6742             {
  6743               /* Last line has no newline.  */
  6744               h -= line_bottom_y (&it);
  6745               it.vpos++;
  6746             }
  6747 
  6748           /* Don't reserve space for extra line spacing of last line.  */
  6749           extra_line_spacing = it.max_extra_line_spacing;
  6750 
  6751           /* If we can't move down NLINES lines because we hit
  6752              the end of the buffer, count in some empty lines.  */
  6753           if (it.vpos < nlines)
  6754             {
  6755               nlines -= it.vpos;
  6756               extra_line_spacing = it.extra_line_spacing;
  6757               h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
  6758             }
  6759           if (h <= 0)
  6760             {
  6761               bidi_unshelve_cache (itdata, false);
  6762               unbind_to (count, Qnil);
  6763               return Qnil;
  6764             }
  6765 
  6766           /* Now find the new top line (starting position) of the window.  */
  6767           start_display (&it, w, pt);
  6768           it.current_y = 0;
  6769           move_it_vertically_backward (&it, h);
  6770 
  6771           /* If extra line spacing is present, we may move too far
  6772              back.  This causes the last line to be only partially
  6773              visible (which triggers redisplay to recenter that line
  6774              in the middle), so move forward.
  6775              But ignore extra line spacing on last line, as it is not
  6776              considered to be part of the visible height of the line.
  6777           */
  6778           h += extra_line_spacing;
  6779           while (-it.current_y > h && it.what != IT_EOB)
  6780             move_it_by_lines (&it, 1);
  6781 
  6782           charpos = IT_CHARPOS (it);
  6783           bytepos = IT_BYTEPOS (it);
  6784 
  6785           bidi_unshelve_cache (itdata, false);
  6786         }
  6787       else
  6788         {
  6789           struct it it;
  6790           struct text_pos pt;
  6791           ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
  6792           int ht = window_internal_height (w);
  6793           void *itdata = bidi_shelve_cache ();
  6794 
  6795           nlines = clip_to_bounds (this_scroll_margin, nlines,
  6796                                    ht - this_scroll_margin - 1);
  6797 
  6798           SET_TEXT_POS (pt, PT, PT_BYTE);
  6799           start_display (&it, w, pt);
  6800 
  6801           /* Move to the beginning of screen line containing PT.  */
  6802           move_it_by_lines (&it, 0);
  6803 
  6804           /* Move back to find the point which is ARG screen lines above PT.  */
  6805           if (nlines > 0)
  6806             {
  6807               it.current_y = 0;
  6808               it.vpos = 0;
  6809               move_it_by_lines (&it, -nlines);
  6810             }
  6811 
  6812           charpos = IT_CHARPOS (it);
  6813           bytepos = IT_BYTEPOS (it);
  6814 
  6815           bidi_unshelve_cache (itdata, false);
  6816         }
  6817       unbind_to (count, Qnil);
  6818     }
  6819   else
  6820     {
  6821       struct position pos;
  6822       int ht = window_internal_height (w);
  6823 
  6824       if (center_p)
  6825         iarg = ht / 2;
  6826       else if (iarg < 0)
  6827         iarg += ht;
  6828 
  6829       /* Don't let it get into the margin at either top or bottom.  */
  6830       iarg = clip_to_bounds (this_scroll_margin, iarg,
  6831                              ht - this_scroll_margin - 1);
  6832 
  6833       pos = *vmotion (PT, PT_BYTE, - iarg, w);
  6834       charpos = pos.bufpos;
  6835       bytepos = pos.bytepos;
  6836     }
  6837 
  6838   /* Set the new window start.  */
  6839   set_marker_both (w->start, w->contents, charpos, bytepos);
  6840   w->window_end_valid = false;
  6841 
  6842   w->optional_new_start = true;
  6843 
  6844   w->start_at_line_beg = (bytepos == BEGV_BYTE
  6845                           || FETCH_BYTE (bytepos - 1) == '\n');
  6846 
  6847   wset_redisplay (w);
  6848 
  6849   return Qnil;
  6850 }
  6851 
  6852 DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
  6853        0, 2, 0,
  6854        doc: /* Return the width in columns of the text display area of WINDOW.
  6855 WINDOW must be a live window and defaults to the selected one.
  6856 
  6857 The returned width does not include dividers, scrollbars, margins,
  6858 fringes, nor any partial-width columns at the right of the text
  6859 area.
  6860 
  6861 Optional argument PIXELWISE non-nil, means to return the width in
  6862 pixels.  */)
  6863   (Lisp_Object window, Lisp_Object pixelwise)
  6864 {
  6865   struct window *w = decode_live_window (window);
  6866 
  6867   if (NILP (pixelwise))
  6868     return make_fixnum (window_box_width (w, TEXT_AREA)
  6869                         / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
  6870   else
  6871     return make_fixnum (window_box_width (w, TEXT_AREA));
  6872 }
  6873 
  6874 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
  6875        0, 2, 0,
  6876        doc: /* Return the height in lines of the text display area of WINDOW.
  6877 WINDOW must be a live window and defaults to the selected one.
  6878 
  6879 The returned height does not include dividers, the mode line, any header
  6880 line, nor any partial-height lines at the bottom of the text area.
  6881 
  6882 Optional argument PIXELWISE non-nil, means to return the height in
  6883 pixels.  */)
  6884   (Lisp_Object window, Lisp_Object pixelwise)
  6885 {
  6886   struct window *w = decode_live_window (window);
  6887 
  6888   if (NILP (pixelwise))
  6889     return make_fixnum (window_box_height (w)
  6890                         / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
  6891   else
  6892     return make_fixnum (window_box_height (w));
  6893 }
  6894 
  6895 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
  6896        1, 1, "P",
  6897        doc: /* Position point relative to window.
  6898 ARG nil means position point at center of window.
  6899 Else, ARG specifies vertical position within the window;
  6900 zero means top of window, negative means relative to bottom
  6901 of window, -1 meaning the last fully visible display line
  6902 of the window.
  6903 
  6904 Value is the screen line of the window point moved to, counting
  6905 from the top of the window.  */)
  6906   (Lisp_Object arg)
  6907 {
  6908   struct window *w = XWINDOW (selected_window);
  6909   int lines, start;
  6910   Lisp_Object window;
  6911 #if false
  6912   int this_scroll_margin;
  6913 #endif
  6914 
  6915   if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
  6916     /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
  6917        when passed below to set_marker_both.  */
  6918     error ("move-to-window-line called from unrelated buffer");
  6919 
  6920   window = selected_window;
  6921   start = marker_position (w->start);
  6922   if (start < BEGV || start > ZV)
  6923     {
  6924       int height = window_internal_height (w);
  6925       Fvertical_motion (make_fixnum (- (height / 2)), window, Qnil);
  6926       set_marker_both (w->start, w->contents, PT, PT_BYTE);
  6927       w->start_at_line_beg = !NILP (Fbolp ());
  6928       w->force_start = true;
  6929     }
  6930   else
  6931     Fgoto_char (w->start);
  6932 
  6933   lines = displayed_window_lines (w);
  6934 
  6935   if (NILP (arg))
  6936     XSETFASTINT (arg, lines / 2);
  6937   else
  6938     {
  6939       EMACS_INT iarg = XFIXNUM (Fprefix_numeric_value (arg));
  6940 
  6941       if (iarg < 0)
  6942         iarg = iarg + lines;
  6943 
  6944 #if false /* This code would prevent move-to-window-line from moving point
  6945              to a place inside the scroll margins (which would cause the
  6946              next redisplay to scroll).  I wrote this code, but then concluded
  6947              it is probably better not to install it.  However, it is here
  6948              inside #if false so as not to lose it.  -- rms.  */
  6949 
  6950       this_scroll_margin = window_scroll_margin (w, MARGIN_IN_LINES);
  6951 
  6952       /* Don't let it get into the margin at either top or bottom.  */
  6953       iarg = max (iarg, this_scroll_margin);
  6954       iarg = min (iarg, lines - this_scroll_margin - 1);
  6955 #endif
  6956 
  6957       arg = make_fixnum (iarg);
  6958     }
  6959 
  6960   /* Skip past a partially visible first line.  */
  6961   if (w->vscroll)
  6962     XSETINT (arg, XFIXNUM (arg) + 1);
  6963 
  6964   return Fvertical_motion (arg, window, Qnil);
  6965 }
  6966 
  6967 
  6968 
  6969 /***********************************************************************
  6970                          Window Configuration
  6971  ***********************************************************************/
  6972 
  6973 struct save_window_data
  6974   {
  6975     union vectorlike_header header;
  6976     Lisp_Object selected_frame;
  6977     Lisp_Object current_window;
  6978     Lisp_Object f_current_buffer;
  6979     Lisp_Object minibuf_scroll_window;
  6980     Lisp_Object minibuf_selected_window;
  6981     Lisp_Object root_window;
  6982     Lisp_Object focus_frame;
  6983     /* A vector, each of whose elements is a struct saved_window
  6984        for one window.  */
  6985     Lisp_Object saved_windows;
  6986 
  6987     /* All fields above are traced by the GC.
  6988        After saved_windows, the fields are ignored by the GC.  */
  6989 
  6990     /* We should be able to do without the following two.  */
  6991     int frame_cols, frame_lines;
  6992     /* These three should get eventually replaced by their pixel
  6993        counterparts.  */
  6994     int frame_menu_bar_lines, frame_tab_bar_lines, frame_tool_bar_lines;
  6995     int frame_text_width, frame_text_height;
  6996     /* These are currently unused.  We need them as soon as we convert
  6997        to pixels.  */
  6998     int frame_menu_bar_height, frame_tab_bar_height, frame_tool_bar_height;
  6999   } GCALIGNED_STRUCT;
  7000 
  7001 /* This is saved as a Lisp_Vector.  */
  7002 struct saved_window
  7003 {
  7004   union vectorlike_header header;
  7005 
  7006   Lisp_Object window, buffer, start, pointm, old_pointm;
  7007   Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
  7008   Lisp_Object left_col, top_line, total_cols, total_lines;
  7009   Lisp_Object normal_cols, normal_lines;
  7010   Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
  7011   Lisp_Object vscroll;
  7012   Lisp_Object parent, prev;
  7013   Lisp_Object start_at_line_beg;
  7014   Lisp_Object display_table;
  7015   Lisp_Object left_margin_cols, right_margin_cols;
  7016   Lisp_Object left_fringe_width, right_fringe_width;
  7017   Lisp_Object fringes_outside_margins, fringes_persistent;
  7018   Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
  7019   Lisp_Object scroll_bar_height, horizontal_scroll_bar_type;
  7020   Lisp_Object scroll_bars_persistent, dedicated;
  7021   Lisp_Object combination_limit, window_parameters;
  7022 };
  7023 
  7024 #define SAVED_WINDOW_N(swv,n) \
  7025   ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
  7026 
  7027 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
  7028        doc: /* Return t if OBJECT is a window-configuration object.  */)
  7029   (Lisp_Object object)
  7030 {
  7031   return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
  7032 }
  7033 
  7034 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
  7035        doc: /* Return the frame that CONFIG, a window-configuration object, is about.  */)
  7036   (Lisp_Object config)
  7037 {
  7038   register struct save_window_data *data;
  7039   struct Lisp_Vector *saved_windows;
  7040 
  7041   CHECK_WINDOW_CONFIGURATION (config);
  7042 
  7043   data = (struct save_window_data *) XVECTOR (config);
  7044   saved_windows = XVECTOR (data->saved_windows);
  7045   return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
  7046 }
  7047 
  7048 DEFUN ("set-window-configuration", Fset_window_configuration,
  7049        Sset_window_configuration, 1, 3, 0,
  7050        doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
  7051 CONFIGURATION must be a value previously returned
  7052 by `current-window-configuration' (which see).
  7053 
  7054 Normally, this function selects the frame of the CONFIGURATION, but if
  7055 DONT-SET-FRAME is non-nil, it leaves selected the frame which was
  7056 current at the start of the function.  If DONT-SET-MINIWINDOW is non-nil,
  7057 the mini-window of the frame doesn't get set to the corresponding element
  7058 of CONFIGURATION.
  7059 
  7060 If CONFIGURATION was made from a frame that is now deleted,
  7061 only frame-independent values can be restored.  In this case,
  7062 the return value is nil.  Otherwise the value is t.  */)
  7063   (Lisp_Object configuration, Lisp_Object dont_set_frame,
  7064    Lisp_Object dont_set_miniwindow)
  7065 {
  7066   register struct save_window_data *data;
  7067   struct Lisp_Vector *saved_windows;
  7068   Lisp_Object new_current_buffer;
  7069   Lisp_Object frame;
  7070   Lisp_Object old_frame = selected_frame;
  7071   struct frame *f;
  7072   ptrdiff_t old_point = -1;
  7073   USE_SAFE_ALLOCA;
  7074 
  7075   CHECK_WINDOW_CONFIGURATION (configuration);
  7076 
  7077   data = (struct save_window_data *) XVECTOR (configuration);
  7078   saved_windows = XVECTOR (data->saved_windows);
  7079 
  7080   new_current_buffer = data->f_current_buffer;
  7081   if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
  7082     new_current_buffer = Qnil;
  7083   else
  7084     {
  7085       if (XBUFFER (new_current_buffer) == current_buffer)
  7086         /* The code further down "preserves point" by saving here PT in
  7087            old_point and then setting it later back into PT.  When the
  7088            current-selected-window and the final-selected-window both show
  7089            the current buffer, this suffers from the problem that the
  7090            current PT is the window-point of the current-selected-window,
  7091            while the final PT is the point of the final-selected-window, so
  7092            this copy from one PT to the other would end up moving the
  7093            window-point of the final-selected-window to the window-point of
  7094            the current-selected-window.  So we have to be careful which
  7095            point of the current-buffer we copy into old_point.  */
  7096         if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
  7097             && WINDOWP (selected_window)
  7098             && EQ (XWINDOW (selected_window)->contents, new_current_buffer)
  7099             && !EQ (selected_window, data->current_window))
  7100           old_point = marker_position (XWINDOW (data->current_window)->pointm);
  7101         else
  7102           old_point = PT;
  7103       else
  7104         /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
  7105            point in new_current_buffer as of the last time this buffer was
  7106            used.  This can be non-deterministic since it can be changed by
  7107            things like jit-lock by mere temporary selection of some random
  7108            window that happens to show this buffer.
  7109            So if possible we want this arbitrary choice of "which point" to
  7110            be the one from the to-be-selected-window so as to prevent this
  7111            window's cursor from being copied from another window.  */
  7112         if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
  7113             /* If current_window = selected_window, its point is in BUF_PT.  */
  7114             && !EQ (selected_window, data->current_window))
  7115           old_point = marker_position (XWINDOW (data->current_window)->pointm);
  7116         else
  7117           old_point = BUF_PT (XBUFFER (new_current_buffer));
  7118     }
  7119 
  7120   frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
  7121   f = XFRAME (frame);
  7122 
  7123   /* If f is a dead frame, don't bother rebuilding its window tree.
  7124      However, there is other stuff we should still try to do below.  */
  7125   if (FRAME_LIVE_P (f))
  7126     {
  7127       Lisp_Object window;
  7128       Lisp_Object dead_windows = Qnil;
  7129       Lisp_Object tem, par, pers;
  7130       struct window *w;
  7131       struct saved_window *p;
  7132       struct window *root_window;
  7133       struct window **leaf_windows;
  7134       ptrdiff_t i, k, n_leaf_windows;
  7135 
  7136       /* Don't do this within the main loop below: This may call Lisp
  7137          code and is thus potentially unsafe while input is blocked.  */
  7138       for (k = 0; k < saved_windows->header.size; k++)
  7139         {
  7140           p = SAVED_WINDOW_N (saved_windows, k);
  7141           window = p->window;
  7142           w = XWINDOW (window);
  7143 
  7144           if (BUFFERP (w->contents)
  7145               && !EQ (w->contents, p->buffer)
  7146               && BUFFER_LIVE_P (XBUFFER (p->buffer))
  7147               && (NILP (Fminibufferp (p->buffer, Qnil))))
  7148             /* If a window we restore gets another buffer, record the
  7149                window's old buffer.  */
  7150             call1 (Qrecord_window_buffer, window);
  7151         }
  7152 
  7153       /* Disallow set_window_size_hook, temporarily.  */
  7154       f->can_set_window_size = false;
  7155       /* The mouse highlighting code could get screwed up
  7156          if it runs during this.  */
  7157       block_input ();
  7158 
  7159       /* "Swap out" point from the selected window's buffer
  7160          into the window itself.  (Normally the pointm of the selected
  7161          window holds garbage.)  We do this now, before
  7162          restoring the window contents, and prevent it from
  7163          being done later on when we select a new window.  */
  7164       if (! NILP (XWINDOW (selected_window)->contents))
  7165         {
  7166           w = XWINDOW (selected_window);
  7167           set_marker_both (w->pointm,
  7168                            w->contents,
  7169                            BUF_PT (XBUFFER (w->contents)),
  7170                            BUF_PT_BYTE (XBUFFER (w->contents)));
  7171         }
  7172 
  7173       fset_redisplay (f);
  7174 
  7175       /* Problem: Freeing all matrices and later allocating them again
  7176          is a serious redisplay flickering problem.  What we would
  7177          really like to do is to free only those matrices not reused
  7178          below.  */
  7179       root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
  7180       ptrdiff_t nwindows = count_windows (root_window);
  7181       SAFE_NALLOCA (leaf_windows, 1, nwindows);
  7182       n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
  7183 
  7184       /* Kludge Alert!
  7185          Mark all windows now on frame as "deleted".
  7186          Restoring the new configuration "undeletes" any that are in it.
  7187 
  7188          Save their current buffers in their height fields, since we may
  7189          need it later, if a buffer saved in the configuration is now
  7190          dead.  */
  7191       delete_all_child_windows (FRAME_ROOT_WINDOW (f));
  7192 
  7193       for (k = 0; k < saved_windows->header.size; k++)
  7194         {
  7195           p = SAVED_WINDOW_N (saved_windows, k);
  7196           window = p->window;
  7197           w = XWINDOW (window);
  7198           wset_next (w, Qnil);
  7199 
  7200           if (!NILP (p->parent))
  7201             wset_parent
  7202               (w, SAVED_WINDOW_N (saved_windows, XFIXNAT (p->parent))->window);
  7203           else
  7204             wset_parent (w, Qnil);
  7205 
  7206           if (!NILP (p->prev))
  7207             {
  7208               wset_prev
  7209                 (w, SAVED_WINDOW_N (saved_windows, XFIXNAT (p->prev))->window);
  7210               wset_next (XWINDOW (w->prev), p->window);
  7211             }
  7212           else
  7213             {
  7214               wset_prev (w, Qnil);
  7215               if (!NILP (w->parent))
  7216                 wset_combination (XWINDOW (w->parent),
  7217                                   (XFIXNUM (p->total_cols)
  7218                                    != XWINDOW (w->parent)->total_cols),
  7219                                   p->window);
  7220             }
  7221 
  7222           /* If we squirreled away the buffer, restore it now.  */
  7223           if (BUFFERP (w->combination_limit))
  7224             wset_buffer (w, w->combination_limit);
  7225           w->pixel_left = XFIXNAT (p->pixel_left);
  7226           w->pixel_top = XFIXNAT (p->pixel_top);
  7227           w->pixel_width = XFIXNAT (p->pixel_width);
  7228           w->pixel_height = XFIXNAT (p->pixel_height);
  7229           w->left_col = XFIXNAT (p->left_col);
  7230           w->top_line = XFIXNAT (p->top_line);
  7231           w->total_cols = XFIXNAT (p->total_cols);
  7232           w->total_lines = XFIXNAT (p->total_lines);
  7233           wset_normal_cols (w, p->normal_cols);
  7234           wset_normal_lines (w, p->normal_lines);
  7235           w->hscroll = XFIXNAT (p->hscroll);
  7236           w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll);
  7237           w->min_hscroll = XFIXNAT (p->min_hscroll);
  7238           w->hscroll_whole = XFIXNAT (p->hscroll_whole);
  7239           w->vscroll = -XFIXNAT (p->vscroll);
  7240           wset_display_table (w, p->display_table);
  7241           w->left_margin_cols = XFIXNUM (p->left_margin_cols);
  7242           w->right_margin_cols = XFIXNUM (p->right_margin_cols);
  7243           w->left_fringe_width = XFIXNUM (p->left_fringe_width);
  7244           w->right_fringe_width = XFIXNUM (p->right_fringe_width);
  7245           w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
  7246           w->fringes_persistent = !NILP (p->fringes_persistent);
  7247           w->scroll_bar_width = XFIXNUM (p->scroll_bar_width);
  7248           w->scroll_bar_height = XFIXNUM (p->scroll_bar_height);
  7249           w->scroll_bars_persistent = !NILP (p->scroll_bars_persistent);
  7250           wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
  7251           wset_horizontal_scroll_bar_type (w, p->horizontal_scroll_bar_type);
  7252           wset_dedicated (w, p->dedicated);
  7253           wset_combination_limit (w, p->combination_limit);
  7254           /* Restore any window parameters that have been saved.
  7255              Parameters that have not been saved are left alone.  */
  7256           for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
  7257             {
  7258               pers = XCAR (tem);
  7259               if (CONSP (pers))
  7260                 {
  7261                   if (NILP (XCDR (pers)))
  7262                     {
  7263                       par = Fassq (XCAR (pers), w->window_parameters);
  7264                       if (CONSP (par) && !NILP (XCDR (par)))
  7265                         /* Reset a parameter to nil if and only if it
  7266                            has a non-nil association.  Don't make new
  7267                            associations.  */
  7268                         Fsetcdr (par, Qnil);
  7269                     }
  7270                   else
  7271                     /* Always restore a non-nil value.  */
  7272                     Fset_window_parameter (window, XCAR (pers), XCDR (pers));
  7273                 }
  7274             }
  7275 
  7276           if ((NILP (dont_set_miniwindow) || !MINI_WINDOW_P (w))
  7277               && BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
  7278             /* If saved buffer is alive, install it, unless it's a
  7279                minibuffer we explicitly prohibit.  */
  7280             {
  7281               wset_buffer (w, p->buffer);
  7282               w->start_at_line_beg = !NILP (p->start_at_line_beg);
  7283               set_marker_restricted (w->start, p->start, w->contents);
  7284               set_marker_restricted (w->pointm, p->pointm, w->contents);
  7285               set_marker_restricted (w->old_pointm, p->old_pointm, w->contents);
  7286               /* As documented in Fcurrent_window_configuration, don't
  7287                  restore the location of point in the buffer which was
  7288                  current when the window configuration was recorded.  */
  7289               if (!EQ (p->buffer, new_current_buffer)
  7290                   && XBUFFER (p->buffer) == current_buffer)
  7291                 Fgoto_char (w->pointm);
  7292             }
  7293           else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
  7294             /* Keep window's old buffer; make sure the markers are real.  */
  7295             {
  7296               /* Set window markers at start of visible range.  */
  7297               if (XMARKER (w->start)->buffer == 0)
  7298                 set_marker_restricted_both (w->start, w->contents, 0, 0);
  7299               if (XMARKER (w->pointm)->buffer == 0)
  7300                 set_marker_restricted_both
  7301                   (w->pointm, w->contents,
  7302                    BUF_PT (XBUFFER (w->contents)),
  7303                    BUF_PT_BYTE (XBUFFER (w->contents)));
  7304               if (XMARKER (w->old_pointm)->buffer == 0)
  7305                 set_marker_restricted_both
  7306                   (w->old_pointm, w->contents,
  7307                    BUF_PT (XBUFFER (w->contents)),
  7308                    BUF_PT_BYTE (XBUFFER (w->contents)));
  7309               w->start_at_line_beg = true;
  7310             }
  7311           else if (!NILP (w->start))
  7312             /* Leaf window has no live buffer, get one.  */
  7313             {
  7314               /* Get the buffer via other_buffer_safely in order to
  7315                  avoid showing an unimportant buffer and, if necessary, to
  7316                  recreate *scratch* in the course (part of Juanma's bs-show
  7317                  scenario from March 2011).  */
  7318               wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
  7319               /* This will set the markers to beginning of visible
  7320                  range.  */
  7321               set_marker_restricted_both (w->start, w->contents, 0, 0);
  7322               set_marker_restricted_both (w->pointm, w->contents, 0, 0);
  7323               set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
  7324               w->start_at_line_beg = true;
  7325               if (!NILP (w->dedicated))
  7326                 /* Record this window as dead.  */
  7327                 dead_windows = Fcons (window, dead_windows);
  7328               /* Make sure window is no more dedicated.  */
  7329               wset_dedicated (w, Qnil);
  7330             }
  7331         }
  7332 
  7333       fset_root_window (f, data->root_window);
  7334       /* Arrange *not* to restore point in the buffer that was
  7335          current when the window configuration was saved.  */
  7336       if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
  7337         set_marker_restricted (XWINDOW (data->current_window)->pointm,
  7338                                make_fixnum (old_point),
  7339                                XWINDOW (data->current_window)->contents);
  7340 
  7341       /* In the following call to select_window, prevent "swapping out
  7342          point" in the old selected window using the buffer that has
  7343          been restored into it.  We already swapped out that point
  7344          from that window's old buffer.
  7345 
  7346          Do not record the buffer here.  We do that in a separate call
  7347          to select_window below.  See also Bug#16207.  */
  7348       select_window (data->current_window, Qt, true);
  7349       BVAR (XBUFFER (XWINDOW (selected_window)->contents),
  7350             last_selected_window)
  7351         = selected_window;
  7352 
  7353       /* We may have deleted windows above.  Then again, maybe we
  7354          haven't: the functions we call to maybe delete windows can
  7355          decide a window cannot be deleted.  Force recalculation of
  7356          Vwindow_list next time it is needed, to make sure stale
  7357          windows with no buffers don't escape into the wild, which
  7358          will cause crashes elsewhere.  */
  7359       Vwindow_list = Qnil;
  7360 
  7361       if (NILP (data->focus_frame)
  7362           || (FRAMEP (data->focus_frame)
  7363               && FRAME_LIVE_P (XFRAME (data->focus_frame))))
  7364         Fredirect_frame_focus (frame, data->focus_frame);
  7365 
  7366       /* Now, free glyph matrices in windows that were not reused.  */
  7367       for (i = 0; i < n_leaf_windows; i++)
  7368         if (NILP (leaf_windows[i]->contents))
  7369           free_window_matrices (leaf_windows[i]);
  7370 
  7371       /* Allow set_window_size_hook again and resize frame's windows
  7372          if necessary.  But change frame size only to preserve window
  7373          minimum sizes.  */
  7374       f->can_set_window_size = true;
  7375       adjust_frame_size (f, -1, -1, 4, false, Qset_window_configuration);
  7376 
  7377       adjust_frame_glyphs (f);
  7378       unblock_input ();
  7379 
  7380       /* Scan dead buffer windows.  */
  7381       for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
  7382         {
  7383           window = XCAR (dead_windows);
  7384           if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
  7385             delete_deletable_window (window);
  7386         }
  7387 
  7388       /* Record the selected window's buffer here.  The window should
  7389          already be the selected one from the call above.  */
  7390       if (WINDOW_LIVE_P (data->current_window))
  7391         select_window (data->current_window, Qnil, false);
  7392 
  7393       /* select_window will have made f the selected frame, so we
  7394          reselect the proper frame here.  do_switch_frame will change
  7395          the selected window too, but that doesn't make the call to
  7396          select_window above totally superfluous; it still sets f's
  7397          selected window.  */
  7398       if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
  7399         do_switch_frame (NILP (dont_set_frame)
  7400                          ? data->selected_frame
  7401                          : old_frame
  7402                          , 0, 0, Qnil);
  7403     }
  7404 
  7405   FRAME_WINDOW_CHANGE (f) = true;
  7406 
  7407   if (!NILP (new_current_buffer))
  7408     {
  7409       Fset_buffer (new_current_buffer);
  7410       /* If the new current buffer doesn't appear in the selected
  7411          window, go to its old point (Bug#12208).
  7412 
  7413          The original fix used data->current_window below which caused
  7414          false positives (compare Bug#31695) when data->current_window
  7415          is not on data->selected_frame.  This happens, for example,
  7416          when read_minibuf restores the configuration of a stand-alone
  7417          minibuffer frame: After switching to the previously selected
  7418          "normal" frame, point of that frame's selected window jumped
  7419          unexpectedly because new_current_buffer is usually *not*
  7420          shown in data->current_window - the minibuffer frame's
  7421          selected window.  Using selected_window instead fixes this
  7422          because do_switch_frame has set up selected_window already to
  7423          the "normal" frame's selected window and that window *does*
  7424          show new_current_buffer.  */
  7425       if (!EQ (XWINDOW (selected_window)->contents, new_current_buffer))
  7426         Fgoto_char (make_fixnum (old_point));
  7427     }
  7428 
  7429   Vminibuf_scroll_window = data->minibuf_scroll_window;
  7430   minibuf_selected_window = data->minibuf_selected_window;
  7431 
  7432   SAFE_FREE ();
  7433   return FRAME_LIVE_P (f) ? Qt : Qnil;
  7434 }
  7435 
  7436 void
  7437 restore_window_configuration (Lisp_Object configuration)
  7438 {
  7439   if (CONSP (configuration))
  7440     Fset_window_configuration (XCAR (configuration),
  7441                                Fcar_safe (XCDR (configuration)),
  7442                                Fcar_safe (Fcdr_safe (XCDR (configuration))));
  7443   else
  7444     Fset_window_configuration (configuration, Qnil, Qnil);
  7445 }
  7446 
  7447 
  7448 /* If WINDOW is an internal window, recursively delete all child windows
  7449    reachable via the next and contents slots of WINDOW.  Otherwise setup
  7450    WINDOW to not show any buffer.  */
  7451 
  7452 void
  7453 delete_all_child_windows (Lisp_Object window)
  7454 {
  7455   register struct window *w;
  7456 
  7457   w = XWINDOW (window);
  7458 
  7459   if (!NILP (w->next))
  7460     /* Delete WINDOW's siblings (we traverse postorderly).  */
  7461     delete_all_child_windows (w->next);
  7462 
  7463   if (WINDOWP (w->contents))
  7464     {
  7465       delete_all_child_windows (w->contents);
  7466       wset_combination (w, false, Qnil);
  7467     }
  7468   else if (BUFFERP (w->contents))
  7469     {
  7470       unshow_buffer (w);
  7471       unchain_marker (XMARKER (w->pointm));
  7472       unchain_marker (XMARKER (w->old_pointm));
  7473       unchain_marker (XMARKER (w->start));
  7474       /* Since combination limit makes sense for an internal windows
  7475          only, we use this slot to save the buffer for the sake of
  7476          possible resurrection in Fset_window_configuration.  */
  7477       wset_combination_limit (w, w->contents);
  7478       wset_buffer (w, Qnil);
  7479     }
  7480 
  7481   Vwindow_list = Qnil;
  7482 }
  7483 
  7484 static ptrdiff_t
  7485 count_windows (struct window *window)
  7486 {
  7487   ptrdiff_t count = 1;
  7488   if (!NILP (window->next))
  7489     count += count_windows (XWINDOW (window->next));
  7490   if (WINDOWP (window->contents))
  7491     count += count_windows (XWINDOW (window->contents));
  7492   return count;
  7493 }
  7494 
  7495 
  7496 /* Fill vector FLAT with leaf windows under W, starting at index I.
  7497    Value is last index + 1.  */
  7498 static ptrdiff_t
  7499 get_leaf_windows (struct window *w, struct window **flat, ptrdiff_t i)
  7500 {
  7501   while (w)
  7502     {
  7503       if (WINDOWP (w->contents))
  7504         i = get_leaf_windows (XWINDOW (w->contents), flat, i);
  7505       else
  7506         flat[i++] = w;
  7507 
  7508       w = NILP (w->next) ? 0 : XWINDOW (w->next);
  7509     }
  7510 
  7511   return i;
  7512 }
  7513 
  7514 
  7515 /* Return a pointer to the glyph W's physical cursor is on.  Value is
  7516    null if W's current matrix is invalid, so that no meaningful glyph
  7517    can be returned.  */
  7518 struct glyph *
  7519 get_phys_cursor_glyph (struct window *w)
  7520 {
  7521   struct glyph_row *row;
  7522   struct glyph *glyph;
  7523   int hpos = w->phys_cursor.hpos;
  7524 
  7525   if (!(w->phys_cursor.vpos >= 0
  7526         && w->phys_cursor.vpos < w->current_matrix->nrows))
  7527     return NULL;
  7528 
  7529   row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
  7530   if (!row->enabled_p)
  7531     return NULL;
  7532 
  7533   if (w->hscroll)
  7534     {
  7535       /* When the window is hscrolled, cursor hpos can legitimately be
  7536          out of bounds, but we draw the cursor at the corresponding
  7537          window margin in that case.  */
  7538       if (!row->reversed_p && hpos < 0)
  7539         hpos = 0;
  7540       if (row->reversed_p && hpos >= row->used[TEXT_AREA])
  7541         hpos = row->used[TEXT_AREA] - 1;
  7542     }
  7543 
  7544   if (0 <= hpos && hpos < row->used[TEXT_AREA])
  7545     glyph = row->glyphs[TEXT_AREA] + hpos;
  7546   else
  7547     glyph = NULL;
  7548 
  7549   return glyph;
  7550 }
  7551 
  7552 
  7553 static ptrdiff_t
  7554 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i)
  7555 {
  7556   struct saved_window *p;
  7557   struct window *w;
  7558   Lisp_Object tem, pers, par;
  7559 
  7560   for (; !NILP (window); window = w->next)
  7561     {
  7562       p = SAVED_WINDOW_N (vector, i);
  7563       w = XWINDOW (window);
  7564 
  7565       wset_temslot (w, make_fixnum (i)); i++;
  7566       p->window = window;
  7567       p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil);
  7568       p->pixel_left = make_fixnum (w->pixel_left);
  7569       p->pixel_top = make_fixnum (w->pixel_top);
  7570       p->pixel_width = make_fixnum (w->pixel_width);
  7571       p->pixel_height = make_fixnum (w->pixel_height);
  7572       p->left_col = make_fixnum (w->left_col);
  7573       p->top_line = make_fixnum (w->top_line);
  7574       p->total_cols = make_fixnum (w->total_cols);
  7575       p->total_lines = make_fixnum (w->total_lines);
  7576       p->normal_cols = w->normal_cols;
  7577       p->normal_lines = w->normal_lines;
  7578       XSETFASTINT (p->hscroll, w->hscroll);
  7579       p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil;
  7580       XSETFASTINT (p->min_hscroll, w->min_hscroll);
  7581       XSETFASTINT (p->hscroll_whole, w->hscroll_whole);
  7582       XSETFASTINT (p->vscroll, -w->vscroll);
  7583       p->display_table = w->display_table;
  7584       p->left_margin_cols = make_fixnum (w->left_margin_cols);
  7585       p->right_margin_cols = make_fixnum (w->right_margin_cols);
  7586       p->left_fringe_width = make_fixnum (w->left_fringe_width);
  7587       p->right_fringe_width = make_fixnum (w->right_fringe_width);
  7588       p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
  7589       p->fringes_persistent = w->fringes_persistent ? Qt : Qnil;
  7590       p->scroll_bar_width = make_fixnum (w->scroll_bar_width);
  7591       p->scroll_bar_height = make_fixnum (w->scroll_bar_height);
  7592       p->scroll_bars_persistent = w->scroll_bars_persistent ? Qt : Qnil;
  7593       p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
  7594       p->horizontal_scroll_bar_type = w->horizontal_scroll_bar_type;
  7595       p->dedicated = w->dedicated;
  7596       p->combination_limit = w->combination_limit;
  7597       p->window_parameters = Qnil;
  7598 
  7599       if (!NILP (Vwindow_persistent_parameters))
  7600         {
  7601           /* Run cycle detection on Vwindow_persistent_parameters.  */
  7602           Lisp_Object tortoise, hare;
  7603 
  7604           hare = tortoise = Vwindow_persistent_parameters;
  7605           while (CONSP (hare))
  7606             {
  7607               hare = XCDR (hare);
  7608               if (!CONSP (hare))
  7609                 break;
  7610 
  7611               hare = XCDR (hare);
  7612               tortoise = XCDR (tortoise);
  7613 
  7614               if (BASE_EQ (hare, tortoise))
  7615                 /* Reset Vwindow_persistent_parameters to Qnil.  */
  7616                 {
  7617                   Vwindow_persistent_parameters = Qnil;
  7618                   break;
  7619                 }
  7620             }
  7621 
  7622           for (tem = Vwindow_persistent_parameters; CONSP (tem);
  7623                tem = XCDR (tem))
  7624             {
  7625               pers = XCAR (tem);
  7626               /* Save values for persistent window parameters. */
  7627               if (CONSP (pers) && !NILP (XCDR (pers)))
  7628                 {
  7629                   par = Fassq (XCAR (pers), w->window_parameters);
  7630                   if (NILP (par))
  7631                     /* If the window has no value for the parameter,
  7632                        make one.  */
  7633                     p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
  7634                                                   p->window_parameters);
  7635                   else
  7636                     /* If the window has a value for the parameter,
  7637                        save it.  */
  7638                     p->window_parameters = Fcons (Fcons (XCAR (par),
  7639                                                          XCDR (par)),
  7640                                                   p->window_parameters);
  7641                 }
  7642             }
  7643         }
  7644 
  7645       if (BUFFERP (w->contents))
  7646         {
  7647           bool window_point_insertion_type
  7648             = !NILP (buffer_local_value
  7649                       (Qwindow_point_insertion_type, w->contents));
  7650 
  7651           /* Save w's value of point in the window configuration.  If w
  7652              is the selected window, then get the value of point from
  7653              the buffer; pointm is garbage in the selected window.  */
  7654           if (EQ (window, selected_window))
  7655             p->pointm = build_marker (XBUFFER (w->contents),
  7656                                       BUF_PT (XBUFFER (w->contents)),
  7657                                       BUF_PT_BYTE (XBUFFER (w->contents)));
  7658           else
  7659             p->pointm = Fcopy_marker (w->pointm, Qnil);
  7660           p->old_pointm = Fcopy_marker (w->old_pointm, Qnil);
  7661           XMARKER (p->pointm)->insertion_type = window_point_insertion_type;
  7662           XMARKER (p->old_pointm)->insertion_type = window_point_insertion_type;
  7663 
  7664           p->start = Fcopy_marker (w->start, Qnil);
  7665           p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
  7666         }
  7667       else
  7668         {
  7669           p->pointm = Qnil;
  7670           p->old_pointm = Qnil;
  7671           p->start = Qnil;
  7672           p->start_at_line_beg = Qnil;
  7673         }
  7674 
  7675       p->parent = NILP (w->parent) ? Qnil : XWINDOW (w->parent)->temslot;
  7676       p->prev = NILP (w->prev) ? Qnil : XWINDOW (w->prev)->temslot;
  7677 
  7678       if (WINDOWP (w->contents))
  7679         i = save_window_save (w->contents, vector, i);
  7680     }
  7681 
  7682   return i;
  7683 }
  7684 
  7685 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
  7686        Scurrent_window_configuration, 0, 1, 0,
  7687        doc: /* Return an object representing the current window configuration of FRAME.
  7688 If FRAME is nil or omitted, use the selected frame.
  7689 This describes the number of windows, their sizes and current buffers,
  7690 and for each displayed buffer, where display starts, and the position of
  7691 point.  An exception is made for point in the current buffer:
  7692 its value is -not- saved.
  7693 This also records the currently selected frame, and FRAME's focus
  7694 redirection (see `redirect-frame-focus').  The variable
  7695 `window-persistent-parameters' specifies which window parameters are
  7696 saved by this function.  */)
  7697   (Lisp_Object frame)
  7698 {
  7699   struct frame *f = decode_live_frame (frame);
  7700   ptrdiff_t n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
  7701   struct save_window_data *data
  7702     = ALLOCATE_PSEUDOVECTOR (struct save_window_data, saved_windows,
  7703                              PVEC_WINDOW_CONFIGURATION);
  7704   data->frame_cols = FRAME_COLS (f);
  7705   data->frame_lines = FRAME_LINES (f);
  7706   data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
  7707   data->frame_tab_bar_lines = FRAME_TAB_BAR_LINES (f);
  7708   data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
  7709   data->frame_text_width = FRAME_TEXT_WIDTH (f);
  7710   data->frame_text_height = FRAME_TEXT_HEIGHT (f);
  7711   data->frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
  7712   data->frame_tab_bar_height = FRAME_TAB_BAR_HEIGHT (f);
  7713   data->frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
  7714   data->selected_frame = selected_frame;
  7715   data->current_window = FRAME_SELECTED_WINDOW (f);
  7716   XSETBUFFER (data->f_current_buffer, current_buffer);
  7717   data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
  7718   data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
  7719   data->root_window = FRAME_ROOT_WINDOW (f);
  7720   data->focus_frame = FRAME_FOCUS_FRAME (f);
  7721   Lisp_Object tem = make_nil_vector (n_windows);
  7722   data->saved_windows = tem;
  7723   for (ptrdiff_t i = 0; i < n_windows; i++)
  7724     ASET (tem, i, make_nil_vector (VECSIZE (struct saved_window)));
  7725   save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
  7726   XSETWINDOW_CONFIGURATION (tem, data);
  7727   return tem;
  7728 }
  7729 
  7730 /* Called after W's margins, fringes or scroll bars was adjusted.  */
  7731 
  7732 static void
  7733 apply_window_adjustment (struct window *w)
  7734 {
  7735   eassert (w);
  7736   clear_glyph_matrix (w->current_matrix);
  7737   w->window_end_valid = false;
  7738   wset_redisplay (w);
  7739   adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
  7740 }
  7741 
  7742 
  7743 /***********************************************************************
  7744                             Marginal Areas
  7745  ***********************************************************************/
  7746 
  7747 static int
  7748 extract_dimension (Lisp_Object dimension)
  7749 {
  7750   if (NILP (dimension))
  7751     return -1;
  7752   return check_integer_range (dimension, 0, INT_MAX);
  7753 }
  7754 
  7755 static struct window *
  7756 set_window_margins (struct window *w, Lisp_Object left_width,
  7757                     Lisp_Object right_width)
  7758 {
  7759   int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
  7760   int left = NILP (left_width) ? 0 : extract_dimension (left_width);
  7761   int right = NILP (right_width) ? 0 : extract_dimension (right_width);
  7762 
  7763   if (w->left_margin_cols != left || w->right_margin_cols != right)
  7764     {
  7765       /* Don't change anything if new margins won't fit.  */
  7766       if ((WINDOW_PIXEL_WIDTH (w)
  7767            - WINDOW_FRINGES_WIDTH (w)
  7768            - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
  7769            - (left + right) * unit)
  7770           >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
  7771         {
  7772           w->left_margin_cols = left;
  7773           w->right_margin_cols = right;
  7774 
  7775           return w;
  7776         }
  7777       else
  7778         return NULL;
  7779     }
  7780   else
  7781     return NULL;
  7782 }
  7783 
  7784 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
  7785        2, 3, 0,
  7786        doc: /* Set width of marginal areas of window WINDOW.
  7787 WINDOW must be a live window and defaults to the selected one.
  7788 
  7789 Second arg LEFT-WIDTH specifies the number of character cells to
  7790 reserve for the left marginal area.  Optional third arg RIGHT-WIDTH
  7791 does the same for the right marginal area.  A nil width parameter
  7792 means no margin.
  7793 
  7794 Leave margins unchanged if WINDOW is not large enough to accommodate
  7795 margins of the desired width.  Return t if any margin was actually
  7796 changed and nil otherwise.  */)
  7797   (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
  7798 {
  7799   struct window *w = set_window_margins (decode_live_window (window),
  7800                                          left_width, right_width);
  7801   return w ? (apply_window_adjustment (w), Qt) : Qnil;
  7802 }
  7803 
  7804 
  7805 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
  7806        0, 1, 0,
  7807        doc: /* Get width of marginal areas of window WINDOW.
  7808 WINDOW must be a live window and defaults to the selected one.
  7809 
  7810 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
  7811 If a marginal area does not exist, its width will be returned
  7812 as nil.  */)
  7813   (Lisp_Object window)
  7814 {
  7815   struct window *w = decode_live_window (window);
  7816   return Fcons (w->left_margin_cols
  7817                 ? make_fixnum (w->left_margin_cols) : Qnil,
  7818                 w->right_margin_cols
  7819                 ? make_fixnum (w->right_margin_cols) : Qnil);
  7820 }
  7821 
  7822 
  7823 
  7824 /***********************************************************************
  7825                             Fringes
  7826  ***********************************************************************/
  7827 
  7828 static struct window *
  7829 set_window_fringes (struct window *w,
  7830                     Lisp_Object left_width, Lisp_Object right_width,
  7831                     Lisp_Object outside_margins, Lisp_Object persistent)
  7832 {
  7833   /* Do nothing on a tty.  */
  7834   if (!FRAME_WINDOW_P (WINDOW_XFRAME (w)))
  7835     return NULL;
  7836   else
  7837     {
  7838       struct frame *f = XFRAME (WINDOW_FRAME (w));
  7839       int old_left = WINDOW_LEFT_FRINGE_WIDTH (w);
  7840       int old_right = WINDOW_RIGHT_FRINGE_WIDTH (w);
  7841       int new_left = extract_dimension (left_width);
  7842       int new_right = extract_dimension (right_width);
  7843       bool outside = !NILP (outside_margins);
  7844       bool changed = false;
  7845       bool failed = false;
  7846 
  7847       /* Check dimensions of new fringes.  Make changes only if they
  7848          fit the window's dimensions.  */
  7849       if ((WINDOW_PIXEL_WIDTH (w)
  7850            - WINDOW_MARGINS_WIDTH (w)
  7851            - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
  7852            - WINDOW_RIGHT_DIVIDER_WIDTH (w)
  7853            - (new_left == -1 ? FRAME_LEFT_FRINGE_WIDTH (f) : new_left)
  7854            - (new_right == -1 ? FRAME_RIGHT_FRINGE_WIDTH (f) : new_right))
  7855           >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
  7856         {
  7857           w->left_fringe_width = new_left;
  7858           w->right_fringe_width = new_right;
  7859           changed = new_left != old_left || new_right != old_right;
  7860         }
  7861       else
  7862         failed = true;
  7863 
  7864       /* Placing fringes outside margins.  */
  7865       if (outside != w->fringes_outside_margins)
  7866         {
  7867           w->fringes_outside_margins = outside;
  7868           changed = true;
  7869         }
  7870 
  7871       /* Make settings persistent unless we failed to apply some
  7872          changes.  */
  7873       if (!failed)
  7874         w->fringes_persistent = !NILP (persistent);
  7875 
  7876       /* This is needed to trigger immediate redisplay of the window
  7877          when its fringes are changed, because fringes are redrawn
  7878          only if update_window is called, so we must trigger that even
  7879          if the window's glyph matrices did not change at all.  */
  7880       if (changed)
  7881         {
  7882           windows_or_buffers_changed = 35;
  7883           return w;
  7884         }
  7885       else
  7886         return NULL;
  7887     }
  7888 }
  7889 
  7890 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
  7891        2, 5, 0,
  7892        doc: /* Set fringes of specified WINDOW.
  7893 WINDOW must specify a live window and defaults to the selected one.
  7894 
  7895 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
  7896 the left fringe.  Optional third arg RIGHT-WIDTH specifies the right
  7897 fringe width.  If a fringe width arg is nil, that means to use the
  7898 frame's default fringe width.  Default fringe widths can be set with
  7899 the command `set-fringe-style'.
  7900 
  7901 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
  7902 outside of the display margins.  By default, fringes are drawn between
  7903 display marginal areas and the text area.
  7904 
  7905 Optional fifth argument PERSISTENT non-nil means that fringe settings
  7906 for WINDOW are persistent, i.e., remain unchanged when another buffer
  7907 is shown in WINDOW.  PERSISTENT nil means that fringes are reset from
  7908 buffer local values when `set-window-buffer' is called on WINDOW with
  7909 the argument KEEP-MARGINS nil.
  7910 
  7911 Leave fringes unchanged if WINDOW is not large enough to accommodate
  7912 fringes of the desired width.  Return t if any fringe was actually
  7913 changed and nil otherwise.  */)
  7914   (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width,
  7915    Lisp_Object outside_margins, Lisp_Object persistent)
  7916 {
  7917   struct window *w
  7918     = set_window_fringes (decode_live_window (window), left_width,
  7919                           right_width, outside_margins, persistent);
  7920   return w ? (apply_window_adjustment (w), Qt) : Qnil;
  7921 }
  7922 
  7923 
  7924 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
  7925        0, 1, 0,
  7926        doc: /* Return fringe settings for specified WINDOW.
  7927 WINDOW must be a live window and defaults to the selected one.
  7928 
  7929 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS
  7930 PERSISTENT), see `set-window-fringes'.  */)
  7931   (Lisp_Object window)
  7932 {
  7933   struct window *w = decode_live_window (window);
  7934 
  7935   return list4 (make_fixnum (WINDOW_LEFT_FRINGE_WIDTH (w)),
  7936                 make_fixnum (WINDOW_RIGHT_FRINGE_WIDTH (w)),
  7937                 WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil,
  7938                 w->fringes_persistent ? Qt : Qnil);
  7939 }
  7940 
  7941 
  7942 
  7943 /***********************************************************************
  7944                             Scroll bars
  7945  ***********************************************************************/
  7946 
  7947 static struct window *
  7948 set_window_scroll_bars (struct window *w, Lisp_Object width,
  7949                         Lisp_Object vertical_type, Lisp_Object height,
  7950                         Lisp_Object horizontal_type, Lisp_Object persistent)
  7951 {
  7952   /* Do nothing on a tty.  */
  7953   if (!FRAME_WINDOW_P (WINDOW_XFRAME (w)))
  7954     return NULL;
  7955   else
  7956     {
  7957       struct frame *f = XFRAME (WINDOW_FRAME (w));
  7958       int new_width = extract_dimension (width);
  7959       bool changed = false;
  7960       bool failed = false;
  7961 
  7962       if (new_width == 0)
  7963         vertical_type = Qnil;
  7964       else if (!(NILP (vertical_type)
  7965                  || EQ (vertical_type, Qleft)
  7966                  || EQ (vertical_type, Qright)
  7967                  || EQ (vertical_type, Qt)))
  7968         error ("Invalid type of vertical scroll bar");
  7969 
  7970       /* Check dimension of new scroll bar.  Make changes only if it
  7971          fit the window's dimensions.  */
  7972       if ((WINDOW_PIXEL_WIDTH (w)
  7973            - WINDOW_MARGINS_WIDTH (w)
  7974            - WINDOW_FRINGES_WIDTH (w)
  7975            - WINDOW_RIGHT_DIVIDER_WIDTH (w)
  7976            - (new_width == -1 ? FRAME_SCROLL_BAR_AREA_WIDTH (f) : new_width))
  7977           >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
  7978         {
  7979           changed = (!EQ (vertical_type, w->vertical_scroll_bar_type)
  7980                      || new_width != WINDOW_SCROLL_BAR_AREA_WIDTH (w));
  7981           wset_vertical_scroll_bar_type (w, vertical_type);
  7982           w->scroll_bar_width = new_width;
  7983         }
  7984       else
  7985         failed = true;
  7986 
  7987 #if USE_HORIZONTAL_SCROLL_BARS
  7988       int new_height = extract_dimension (height);
  7989 
  7990       if ((MINI_WINDOW_P (w) && !EQ (horizontal_type, Qbottom))
  7991           || new_height == 0)
  7992         horizontal_type = Qnil;
  7993 
  7994       if (!(NILP (horizontal_type)
  7995             || EQ (horizontal_type, Qbottom)
  7996             || EQ (horizontal_type, Qt)))
  7997         error ("Invalid type of horizontal scroll bar");
  7998 
  7999       /* Don't change anything if new scroll bar won't fit.  */
  8000       if ((WINDOW_PIXEL_HEIGHT (w)
  8001            - WINDOW_TAB_LINE_HEIGHT (w)
  8002            - WINDOW_HEADER_LINE_HEIGHT (w)
  8003            - WINDOW_MODE_LINE_HEIGHT (w)
  8004            - (new_height == -1 ? FRAME_SCROLL_BAR_AREA_HEIGHT (f) : new_height))
  8005           >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
  8006         {
  8007           changed = (changed
  8008                      || !EQ (horizontal_type, w->horizontal_scroll_bar_type)
  8009                      || new_height != WINDOW_SCROLL_BAR_AREA_HEIGHT (w));
  8010           wset_horizontal_scroll_bar_type (w, horizontal_type);
  8011           w->scroll_bar_height = new_height;
  8012         }
  8013       else
  8014         failed = true;
  8015 #else
  8016       wset_horizontal_scroll_bar_type (w, Qnil);
  8017 #endif
  8018 
  8019       /* Make settings persistent unless we failed to apply some
  8020          changes.  */
  8021       if (!failed)
  8022         w->scroll_bars_persistent = !NILP (persistent);
  8023 
  8024       /* This is needed to trigger immediate redisplay of the window when
  8025          scroll bars are changed, because scroll bars are redisplayed only
  8026          if more than a single window needs to be considered, see
  8027          redisplay_internal.  */
  8028       if (changed)
  8029         wset_redisplay (w);
  8030 
  8031       return changed ? w : NULL;
  8032     }
  8033 }
  8034 
  8035 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
  8036        Sset_window_scroll_bars, 1, 6, 0,
  8037        doc: /* Set width and type of scroll bars of specified WINDOW.
  8038 WINDOW must specify a live window and defaults to the selected one.
  8039 
  8040 Second argument WIDTH specifies the pixel width for the vertical scroll
  8041 bar.  If WIDTH is nil, use the scroll bar width of WINDOW's frame.
  8042 Third argument VERTICAL-TYPE specifies the type of the vertical scroll
  8043 bar: left, right, nil or t where nil means to not display a vertical
  8044 scroll bar on WINDOW and t means to use WINDOW frame's vertical scroll
  8045 bar type.
  8046 
  8047 Fourth argument HEIGHT specifies the pixel height for the horizontal
  8048 scroll bar.  If HEIGHT is nil, use the scroll bar height of WINDOW's
  8049 frame.  Fifth argument HORIZONTAL-TYPE specifies the type of the
  8050 horizontal scroll bar: bottom, nil, or t where nil means to not
  8051 display a horizontal scroll bar on WINDOW and t means to use WINDOW
  8052 frame's horizontal scroll bar type.  If WINDOW is a mini window, t
  8053 effectively behaves like nil.  HORIZONTAL-TYPE must equal bottom in
  8054 order to show a scroll bar for mini windows.
  8055 
  8056 Optional sixth argument PERSISTENT non-nil means that scroll bar
  8057 settings for WINDOW are persistent, i.e., remain unchanged when
  8058 another buffer is shown in WINDOW.  PERSISTENT nil means that scroll
  8059 bars are reset from buffer local values when `set-window-buffer' is
  8060 called on WINDOW with the argument KEEP-MARGINS nil.
  8061 
  8062 If WINDOW is not large enough to accommodate a scroll bar of the
  8063 desired dimension, leave the corresponding scroll bar unchanged.
  8064 Return t if scroll bars were actually changed and nil otherwise.  */)
  8065   (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type,
  8066    Lisp_Object height, Lisp_Object horizontal_type, Lisp_Object persistent)
  8067 {
  8068   struct window *w
  8069     = set_window_scroll_bars (decode_live_window (window),
  8070                               width, vertical_type, height,
  8071                               horizontal_type, persistent);
  8072   return w ? (apply_window_adjustment (w), Qt) : Qnil;
  8073 }
  8074 
  8075 
  8076 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
  8077        0, 1, 0,
  8078        doc: /* Get width and type of scroll bars of window WINDOW.
  8079 WINDOW must be a live window and defaults to the selected one.
  8080 
  8081 Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES
  8082 HORIZONTAL-TYPE PERSISTENT), see `set-window-scroll-bars'.  If WIDTH
  8083 or HEIGHT is nil or VERTICAL-TYPE or HORIZONTAL-TYPE is t, WINDOW is
  8084 using the frame's corresponding value.  */)
  8085   (Lisp_Object window)
  8086 {
  8087   struct window *w = decode_live_window (window);
  8088 
  8089   return Fcons (((w->scroll_bar_width >= 0)
  8090                  ? make_fixnum (w->scroll_bar_width)
  8091                  : Qnil),
  8092                 Fcons (make_fixnum (WINDOW_SCROLL_BAR_COLS (w)),
  8093                        list5 (w->vertical_scroll_bar_type,
  8094                               ((w->scroll_bar_height >= 0)
  8095                                ? make_fixnum (w->scroll_bar_height)
  8096                                : Qnil),
  8097                               make_fixnum (WINDOW_SCROLL_BAR_LINES (w)),
  8098                               w->horizontal_scroll_bar_type,
  8099                               w->scroll_bars_persistent ? Qt : Qnil)));
  8100 }
  8101 
  8102 /***********************************************************************
  8103                            Smooth scrolling
  8104  ***********************************************************************/
  8105 
  8106 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
  8107        doc: /* Return the amount by which WINDOW is scrolled vertically.
  8108 This takes effect when displaying tall lines or images.
  8109 
  8110 If WINDOW is omitted or nil, it defaults to the selected window.
  8111 Normally, value is a multiple of the canonical character height of WINDOW;
  8112 optional second arg PIXELS-P means value is measured in pixels.  */)
  8113   (Lisp_Object window, Lisp_Object pixels_p)
  8114 {
  8115   Lisp_Object result;
  8116   struct window *w = decode_live_window (window);
  8117   struct frame *f = XFRAME (w->frame);
  8118 
  8119   if (FRAME_WINDOW_P (f))
  8120     result = (NILP (pixels_p)
  8121               ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
  8122               : make_fixnum (-w->vscroll));
  8123   else
  8124     result = make_fixnum (0);
  8125   return result;
  8126 }
  8127 
  8128 
  8129 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
  8130        2, 4, 0,
  8131        doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
  8132 This takes effect when displaying tall lines or images.
  8133 
  8134 WINDOW nil means use the selected window.  Normally, VSCROLL is a
  8135 non-negative multiple of the canonical character height of WINDOW;
  8136 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
  8137 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
  8138 corresponds to an integral number of pixels.  The return value is the
  8139 result of this rounding.
  8140 If PIXELS-P is non-nil, the return value is VSCROLL.
  8141 
  8142 PRESERVE-VSCROLL-P makes setting the start of WINDOW preserve the
  8143 vscroll if its start is "frozen" due to a resized mini-window.  */)
  8144   (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p,
  8145    Lisp_Object preserve_vscroll_p)
  8146 {
  8147   struct window *w = decode_live_window (window);
  8148   struct frame *f = XFRAME (w->frame);
  8149 
  8150   CHECK_NUMBER (vscroll);
  8151 
  8152   if (FRAME_WINDOW_P (f))
  8153     {
  8154       int old_dy = w->vscroll;
  8155 
  8156       w->vscroll = - (NILP (pixels_p)
  8157                       ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
  8158                       : XFLOATINT (vscroll));
  8159       w->vscroll = min (w->vscroll, 0);
  8160 
  8161       if (w->vscroll != old_dy)
  8162         {
  8163           /* Adjust glyph matrix of the frame if the virtual display
  8164              area becomes larger than before.  */
  8165           if (w->vscroll < 0 && w->vscroll < old_dy)
  8166             adjust_frame_glyphs (f);
  8167 
  8168           /* Prevent redisplay shortcuts.  */
  8169           XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
  8170 
  8171           /* Mark W for redisplay.  (bug#55299) */
  8172           wset_redisplay (w);
  8173         }
  8174 
  8175       w->preserve_vscroll_p = !NILP (preserve_vscroll_p);
  8176     }
  8177 
  8178   return Fwindow_vscroll (window, pixels_p);
  8179 }
  8180 
  8181 
  8182 /* Call FN for all leaf windows on frame F.  FN is called with the
  8183    first argument being a pointer to the leaf window, and with
  8184    additional argument USER_DATA.  Stops when FN returns 0.  */
  8185 
  8186 static void
  8187 foreach_window (struct frame *f, bool (*fn) (struct window *, void *),
  8188                 void *user_data)
  8189 {
  8190   /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil.  */
  8191   if (WINDOWP (FRAME_ROOT_WINDOW (f)))
  8192     foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
  8193 }
  8194 
  8195 
  8196 /* Helper function for foreach_window.  Call FN for all leaf windows
  8197    reachable from W.  FN is called with the first argument being a
  8198    pointer to the leaf window, and with additional argument USER_DATA.
  8199    Stop when FN returns false.  Value is false if stopped by FN.  */
  8200 
  8201 static bool
  8202 foreach_window_1 (struct window *w, bool (*fn) (struct window *, void *),
  8203                   void *user_data)
  8204 {
  8205   bool cont;
  8206 
  8207   for (cont = true; w && cont;)
  8208     {
  8209       if (WINDOWP (w->contents))
  8210         cont = foreach_window_1 (XWINDOW (w->contents), fn, user_data);
  8211       else
  8212         cont = fn (w, user_data);
  8213 
  8214       w = NILP (w->next) ? 0 : XWINDOW (w->next);
  8215     }
  8216 
  8217   return cont;
  8218 }
  8219 
  8220 /***********************************************************************
  8221                             Initialization
  8222  ***********************************************************************/
  8223 
  8224 /* Return true if window configurations CONFIGURATION1 and CONFIGURATION2
  8225    describe the same state of affairs.  This is used by Fequal.
  8226 
  8227    Ignore non-matching scroll positions and the like.
  8228 
  8229    This ignores a couple of things like the dedication status of
  8230    window, combination_limit and the like.  This might have to be
  8231    fixed.  */
  8232 
  8233 static bool
  8234 compare_window_configurations (Lisp_Object configuration1,
  8235                                Lisp_Object configuration2)
  8236 {
  8237   struct save_window_data *d1, *d2;
  8238   struct Lisp_Vector *sws1, *sws2;
  8239   ptrdiff_t i;
  8240 
  8241   CHECK_WINDOW_CONFIGURATION (configuration1);
  8242   CHECK_WINDOW_CONFIGURATION (configuration2);
  8243 
  8244   d1 = (struct save_window_data *) XVECTOR (configuration1);
  8245   d2 = (struct save_window_data *) XVECTOR (configuration2);
  8246   sws1 = XVECTOR (d1->saved_windows);
  8247   sws2 = XVECTOR (d2->saved_windows);
  8248 
  8249   /* Frame settings must match.  */
  8250   if (d1->frame_cols != d2->frame_cols
  8251       || d1->frame_lines != d2->frame_lines
  8252       || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
  8253       || !EQ (d1->selected_frame, d2->selected_frame)
  8254       || !EQ (d1->f_current_buffer, d2->f_current_buffer)
  8255       || !EQ (d1->focus_frame, d2->focus_frame)
  8256       /* Verify that the two configurations have the same number of windows.  */
  8257       || sws1->header.size != sws2->header.size)
  8258     return false;
  8259 
  8260   for (i = 0; i < sws1->header.size; i++)
  8261     {
  8262       struct saved_window *sw1, *sw2;
  8263 
  8264       sw1 = SAVED_WINDOW_N (sws1, i);
  8265       sw2 = SAVED_WINDOW_N (sws2, i);
  8266 
  8267       if (
  8268            /* The "current" windows in the two configurations must
  8269               correspond to each other.  */
  8270           EQ (d1->current_window, sw1->window)
  8271           != EQ (d2->current_window, sw2->window)
  8272           /* Windows' buffers must match.  */
  8273           || !EQ (sw1->buffer, sw2->buffer)
  8274           || !EQ (sw1->pixel_left, sw2->pixel_left)
  8275           || !EQ (sw1->pixel_top, sw2->pixel_top)
  8276           || !EQ (sw1->pixel_height, sw2->pixel_height)
  8277           || !EQ (sw1->pixel_width, sw2->pixel_width)
  8278           || !EQ (sw1->left_col, sw2->left_col)
  8279           || !EQ (sw1->top_line, sw2->top_line)
  8280           || !EQ (sw1->total_cols, sw2->total_cols)
  8281           || !EQ (sw1->total_lines, sw2->total_lines)
  8282           || !EQ (sw1->display_table, sw2->display_table)
  8283           /* The next two disjuncts check the window structure for
  8284              equality.  */
  8285           || !EQ (sw1->parent, sw2->parent)
  8286           || !EQ (sw1->prev, sw2->prev)
  8287           || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
  8288           || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
  8289           || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
  8290           || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
  8291           || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
  8292           || !EQ (sw1->fringes_persistent, sw2->fringes_persistent)
  8293           || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
  8294           || !EQ (sw1->scroll_bar_height, sw2->scroll_bar_height)
  8295           || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type)
  8296           || !EQ (sw1->horizontal_scroll_bar_type, sw2->horizontal_scroll_bar_type)
  8297           || !EQ (sw1->scroll_bars_persistent, sw2->scroll_bars_persistent))
  8298         return false;
  8299     }
  8300 
  8301   return true;
  8302 }
  8303 
  8304 DEFUN ("window-configuration-equal-p", Fwindow_configuration_equal_p,
  8305        Swindow_configuration_equal_p, 2, 2, 0,
  8306        doc: /* Say whether two window configurations have the same window layout.
  8307 This function ignores details such as the values of point and
  8308 scrolling positions.  */)
  8309   (Lisp_Object x, Lisp_Object y)
  8310 {
  8311   if (compare_window_configurations (x, y))
  8312     return Qt;
  8313   return Qnil;
  8314 }
  8315 
  8316 
  8317 static void init_window_once_for_pdumper (void);
  8318 
  8319 void
  8320 init_window_once (void)
  8321 {
  8322   minibuf_window = Qnil;
  8323   staticpro (&minibuf_window);
  8324 
  8325   selected_window = Qnil;
  8326   staticpro (&selected_window);
  8327 
  8328   Vwindow_list = Qnil;
  8329   staticpro (&Vwindow_list);
  8330 
  8331   minibuf_selected_window = Qnil;
  8332   staticpro (&minibuf_selected_window);
  8333   old_selected_window = Qnil;
  8334   staticpro (&old_selected_window);
  8335 
  8336   pdumper_do_now_and_after_late_load (init_window_once_for_pdumper);
  8337 }
  8338 
  8339 static void init_window_once_for_pdumper (void)
  8340 {
  8341   window_scroll_pixel_based_preserve_x = -1;
  8342   window_scroll_pixel_based_preserve_y = -1;
  8343   window_scroll_preserve_hpos = -1;
  8344   window_scroll_preserve_vpos = -1;
  8345   PDUMPER_IGNORE (sequence_number);
  8346 
  8347   PDUMPER_RESET_LV (minibuf_window, Qnil);
  8348   PDUMPER_RESET_LV (selected_window, Qnil);
  8349   PDUMPER_RESET_LV (Vwindow_list, Qnil);
  8350   PDUMPER_RESET_LV (minibuf_selected_window, Qnil);
  8351 
  8352   /* Hack: if mode_line_in_non_selected_windows is true (which it may
  8353      be, if we're restoring from a dump) the guts of
  8354      make_initial_frame will try to access selected_window, which is
  8355      invalid at this point, and lose.  For the purposes of creating
  8356      the initial frame and window, this variable must be false.  */
  8357   bool old_mode_line_in_non_selected_windows;
  8358 
  8359   /* Snapshot dumped_with_pdumper to suppress compiler warning.  */
  8360   bool saved_dumped_with_pdumper = dumped_with_pdumper_p ();
  8361   if (saved_dumped_with_pdumper)
  8362     {
  8363       old_mode_line_in_non_selected_windows
  8364         = mode_line_in_non_selected_windows;
  8365       mode_line_in_non_selected_windows = false;
  8366     }
  8367   struct frame *f = make_initial_frame ();
  8368   if (saved_dumped_with_pdumper)
  8369     mode_line_in_non_selected_windows =
  8370       old_mode_line_in_non_selected_windows;
  8371   XSETFRAME (selected_frame, f);
  8372   old_selected_frame = Vterminal_frame = selected_frame;
  8373   minibuf_window = f->minibuffer_window;
  8374   old_selected_window = selected_window = f->selected_window;
  8375 }
  8376 
  8377 void
  8378 init_window (void)
  8379 {
  8380   Vwindow_list = Qnil;
  8381 }
  8382 
  8383 void
  8384 syms_of_window (void)
  8385 {
  8386   DEFSYM (Qscroll_up, "scroll-up");
  8387   DEFSYM (Qscroll_down, "scroll-down");
  8388   DEFSYM (Qscroll_command, "scroll-command");
  8389 
  8390   Fput (Qscroll_up, Qscroll_command, Qt);
  8391   Fput (Qscroll_down, Qscroll_command, Qt);
  8392 
  8393   DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
  8394   DEFSYM (Qwindow_state_change_hook, "window-state-change-hook");
  8395   DEFSYM (Qwindow_state_change_functions, "window-state-change-functions");
  8396   DEFSYM (Qwindow_size_change_functions, "window-size-change-functions");
  8397   DEFSYM (Qwindow_buffer_change_functions, "window-buffer-change-functions");
  8398   DEFSYM (Qwindow_selection_change_functions, "window-selection-change-functions");
  8399   DEFSYM (Qwindowp, "windowp");
  8400   DEFSYM (Qwindow_configuration_p, "window-configuration-p");
  8401   DEFSYM (Qwindow_live_p, "window-live-p");
  8402   DEFSYM (Qwindow_valid_p, "window-valid-p");
  8403   DEFSYM (Qwindow_deletable_p, "window-deletable-p");
  8404   DEFSYM (Qdelete_window, "delete-window");
  8405   DEFSYM (Qwindow__resize_root_window, "window--resize-root-window");
  8406   DEFSYM (Qwindow__resize_root_window_vertically,
  8407           "window--resize-root-window-vertically");
  8408   DEFSYM (Qwindow__resize_mini_frame, "window--resize-mini-frame");
  8409   DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
  8410   DEFSYM (Qsafe, "safe");
  8411   DEFSYM (Qdisplay_buffer, "display-buffer");
  8412   DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
  8413   DEFSYM (Qrecord_window_buffer, "record-window-buffer");
  8414   DEFSYM (Qget_mru_window, "get-mru-window");
  8415   DEFSYM (Qwindow_size, "window-size");
  8416   DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
  8417   DEFSYM (Qabove, "above");
  8418   DEFSYM (Qclone_of, "clone-of");
  8419   DEFSYM (Qfloor, "floor");
  8420   DEFSYM (Qceiling, "ceiling");
  8421   DEFSYM (Qmark_for_redisplay, "mark-for-redisplay");
  8422   DEFSYM (Qmode_line_format, "mode-line-format");
  8423   DEFSYM (Qheader_line_format, "header-line-format");
  8424   DEFSYM (Qtab_line_format, "tab-line-format");
  8425   DEFSYM (Qno_other_window, "no-other-window");
  8426 
  8427   DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
  8428                doc: /* Non-nil means call as function to display a help buffer.
  8429 The function is called with one argument, the buffer to be displayed.
  8430 Used by `with-output-to-temp-buffer'.
  8431 If this function is used, then it must do the entire job of showing
  8432 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.  */);
  8433   Vtemp_buffer_show_function = Qnil;
  8434 
  8435   DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
  8436                doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll.  */);
  8437   Vminibuf_scroll_window = Qnil;
  8438 
  8439   DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
  8440                doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
  8441 If the minibuffer is active, the `minibuffer-scroll-window' mode line
  8442 is displayed in the `mode-line' face.  */);
  8443   mode_line_in_non_selected_windows = true;
  8444 
  8445   DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
  8446                doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window.  */);
  8447   Vother_window_scroll_buffer = Qnil;
  8448 
  8449   DEFVAR_LISP ("other-window-scroll-default", Vother_window_scroll_default,
  8450                doc: /* Function that provides the window to scroll by \\[scroll-other-window].
  8451 The function `other-window-for-scrolling' first tries to use
  8452 `minibuffer-scroll-window' and `other-window-scroll-buffer'.
  8453 But when both are nil, then by default it uses a neighboring window.
  8454 This variable is intended to get another default instead of `next-window'.  */);
  8455   Vother_window_scroll_default = Qnil;
  8456 
  8457   DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
  8458                doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines.  */);
  8459   auto_window_vscroll_p = true;
  8460 
  8461   DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
  8462               doc: /* Number of lines of continuity when scrolling by screenfuls.  */);
  8463   next_screen_context_lines = 2;
  8464 
  8465   DEFVAR_LISP ("scroll-preserve-screen-position",
  8466                Vscroll_preserve_screen_position,
  8467                doc: /* Controls if scroll commands move point to keep its screen position unchanged.
  8468 
  8469 A value of nil means point does not keep its screen position except
  8470 at the scroll margin or window boundary respectively.
  8471 
  8472 A value of t means point keeps its screen position if the scroll
  8473 command moved it vertically out of the window, e.g. when scrolling
  8474 by full screens.  If point is within `next-screen-context-lines' lines
  8475 from the edges of the window, point will typically not keep its screen
  8476 position when doing commands like `scroll-up-command'/`scroll-down-command'
  8477 and the like.
  8478 
  8479 Any other value means point always keeps its screen position.
  8480 Scroll commands should have the `scroll-command' property
  8481 on their symbols to be controlled by this variable.  */);
  8482   Vscroll_preserve_screen_position = Qnil;
  8483 
  8484   DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
  8485                doc: /* Insertion type of marker to use for `window-point'.
  8486 See `marker-insertion-type' for the meaning of the possible values.  */);
  8487   Vwindow_point_insertion_type = Qnil;
  8488   DEFSYM (Qwindow_point_insertion_type, "window-point-insertion-type");
  8489 
  8490   DEFVAR_LISP ("window-buffer-change-functions", Vwindow_buffer_change_functions,
  8491                doc: /* Functions called during redisplay when window buffers have changed.
  8492 The value should be a list of functions that take one argument.
  8493 
  8494 Functions specified buffer-locally are called for each window showing
  8495 the corresponding buffer if and only if that window has been added or
  8496 changed its buffer since the last redisplay.  In this case the window
  8497 is passed as argument.
  8498 
  8499 Functions specified by the default value are called for each frame if
  8500 at least one window on that frame has been added, deleted or changed
  8501 its buffer since the last redisplay.  In this case the frame is passed
  8502 as argument.  */);
  8503   Vwindow_buffer_change_functions = Qnil;
  8504 
  8505   DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions,
  8506                doc: /* Functions called during redisplay when window sizes have changed.
  8507 The value should be a list of functions that take one argument.
  8508 
  8509 Functions specified buffer-locally are called for each window showing
  8510 the corresponding buffer if and only if that window has been added or
  8511 changed its buffer or its total or body size since the last redisplay.
  8512 In this case the window is passed as argument.
  8513 
  8514 Functions specified by the default value are called for each frame if
  8515 at least one window on that frame has been added or changed its buffer
  8516 or its total or body size since the last redisplay.  In this case the
  8517 frame is passed as argument.
  8518 
  8519 For instance, to hide the title bar when the frame is maximized, you
  8520 can add `frame-hide-title-bar-when-maximized' to this variable.  */);
  8521   Vwindow_size_change_functions = Qnil;
  8522 
  8523   DEFVAR_LISP ("window-selection-change-functions", Vwindow_selection_change_functions,
  8524                doc: /* Functions called during redisplay when the selected window has changed.
  8525 The value should be a list of functions that take one argument.
  8526 
  8527 Functions specified buffer-locally are called for each window showing
  8528 the corresponding buffer if and only if that window has been selected
  8529 or deselected since the last redisplay.  In this case the window is
  8530 passed as argument.
  8531 
  8532 Functions specified by the default value are called for each frame if
  8533 the frame's selected window has changed since the last redisplay.  In
  8534 this case the frame is passed as argument.  */);
  8535   Vwindow_selection_change_functions = Qnil;
  8536 
  8537   DEFVAR_LISP ("window-state-change-functions", Vwindow_state_change_functions,
  8538                doc: /* Functions called during redisplay when the window state changed.
  8539 The value should be a list of functions that take one argument.
  8540 
  8541 Functions specified buffer-locally are called for each window showing
  8542 the corresponding buffer if and only if that window has been added,
  8543 resized, changed its buffer or has been (de-)selected since the last
  8544 redisplay.  In this case the window is passed as argument.
  8545 
  8546 Functions specified by the default value are called for each frame if
  8547 at least one window on that frame has been added, deleted, changed its
  8548 buffer or its total or body size or the frame has been (de-)selected,
  8549 its selected window has changed or the window state change flag has
  8550 been set for this frame since the last redisplay.  In this case the
  8551 frame is passed as argument.  */);
  8552   Vwindow_state_change_functions = Qnil;
  8553 
  8554   DEFVAR_LISP ("window-state-change-hook", Vwindow_state_change_hook,
  8555                doc: /* Functions called during redisplay when the window state changed.
  8556 The value should be a list of functions that take no argument.
  8557 
  8558 This hook is called during redisplay when at least one window has been
  8559 added, deleted, (de-)selected, changed its buffer or its total or body
  8560 size or the window state change flag has been set for at least one
  8561 frame.  This hook is called after all other window change functions
  8562 have been run and should be used only if a function should react to
  8563 changes that happened on at least two frames since last redisplay or
  8564 the function intends to change the window configuration.  */);
  8565   Vwindow_state_change_hook = Qnil;
  8566 
  8567   DEFVAR_LISP ("window-configuration-change-hook", Vwindow_configuration_change_hook,
  8568                doc: /* Functions called during redisplay when window configuration has changed.
  8569 The value should be a list of functions that take no argument.
  8570 
  8571 Functions specified buffer-locally are called for each window showing
  8572 the corresponding buffer if at least one window on that frame has been
  8573 added, deleted or changed its buffer or its total or body size since
  8574 the last redisplay.  Each call is performed with the window showing
  8575 the buffer temporarily selected.
  8576 
  8577 Functions specified by the default value are called for each frame if
  8578 at least one window on that frame has been added, deleted or changed
  8579 its buffer or its total or body size since the last redisplay.  Each
  8580 call is performed with the frame temporarily selected.  */);
  8581   Vwindow_configuration_change_hook = Qnil;
  8582 
  8583   DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
  8584                doc: /* Non-nil means `recenter' redraws entire frame.
  8585 If this option is non-nil, then the `recenter' command with a nil
  8586 argument will redraw the entire frame; the special value `tty' causes
  8587 the frame to be redrawn only if it is a tty frame.  */);
  8588   Vrecenter_redisplay = Qtty;
  8589 
  8590   DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
  8591                doc: /* If t, resize window combinations proportionally.
  8592 If this variable is nil, splitting a window gets the entire screen space
  8593 for displaying the new window from the window to split.  Deleting and
  8594 resizing a window preferably resizes one adjacent window only.
  8595 
  8596 If this variable is t, splitting a window tries to get the space
  8597 proportionally from all windows in the same combination.  This also
  8598 allows splitting a window that is otherwise too small or of fixed size.
  8599 Resizing and deleting a window proportionally resize all windows in the
  8600 same combination.
  8601 
  8602 Other values are reserved for future use.
  8603 
  8604 A specific split operation may ignore the value of this variable if it
  8605 is affected by a non-nil value of `window-combination-limit'.  */);
  8606   Vwindow_combination_resize = Qnil;
  8607 
  8608   DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
  8609                doc: /* If non-nil, splitting a window makes a new parent window.
  8610 The following values are recognized:
  8611 
  8612 nil means splitting a window will create a new parent window only if the
  8613     window has no parent window or the window shall become part of a
  8614     combination orthogonal to the one it is part of.
  8615 
  8616 `window-size' means that splitting a window for displaying a buffer
  8617     makes a new parent window provided `display-buffer' is supposed to
  8618     explicitly set the window's size due to the presence of a
  8619     `window-height' or `window-width' entry in the alist used by
  8620     `display-buffer'.  Otherwise, this value is handled like nil.
  8621 
  8622 `temp-buffer-resize' means that splitting a window for displaying a
  8623     temporary buffer via `with-temp-buffer-window' makes a new parent
  8624     window only if `temp-buffer-resize-mode' is enabled.  Otherwise,
  8625     this value is handled like nil.
  8626 
  8627 `temp-buffer' means that splitting a window for displaying a temporary
  8628     buffer via `with-temp-buffer-window' always makes a new parent
  8629     window.  Otherwise, this value is handled like nil.
  8630 
  8631 `display-buffer' means that splitting a window for displaying a buffer
  8632     always makes a new parent window.  Since temporary buffers are
  8633     displayed by the function `display-buffer', this value is stronger
  8634     than `temp-buffer'.  Splitting a window for other purpose makes a
  8635     new parent window only if needed.
  8636 
  8637 t means that splitting a window always creates a new parent window.  If
  8638     all splits behave this way, each frame's window tree is a binary
  8639     tree and every window but the frame's root window has exactly one
  8640     sibling.
  8641 
  8642 The default value is `window-size'.  Other values are reserved for
  8643 future use.  */);
  8644   Vwindow_combination_limit = Qwindow_size;
  8645 
  8646   DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
  8647                doc: /* Alist of persistent window parameters.
  8648 This alist specifies which window parameters shall get saved by
  8649 `current-window-configuration' and `window-state-get' and subsequently
  8650 restored to their previous values by `set-window-configuration' and
  8651 `window-state-put'.
  8652 
  8653 The car of each entry of this alist is the symbol specifying the
  8654 parameter.  The cdr is one of the following:
  8655 
  8656 nil means the parameter is neither saved by `window-state-get' nor by
  8657 `current-window-configuration'.
  8658 
  8659 t means the parameter is saved by `current-window-configuration' and,
  8660 provided its WRITABLE argument is nil, by `window-state-get'.
  8661 
  8662 The symbol `writable' means the parameter is saved unconditionally by
  8663 both `current-window-configuration' and `window-state-get'.  Do not use
  8664 this value for parameters without read syntax (like windows or frames).
  8665 
  8666 Parameters not saved by `current-window-configuration' or
  8667 `window-state-get' are left alone by `set-window-configuration'
  8668 respectively are not installed by `window-state-put'.  */);
  8669   Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
  8670 
  8671   DEFVAR_BOOL ("window-resize-pixelwise", window_resize_pixelwise,
  8672                doc: /*  Non-nil means resize windows pixelwise.
  8673 This currently affects the functions: `split-window', `maximize-window',
  8674 `minimize-window', `fit-window-to-buffer' and `fit-frame-to-buffer', and
  8675 all functions that symmetrically resize a parent window.
  8676 
  8677 Note that when a frame's pixel size is not a multiple of the
  8678 frame's character size, at least one window may get resized
  8679 pixelwise even if this option is nil.  */);
  8680   window_resize_pixelwise = false;
  8681 
  8682   DEFVAR_BOOL ("fast-but-imprecise-scrolling",
  8683                fast_but_imprecise_scrolling,
  8684                doc: /* When non-nil, accelerate scrolling operations.
  8685 This comes into play when scrolling rapidly over previously
  8686 unfontified buffer regions.  Only those portions of the buffer which
  8687 are actually going to be displayed get fontified.
  8688 
  8689 Note that this optimization can cause the portion of the buffer
  8690 displayed after a scrolling operation to be somewhat inaccurate.  */);
  8691   fast_but_imprecise_scrolling = false;
  8692 
  8693   defsubr (&Sselected_window);
  8694   defsubr (&Sold_selected_window);
  8695   defsubr (&Sminibuffer_window);
  8696   defsubr (&Swindow_minibuffer_p);
  8697   defsubr (&Swindowp);
  8698   defsubr (&Swindow_valid_p);
  8699   defsubr (&Swindow_live_p);
  8700   defsubr (&Swindow_frame);
  8701   defsubr (&Sframe_root_window);
  8702   defsubr (&Sframe_first_window);
  8703   defsubr (&Sframe_selected_window);
  8704   defsubr (&Sframe_old_selected_window);
  8705   defsubr (&Sset_frame_selected_window);
  8706   defsubr (&Spos_visible_in_window_p);
  8707   defsubr (&Swindow_line_height);
  8708   defsubr (&Swindow_buffer);
  8709   defsubr (&Swindow_old_buffer);
  8710   defsubr (&Swindow_parent);
  8711   defsubr (&Swindow_top_child);
  8712   defsubr (&Swindow_left_child);
  8713   defsubr (&Swindow_next_sibling);
  8714   defsubr (&Swindow_prev_sibling);
  8715   defsubr (&Swindow_combination_limit);
  8716   defsubr (&Sset_window_combination_limit);
  8717   defsubr (&Swindow_use_time);
  8718   defsubr (&Swindow_pixel_width);
  8719   defsubr (&Swindow_pixel_height);
  8720   defsubr (&Swindow_old_pixel_width);
  8721   defsubr (&Swindow_old_pixel_height);
  8722   defsubr (&Swindow_old_body_pixel_width);
  8723   defsubr (&Swindow_old_body_pixel_height);
  8724   defsubr (&Swindow_total_width);
  8725   defsubr (&Swindow_total_height);
  8726   defsubr (&Swindow_normal_size);
  8727   defsubr (&Swindow_new_pixel);
  8728   defsubr (&Swindow_new_total);
  8729   defsubr (&Swindow_new_normal);
  8730   defsubr (&Swindow_pixel_left);
  8731   defsubr (&Swindow_pixel_top);
  8732   defsubr (&Swindow_left_column);
  8733   defsubr (&Swindow_top_line);
  8734   defsubr (&Sset_window_new_pixel);
  8735   defsubr (&Sset_window_new_total);
  8736   defsubr (&Sset_window_new_normal);
  8737   defsubr (&Swindow_resize_apply);
  8738   defsubr (&Swindow_resize_apply_total);
  8739   defsubr (&Swindow_body_height);
  8740   defsubr (&Swindow_body_width);
  8741   defsubr (&Swindow_hscroll);
  8742   defsubr (&Sset_window_hscroll);
  8743   defsubr (&Swindow_mode_line_height);
  8744   defsubr (&Swindow_header_line_height);
  8745   defsubr (&Swindow_tab_line_height);
  8746   defsubr (&Swindow_right_divider_width);
  8747   defsubr (&Swindow_bottom_divider_width);
  8748   defsubr (&Swindow_scroll_bar_width);
  8749   defsubr (&Swindow_scroll_bar_height);
  8750   defsubr (&Scoordinates_in_window_p);
  8751   defsubr (&Swindow_at);
  8752   defsubr (&Swindow_point);
  8753   defsubr (&Swindow_old_point);
  8754   defsubr (&Swindow_start);
  8755   defsubr (&Swindow_end);
  8756   defsubr (&Sset_window_point);
  8757   defsubr (&Sset_window_start);
  8758   defsubr (&Swindow_dedicated_p);
  8759   defsubr (&Swindow_lines_pixel_dimensions);
  8760   defsubr (&Sset_window_dedicated_p);
  8761   defsubr (&Swindow_display_table);
  8762   defsubr (&Sset_window_display_table);
  8763   defsubr (&Snext_window);
  8764   defsubr (&Sprevious_window);
  8765   defsubr (&Sget_buffer_window);
  8766   defsubr (&Sdelete_other_windows_internal);
  8767   defsubr (&Sdelete_window_internal);
  8768   defsubr (&Sresize_mini_window_internal);
  8769   defsubr (&Sset_window_buffer);
  8770   defsubr (&Srun_window_configuration_change_hook);
  8771   defsubr (&Srun_window_scroll_functions);
  8772   defsubr (&Sselect_window);
  8773   defsubr (&Sforce_window_update);
  8774   defsubr (&Ssplit_window_internal);
  8775   defsubr (&Sscroll_up);
  8776   defsubr (&Sscroll_down);
  8777   defsubr (&Sscroll_left);
  8778   defsubr (&Sscroll_right);
  8779   defsubr (&Sother_window_for_scrolling);
  8780   defsubr (&Sminibuffer_selected_window);
  8781   defsubr (&Srecenter);
  8782   defsubr (&Swindow_text_width);
  8783   defsubr (&Swindow_text_height);
  8784   defsubr (&Smove_to_window_line);
  8785   defsubr (&Swindow_configuration_p);
  8786   defsubr (&Swindow_configuration_frame);
  8787   defsubr (&Sset_window_configuration);
  8788   defsubr (&Scurrent_window_configuration);
  8789   defsubr (&Sset_window_margins);
  8790   defsubr (&Swindow_margins);
  8791   defsubr (&Sset_window_fringes);
  8792   defsubr (&Swindow_fringes);
  8793   defsubr (&Sset_window_scroll_bars);
  8794   defsubr (&Swindow_scroll_bars);
  8795   defsubr (&Swindow_vscroll);
  8796   defsubr (&Sset_window_vscroll);
  8797   defsubr (&Swindow_configuration_equal_p);
  8798   defsubr (&Swindow_bump_use_time);
  8799   defsubr (&Swindow_list);
  8800   defsubr (&Swindow_list_1);
  8801   defsubr (&Swindow_prev_buffers);
  8802   defsubr (&Sset_window_prev_buffers);
  8803   defsubr (&Swindow_next_buffers);
  8804   defsubr (&Sset_window_next_buffers);
  8805   defsubr (&Swindow_parameters);
  8806   defsubr (&Swindow_parameter);
  8807   defsubr (&Sset_window_parameter);
  8808 }

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