More xmalloc and related cleanup.
[bpt/emacs.git] / src / window.c
CommitLineData
7ab12479
JB
1/* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
acaf905b 3 Copyright (C) 1985-1987, 1993-1998, 2000-2012
8cabe764 4 Free Software Foundation, Inc.
7ab12479
JB
5
6This file is part of GNU Emacs.
7
9ec0b715 8GNU Emacs is free software: you can redistribute it and/or modify
7ab12479 9it under the terms of the GNU General Public License as published by
9ec0b715
GM
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
7ab12479
JB
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
9ec0b715 19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
7ab12479 20
18160b98 21#include <config.h>
4d553a13 22#include <stdio.h>
d7306fe6 23#include <setjmp.h>
4d553a13 24
7ab12479 25#include "lisp.h"
e5560ff7 26#include "character.h"
7ab12479 27#include "buffer.h"
3e4731a3 28#include "keyboard.h"
e35f6ff7 29#include "keymap.h"
44fa5b1e 30#include "frame.h"
7ab12479
JB
31#include "window.h"
32#include "commands.h"
33#include "indent.h"
34#include "termchar.h"
35#include "disptab.h"
dfcf069d 36#include "dispextern.h"
5500c422
GM
37#include "blockinput.h"
38#include "intervals.h"
de509a60 39#include "termhooks.h" /* For FRAME_TERMINAL. */
5500c422 40
6d55d620 41#ifdef HAVE_X_WINDOWS
dfcf069d 42#include "xterm.h"
5500c422 43#endif /* HAVE_X_WINDOWS */
8f23f280
AI
44#ifdef WINDOWSNT
45#include "w32term.h"
46#endif
1e3c8885
EZ
47#ifdef MSDOS
48#include "msdos.h"
49#endif
edfda783
AR
50#ifdef HAVE_NS
51#include "nsterm.h"
52#endif
5500c422 53
9397e56f 54Lisp_Object Qwindowp, Qwindow_live_p;
b9e809c2 55static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer;
9397e56f 56static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
b9e809c2 57static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
5386012d 58static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
955cbe7b 59static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
b9e809c2 60static Lisp_Object Qsafe, Qabove, Qbelow;
34a02f46 61static Lisp_Object Qauto_buffer_name, Qclone_of;
b9e809c2 62
f57e2426
J
63static int displayed_window_lines (struct window *);
64static struct window *decode_window (Lisp_Object);
65static int count_windows (struct window *);
66static int get_leaf_windows (struct window *, struct window **, int);
d311d28c 67static void window_scroll (Lisp_Object, EMACS_INT, int, int);
f57e2426
J
68static void window_scroll_pixel_based (Lisp_Object, int, int, int);
69static void window_scroll_line_based (Lisp_Object, int, int, int);
f57e2426 70static int freeze_window_start (struct window *, void *);
f57e2426
J
71static Lisp_Object window_list (void);
72static int add_window_to_list (struct window *, void *);
73static int candidate_window_p (Lisp_Object, Lisp_Object, Lisp_Object,
74 Lisp_Object);
75static Lisp_Object next_window (Lisp_Object, Lisp_Object,
76 Lisp_Object, int);
77static void decode_next_window_args (Lisp_Object *, Lisp_Object *,
78 Lisp_Object *);
2f7c71a1 79static void foreach_window (struct frame *,
f95464e4 80 int (* fn) (struct window *, void *),
2f7c71a1 81 void *);
f57e2426
J
82static int foreach_window_1 (struct window *,
83 int (* fn) (struct window *, void *),
84 void *);
85static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object);
d615d6d2
MR
86static int window_resize_check (struct window *, int);
87static void window_resize_apply (struct window *, int);
7c82f3e2 88static Lisp_Object select_window (Lisp_Object, Lisp_Object, int);
b7354ddf 89
7ab12479
JB
90/* This is the window in which the terminal's cursor should
91 be left when nothing is being done with it. This must
92 always be a leaf window, and its buffer is selected by
93 the top level editing loop at the end of each command.
94
95 This value is always the same as
44fa5b1e 96 FRAME_SELECTED_WINDOW (selected_frame). */
7ab12479
JB
97Lisp_Object selected_window;
98
67492200
GM
99/* A list of all windows for use by next_window and Fwindow_list.
100 Functions creating or deleting windows should invalidate this cache
101 by setting it to nil. */
67492200
GM
102Lisp_Object Vwindow_list;
103
5500c422
GM
104/* The mini-buffer window of the selected frame.
105 Note that you cannot test for mini-bufferness of an arbitrary window
106 by comparing against this; but you can test for mini-bufferness of
7ab12479
JB
107 the selected window. */
108Lisp_Object minibuf_window;
109
3f49fddc
KS
110/* Non-nil means it is the window whose mode line should be
111 shown as the selected window when the minibuffer is selected. */
3dbab091 112Lisp_Object minibuf_selected_window;
3f49fddc 113
a58ec57d 114/* Hook run at end of temp_output_buffer_show. */
955cbe7b 115static Lisp_Object Qtemp_buffer_show_hook;
a58ec57d 116
7ab12479
JB
117/* Incremented for each window created. */
118static int sequence_number;
119
5b03d3c0
RS
120/* Nonzero after init_window_once has finished. */
121static int window_initialized;
122
543f5fb1 123/* Hook to run when window config changes. */
eeca6f6f 124static Lisp_Object Qwindow_configuration_change_hook;
0d384044 125
66d43aea 126/* Used by the function window_scroll_pixel_based */
c876b227 127static int window_scroll_pixel_based_preserve_x;
66fe93d1 128static int window_scroll_pixel_based_preserve_y;
66d43aea 129
c876b227 130/* Same for window_scroll_line_based. */
d311d28c
PE
131static EMACS_INT window_scroll_preserve_hpos;
132static EMACS_INT window_scroll_preserve_vpos;
f230ecc9
MR
133\f
134static struct window *
135decode_window (register Lisp_Object window)
136{
137 if (NILP (window))
138 return XWINDOW (selected_window);
c876b227 139
f230ecc9
MR
140 CHECK_LIVE_WINDOW (window);
141 return XWINDOW (window);
142}
143
144static struct window *
145decode_any_window (register Lisp_Object window)
146{
147 if (NILP (window))
148 return XWINDOW (selected_window);
149
150 CHECK_WINDOW (window);
151 return XWINDOW (window);
152}
666e158e 153
7ab12479 154DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
f230ecc9 155 doc: /* Return t if OBJECT is a window and nil otherwise. */)
5842a27b 156 (Lisp_Object object)
7ab12479 157{
413430c5 158 return WINDOWP (object) ? Qt : Qnil;
7ab12479
JB
159}
160
806b4d9b 161DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
f230ecc9 162 doc: /* Return t if OBJECT is a live window and nil otherwise.
49745b39
CY
163A live window is a window that displays a buffer.
164Internal windows and deleted windows are not live. */)
5842a27b 165 (Lisp_Object object)
605be8af 166{
9e571f49 167 return WINDOW_LIVE_P (object) ? Qt : Qnil;
605be8af 168}
727e958e
MR
169\f
170/* Frames and windows. */
171DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
172 doc: /* Return the frame that window WINDOW is on.
49745b39 173If WINDOW is omitted or nil, it defaults to the selected window. */)
727e958e
MR
174 (Lisp_Object window)
175{
176 return decode_any_window (window)->frame;
177}
178
179DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
87e68db4
JB
180 doc: /* Return the root window of FRAME-OR-WINDOW.
181If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
49745b39
CY
182With a frame argument, return that frame's root window.
183With a window argument, return the root window of that window's frame. */)
727e958e
MR
184 (Lisp_Object frame_or_window)
185{
186 Lisp_Object window;
187
188 if (NILP (frame_or_window))
189 window = SELECTED_FRAME ()->root_window;
190 else if (WINDOWP (frame_or_window))
191 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
192 else
193 {
194 CHECK_LIVE_FRAME (frame_or_window);
195 window = XFRAME (frame_or_window)->root_window;
196 }
197
198 return window;
199}
200
201DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
49745b39
CY
202 doc: /* Return the minibuffer window for frame FRAME.
203If FRAME is omitted or nil, it defaults to the selected frame. */)
727e958e
MR
204 (Lisp_Object frame)
205{
206 if (NILP (frame))
207 frame = selected_frame;
208 CHECK_LIVE_FRAME (frame);
209 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
210}
211
212DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
213 Swindow_minibuffer_p, 0, 1, 0,
214 doc: /* Return non-nil if WINDOW is a minibuffer window.
49745b39 215If WINDOW is omitted or nil, it defaults to the selected window. */)
727e958e
MR
216 (Lisp_Object window)
217{
218 return MINI_WINDOW_P (decode_any_window (window)) ? Qt : Qnil;
219}
220
221/* Don't move this to window.el - this must be a safe routine. */
222DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
87e68db4
JB
223 doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
224If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
225Else if FRAME-OR-WINDOW denotes any window, return the first window of
226that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
727e958e
MR
227the first window of that frame. */)
228 (Lisp_Object frame_or_window)
229{
230 Lisp_Object window;
231
232 if (NILP (frame_or_window))
233 window = SELECTED_FRAME ()->root_window;
234 else if (WINDOWP (frame_or_window))
235 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
236 else
237 {
238 CHECK_LIVE_FRAME (frame_or_window);
239 window = XFRAME (frame_or_window)->root_window;
240 }
241
242 while (NILP (XWINDOW (window)->buffer))
243 {
244 if (! NILP (XWINDOW (window)->hchild))
245 window = XWINDOW (window)->hchild;
246 else if (! NILP (XWINDOW (window)->vchild))
247 window = XWINDOW (window)->vchild;
248 else
249 abort ();
250 }
251
252 return window;
253}
254
255DEFUN ("frame-selected-window", Fframe_selected_window,
256 Sframe_selected_window, 0, 1, 0,
87e68db4
JB
257 doc: /* Return the selected window of FRAME-OR-WINDOW.
258If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
259Else if FRAME-OR-WINDOW denotes any window, return the selected window
260of that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
727e958e
MR
261the selected window of that frame. */)
262 (Lisp_Object frame_or_window)
263{
264 Lisp_Object window;
265
266 if (NILP (frame_or_window))
267 window = SELECTED_FRAME ()->selected_window;
268 else if (WINDOWP (frame_or_window))
269 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
270 else
271 {
272 CHECK_LIVE_FRAME (frame_or_window);
273 window = XFRAME (frame_or_window)->selected_window;
274 }
275
276 return window;
277}
278
279DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
280 Sset_frame_selected_window, 2, 3, 0,
281 doc: /* Set selected window of FRAME to WINDOW.
282FRAME must be a live frame and defaults to the selected one. If FRAME
283is the selected frame, this makes WINDOW the selected window. Optional
284argument NORECORD non-nil means to neither change the order of recently
285selected windows nor the buffer list. WINDOW must denote a live window.
286Return WINDOW. */)
287 (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
288{
289 if (NILP (frame))
290 frame = selected_frame;
291
292 CHECK_LIVE_FRAME (frame);
293 CHECK_LIVE_WINDOW (window);
294
295 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
296 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
297
298 if (EQ (frame, selected_frame))
299 return Fselect_window (window, norecord);
300 else
301 return XFRAME (frame)->selected_window = window;
302}
303
304DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
305 doc: /* Return the selected window.
306The selected window is the window in which the standard cursor for
307selected windows appears and to which many commands apply. */)
308 (void)
309{
310 return selected_window;
311}
312
9397e56f
MR
313int window_select_count;
314
727e958e
MR
315/* If select_window is called with inhibit_point_swap non-zero it will
316 not store point of the old selected window's buffer back into that
317 window's pointm slot. This is needed by Fset_window_configuration to
318 avoid that the display routine is called with selected_window set to
319 Qnil causing a subsequent crash. */
320static Lisp_Object
321select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
322{
323 register struct window *w;
324 register struct window *ow;
325 struct frame *sf;
326
327 CHECK_LIVE_WINDOW (window);
328
329 w = XWINDOW (window);
330 w->frozen_window_start_p = 0;
331
332 if (NILP (norecord))
333 {
45942c7d 334 w->use_time = ++window_select_count;
727e958e
MR
335 record_buffer (w->buffer);
336 }
337
338 if (EQ (window, selected_window) && !inhibit_point_swap)
339 return window;
340
341 sf = SELECTED_FRAME ();
342 if (XFRAME (WINDOW_FRAME (w)) != sf)
343 {
344 XFRAME (WINDOW_FRAME (w))->selected_window = window;
345 /* Use this rather than Fhandle_switch_frame
346 so that FRAME_FOCUS_FRAME is moved appropriately as we
347 move around in the state where a minibuffer in a separate
348 frame is active. */
349 Fselect_frame (WINDOW_FRAME (w), norecord);
350 /* Fselect_frame called us back so we've done all the work already. */
351 eassert (EQ (window, selected_window));
352 return window;
353 }
354 else
355 sf->selected_window = window;
356
357 /* Store the current buffer's actual point into the
358 old selected window. It belongs to that window,
359 and when the window is not selected, must be in the window. */
360 if (!inhibit_point_swap)
361 {
362 ow = XWINDOW (selected_window);
363 if (! NILP (ow->buffer))
364 set_marker_both (ow->pointm, ow->buffer,
365 BUF_PT (XBUFFER (ow->buffer)),
366 BUF_PT_BYTE (XBUFFER (ow->buffer)));
367 }
368
369 selected_window = window;
370
371 Fset_buffer (w->buffer);
372
373 BVAR (XBUFFER (w->buffer), last_selected_window) = window;
374
375 /* Go to the point recorded in the window.
376 This is important when the buffer is in more
377 than one window. It also matters when
378 redisplay_window has altered point after scrolling,
379 because it makes the change only in the window. */
380 {
d311d28c 381 register ptrdiff_t new_point = marker_position (w->pointm);
727e958e
MR
382 if (new_point < BEGV)
383 SET_PT (BEGV);
384 else if (new_point > ZV)
385 SET_PT (ZV);
386 else
387 SET_PT (new_point);
388 }
389
390 windows_or_buffers_changed++;
391 return window;
392}
393
394DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
395 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
396Also make WINDOW's buffer current and make WINDOW the frame's selected
397window. Return WINDOW.
398
399Optional second arg NORECORD non-nil means do not put this buffer at the
400front of the buffer list and do not make this window the most recently
401selected one.
605be8af 402
727e958e
MR
403Note that the main editor command loop sets the current buffer to the
404buffer of the selected window before each command. */)
405 (register Lisp_Object window, Lisp_Object norecord)
406{
407 return select_window (window, norecord, 0);
408}
409\f
bf60a96b 410DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
49745b39
CY
411 doc: /* Return the buffer displayed in window WINDOW.
412If WINDOW is omitted or nil, it defaults to the selected window.
413Return nil for an internal window or a deleted window. */)
bf60a96b
MR
414 (Lisp_Object window)
415{
416 return decode_any_window (window)->buffer;
417}
418
419DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
49745b39
CY
420 doc: /* Return the parent window of window WINDOW.
421If WINDOW is omitted or nil, it defaults to the selected window.
422Return nil for a window with no parent (e.g. a root window). */)
bf60a96b
MR
423 (Lisp_Object window)
424{
425 return decode_any_window (window)->parent;
426}
427
49745b39
CY
428DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 1, 1, 0,
429 doc: /* Return the topmost child window of window WINDOW.
430Return nil if WINDOW is a live window (live windows have no children).
431Return nil if WINDOW is an internal window whose children form a
432horizontal combination. */)
bf60a96b
MR
433 (Lisp_Object window)
434{
49745b39 435 CHECK_WINDOW (window);
bf60a96b
MR
436 return decode_any_window (window)->vchild;
437}
438
49745b39
CY
439DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 1, 1, 0,
440 doc: /* Return the leftmost child window of window WINDOW.
441Return nil if WINDOW is a live window (live windows have no children).
442Return nil if WINDOW is an internal window whose children form a
443vertical combination. */)
bf60a96b
MR
444 (Lisp_Object window)
445{
49745b39 446 CHECK_WINDOW (window);
bf60a96b
MR
447 return decode_any_window (window)->hchild;
448}
449
d68443dc 450DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
49745b39
CY
451 doc: /* Return the next sibling window of window WINDOW.
452If WINDOW is omitted or nil, it defaults to the selected window.
d68443dc 453Return nil if WINDOW has no next sibling. */)
bf60a96b
MR
454 (Lisp_Object window)
455{
456 return decode_any_window (window)->next;
457}
458
d68443dc 459DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
49745b39
CY
460 doc: /* Return the previous sibling window of window WINDOW.
461If WINDOW is omitted or nil, it defaults to the selected window.
d68443dc 462Return nil if WINDOW has no previous sibling. */)
bf60a96b
MR
463 (Lisp_Object window)
464{
465 return decode_any_window (window)->prev;
466}
67492200 467
df05a53c 468DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
b6f67890 469 doc: /* Return combination limit of window WINDOW.
be7f5545 470If the return value is nil, child windows of WINDOW can be recombined with
b6f67890 471WINDOW's siblings. A return value of t means that child windows of
496e208e 472WINDOW are never \(re-)combined with WINDOW's siblings. */)
496e208e 473 (Lisp_Object window)
7ab12479 474{
b6f67890 475 return decode_any_window (window)->combination_limit;
7ab12479 476}
53bb6b99 477
b6f67890 478DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
d2999b1a
MR
479 doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
480If LIMIT is nil, child windows of WINDOW can be recombined with
481WINDOW's siblings. LIMIT t means that child windows of WINDOW are
b6f67890
MR
482never \(re-)combined with WINDOW's siblings. Other values are reserved
483for future use. */)
d2999b1a 484 (Lisp_Object window, Lisp_Object limit)
b3a10345 485{
496e208e 486 register struct window *w = decode_any_window (window);
b3a10345 487
d2999b1a 488 w->combination_limit = limit;
b3a10345 489
b6f67890 490 return w->combination_limit;
496e208e 491}
7bbc67d2 492
496e208e 493DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
49745b39
CY
494 doc: /* Return the use time of window WINDOW.
495If WINDOW is omitted or nil, it defaults to the selected window.
496The window with the highest use time is the most recently selected
497one. The window with the lowest use time is the least recently
498selected one. */)
496e208e
MR
499 (Lisp_Object window)
500{
45942c7d 501 return make_number (decode_window (window)->use_time);
496e208e 502}
abde8f8c 503\f
105216ed
CY
504DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 1, 0,
505 doc: /* Return the total height, in lines, of window WINDOW.
49745b39 506If WINDOW is omitted or nil, it defaults to the selected window.
b3a10345 507
105216ed
CY
508The return value includes the mode line and header line, if any.
509If WINDOW is an internal window, the total height is the height
510of the screen areas spanned by its children.
536833ab 511
105216ed
CY
512On a graphical display, this total height is reported as an
513integer multiple of the default character height. */)
514 (Lisp_Object window)
496e208e 515{
105216ed
CY
516 return decode_any_window (window)->total_lines;
517}
536833ab 518
105216ed
CY
519DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 1, 0,
520 doc: /* Return the total width, in columns, of window WINDOW.
521If WINDOW is omitted or nil, it defaults to the selected window.
b3a10345 522
105216ed
CY
523The return value includes any vertical dividers or scroll bars
524belonging to WINDOW. If WINDOW is an internal window, the total width
525is the width of the screen areas spanned by its children.
b3a10345 526
105216ed
CY
527On a graphical display, this total width is reported as an
528integer multiple of the default character width. */)
496e208e
MR
529 (Lisp_Object window)
530{
105216ed 531 return decode_any_window (window)->total_cols;
abde8f8c 532}
b3a10345 533
496e208e 534DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
49745b39
CY
535 doc: /* Return the new total size of window WINDOW.
536If WINDOW is omitted or nil, it defaults to the selected window. */)
496e208e
MR
537 (Lisp_Object window)
538{
539 return decode_any_window (window)->new_total;
540}
541
542DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
49745b39
CY
543 doc: /* Return the normal height of window WINDOW.
544If WINDOW is omitted or nil, it defaults to the selected window.
545If HORIZONTAL is non-nil, return the normal width of WINDOW. */)
496e208e
MR
546 (Lisp_Object window, Lisp_Object horizontal)
547{
548 if (NILP (horizontal))
549 return decode_any_window (window)->normal_lines;
550 else
551 return decode_any_window (window)->normal_cols;
552}
553
554DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
49745b39
CY
555 doc: /* Return new normal size of window WINDOW.
556If WINDOW is omitted or nil, it defaults to the selected window. */)
496e208e
MR
557 (Lisp_Object window)
558{
559 return decode_any_window (window)->new_normal;
560}
561
abde8f8c 562DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
49745b39 563 doc: /* Return left column of window WINDOW.
105216ed
CY
564This is the distance, in columns, between the left edge of WINDOW and
565the left edge of the frame's window area. For instance, the return
566value is 0 if there is no window to the left of WINDOW.
567
49745b39 568If WINDOW is omitted or nil, it defaults to the selected window. */)
abde8f8c
MR
569 (Lisp_Object window)
570{
571 return decode_any_window (window)->left_col;
572}
573
574DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
49745b39 575 doc: /* Return top line of window WINDOW.
105216ed
CY
576This is the distance, in lines, between the top of WINDOW and the top
577of the frame's window area. For instance, the return value is 0 if
578there is no window above WINDOW.
579
49745b39 580If WINDOW is omitted or nil, it defaults to the selected window. */)
abde8f8c
MR
581 (Lisp_Object window)
582{
583 return decode_any_window (window)->top_line;
584}
585
586/* Return the number of lines of W's body. Don't count any mode or
587 header line of W. */
588
46a4ce9e 589static int
abde8f8c
MR
590window_body_lines (struct window *w)
591{
592 int height = XFASTINT (w->total_lines);
593
594 if (!MINI_WINDOW_P (w))
595 {
596 if (WINDOW_WANTS_MODELINE_P (w))
597 --height;
598 if (WINDOW_WANTS_HEADER_LINE_P (w))
599 --height;
600 }
601
602 return height;
603}
604
605/* Return the number of columns of W's body. Don't count columns
606 occupied by the scroll bar or the vertical bar separating W from its
607 right sibling. On window-systems don't count fringes or display
608 margins either. */
609
610int
611window_body_cols (struct window *w)
612{
613 struct frame *f = XFRAME (WINDOW_FRAME (w));
614 int width = XINT (w->total_cols);
615
616 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
617 /* Scroll bars occupy a few columns. */
618 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
619 else if (!FRAME_WINDOW_P (f)
620 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
621 /* The column of `|' characters separating side-by-side windows
622 occupies one column only. */
623 width -= 1;
624
625 if (FRAME_WINDOW_P (f))
626 /* On window-systems, fringes and display margins cannot be
627 used for normal text. */
628 width -= (WINDOW_FRINGE_COLS (w)
629 + WINDOW_LEFT_MARGIN_COLS (w)
630 + WINDOW_RIGHT_MARGIN_COLS (w));
631
632 return width;
633}
634
105216ed
CY
635DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 1, 0,
636 doc: /* Return the height, in lines, of WINDOW's text area.
637If WINDOW is omitted or nil, it defaults to the selected window.
638Signal an error if the window is not live.
89bd5ee1 639
105216ed
CY
640The returned height does not include the mode line or header line.
641On a graphical display, the height is expressed as an integer multiple
642of the default character height. If a line at the bottom of the text
643area is only partially visible, that counts as a whole line; to
644exclude partially-visible lines, use `window-text-height'. */)
645 (Lisp_Object window)
abde8f8c 646{
105216ed
CY
647 struct window *w = decode_window (window);
648 return make_number (window_body_lines (w));
649}
abde8f8c 650
105216ed
CY
651DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 1, 0,
652 doc: /* Return the width, in columns, of WINDOW's text area.
653If WINDOW is omitted or nil, it defaults to the selected window.
654Signal an error if the window is not live.
655
656The return value does not include any vertical dividers, fringe or
657marginal areas, or scroll bars. On a graphical display, the width is
658expressed as an integer multiple of the default character width. */)
659 (Lisp_Object window)
660{
661 struct window *w = decode_window (window);
662 return make_number (window_body_cols (w));
abde8f8c 663}
536833ab 664
7ab12479 665DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
c85322d0 666 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
496e208e 667WINDOW must be a live window and defaults to the selected one. */)
5842a27b 668 (Lisp_Object window)
7ab12479 669{
80b00b08 670 return make_number (decode_window (window)->hscroll);
7ab12479
JB
671}
672
24a212eb
PE
673/* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
674 range, returning the new amount as a fixnum. */
675static Lisp_Object
676set_window_hscroll (struct window *w, EMACS_INT hscroll)
677{
4e71fd89
PE
678 /* Horizontal scrolling has problems with large scroll amounts.
679 It's too slow with long lines, and even with small lines the
680 display can be messed up. For now, though, impose only the limits
681 required by the internal representation: horizontal scrolling must
682 fit in fixnum (since it's visible to Elisp) and into ptrdiff_t
683 (since it's stored in a ptrdiff_t). */
684 ptrdiff_t hscroll_max = min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX);
685 ptrdiff_t new_hscroll = clip_to_bounds (0, hscroll, hscroll_max);
24a212eb
PE
686
687 /* Prevent redisplay shortcuts when changing the hscroll. */
688 if (w->hscroll != new_hscroll)
689 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
690
691 w->hscroll = new_hscroll;
692 return make_number (new_hscroll);
693}
694
7ab12479 695DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
fdb82f93 696 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
0cf34688 697If WINDOW is nil, the selected window is used.
24a212eb
PE
698Clip the number to a reasonable value if out of range.
699Return the new number. NCOL should be zero or positive.
ebadb1e4
EZ
700
701Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
120b7781 702window so that the location of point moves off-window. */)
5842a27b 703 (Lisp_Object window, Lisp_Object ncol)
7ab12479 704{
ea68264b 705 struct window *w = decode_window (window);
7ab12479 706
b7826503 707 CHECK_NUMBER (ncol);
24a212eb 708 return set_window_hscroll (w, XINT (ncol));
7ab12479
JB
709}
710
190eb263
RS
711DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
712 Swindow_redisplay_end_trigger, 0, 1, 0,
fdb82f93 713 doc: /* Return WINDOW's redisplay end trigger value.
c85322d0 714WINDOW defaults to the selected window.
fdb82f93 715See `set-window-redisplay-end-trigger' for more information. */)
5842a27b 716 (Lisp_Object window)
190eb263
RS
717{
718 return decode_window (window)->redisplay_end_trigger;
719}
720
721DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
722 Sset_window_redisplay_end_trigger, 2, 2, 0,
fdb82f93
PJ
723 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
724VALUE should be a buffer position (typically a marker) or nil.
725If it is a buffer position, then if redisplay in WINDOW reaches a position
726beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
727with two arguments: WINDOW, and the end trigger value.
728Afterwards the end-trigger value is reset to nil. */)
5842a27b 729 (register Lisp_Object window, Lisp_Object value)
190eb263
RS
730{
731 register struct window *w;
732
733 w = decode_window (window);
734 w->redisplay_end_trigger = value;
735 return value;
736}
737
7ab12479 738DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
fdb82f93 739 doc: /* Return a list of the edge coordinates of WINDOW.
b35ac83e
CY
740The list has the form (LEFT TOP RIGHT BOTTOM).
741TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
742all relative to 0, 0 at top left corner of frame.
743
744RIGHT is one more than the rightmost column occupied by WINDOW.
745BOTTOM is one more than the bottommost row occupied by WINDOW.
746The edges include the space used by WINDOW's scroll bar, display
747margins, fringes, header line, and/or mode line. For the edges of
748just the text area, use `window-inside-edges'. */)
5842a27b 749 (Lisp_Object window)
7ab12479 750{
6b61353c 751 register struct window *w = decode_any_window (window);
7ab12479 752
949cf20f
KS
753 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
754 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
755 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
756 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
757 Qnil))));
7ab12479
JB
758}
759
c99a9eb3
RS
760DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
761 doc: /* Return a list of the edge pixel coordinates of WINDOW.
b35ac83e
CY
762The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
763the top left corner of the frame.
764
765RIGHT is one more than the rightmost x position occupied by WINDOW.
766BOTTOM is one more than the bottommost y position occupied by WINDOW.
767The pixel edges include the space used by WINDOW's scroll bar, display
768margins, fringes, header line, and/or mode line. For the pixel edges
769of just the text area, use `window-inside-pixel-edges'. */)
5842a27b 770 (Lisp_Object window)
c99a9eb3 771{
6b61353c 772 register struct window *w = decode_any_window (window);
c99a9eb3
RS
773
774 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
775 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
776 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
777 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
778 Qnil))));
779}
780
9d5405ec 781static void
5e617bc2 782calc_absolute_offset (struct window *w, int *add_x, int *add_y)
9d5405ec
J
783{
784 struct frame *f = XFRAME (w->frame);
785 *add_y = f->top_pos;
786#ifdef FRAME_MENUBAR_HEIGHT
787 *add_y += FRAME_MENUBAR_HEIGHT (f);
788#endif
bfeabdc3
JD
789#ifdef FRAME_TOOLBAR_TOP_HEIGHT
790 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
791#elif FRAME_TOOLBAR_HEIGHT
9d5405ec
J
792 *add_y += FRAME_TOOLBAR_HEIGHT (f);
793#endif
794#ifdef FRAME_NS_TITLEBAR_HEIGHT
795 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
796#endif
797 *add_x = f->left_pos;
bfeabdc3
JD
798#ifdef FRAME_TOOLBAR_LEFT_WIDTH
799 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
800#endif
9d5405ec
J
801}
802
803DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
804 Swindow_absolute_pixel_edges, 0, 1, 0,
805 doc: /* Return a list of the edge pixel coordinates of WINDOW.
806The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
807the top left corner of the display.
808
809RIGHT is one more than the rightmost x position occupied by WINDOW.
810BOTTOM is one more than the bottommost y position occupied by WINDOW.
811The pixel edges include the space used by WINDOW's scroll bar, display
812margins, fringes, header line, and/or mode line. For the pixel edges
c49d071a 813of just the text area, use `window-inside-absolute-pixel-edges'. */)
5842a27b 814 (Lisp_Object window)
9d5405ec
J
815{
816 register struct window *w = decode_any_window (window);
817 int add_x, add_y;
ed3751c8 818 calc_absolute_offset (w, &add_x, &add_y);
9d5405ec
J
819
820 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w) + add_x),
821 Fcons (make_number (WINDOW_TOP_EDGE_Y (w) + add_y),
822 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w) + add_x),
823 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w) + add_y),
824 Qnil))));
825}
826
c99a9eb3
RS
827DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
828 doc: /* Return a list of the edge coordinates of WINDOW.
b35ac83e
CY
829The list has the form (LEFT TOP RIGHT BOTTOM).
830TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
831all relative to 0, 0 at top left corner of frame.
832
833RIGHT is one more than the rightmost column of WINDOW's text area.
834BOTTOM is one more than the bottommost row of WINDOW's text area.
835The inside edges do not include the space used by the WINDOW's scroll
836bar, display margins, fringes, header line, and/or mode line. */)
5842a27b 837 (Lisp_Object window)
c99a9eb3 838{
2fbdc249 839 register struct window *w = decode_window (window);
c99a9eb3
RS
840
841 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
842 + WINDOW_LEFT_MARGIN_COLS (w)
843 + WINDOW_LEFT_FRINGE_COLS (w)),
844 make_number (WINDOW_TOP_EDGE_LINE (w)
845 + WINDOW_HEADER_LINE_LINES (w)),
f3fbdb1f 846 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
c99a9eb3
RS
847 - WINDOW_RIGHT_MARGIN_COLS (w)
848 - WINDOW_RIGHT_FRINGE_COLS (w)),
849 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
850 - WINDOW_MODE_LINE_LINES (w)));
851}
852
853DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
2fbdc249
CY
854 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
855The list has the form (LEFT TOP RIGHT BOTTOM), all relative to (0,0)
856at the top left corner of the frame's window area.
b35ac83e
CY
857
858RIGHT is one more than the rightmost x position of WINDOW's text area.
859BOTTOM is one more than the bottommost y position of WINDOW's text area.
860The inside edges do not include the space used by WINDOW's scroll bar,
c99a9eb3 861display margins, fringes, header line, and/or mode line. */)
5842a27b 862 (Lisp_Object window)
c99a9eb3 863{
2fbdc249 864 register struct window *w = decode_window (window);
c99a9eb3
RS
865
866 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
867 + WINDOW_LEFT_MARGIN_WIDTH (w)
868 + WINDOW_LEFT_FRINGE_WIDTH (w)),
869 make_number (WINDOW_TOP_EDGE_Y (w)
870 + WINDOW_HEADER_LINE_HEIGHT (w)),
f3fbdb1f 871 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
c99a9eb3
RS
872 - WINDOW_RIGHT_MARGIN_WIDTH (w)
873 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
874 make_number (WINDOW_BOTTOM_EDGE_Y (w)
875 - WINDOW_MODE_LINE_HEIGHT (w)));
876}
877
9d5405ec
J
878DEFUN ("window-inside-absolute-pixel-edges",
879 Fwindow_inside_absolute_pixel_edges,
880 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
2fbdc249
CY
881 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
882The list has the form (LEFT TOP RIGHT BOTTOM), all relative to (0,0)
883at the top left corner of the frame's window area.
9d5405ec
J
884
885RIGHT is one more than the rightmost x position of WINDOW's text area.
886BOTTOM is one more than the bottommost y position of WINDOW's text area.
887The inside edges do not include the space used by WINDOW's scroll bar,
888display margins, fringes, header line, and/or mode line. */)
5842a27b 889 (Lisp_Object window)
9d5405ec 890{
2fbdc249 891 register struct window *w = decode_window (window);
9d5405ec 892 int add_x, add_y;
ed3751c8 893 calc_absolute_offset (w, &add_x, &add_y);
9d5405ec
J
894
895 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
896 + WINDOW_LEFT_MARGIN_WIDTH (w)
897 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
898 make_number (WINDOW_TOP_EDGE_Y (w)
899 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
900 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
901 - WINDOW_RIGHT_MARGIN_WIDTH (w)
902 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
903 make_number (WINDOW_BOTTOM_EDGE_Y (w)
904 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
905}
906
9173a8fb 907/* Test if the character at column X, row Y is within window W.
341f3858 908 If it is not, return ON_NOTHING;
9173a8fb 909 if it is in the window's text area, return ON_TEXT;
341f3858 910 if it is on the window's modeline, return ON_MODE_LINE;
d5783c40 911 if it is on the border between the window and its right sibling,
341f3858 912 return ON_VERTICAL_BORDER.
9173a8fb 913 if it is on a scroll bar, return ON_SCROLL_BAR.
341f3858 914 if it is on the window's top line, return ON_HEADER_LINE;
81d189fd 915 if it is in left or right fringe of the window,
9173a8fb 916 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
49b996e7 917 if it is in the marginal area to the left/right of the window,
9173a8fb 918 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
5500c422
GM
919
920 X and Y are frame relative pixel coordinates. */
921
7442878f 922static enum window_part
9173a8fb 923coordinates_in_window (register struct window *w, int x, int y)
d5783c40 924{
b0228ace 925 struct frame *f = XFRAME (WINDOW_FRAME (w));
7442878f 926 enum window_part part;
949cf20f 927 int ux = FRAME_COLUMN_WIDTH (f);
c7b08b0d
MR
928 int left_x = WINDOW_LEFT_EDGE_X (w);
929 int right_x = WINDOW_RIGHT_EDGE_X (w);
930 int top_y = WINDOW_TOP_EDGE_Y (w);
931 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
dad75588
GM
932 /* The width of the area where the vertical line can be dragged.
933 (Between mode lines for instance. */
934 int grabbable_width = ux;
949cf20f 935 int lmargin_width, rmargin_width, text_left, text_right;
9173a8fb 936
c7b08b0d
MR
937 /* Outside any interesting row or column? */
938 if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
9173a8fb 939 return ON_NOTHING;
b0228ace 940
c7b08b0d
MR
941 /* On the mode line or header line? */
942 if ((WINDOW_WANTS_MODELINE_P (w)
943 && y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
944 && (part = ON_MODE_LINE))
945 || (WINDOW_WANTS_HEADER_LINE_P (w)
946 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
947 && (part = ON_HEADER_LINE)))
948 {
949 /* If it's under/over the scroll bar portion of the mode/header
950 line, say it's on the vertical line. That's to be able to
951 resize windows horizontally in case we're using toolkit scroll
952 bars. Note: If scrollbars are on the left, the window that
953 must be eventually resized is that on the left of WINDOW. */
954 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
955 && !WINDOW_LEFTMOST_P (w)
956 && eabs (x - left_x) < grabbable_width)
957 || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
958 && !WINDOW_RIGHTMOST_P (w)
959 && eabs (x - right_x) < grabbable_width))
960 return ON_VERTICAL_BORDER;
961 else
962 return part;
963 }
964
466539bc
EZ
965 /* In what's below, we subtract 1 when computing right_x because we
966 want the rightmost pixel, which is given by left_pixel+width-1. */
5500c422
GM
967 if (w->pseudo_window_p)
968 {
969 left_x = 0;
949cf20f 970 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
5500c422
GM
971 }
972 else
973 {
949cf20f
KS
974 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
975 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
5500c422 976 }
37962e60 977
949cf20f 978 /* Outside any interesting column? */
9173a8fb
CY
979 if (x < left_x || x > right_x)
980 return ON_SCROLL_BAR;
949cf20f
KS
981
982 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
983 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
79fd290e 984
949cf20f
KS
985 text_left = window_box_left (w, TEXT_AREA);
986 text_right = text_left + window_box_width (w, TEXT_AREA);
987
988 if (FRAME_WINDOW_P (f))
fbad6f9a 989 {
447e9da0 990 if (!w->pseudo_window_p
949cf20f 991 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
447e9da0 992 && !WINDOW_RIGHTMOST_P (w)
9173a8fb
CY
993 && (eabs (x - right_x) < grabbable_width))
994 return ON_VERTICAL_BORDER;
fbad6f9a 995 }
9173a8fb
CY
996 /* Need to say "x > right_x" rather than >=, since on character
997 terminals, the vertical line's x coordinate is right_x. */
998 else if (!w->pseudo_window_p
999 && !WINDOW_RIGHTMOST_P (w)
1000 && x > right_x - ux)
1001 return ON_VERTICAL_BORDER;
1002
1003 if (x < text_left)
949cf20f
KS
1004 {
1005 if (lmargin_width > 0
1006 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
9173a8fb
CY
1007 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1008 : (x < left_x + lmargin_width)))
1009 return ON_LEFT_MARGIN;
1010
949cf20f
KS
1011 return ON_LEFT_FRINGE;
1012 }
1013
9173a8fb 1014 if (x >= text_right)
949cf20f
KS
1015 {
1016 if (rmargin_width > 0
1017 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
9173a8fb
CY
1018 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1019 : (x >= right_x - rmargin_width)))
1020 return ON_RIGHT_MARGIN;
1021
949cf20f
KS
1022 return ON_RIGHT_FRINGE;
1023 }
1024
1025 /* Everything special ruled out - must be on text area */
949cf20f 1026 return ON_TEXT;
d5783c40
JB
1027}
1028
9173a8fb
CY
1029/* Take X is the frame-relative pixel x-coordinate, and return the
1030 x-coordinate relative to part PART of window W. */
1031int
1032window_relative_x_coord (struct window *w, enum window_part part, int x)
1033{
1034 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1035
1036 switch (part)
1037 {
1038 case ON_TEXT:
1039 return x - window_box_left (w, TEXT_AREA);
1040
1041 case ON_LEFT_FRINGE:
1042 return x - left_x;
1043
1044 case ON_RIGHT_FRINGE:
1045 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1046
1047 case ON_LEFT_MARGIN:
1048 return (x - left_x
1049 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1050 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1051
1052 case ON_RIGHT_MARGIN:
1053 return (x + 1
1054 - ((w->pseudo_window_p)
1055 ? WINDOW_TOTAL_WIDTH (w)
1056 : WINDOW_BOX_RIGHT_EDGE_X (w))
1057 + window_box_width (w, RIGHT_MARGIN_AREA)
1058 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1059 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1060 }
1061
1062 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1063 return 0;
1064}
1065
b0228ace 1066
d5783c40 1067DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
fdb82f93
PJ
1068 Scoordinates_in_window_p, 2, 2, 0,
1069 doc: /* Return non-nil if COORDINATES are in WINDOW.
90ec88df 1070WINDOW must be a live window.
fdb82f93
PJ
1071COORDINATES is a cons of the form (X . Y), X and Y being distances
1072measured in characters from the upper-left corner of the frame.
23fe745a 1073\(0 . 0) denotes the character in the upper left corner of the
fdb82f93
PJ
1074frame.
1075If COORDINATES are in the text portion of WINDOW,
1076 the coordinates relative to the window are returned.
1077If they are in the mode line of WINDOW, `mode-line' is returned.
1078If they are in the top mode line of WINDOW, `header-line' is returned.
81d189fd
KS
1079If they are in the left fringe of WINDOW, `left-fringe' is returned.
1080If they are in the right fringe of WINDOW, `right-fringe' is returned.
fdb82f93 1081If they are on the border between WINDOW and its right sibling,
49b996e7
GM
1082 `vertical-line' is returned.
1083If they are in the windows's left or right marginal areas, `left-margin'\n\
1084 or `right-margin' is returned. */)
5842a27b 1085 (register Lisp_Object coordinates, Lisp_Object window)
d5783c40 1086{
5500c422
GM
1087 struct window *w;
1088 struct frame *f;
d5783c40 1089 int x, y;
5500c422 1090 Lisp_Object lx, ly;
d5783c40 1091
90ec88df 1092 CHECK_LIVE_WINDOW (window);
5500c422
GM
1093 w = XWINDOW (window);
1094 f = XFRAME (w->frame);
b7826503 1095 CHECK_CONS (coordinates);
5500c422
GM
1096 lx = Fcar (coordinates);
1097 ly = Fcdr (coordinates);
b7826503
PJ
1098 CHECK_NUMBER_OR_FLOAT (lx);
1099 CHECK_NUMBER_OR_FLOAT (ly);
81159bb9
RS
1100 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1101 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
5500c422 1102
9173a8fb 1103 switch (coordinates_in_window (w, x, y))
d5783c40 1104 {
7442878f 1105 case ON_NOTHING:
d5783c40
JB
1106 return Qnil;
1107
7442878f 1108 case ON_TEXT:
9173a8fb
CY
1109 /* Convert X and Y to window relative pixel coordinates, and
1110 return the canonical char units. */
1111 x -= window_box_left (w, TEXT_AREA);
1112 y -= WINDOW_TOP_EDGE_Y (w);
949cf20f
KS
1113 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1114 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
d5783c40 1115
7442878f 1116 case ON_MODE_LINE:
d5783c40 1117 return Qmode_line;
37962e60 1118
7442878f 1119 case ON_VERTICAL_BORDER:
e5d77022 1120 return Qvertical_line;
d5783c40 1121
7442878f 1122 case ON_HEADER_LINE:
045dee35 1123 return Qheader_line;
5500c422 1124
7442878f
GM
1125 case ON_LEFT_FRINGE:
1126 return Qleft_fringe;
177c0ea7 1127
7442878f
GM
1128 case ON_RIGHT_FRINGE:
1129 return Qright_fringe;
fbad6f9a 1130
49b996e7
GM
1131 case ON_LEFT_MARGIN:
1132 return Qleft_margin;
177c0ea7 1133
49b996e7
GM
1134 case ON_RIGHT_MARGIN:
1135 return Qright_margin;
1136
6487f669
RS
1137 case ON_SCROLL_BAR:
1138 /* Historically we are supposed to return nil in this case. */
1139 return Qnil;
1140
d5783c40
JB
1141 default:
1142 abort ();
1143 }
1144}
1145
67492200
GM
1146
1147/* Callback for foreach_window, used in window_from_coordinates.
f95464e4
GM
1148 Check if window W contains coordinates specified by USER_DATA which
1149 is actually a pointer to a struct check_window_data CW.
1150
1151 Check if window W contains coordinates *CW->x and *CW->y. If it
1152 does, return W in *CW->window, as Lisp_Object, and return in
5372262f 1153 *CW->part the part of the window under coordinates *X,*Y. Return
f95464e4
GM
1154 zero from this function to stop iterating over windows. */
1155
1156struct check_window_data
1157{
1158 Lisp_Object *window;
9173a8fb 1159 int x, y;
341f3858 1160 enum window_part *part;
f95464e4 1161};
67492200
GM
1162
1163static int
971de7fb 1164check_window_containing (struct window *w, void *user_data)
67492200 1165{
f95464e4 1166 struct check_window_data *cw = (struct check_window_data *) user_data;
7442878f
GM
1167 enum window_part found;
1168 int continue_p = 1;
67492200 1169
f95464e4 1170 found = coordinates_in_window (w, cw->x, cw->y);
7442878f 1171 if (found != ON_NOTHING)
67492200 1172 {
341f3858 1173 *cw->part = found;
f95464e4 1174 XSETWINDOW (*cw->window, w);
7442878f 1175 continue_p = 0;
67492200 1176 }
177c0ea7 1177
7442878f 1178 return continue_p;
67492200
GM
1179}
1180
1181
5500c422 1182/* Find the window containing frame-relative pixel position X/Y and
949cf20f
KS
1183 return it as a Lisp_Object.
1184
1185 If X, Y is on one of the window's special `window_part' elements,
9173a8fb 1186 set *PART to the id of that element.
949cf20f 1187
341f3858 1188 If there is no window under X, Y return nil and leave *PART
67492200
GM
1189 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1190
1191 This function was previously implemented with a loop cycling over
1192 windows with Fnext_window, and starting with the frame's selected
1193 window. It turned out that this doesn't work with an
1194 implementation of next_window using Vwindow_list, because
1195 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1196 tree of F when this function is called asynchronously from
1197 note_mouse_highlight. The original loop didn't terminate in this
1198 case. */
5500c422 1199
7ab12479 1200Lisp_Object
9173a8fb
CY
1201window_from_coordinates (struct frame *f, int x, int y,
1202 enum window_part *part, int tool_bar_p)
7ab12479 1203{
67492200 1204 Lisp_Object window;
f95464e4 1205 struct check_window_data cw;
341f3858
KS
1206 enum window_part dummy;
1207
1208 if (part == 0)
1209 part = &dummy;
5500c422 1210
67492200 1211 window = Qnil;
9173a8fb 1212 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
f95464e4 1213 foreach_window (f, check_window_containing, &cw);
177c0ea7 1214
67492200
GM
1215 /* If not found above, see if it's in the tool bar window, if a tool
1216 bar exists. */
1217 if (NILP (window)
1218 && tool_bar_p
1219 && WINDOWP (f->tool_bar_window)
949cf20f 1220 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
9173a8fb 1221 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
7442878f 1222 != ON_NOTHING))
5500c422 1223 {
341f3858 1224 *part = ON_TEXT;
67492200 1225 window = f->tool_bar_window;
5500c422 1226 }
37962e60 1227
67492200 1228 return window;
7ab12479
JB
1229}
1230
ab17c3f2 1231DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
fdb82f93 1232 doc: /* Return window containing coordinates X and Y on FRAME.
496e208e 1233FRAME must be a live frame and defaults to the selected one.
fdb82f93
PJ
1234The top left corner of the frame is considered to be row 0,
1235column 0. */)
5842a27b 1236 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
7ab12479 1237{
5500c422 1238 struct frame *f;
7ab12479 1239
44fa5b1e 1240 if (NILP (frame))
1ae1a37d 1241 frame = selected_frame;
b7826503 1242 CHECK_LIVE_FRAME (frame);
5500c422 1243 f = XFRAME (frame);
7ab12479 1244
5500c422 1245 /* Check that arguments are integers or floats. */
b7826503
PJ
1246 CHECK_NUMBER_OR_FLOAT (x);
1247 CHECK_NUMBER_OR_FLOAT (y);
5500c422 1248
177c0ea7 1249 return window_from_coordinates (f,
2c77cf3b
RS
1250 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1251 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1252 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1253 + FRAME_INTERNAL_BORDER_WIDTH (f)),
9173a8fb 1254 0, 0);
7ab12479
JB
1255}
1256
1257DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
fdb82f93 1258 doc: /* Return current value of point in WINDOW.
496e208e 1259WINDOW must be a live window and defaults to the selected one.
c85322d0 1260
fdb82f93
PJ
1261For a nonselected window, this is the value point would have
1262if that window were selected.
1263
1264Note that, when WINDOW is the selected window and its buffer
1265is also currently selected, the value returned is the same as (point).
1266It would be more strictly correct to return the `top-level' value
1267of point, outside of any save-excursion forms.
1268But that is hard to define. */)
5842a27b 1269 (Lisp_Object window)
7ab12479
JB
1270{
1271 register struct window *w = decode_window (window);
1272
1273 if (w == XWINDOW (selected_window)
1274 && current_buffer == XBUFFER (w->buffer))
1275 return Fpoint ();
1276 return Fmarker_position (w->pointm);
1277}
1278
1279DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
fdb82f93 1280 doc: /* Return position at which display currently starts in WINDOW.
496e208e 1281WINDOW must be a live window and defaults to the selected one.
fdb82f93 1282This is updated by redisplay or by calling `set-window-start'. */)
5842a27b 1283 (Lisp_Object window)
7ab12479
JB
1284{
1285 return Fmarker_position (decode_window (window)->start);
1286}
1287
8646118f
RS
1288/* This is text temporarily removed from the doc string below.
1289
fdb82f93
PJ
1290This function returns nil if the position is not currently known.
1291That happens when redisplay is preempted and doesn't finish.
1292If in that case you want to compute where the end of the window would
1293have been if redisplay had finished, do this:
1294 (save-excursion
1295 (goto-char (window-start window))
1296 (vertical-motion (1- (window-height window)) window)
8646118f
RS
1297 (point))") */
1298
478292ed 1299DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
fdb82f93 1300 doc: /* Return position at which display currently ends in WINDOW.
496e208e 1301WINDOW must be a live window and defaults to the selected one.
fdb82f93
PJ
1302This is updated by redisplay, when it runs to completion.
1303Simply changing the buffer text or setting `window-start'
1304does not update this value.
87e68db4 1305Return nil if there is no recorded value. (This can happen if the
a0a37a6f 1306last redisplay of WINDOW was preempted, and did not finish.)
fdb82f93
PJ
1307If UPDATE is non-nil, compute the up-to-date position
1308if it isn't already recorded. */)
5842a27b 1309 (Lisp_Object window, Lisp_Object update)
7ab12479
JB
1310{
1311 Lisp_Object value;
1312 struct window *w = decode_window (window);
5a41ab94 1313 Lisp_Object buf;
31790df3 1314 struct buffer *b;
5a41ab94
RS
1315
1316 buf = w->buffer;
b7826503 1317 CHECK_BUFFER (buf);
b3a10345 1318 b = XBUFFER (buf);
5a41ab94 1319
8646118f 1320#if 0 /* This change broke some things. We should make it later. */
7250968e
RS
1321 /* If we don't know the end position, return nil.
1322 The user can compute it with vertical-motion if he wants to.
1323 It would be nicer to do it automatically,
1324 but that's so slow that it would probably bother people. */
1325 if (NILP (w->window_end_valid))
1326 return Qnil;
8646118f 1327#endif
7250968e 1328
478292ed
RS
1329 if (! NILP (update)
1330 && ! (! NILP (w->window_end_valid)
80b00b08
DA
1331 && w->last_modified >= BUF_MODIFF (b)
1332 && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b))
41791a20 1333 && !noninteractive)
478292ed 1334 {
cbc099e5
GM
1335 struct text_pos startp;
1336 struct it it;
b3a10345 1337 struct buffer *old_buffer = NULL;
57b3e30b 1338 void *itdata = NULL;
b3a10345
KS
1339
1340 /* Cannot use Fvertical_motion because that function doesn't
1341 cope with variable-height lines. */
1342 if (b != current_buffer)
1343 {
1344 old_buffer = current_buffer;
1345 set_buffer_internal (b);
1346 }
2d6d9df0
GM
1347
1348 /* In case W->start is out of the range, use something
cb795ec4 1349 reasonable. This situation occurred when loading a file with
2d6d9df0
GM
1350 `-l' containing a call to `rmail' with subsequent other
1351 commands. At the end, W->start happened to be BEG, while
cbc099e5 1352 rmail had already narrowed the buffer. */
2d6d9df0 1353 if (XMARKER (w->start)->charpos < BEGV)
cbc099e5 1354 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
2d6d9df0 1355 else if (XMARKER (w->start)->charpos > ZV)
cbc099e5 1356 SET_TEXT_POS (startp, ZV, ZV_BYTE);
2d6d9df0 1357 else
cbc099e5
GM
1358 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1359
57b3e30b 1360 itdata = bidi_shelve_cache ();
cbc099e5
GM
1361 start_display (&it, w, startp);
1362 move_it_vertically (&it, window_box_height (w));
c3c45f65
GM
1363 if (it.current_y < it.last_visible_y)
1364 move_it_past_eol (&it);
cbc099e5 1365 value = make_number (IT_CHARPOS (it));
35928349 1366 bidi_unshelve_cache (itdata, 0);
177c0ea7 1367
99593a9d
GM
1368 if (old_buffer)
1369 set_buffer_internal (old_buffer);
478292ed
RS
1370 }
1371 else
b3a10345 1372 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
7ab12479
JB
1373
1374 return value;
1375}
1376
a7ca3326 1377DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
a0a37a6f
LT
1378 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1379Return POS. */)
5842a27b 1380 (Lisp_Object window, Lisp_Object pos)
7ab12479
JB
1381{
1382 register struct window *w = decode_window (window);
1383
b7826503 1384 CHECK_NUMBER_COERCE_MARKER (pos);
e90c4fe6
RS
1385 if (w == XWINDOW (selected_window)
1386 && XBUFFER (w->buffer) == current_buffer)
7ab12479
JB
1387 Fgoto_char (pos);
1388 else
1389 set_marker_restricted (w->pointm, pos, w->buffer);
799417bd 1390
0685cb3c
GM
1391 /* We have to make sure that redisplay updates the window to show
1392 the new value of point. */
1393 if (!EQ (window, selected_window))
799417bd 1394 ++windows_or_buffers_changed;
177c0ea7 1395
7ab12479
JB
1396 return pos;
1397}
1398
1399DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
fdb82f93 1400 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
0cf34688 1401If WINDOW is nil, the selected window is used. Return POS.
d653c8cc
MR
1402Optional third arg NOFORCE non-nil inhibits next redisplay from
1403overriding motion of point in order to display at this exact start. */)
5842a27b 1404 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
7ab12479
JB
1405{
1406 register struct window *w = decode_window (window);
1407
b7826503 1408 CHECK_NUMBER_COERCE_MARKER (pos);
7ab12479
JB
1409 set_marker_restricted (w->start, pos, w->buffer);
1410 /* this is not right, but much easier than doing what is right. */
c98ff5dd 1411 w->start_at_line_beg = 0;
265a9e55 1412 if (NILP (noforce))
c98ff5dd
DA
1413 w->force_start = 1;
1414 w->update_mode_line = 1;
80b00b08
DA
1415 w->last_modified = 0;
1416 w->last_overlay_modified = 0;
62c07cc7
JB
1417 if (!EQ (window, selected_window))
1418 windows_or_buffers_changed++;
ce7fae7d 1419
7ab12479
JB
1420 return pos;
1421}
1422
496e208e
MR
1423DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1424 Spos_visible_in_window_p, 0, 3, 0,
1425 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1426Return nil if that position is scrolled vertically out of view.
1427If a character is only partially visible, nil is returned, unless the
1428optional argument PARTIALLY is non-nil.
1429If POS is only out of view because of horizontal scrolling, return non-nil.
1430If POS is t, it specifies the position of the last visible glyph in WINDOW.
1431POS defaults to point in WINDOW; WINDOW defaults to the selected window.
1432
1433If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1434return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1435where X and Y are the pixel coordinates relative to the top left corner
1436of the window. The remaining elements are omitted if the character after
1437POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1438off-window at the top and bottom of the row, ROWH is the height of the
1439display row, and VPOS is the row number (0-based) containing POS. */)
1440 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1441{
1442 register struct window *w;
1443 register EMACS_INT posint;
1444 register struct buffer *buf;
1445 struct text_pos top;
1446 Lisp_Object in_window = Qnil;
1447 int rtop, rbot, rowh, vpos, fully_p = 1;
1448 int x, y;
1449
1450 w = decode_window (window);
1451 buf = XBUFFER (w->buffer);
1452 SET_TEXT_POS_FROM_MARKER (top, w->start);
1453
1454 if (EQ (pos, Qt))
1455 posint = -1;
1456 else if (!NILP (pos))
1457 {
1458 CHECK_NUMBER_COERCE_MARKER (pos);
1459 posint = XINT (pos);
1460 }
1461 else if (w == XWINDOW (selected_window))
1462 posint = PT;
1463 else
1464 posint = XMARKER (w->pointm)->charpos;
1465
1466 /* If position is above window start or outside buffer boundaries,
1467 or if window start is out of range, position is not visible. */
1468 if ((EQ (pos, Qt)
1469 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1470 && CHARPOS (top) >= BUF_BEGV (buf)
1471 && CHARPOS (top) <= BUF_ZV (buf)
1472 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
1473 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
1474 in_window = Qt;
1475
1476 if (!NILP (in_window) && !NILP (partially))
1477 {
1478 Lisp_Object part = Qnil;
1479 if (!fully_p)
1480 part = list4 (make_number (rtop), make_number (rbot),
1481 make_number (rowh), make_number (vpos));
1482 in_window = Fcons (make_number (x),
1483 Fcons (make_number (y), part));
1484 }
1485
1486 return in_window;
1487}
1488
1489DEFUN ("window-line-height", Fwindow_line_height,
1490 Swindow_line_height, 0, 2, 0,
1491 doc: /* Return height in pixels of text line LINE in window WINDOW.
1492WINDOW defaults to the selected window.
1493
1494Return height of current line if LINE is omitted or nil. Return height of
1495header or mode line if LINE is `header-line' or `mode-line'.
1496Otherwise, LINE is a text line number starting from 0. A negative number
1497counts from the end of the window.
1498
1499Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1500in pixels of the visible part of the line, VPOS and YPOS are the
1501vertical position in lines and pixels of the line, relative to the top
1502of the first text line, and OFFBOT is the number of off-window pixels at
1503the bottom of the text line. If there are off-window pixels at the top
1504of the (first) text line, YPOS is negative.
1505
1506Return nil if window display is not up-to-date. In that case, use
1507`pos-visible-in-window-p' to obtain the information. */)
1508 (Lisp_Object line, Lisp_Object window)
1509{
1510 register struct window *w;
1511 register struct buffer *b;
1512 struct glyph_row *row, *end_row;
d311d28c
PE
1513 int max_y, crop, i;
1514 EMACS_INT n;
496e208e
MR
1515
1516 w = decode_window (window);
1517
1518 if (noninteractive || w->pseudo_window_p)
1519 return Qnil;
1520
1521 CHECK_BUFFER (w->buffer);
1522 b = XBUFFER (w->buffer);
1523
1524 /* Fail if current matrix is not up-to-date. */
1525 if (NILP (w->window_end_valid)
1526 || current_buffer->clip_changed
1527 || current_buffer->prevent_redisplay_optimizations_p
80b00b08
DA
1528 || w->last_modified < BUF_MODIFF (b)
1529 || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b))
496e208e
MR
1530 return Qnil;
1531
1532 if (NILP (line))
1533 {
1534 i = w->cursor.vpos;
1535 if (i < 0 || i >= w->current_matrix->nrows
1536 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1537 return Qnil;
1538 max_y = window_text_bottom_y (w);
1539 goto found_row;
1540 }
1541
1542 if (EQ (line, Qheader_line))
1543 {
1544 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1545 return Qnil;
1546 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1547 if (!row->enabled_p)
1548 return Qnil;
1549 return list4 (make_number (row->height),
1550 make_number (0), make_number (0),
1551 make_number (0));
1552 }
1553
1554 if (EQ (line, Qmode_line))
1555 {
1556 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1557 if (!row->enabled_p)
1558 return Qnil;
1559 return list4 (make_number (row->height),
1560 make_number (0), /* not accurate */
1561 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
1562 + window_text_bottom_y (w)),
1563 make_number (0));
1564 }
1565
1566 CHECK_NUMBER (line);
1567 n = XINT (line);
1568
1569 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1570 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1571 max_y = window_text_bottom_y (w);
1572 i = 0;
1573
1574 while ((n < 0 || i < n)
1575 && row <= end_row && row->enabled_p
1576 && row->y + row->height < max_y)
1577 row++, i++;
1578
1579 if (row > end_row || !row->enabled_p)
1580 return Qnil;
1581
1582 if (++n < 0)
1583 {
1584 if (-n > i)
1585 return Qnil;
1586 row += n;
1587 i += n;
1588 }
1589
1590 found_row:
1591 crop = max (0, (row->y + row->height) - max_y);
1592 return list4 (make_number (row->height + min (0, row->y) - crop),
1593 make_number (i),
1594 make_number (row->y),
1595 make_number (crop));
1596}
d653c8cc 1597
a7ca3326 1598DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
d653c8cc
MR
1599 0, 1, 0,
1600 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
12bb3111 1601More precisely, return the value assigned by the last call of
7bfac547
MR
1602`set-window-dedicated-p' for WINDOW. Return nil if that function was
1603never called with WINDOW as its argument, or the value set by that
1604function was internally reset since its last call. WINDOW defaults to
1605the selected window.
1606
1607When a window is dedicated to its buffer, `display-buffer' will refrain
1608from displaying another buffer in it. `get-lru-window' and
1609`get-largest-window' treat dedicated windows specially.
1610`delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1611`kill-buffer' can delete a dedicated window and the containing frame.
1612
1613Functions like `set-window-buffer' may change the buffer displayed by a
1614window, unless that window is "strongly" dedicated to its buffer, that
1615is the value returned by `window-dedicated-p' is t. */)
5842a27b 1616 (Lisp_Object window)
7ab12479
JB
1617{
1618 return decode_window (window)->dedicated;
1619}
1620
d207b766
RS
1621DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1622 Sset_window_dedicated_p, 2, 2, 0,
d653c8cc 1623 doc: /* Mark WINDOW as dedicated according to FLAG.
496e208e
MR
1624WINDOW must be a live window and defaults to the selected one. FLAG
1625non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
1626mark WINDOW as non-dedicated. Return FLAG.
d653c8cc 1627
7bfac547
MR
1628When a window is dedicated to its buffer, `display-buffer' will refrain
1629from displaying another buffer in it. `get-lru-window' and
1630`get-largest-window' treat dedicated windows specially.
496e208e
MR
1631`delete-windows-on', `replace-buffer-in-windows', `quit-window',
1632`quit-restore-window' and `kill-buffer' can delete a dedicated window
1633and the containing frame.
7bfac547
MR
1634
1635As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1636its buffer. Functions like `set-window-buffer' may change the buffer
1637displayed by a window, unless that window is strongly dedicated to its
1638buffer. If and when `set-window-buffer' displays another buffer in a
496e208e 1639window, it also makes sure that the window is no more dedicated. */)
5842a27b 1640 (Lisp_Object window, Lisp_Object flag)
7ab12479
JB
1641{
1642 register struct window *w = decode_window (window);
1643
d653c8cc 1644 w->dedicated = flag;
7ab12479
JB
1645 return w->dedicated;
1646}
1647
496e208e
MR
1648DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
1649 0, 1, 0,
1650 doc: /* Return buffers previously shown in WINDOW.
1651WINDOW must be a live window and defaults to the selected one.
1652
94e0933e
CY
1653The return value is a list of elements (BUFFER WINDOW-START POS),
1654where BUFFER is a buffer, WINDOW-START is the start position of the
1655window for that buffer, and POS is a window-specific point value. */)
496e208e
MR
1656 (Lisp_Object window)
1657{
1658 return decode_window (window)->prev_buffers;
1659}
1660
1661DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
1662 Sset_window_prev_buffers, 2, 2, 0,
1663 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
94e0933e 1664WINDOW must be a live window and defaults to the selected one.
496e208e 1665
94e0933e
CY
1666PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
1667where BUFFER is a buffer, WINDOW-START is the start position of the
1668window for that buffer, and POS is a window-specific point value. */)
496e208e
MR
1669 (Lisp_Object window, Lisp_Object prev_buffers)
1670{
9b1c252e 1671 return decode_window (window)->prev_buffers = prev_buffers;
496e208e
MR
1672}
1673
1674DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
1675 0, 1, 0,
1676 doc: /* Return list of buffers recently re-shown in WINDOW.
1677WINDOW must be a live window and defaults to the selected one. */)
1678 (Lisp_Object window)
1679{
1680 return decode_window (window)->next_buffers;
1681}
1682
1683DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
1684 Sset_window_next_buffers, 2, 2, 0,
1685 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
94e0933e
CY
1686WINDOW must be a live window and defaults to the selected one.
1687NEXT-BUFFERS should be a list of buffers. */)
496e208e
MR
1688 (Lisp_Object window, Lisp_Object next_buffers)
1689{
9b1c252e 1690 return decode_window (window)->next_buffers = next_buffers;
496e208e 1691}
d653c8cc 1692
cfbb2395
JB
1693DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1694 0, 1, 0,
d653c8cc
MR
1695 doc: /* Return the parameters of WINDOW and their values.
1696WINDOW defaults to the selected window. The return value is a list of
87e68db4 1697elements of the form (PARAMETER . VALUE). */)
5842a27b 1698 (Lisp_Object window)
cfbb2395 1699{
496e208e 1700 return Fcopy_alist (decode_any_window (window)->window_parameters);
cfbb2395
JB
1701}
1702
1703DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1704 2, 2, 0,
d653c8cc
MR
1705 doc: /* Return WINDOW's value for PARAMETER.
1706WINDOW defaults to the selected window. */)
5842a27b 1707 (Lisp_Object window, Lisp_Object parameter)
cfbb2395 1708{
927abf37
JB
1709 Lisp_Object result;
1710
496e208e 1711 result = Fassq (parameter, decode_any_window (window)->window_parameters);
927abf37 1712 return CDR_SAFE (result);
cfbb2395
JB
1713}
1714
cfbb2395
JB
1715DEFUN ("set-window-parameter", Fset_window_parameter,
1716 Sset_window_parameter, 3, 3, 0,
d653c8cc
MR
1717 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1718WINDOW defaults to the selected window. Return VALUE. */)
5842a27b 1719 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
cfbb2395 1720{
496e208e 1721 register struct window *w = decode_any_window (window);
cfbb2395
JB
1722 Lisp_Object old_alist_elt;
1723
1724 old_alist_elt = Fassq (parameter, w->window_parameters);
12bb3111 1725 if (NILP (old_alist_elt))
cfbb2395
JB
1726 w->window_parameters = Fcons (Fcons (parameter, value), w->window_parameters);
1727 else
1728 Fsetcdr (old_alist_elt, value);
927abf37 1729 return value;
cfbb2395
JB
1730}
1731
7ab12479
JB
1732DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1733 0, 1, 0,
c85322d0
EZ
1734 doc: /* Return the display-table that WINDOW is using.
1735WINDOW defaults to the selected window. */)
5842a27b 1736 (Lisp_Object window)
7ab12479
JB
1737{
1738 return decode_window (window)->display_table;
1739}
1740
5500c422
GM
1741/* Get the display table for use on window W. This is either W's
1742 display table or W's buffer's display table. Ignore the specified
1743 tables if they are not valid; if no valid table is specified,
1744 return 0. */
7ab12479 1745
319315f1 1746struct Lisp_Char_Table *
971de7fb 1747window_display_table (struct window *w)
7ab12479 1748{
c756cdbe
GM
1749 struct Lisp_Char_Table *dp = NULL;
1750
1751 if (DISP_TABLE_P (w->display_table))
1752 dp = XCHAR_TABLE (w->display_table);
1753 else if (BUFFERP (w->buffer))
1754 {
1755 struct buffer *b = XBUFFER (w->buffer);
177c0ea7 1756
4b4deea2
TT
1757 if (DISP_TABLE_P (BVAR (b, display_table)))
1758 dp = XCHAR_TABLE (BVAR (b, display_table));
c756cdbe
GM
1759 else if (DISP_TABLE_P (Vstandard_display_table))
1760 dp = XCHAR_TABLE (Vstandard_display_table);
1761 }
171d003c 1762
c756cdbe 1763 return dp;
7ab12479
JB
1764}
1765
3a2712f9 1766DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
fdb82f93 1767 doc: /* Set WINDOW's display-table to TABLE. */)
5842a27b 1768 (register Lisp_Object window, Lisp_Object table)
7ab12479
JB
1769{
1770 register struct window *w;
7ab12479
JB
1771
1772 w = decode_window (window);
1773 w->display_table = table;
1774 return table;
1775}
1776\f
562dd5e9 1777/* Record info on buffer window W is displaying
7ab12479 1778 when it is about to cease to display that buffer. */
dfcf069d 1779static void
971de7fb 1780unshow_buffer (register struct window *w)
7ab12479 1781{
12cae7c0 1782 Lisp_Object buf;
b73ea88e 1783 struct buffer *b;
7ab12479 1784
12cae7c0 1785 buf = w->buffer;
b73ea88e
RS
1786 b = XBUFFER (buf);
1787 if (b != XMARKER (w->pointm)->buffer)
7ab12479
JB
1788 abort ();
1789
573f41ab 1790#if 0
7ab12479
JB
1791 if (w == XWINDOW (selected_window)
1792 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1793 /* Do this except when the selected window's buffer
1794 is being removed from some other window. */
573f41ab
RS
1795#endif
1796 /* last_window_start records the start position that this buffer
1797 had in the last window to be disconnected from it.
1798 Now that this statement is unconditional,
1799 it is possible for the buffer to be displayed in the
1800 selected window, while last_window_start reflects another
1801 window which was recently showing the same buffer.
1802 Some people might say that might be a good thing. Let's see. */
b73ea88e 1803 b->last_window_start = marker_position (w->start);
7ab12479
JB
1804
1805 /* Point in the selected window's buffer
1806 is actually stored in that buffer, and the window's pointm isn't used.
1807 So don't clobber point in that buffer. */
719eaeb1
GM
1808 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1809 /* This line helps to fix Horsley's testbug.el bug. */
4b4deea2
TT
1810 && !(WINDOWP (BVAR (b, last_selected_window))
1811 && w != XWINDOW (BVAR (b, last_selected_window))
1812 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->buffer)))
b73ea88e
RS
1813 temp_set_point_both (b,
1814 clip_to_bounds (BUF_BEGV (b),
1815 XMARKER (w->pointm)->charpos,
1816 BUF_ZV (b)),
1817 clip_to_bounds (BUF_BEGV_BYTE (b),
1818 marker_byte_position (w->pointm),
1819 BUF_ZV_BYTE (b)));
177c0ea7 1820
4b4deea2
TT
1821 if (WINDOWP (BVAR (b, last_selected_window))
1822 && w == XWINDOW (BVAR (b, last_selected_window)))
1823 BVAR (b, last_selected_window) = Qnil;
7ab12479
JB
1824}
1825
1a13852e
MR
1826/* Put NEW into the window structure in place of OLD. SETFLAG zero
1827 means change window structure only. Otherwise store geometry and
1828 other settings as well. */
dfcf069d 1829static void
1a13852e 1830replace_window (Lisp_Object old, Lisp_Object new, int setflag)
7ab12479
JB
1831{
1832 register Lisp_Object tem;
1a13852e 1833 register struct window *o = XWINDOW (old), *n = XWINDOW (new);
7ab12479 1834
1a13852e
MR
1835 /* If OLD is its frame's root window, then NEW is the new
1836 root window for that frame. */
7f4161e0 1837 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1a13852e
MR
1838 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = new;
1839
1840 if (setflag)
1841 {
1842 n->left_col = o->left_col;
1843 n->top_line = o->top_line;
1844 n->total_cols = o->total_cols;
1845 n->total_lines = o->total_lines;
1846 n->normal_cols = o->normal_cols;
1847 o->normal_cols = make_float (1.0);
1848 n->normal_lines = o->normal_lines;
1849 o->normal_lines = make_float (1.0);
1850 n->desired_matrix = n->current_matrix = 0;
1851 n->vscroll = 0;
1852 memset (&n->cursor, 0, sizeof (n->cursor));
1853 memset (&n->last_cursor, 0, sizeof (n->last_cursor));
1854 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
1855 n->phys_cursor_type = -1;
1856 n->phys_cursor_width = -1;
1857 n->must_be_updated_p = 0;
1858 n->pseudo_window_p = 0;
1859 XSETFASTINT (n->window_end_vpos, 0);
1860 XSETFASTINT (n->window_end_pos, 0);
1861 n->window_end_valid = Qnil;
1862 n->frozen_window_start_p = 0;
1a13852e
MR
1863 }
1864
1865 n->next = tem = o->next;
265a9e55 1866 if (!NILP (tem))
1a13852e 1867 XWINDOW (tem)->prev = new;
7ab12479 1868
1a13852e 1869 n->prev = tem = o->prev;
265a9e55 1870 if (!NILP (tem))
1a13852e 1871 XWINDOW (tem)->next = new;
7ab12479 1872
1a13852e 1873 n->parent = tem = o->parent;
265a9e55 1874 if (!NILP (tem))
7ab12479
JB
1875 {
1876 if (EQ (XWINDOW (tem)->vchild, old))
1a13852e 1877 XWINDOW (tem)->vchild = new;
7ab12479 1878 if (EQ (XWINDOW (tem)->hchild, old))
1a13852e 1879 XWINDOW (tem)->hchild = new;
7ab12479 1880 }
1a13852e
MR
1881}
1882
1883/* If window WINDOW and its parent window are iso-combined, merge
1884 WINDOW's children into those of its parent window and mark WINDOW as
1885 deleted. */
1886
1887static void
1888recombine_windows (Lisp_Object window)
1889{
1890 struct window *w, *p, *c;
1891 Lisp_Object parent, child;
1892 int horflag;
1893
1894 w = XWINDOW (window);
1895 parent = w->parent;
b6f67890 1896 if (!NILP (parent) && NILP (w->combination_limit))
1a13852e
MR
1897 {
1898 p = XWINDOW (parent);
1899 if (((!NILP (p->vchild) && !NILP (w->vchild))
1900 || (!NILP (p->hchild) && !NILP (w->hchild))))
1901 /* WINDOW and PARENT are both either a vertical or a horizontal
1902 combination. */
1903 {
1904 horflag = NILP (w->vchild);
1905 child = horflag ? w->hchild : w->vchild;
1906 c = XWINDOW (child);
1907
1908 /* Splice WINDOW's children into its parent's children and
1909 assign new normal sizes. */
1910 if (NILP (w->prev))
1911 if (horflag)
1912 p->hchild = child;
1913 else
1914 p->vchild = child;
1915 else
1916 {
1917 c->prev = w->prev;
1918 XWINDOW (w->prev)->next = child;
1919 }
1920
1921 while (c)
1922 {
1923 c->parent = parent;
1924
1925 if (horflag)
1926 c->normal_cols
1927 = make_float (XFLOATINT (c->total_cols)
1928 / XFLOATINT (p->total_cols));
1929 else
1930 c->normal_lines
1931 = make_float (XFLOATINT (c->total_lines)
1932 / XFLOATINT (p->total_lines));
1933
1934 if (NILP (c->next))
1935 {
1936 if (!NILP (w->next))
1937 {
1938 c->next = w->next;
1939 XWINDOW (c->next)->prev = child;
1940 }
1941
1942 c = 0;
1943 }
1944 else
1945 {
1946 child = c->next;
1947 c = XWINDOW (child);
1948 }
1949 }
7ab12479 1950
1a13852e
MR
1951 /* WINDOW can be deleted now. */
1952 w->vchild = w->hchild = Qnil;
1953 }
1954 }
7ab12479 1955}
6198ccd0
MR
1956
1957/* If WINDOW can be deleted, delete it. */
4475bec4 1958static void
6198ccd0
MR
1959delete_deletable_window (Lisp_Object window)
1960{
1961 if (!NILP (call1 (Qwindow_deletable_p, window)))
1962 call1 (Qdelete_window, window);
1963}
1a13852e 1964\f
67492200
GM
1965/***********************************************************************
1966 Window List
1967 ***********************************************************************/
1968
f95464e4
GM
1969/* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1970 pointer. This is a callback function for foreach_window, used in
496e208e 1971 the window_list function. */
67492200
GM
1972
1973static int
971de7fb 1974add_window_to_list (struct window *w, void *user_data)
67492200 1975{
f95464e4 1976 Lisp_Object *list = (Lisp_Object *) user_data;
67492200
GM
1977 Lisp_Object window;
1978 XSETWINDOW (window, w);
212116d6 1979 *list = Fcons (window, *list);
67492200
GM
1980 return 1;
1981}
1982
1983
1984/* Return a list of all windows, for use by next_window. If
1985 Vwindow_list is a list, return that list. Otherwise, build a new
1986 list, cache it in Vwindow_list, and return that. */
1987
1988static Lisp_Object
971de7fb 1989window_list (void)
67492200
GM
1990{
1991 if (!CONSP (Vwindow_list))
1992 {
1993 Lisp_Object tail;
212116d6 1994
67492200
GM
1995 Vwindow_list = Qnil;
1996 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
212116d6
GM
1997 {
1998 Lisp_Object args[2];
1999
2000 /* We are visiting windows in canonical order, and add
2001 new windows at the front of args[1], which means we
2002 have to reverse this list at the end. */
2003 args[1] = Qnil;
2004 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
2005 args[0] = Vwindow_list;
2006 args[1] = Fnreverse (args[1]);
2007 Vwindow_list = Fnconc (2, args);
2008 }
67492200 2009 }
177c0ea7 2010
67492200
GM
2011 return Vwindow_list;
2012}
2013
2014
118ea242
GM
2015/* Value is non-zero if WINDOW satisfies the constraints given by
2016 OWINDOW, MINIBUF and ALL_FRAMES.
67492200 2017
118ea242
GM
2018 MINIBUF t means WINDOW may be minibuffer windows.
2019 `lambda' means WINDOW may not be a minibuffer window.
2020 a window means a specific minibuffer window
67492200 2021
118ea242
GM
2022 ALL_FRAMES t means search all frames,
2023 nil means search just current frame,
aa248733
MS
2024 `visible' means search just visible frames on the
2025 current terminal,
2026 0 means search visible and iconified frames on the
2027 current terminal,
118ea242
GM
2028 a window means search the frame that window belongs to,
2029 a frame means consider windows on that frame, only. */
67492200
GM
2030
2031static int
971de7fb 2032candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf, Lisp_Object all_frames)
67492200
GM
2033{
2034 struct window *w = XWINDOW (window);
2035 struct frame *f = XFRAME (w->frame);
2036 int candidate_p = 1;
2037
2038 if (!BUFFERP (w->buffer))
2039 candidate_p = 0;
2040 else if (MINI_WINDOW_P (w)
2041 && (EQ (minibuf, Qlambda)
2042 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2043 {
2044 /* If MINIBUF is `lambda' don't consider any mini-windows.
2045 If it is a window, consider only that one. */
2046 candidate_p = 0;
2047 }
118ea242
GM
2048 else if (EQ (all_frames, Qt))
2049 candidate_p = 1;
67492200 2050 else if (NILP (all_frames))
118ea242 2051 {
a54e2c05 2052 eassert (WINDOWP (owindow));
118ea242
GM
2053 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2054 }
67492200
GM
2055 else if (EQ (all_frames, Qvisible))
2056 {
2057 FRAME_SAMPLE_VISIBILITY (f);
de509a60
SM
2058 candidate_p = FRAME_VISIBLE_P (f)
2059 && (FRAME_TERMINAL (XFRAME (w->frame))
2060 == FRAME_TERMINAL (XFRAME (selected_frame)));
2061
67492200
GM
2062 }
2063 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2064 {
2065 FRAME_SAMPLE_VISIBILITY (f);
ca2d5566
SM
2066 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2067#ifdef HAVE_X_WINDOWS
2068 /* Yuck!! If we've just created the frame and the
2069 window-manager requested the user to place it
2070 manually, the window may still not be considered
2071 `visible'. I'd argue it should be at least
2072 something like `iconified', but don't know how to do
2073 that yet. --Stef */
2074 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2075 && !f->output_data.x->has_been_visible)
2076#endif
de509a60
SM
2077 )
2078 && (FRAME_TERMINAL (XFRAME (w->frame))
2079 == FRAME_TERMINAL (XFRAME (selected_frame)));
67492200 2080 }
67492200
GM
2081 else if (WINDOWP (all_frames))
2082 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2083 || EQ (XWINDOW (all_frames)->frame, w->frame)
2084 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
118ea242
GM
2085 else if (FRAMEP (all_frames))
2086 candidate_p = EQ (all_frames, w->frame);
67492200
GM
2087
2088 return candidate_p;
2089}
2090
2091
2092/* Decode arguments as allowed by Fnext_window, Fprevious_window, and
aa248733
MS
2093 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2094 MINIBUF, and ALL_FRAMES. */
67492200
GM
2095
2096static void
971de7fb 2097decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
67492200
GM
2098{
2099 if (NILP (*window))
2100 *window = selected_window;
2101 else
b7826503 2102 CHECK_LIVE_WINDOW (*window);
177c0ea7 2103
67492200
GM
2104 /* MINIBUF nil may or may not include minibuffers. Decide if it
2105 does. */
2106 if (NILP (*minibuf))
2107 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2108 else if (!EQ (*minibuf, Qt))
2109 *minibuf = Qlambda;
177c0ea7 2110
67492200
GM
2111 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2112 => count none of them, or a specific minibuffer window (the
2113 active one) to count. */
2114
2115 /* ALL_FRAMES nil doesn't specify which frames to include. */
2116 if (NILP (*all_frames))
2117 *all_frames = (!EQ (*minibuf, Qlambda)
2118 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
2119 : Qnil);
2120 else if (EQ (*all_frames, Qvisible))
2121 ;
0f8fe9a2 2122 else if (EQ (*all_frames, make_number (0)))
67492200
GM
2123 ;
2124 else if (FRAMEP (*all_frames))
2125 ;
2126 else if (!EQ (*all_frames, Qt))
2127 *all_frames = Qnil;
67492200
GM
2128}
2129
2130
ab6d1131 2131/* Return the next or previous window of WINDOW in cyclic ordering
67492200
GM
2132 of windows. NEXT_P non-zero means return the next window. See the
2133 documentation string of next-window for the meaning of MINIBUF and
2134 ALL_FRAMES. */
2135
2136static Lisp_Object
971de7fb 2137next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
67492200
GM
2138{
2139 decode_next_window_args (&window, &minibuf, &all_frames);
177c0ea7 2140
67492200
GM
2141 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2142 return the first window on the frame. */
2143 if (FRAMEP (all_frames)
2144 && !EQ (all_frames, XWINDOW (window)->frame))
2145 return Fframe_first_window (all_frames);
177c0ea7 2146
212116d6 2147 if (next_p)
67492200
GM
2148 {
2149 Lisp_Object list;
177c0ea7 2150
67492200
GM
2151 /* Find WINDOW in the list of all windows. */
2152 list = Fmemq (window, window_list ());
2153
2154 /* Scan forward from WINDOW to the end of the window list. */
2155 if (CONSP (list))
2156 for (list = XCDR (list); CONSP (list); list = XCDR (list))
118ea242 2157 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
67492200
GM
2158 break;
2159
2160 /* Scan from the start of the window list up to WINDOW. */
2161 if (!CONSP (list))
2162 for (list = Vwindow_list;
2163 CONSP (list) && !EQ (XCAR (list), window);
2164 list = XCDR (list))
118ea242 2165 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
67492200
GM
2166 break;
2167
2168 if (CONSP (list))
2169 window = XCAR (list);
2170 }
2171 else
2172 {
2173 Lisp_Object candidate, list;
177c0ea7 2174
67492200
GM
2175 /* Scan through the list of windows for candidates. If there are
2176 candidate windows in front of WINDOW, the last one of these
2177 is the one we want. If there are candidates following WINDOW
2178 in the list, again the last one of these is the one we want. */
2179 candidate = Qnil;
2180 for (list = window_list (); CONSP (list); list = XCDR (list))
2181 {
2182 if (EQ (XCAR (list), window))
2183 {
2184 if (WINDOWP (candidate))
2185 break;
2186 }
118ea242
GM
2187 else if (candidate_window_p (XCAR (list), window, minibuf,
2188 all_frames))
67492200
GM
2189 candidate = XCAR (list);
2190 }
2191
2192 if (WINDOWP (candidate))
2193 window = candidate;
2194 }
2195
2196 return window;
2197}
7ab12479 2198
7ab12479 2199
a7ca3326 2200DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
a9b9b7f5 2201 doc: /* Return live window after WINDOW in the cyclic ordering of windows.
87e68db4 2202WINDOW must be a live window and defaults to the selected one. The
9397e56f
MR
2203optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2204consider.
2205
2206MINIBUF nil or omitted means consider the minibuffer window only if the
2207minibuffer is active. MINIBUF t means consider the minibuffer window
2208even if the minibuffer is not active. Any other value means do not
2209consider the minibuffer window even if the minibuffer is active.
2210
2211ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2212plus the minibuffer window if specified by the MINIBUF argument. If the
2213minibuffer counts, consider all windows on all frames that share that
2214minibuffer too. The following non-nil values of ALL-FRAMES have special
2215meanings:
2216
2217- t means consider all windows on all existing frames.
2218
2219- `visible' means consider all windows on all visible frames.
2220
2221- 0 (the number zero) means consider all windows on all visible and
2222 iconified frames.
2223
2224- A frame means consider all windows on that frame only.
ab6d1131 2225
ab6d1131 2226Anything else means consider all windows on WINDOW's frame and no
9397e56f 2227others.
fdb82f93
PJ
2228
2229If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2230`next-window' to iterate through the entire cycle of acceptable
2231windows, eventually ending up back at the window you started with.
2232`previous-window' traverses the same cycle, in the reverse order. */)
5842a27b 2233 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
7ab12479 2234{
67492200 2235 return next_window (window, minibuf, all_frames, 1);
7ab12479
JB
2236}
2237
67492200 2238
26f6279d 2239DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
a9b9b7f5 2240 doc: /* Return live window before WINDOW in the cyclic ordering of windows.
9397e56f
MR
2241WINDOW must be a live window and defaults to the selected one. The
2242optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2243consider.
2244
2245MINIBUF nil or omitted means consider the minibuffer window only if the
2246minibuffer is active. MINIBUF t means consider the minibuffer window
2247even if the minibuffer is not active. Any other value means do not
2248consider the minibuffer window even if the minibuffer is active.
2249
2250ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2251plus the minibuffer window if specified by the MINIBUF argument. If the
2252minibuffer counts, consider all windows on all frames that share that
2253minibuffer too. The following non-nil values of ALL-FRAMES have special
2254meanings:
2255
2256- t means consider all windows on all existing frames.
2257
2258- `visible' means consider all windows on all visible frames.
2259
2260- 0 (the number zero) means consider all windows on all visible and
2261 iconified frames.
2262
2263- A frame means consider all windows on that frame only.
2264
2265Anything else means consider all windows on WINDOW's frame and no
2266others.
ab6d1131
MR
2267
2268If you use consistent values for MINIBUF and ALL-FRAMES, you can
2269use `previous-window' to iterate through the entire cycle of
2270acceptable windows, eventually ending up back at the window you
2271started with. `next-window' traverses the same cycle, in the
2272reverse order. */)
5842a27b 2273 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
7ab12479 2274{
67492200 2275 return next_window (window, minibuf, all_frames, 0);
7ab12479
JB
2276}
2277
67492200 2278
ab6d1131 2279/* Return a list of windows in cyclic ordering. Arguments are like
cd2904bd
GM
2280 for `next-window'. */
2281
2282static Lisp_Object
971de7fb 2283window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
67492200 2284{
403de3b4 2285 Lisp_Object tail, list, rest;
67492200
GM
2286
2287 decode_next_window_args (&window, &minibuf, &all_frames);
2288 list = Qnil;
177c0ea7 2289
67492200 2290 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
118ea242 2291 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
67492200 2292 list = Fcons (XCAR (tail), list);
177c0ea7 2293
403de3b4
RS
2294 /* Rotate the list to start with WINDOW. */
2295 list = Fnreverse (list);
2296 rest = Fmemq (window, list);
2297 if (!NILP (rest) && !EQ (rest, list))
2298 {
1725a7c9 2299 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
403de3b4
RS
2300 ;
2301 XSETCDR (tail, Qnil);
2302 list = nconc2 (rest, list);
2303 }
2304 return list;
67492200
GM
2305}
2306
2307
abde8f8c
MR
2308DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2309 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2310FRAME nil or omitted means use the selected frame.
49745b39 2311WINDOW nil or omitted means use the window selected within FRAME.
abde8f8c
MR
2312MINIBUF t means include the minibuffer window, even if it isn't active.
2313MINIBUF nil or omitted means include the minibuffer window only
2314if it's active.
2315MINIBUF neither nil nor t means never include the minibuffer window. */)
2316 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2317{
2318 if (NILP (window))
2319 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2320 CHECK_WINDOW (window);
2321 if (NILP (frame))
2322 frame = selected_frame;
2323
2324 if (!EQ (frame, XWINDOW (window)->frame))
2325 error ("Window is on a different frame");
2326
2327 return window_list_1 (window, minibuf, frame);
2328}
2329
2330
1a13852e
MR
2331DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2332 doc: /* Return a list of all live windows.
2333WINDOW specifies the first window to list and defaults to the selected
2334window.
2335
2336Optional argument MINIBUF nil or omitted means consider the minibuffer
2337window only if the minibuffer is active. MINIBUF t means consider the
2338minibuffer window even if the minibuffer is not active. Any other value
2339means do not consider the minibuffer window even if the minibuffer is
2340active.
2341
2342Optional argument ALL-FRAMES nil or omitted means consider all windows
2343on WINDOW's frame, plus the minibuffer window if specified by the
2344MINIBUF argument. If the minibuffer counts, consider all windows on all
2345frames that share that minibuffer too. The following non-nil values of
2346ALL-FRAMES have special meanings:
2347
2348- t means consider all windows on all existing frames.
2349
2350- `visible' means consider all windows on all visible frames.
2351
2352- 0 (the number zero) means consider all windows on all visible and
2353 iconified frames.
2354
2355- A frame means consider all windows on that frame only.
2356
2357Anything else means consider all windows on WINDOW's frame and no
2358others.
2359
2360If WINDOW is not on the list of windows returned, some other window will
8350f087 2361be listed first but no error is signaled. */)
1a13852e
MR
2362 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2363{
2364 return window_list_1 (window, minibuf, all_frames);
2365}
7ab12479
JB
2366\f
2367/* Look at all windows, performing an operation specified by TYPE
2368 with argument OBJ.
75d8f668 2369 If FRAMES is Qt, look at all frames;
75d8f668 2370 Qnil, look at just the selected frame;
89bca612 2371 Qvisible, look at visible frames;
75d8f668 2372 a frame, just look at windows on that frame.
85fe3b5e 2373 If MINI is non-zero, perform the operation on minibuffer windows too. */
7ab12479
JB
2374
2375enum window_loop
2376{
2377 WINDOW_LOOP_UNUSED,
9397e56f
MR
2378 GET_BUFFER_WINDOW, /* Arg is buffer */
2379 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2380 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
3f8ab7bd 2381 CHECK_ALL_WINDOWS
7ab12479
JB
2382};
2383
2384static Lisp_Object
971de7fb 2385window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
7ab12479 2386{
118ea242 2387 Lisp_Object window, windows, best_window, frame_arg;
9397e56f 2388 int frame_best_window_flag = 0;
118ea242 2389 struct frame *f;
ffdc852d 2390 struct gcpro gcpro1;
177c0ea7 2391
44fa5b1e
JB
2392 /* If we're only looping through windows on a particular frame,
2393 frame points to that frame. If we're looping through windows
2394 on all frames, frame is 0. */
2395 if (FRAMEP (frames))
118ea242 2396 f = XFRAME (frames);
44fa5b1e 2397 else if (NILP (frames))
118ea242 2398 f = SELECTED_FRAME ();
7ab12479 2399 else
118ea242 2400 f = NULL;
177c0ea7 2401
118ea242 2402 if (f)
89bca612 2403 frame_arg = Qlambda;
0f8fe9a2 2404 else if (EQ (frames, make_number (0)))
f812f9c6 2405 frame_arg = frames;
89bca612
RS
2406 else if (EQ (frames, Qvisible))
2407 frame_arg = frames;
118ea242
GM
2408 else
2409 frame_arg = Qt;
7ab12479 2410
89bca612
RS
2411 /* frame_arg is Qlambda to stick to one frame,
2412 Qvisible to consider all visible frames,
2413 or Qt otherwise. */
2414
7ab12479 2415 /* Pick a window to start with. */
017b2bad 2416 if (WINDOWP (obj))
118ea242
GM
2417 window = obj;
2418 else if (f)
2419 window = FRAME_SELECTED_WINDOW (f);
7ab12479 2420 else
118ea242 2421 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
4b206065 2422
cd2904bd 2423 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
118ea242 2424 GCPRO1 (windows);
7ab12479 2425 best_window = Qnil;
118ea242 2426
e67a1dea 2427 for (; CONSP (windows); windows = XCDR (windows))
7ab12479 2428 {
118ea242 2429 struct window *w;
177c0ea7 2430
118ea242
GM
2431 window = XCAR (windows);
2432 w = XWINDOW (window);
177c0ea7 2433
118ea242
GM
2434 /* Note that we do not pay attention here to whether the frame
2435 is visible, since Fwindow_list skips non-visible frames if
2436 that is desired, under the control of frame_arg. */
2437 if (!MINI_WINDOW_P (w)
9397e56f
MR
2438 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2439 consider all windows. */
2440 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
7ab12479
JB
2441 || (mini && minibuf_level > 0))
2442 switch (type)
2443 {
2444 case GET_BUFFER_WINDOW:
118ea242 2445 if (EQ (w->buffer, obj)
9397e56f
MR
2446 /* Don't find any minibuffer window except the one that
2447 is currently in use. */
2448 && (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
118ea242 2449 {
9397e56f
MR
2450 if (EQ (window, selected_window))
2451 /* Preferably return the selected window. */
ca2d5566 2452 RETURN_UNGCPRO (window);
9397e56f
MR
2453 else if (EQ (XWINDOW (window)->frame, selected_frame)
2454 && !frame_best_window_flag)
2455 /* Prefer windows on the current frame (but don't
2456 choose another one if we have one already). */
118ea242 2457 {
9397e56f
MR
2458 best_window = window;
2459 frame_best_window_flag = 1;
7ab12479 2460 }
9397e56f
MR
2461 else if (NILP (best_window))
2462 best_window = window;
7ab12479
JB
2463 }
2464 break;
2465
9397e56f
MR
2466 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2467 /* We could simply check whether the buffer shown by window
2468 is live, and show another buffer in case it isn't. */
118ea242 2469 if (EQ (w->buffer, obj))
7ab12479 2470 {
9397e56f
MR
2471 /* Undedicate WINDOW. */
2472 w->dedicated = Qnil;
2473 /* Make WINDOW show the buffer returned by
2474 other_buffer_safely, don't run any hooks. */
2475 set_window_buffer
2476 (window, other_buffer_safely (w->buffer), 0, 0);
2477 /* If WINDOW is the selected window, make its buffer
2478 current. But do so only if the window shows the
2479 current buffer (Bug#6454). */
2480 if (EQ (window, selected_window)
2481 && XBUFFER (w->buffer) == current_buffer)
2482 Fset_buffer (w->buffer);
7ab12479
JB
2483 }
2484 break;
3f8ab7bd 2485
6b61353c
KH
2486 case REDISPLAY_BUFFER_WINDOWS:
2487 if (EQ (w->buffer, obj))
2488 {
2489 mark_window_display_accurate (window, 0);
c98ff5dd 2490 w->update_mode_line = 1;
6b61353c
KH
2491 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2492 ++update_mode_lines;
2493 best_window = window;
2494 }
2495 break;
2496
3f8ab7bd
RS
2497 /* Check for a window that has a killed buffer. */
2498 case CHECK_ALL_WINDOWS:
118ea242 2499 if (! NILP (w->buffer)
4b4deea2 2500 && NILP (BVAR (XBUFFER (w->buffer), name)))
3f8ab7bd 2501 abort ();
118ea242 2502 break;
6bbd7a29
GM
2503
2504 case WINDOW_LOOP_UNUSED:
2505 break;
7ab12479 2506 }
7ab12479 2507 }
7ab12479 2508
118ea242 2509 UNGCPRO;
7ab12479 2510 return best_window;
37962e60 2511}
605be8af 2512
3f8ab7bd
RS
2513/* Used for debugging. Abort if any window has a dead buffer. */
2514
e3b27b31 2515extern void check_all_windows (void) EXTERNALLY_VISIBLE;
233a4a2c 2516void
971de7fb 2517check_all_windows (void)
3f8ab7bd
RS
2518{
2519 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2520}
2521
a7ca3326 2522DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
fec89261 2523 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
496e208e
MR
2524BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2525the current buffer.
2526
2527The optional argument ALL-FRAMES specifies the frames to consider:
2528
2529- t means consider all windows on all existing frames.
2530
2531- `visible' means consider all windows on all visible frames.
2532
2533- 0 (the number zero) means consider all windows on all visible
2534 and iconified frames.
2535
2536- A frame means consider all windows on that frame only.
2537
2538Any other value of ALL-FRAMES means consider all windows on the
2539selected frame and no others. */)
2540 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
7ab12479 2541{
fec89261
MR
2542 Lisp_Object buffer;
2543
2544 if (NILP (buffer_or_name))
2545 buffer = Fcurrent_buffer ();
2546 else
2547 buffer = Fget_buffer (buffer_or_name);
2548
017b2bad 2549 if (BUFFERP (buffer))
496e208e 2550 return window_loop (GET_BUFFER_WINDOW, buffer, 1, all_frames);
7ab12479
JB
2551 else
2552 return Qnil;
2553}
2554
4b66faf3 2555static Lisp_Object
1a13852e
MR
2556resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore)
2557{
5386012d 2558 return call4 (Qwindow_resize_root_window, window, delta, horizontal, ignore);
1a13852e
MR
2559}
2560
2561
2562DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
2563 Sdelete_other_windows_internal, 0, 2, "",
2564 doc: /* Make WINDOW fill its frame.
2565Only the frame WINDOW is on is affected. WINDOW may be any window and
2566defaults to the selected one.
2567
be7f5545
MR
2568Optional argument ROOT, if non-nil, must specify an internal window such
2569that WINDOW is in its window subtree. If this is the case, replace ROOT
2570by WINDOW and leave alone any windows not part of ROOT's subtree.
1a13852e
MR
2571
2572When WINDOW is live try to reduce display jumps by keeping the text
2573previously visible in WINDOW in the same place on the frame. Doing this
2574depends on the value of (window-start WINDOW), so if calling this
2575function in a program gives strange scrolling, make sure the
2576window-start value is reasonable when this function is called. */)
2577 (Lisp_Object window, Lisp_Object root)
2578{
2579 struct window *w, *r, *s;
2580 struct frame *f;
46a4ce9e 2581 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
d311d28c 2582 ptrdiff_t startpos IF_LINT (= 0);
46a4ce9e 2583 int top IF_LINT (= 0), new_top, resize_failed;
1a13852e
MR
2584
2585 w = decode_any_window (window);
2586 XSETWINDOW (window, w);
2587 f = XFRAME (w->frame);
2588
2589 if (NILP (root))
2590 /* ROOT is the frame's root window. */
2591 {
2592 root = FRAME_ROOT_WINDOW (f);
2593 r = XWINDOW (root);
2594 }
2595 else
2596 /* ROOT must be an ancestor of WINDOW. */
2597 {
2598 r = decode_any_window (root);
2599 pwindow = XWINDOW (window)->parent;
2600 while (!NILP (pwindow))
2601 if (EQ (pwindow, root))
2602 break;
2603 else
2604 pwindow = XWINDOW (pwindow)->parent;
2605 if (!EQ (pwindow, root))
2606 error ("Specified root is not an ancestor of specified window");
2607 }
2608
2609 if (EQ (window, root))
2610 /* A noop. */
2611 return Qnil;
2612 /* I don't understand the "top > 0" part below. If we deal with a
2613 standalone minibuffer it would have been caught by the preceding
2614 test. */
2615 else if (MINI_WINDOW_P (w)) /* && top > 0) */
2616 error ("Can't expand minibuffer to full frame");
2617
2618 if (!NILP (w->buffer))
2619 {
2620 startpos = marker_position (w->start);
2621 top = WINDOW_TOP_EDGE_LINE (w)
2622 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2623 /* Make sure WINDOW is the frame's selected window. */
2624 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
2625 {
2626 if (EQ (selected_frame, w->frame))
2627 Fselect_window (window, Qnil);
2628 else
2629 FRAME_SELECTED_WINDOW (f) = window;
2630 }
2631 }
2632 else
2633 {
be7f5545
MR
2634 /* See if the frame's selected window is a part of the window
2635 subtree rooted at WINDOW, by finding all the selected window's
2636 parents and comparing each one with WINDOW. If it isn't we
2637 need a new selected window for this frame. */
1a13852e
MR
2638 swindow = FRAME_SELECTED_WINDOW (f);
2639 while (1)
2640 {
2641 pwindow = swindow;
2642 while (!NILP (pwindow) && !EQ (window, pwindow))
2643 pwindow = XWINDOW (pwindow)->parent;
2644
2645 if (EQ (window, pwindow))
2646 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
2647 as the new selected window. */
2648 break;
2649 else
2650 /* Else try the previous window of SWINDOW. */
2651 swindow = Fprevious_window (swindow, Qlambda, Qnil);
2652 }
2653
2654 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
2655 {
2656 if (EQ (selected_frame, w->frame))
2657 Fselect_window (swindow, Qnil);
2658 else
2659 FRAME_SELECTED_WINDOW (f) = swindow;
2660 }
2661 }
2662
2663 BLOCK_INPUT;
4c5501e9
EZ
2664 if (!FRAME_INITIAL_P (f))
2665 {
2666 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2667
2668 /* We are going to free the glyph matrices of WINDOW, and with
2669 that we might lose any information about glyph rows that have
2670 some of their glyphs highlighted in mouse face. (These rows
2671 are marked with a non-zero mouse_face_p flag.) If WINDOW
2672 indeed has some glyphs highlighted in mouse face, signal to
2673 frame's up-to-date hook that mouse highlight was overwritten,
2674 so that it will arrange for redisplaying the highlight. */
2675 if (EQ (hlinfo->mouse_face_window, window))
2676 {
2677 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
2678 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
2679 hlinfo->mouse_face_window = Qnil;
2680 }
a6b1c7cc 2681 }
1a13852e
MR
2682 free_window_matrices (r);
2683
2684 windows_or_buffers_changed++;
2685 Vwindow_list = Qnil;
2686 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
46a4ce9e 2687 resize_failed = 0;
1a13852e
MR
2688
2689 if (NILP (w->buffer))
2690 {
be7f5545 2691 /* Resize child windows vertically. */
1a13852e
MR
2692 XSETINT (delta, XINT (r->total_lines) - XINT (w->total_lines));
2693 w->top_line = r->top_line;
2694 resize_root_window (window, delta, Qnil, Qnil);
d615d6d2
MR
2695 if (window_resize_check (w, 0))
2696 window_resize_apply (w, 0);
1a13852e
MR
2697 else
2698 {
2699 resize_root_window (window, delta, Qnil, Qt);
d615d6d2
MR
2700 if (window_resize_check (w, 0))
2701 window_resize_apply (w, 0);
1a13852e
MR
2702 else
2703 resize_failed = 1;
2704 }
2705
be7f5545 2706 /* Resize child windows horizontally. */
1a13852e
MR
2707 if (!resize_failed)
2708 {
2709 w->left_col = r->left_col;
2710 XSETINT (delta, XINT (r->total_cols) - XINT (w->total_cols));
2711 w->left_col = r->left_col;
2712 resize_root_window (window, delta, Qt, Qnil);
d615d6d2
MR
2713 if (window_resize_check (w, 1))
2714 window_resize_apply (w, 1);
1a13852e
MR
2715 else
2716 {
2717 resize_root_window (window, delta, Qt, Qt);
d615d6d2
MR
2718 if (window_resize_check (w, 1))
2719 window_resize_apply (w, 1);
1a13852e
MR
2720 else
2721 resize_failed = 1;
2722 }
2723 }
2724
2725 if (resize_failed)
2726 /* Play safe, if we still can ... */
2727 {
2728 window = swindow;
2729 w = XWINDOW (window);
2730 }
2731 }
2732
2733 /* Cleanly unlink WINDOW from window-tree. */
2734 if (!NILP (w->prev))
2735 /* Get SIBLING above (on the left of) WINDOW. */
2736 {
2737 sibling = w->prev;
2738 s = XWINDOW (sibling);
2739 s->next = w->next;
2740 if (!NILP (s->next))
2741 XWINDOW (s->next)->prev = sibling;
2742 }
2743 else
2744 /* Get SIBLING below (on the right of) WINDOW. */
2745 {
2746 sibling = w->next;
2747 s = XWINDOW (sibling);
2748 s->prev = Qnil;
2749 if (!NILP (XWINDOW (w->parent)->vchild))
2750 XWINDOW (w->parent)->vchild = sibling;
2751 else
2752 XWINDOW (w->parent)->hchild = sibling;
2753 }
2754
be7f5545 2755 /* Delete ROOT and all child windows of ROOT. */
1a13852e
MR
2756 if (!NILP (r->vchild))
2757 {
be7f5545 2758 delete_all_child_windows (r->vchild);
1a13852e
MR
2759 r->vchild = Qnil;
2760 }
2761 else if (!NILP (r->hchild))
2762 {
be7f5545 2763 delete_all_child_windows (r->hchild);
1a13852e
MR
2764 r->hchild = Qnil;
2765 }
2766
2767 replace_window (root, window, 1);
2768
1a13852e
MR
2769 /* This must become SWINDOW anyway ....... */
2770 if (!NILP (w->buffer) && !resize_failed)
2771 {
2772 /* Try to minimize scrolling, by setting the window start to the
2773 point will cause the text at the old window start to be at the
2774 same place on the frame. But don't try to do this if the
2775 window start is outside the visible portion (as might happen
2776 when the display is not current, due to typeahead). */
2777 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2778 if (new_top != top
2779 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2780 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2781 {
2782 struct position pos;
2783 struct buffer *obuf = current_buffer;
2784
2785 Fset_buffer (w->buffer);
2786 /* This computation used to temporarily move point, but that
2787 can have unwanted side effects due to text properties. */
2788 pos = *vmotion (startpos, -top, w);
2789
2790 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2791 w->window_end_valid = Qnil;
c98ff5dd
DA
2792 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
2793 || FETCH_BYTE (pos.bytepos - 1) == '\n');
1a13852e
MR
2794 /* We need to do this, so that the window-scroll-functions
2795 get called. */
c98ff5dd 2796 w->optional_new_start = 1;
1a13852e
MR
2797
2798 set_buffer_internal (obuf);
2799 }
2800 }
2801
2802 adjust_glyphs (f);
2803 UNBLOCK_INPUT;
2804
2805 run_window_configuration_change_hook (f);
2806
2807 return Qnil;
2808}
2809
2810
9397e56f
MR
2811void
2812replace_buffer_in_windows (Lisp_Object buffer)
7ab12479 2813{
9397e56f 2814 call1 (Qreplace_buffer_in_windows, buffer);
7ab12479
JB
2815}
2816
ff58478b 2817
9397e56f
MR
2818/* Safely replace BUFFER with some other buffer in all windows of all
2819 frames, even those on other keyboards. */
ff58478b
RS
2820
2821void
9397e56f 2822replace_buffer_in_windows_safely (Lisp_Object buffer)
ff58478b
RS
2823{
2824 Lisp_Object tail, frame;
2825
9397e56f
MR
2826 /* A single call to window_loop won't do the job because it only
2827 considers frames on the current keyboard. So loop manually over
2828 frames, and handle each one. */
ff58478b 2829 FOR_EACH_FRAME (tail, frame)
9397e56f 2830 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
ff58478b 2831}
7ab12479 2832\f
a481b3ea
JB
2833/* If *ROWS or *COLS are too small a size for FRAME, set them to the
2834 minimum allowable size. */
5500c422 2835
605be8af 2836void
971de7fb 2837check_frame_size (FRAME_PTR frame, int *rows, int *cols)
a481b3ea 2838{
628df3bf 2839 /* For height, we have to see:
54b8bcb5
RS
2840 how many windows the frame has at minimum (one or two),
2841 and whether it has a menu bar or other special stuff at the top. */
2842 int min_height
2843 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2844 ? MIN_SAFE_WINDOW_HEIGHT
2845 : 2 * MIN_SAFE_WINDOW_HEIGHT);
177c0ea7 2846
5500c422
GM
2847 if (FRAME_TOP_MARGIN (frame) > 0)
2848 min_height += FRAME_TOP_MARGIN (frame);
a481b3ea
JB
2849
2850 if (*rows < min_height)
2851 *rows = min_height;
2852 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2853 *cols = MIN_SAFE_WINDOW_WIDTH;
2854}
2855
79fd290e 2856/* Adjust the margins of window W if text area is too small.
949cf20f
KS
2857 Return 1 if window width is ok after adjustment; 0 if window
2858 is still too narrow. */
2859
2860static int
971de7fb 2861adjust_window_margins (struct window *w)
949cf20f
KS
2862{
2863 int box_cols = (WINDOW_TOTAL_COLS (w)
2864 - WINDOW_FRINGE_COLS (w)
2865 - WINDOW_SCROLL_BAR_COLS (w));
2866 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2867 + WINDOW_RIGHT_MARGIN_COLS (w));
2868
2869 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2870 return 1;
2871
2872 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2873 return 0;
2874
2875 /* Window's text area is too narrow, but reducing the window
2876 margins will fix that. */
2877 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2878 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2879 {
2880 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2881 w->left_margin_cols = w->right_margin_cols
2882 = make_number (margin_cols/2);
2883 else
2884 w->right_margin_cols = make_number (margin_cols);
2885 }
2886 else
2887 w->left_margin_cols = make_number (margin_cols);
2888 return 1;
2889}
562dd5e9 2890\f
9397e56f
MR
2891/* The following three routines are needed for running a window's
2892 configuration change hook. */
562dd5e9
MR
2893static void
2894run_funs (Lisp_Object funs)
2895{
2896 for (; CONSP (funs); funs = XCDR (funs))
2897 if (!EQ (XCAR (funs), Qt))
2898 call0 (XCAR (funs));
2899}
6b61353c 2900
9397e56f
MR
2901static Lisp_Object
2902select_window_norecord (Lisp_Object window)
2903{
2904 return WINDOW_LIVE_P (window)
2905 ? Fselect_window (window, Qt) : selected_window;
2906}
2907
2908static Lisp_Object
2909select_frame_norecord (Lisp_Object frame)
2910{
2911 return FRAME_LIVE_P (XFRAME (frame))
2912 ? Fselect_frame (frame, Qt) : selected_frame;
2913}
6b61353c 2914
562dd5e9
MR
2915void
2916run_window_configuration_change_hook (struct frame *f)
2917{
d311d28c 2918 ptrdiff_t count = SPECPDL_INDEX ();
562dd5e9
MR
2919 Lisp_Object frame, global_wcch
2920 = Fdefault_value (Qwindow_configuration_change_hook);
2921 XSETFRAME (frame, f);
6b61353c 2922
d1f55f16 2923 if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
562dd5e9 2924 return;
6b61353c 2925
562dd5e9
MR
2926 /* Use the right buffer. Matters when running the local hooks. */
2927 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
6b61353c 2928 {
562dd5e9
MR
2929 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2930 Fset_buffer (Fwindow_buffer (Qnil));
2931 }
6a44ffb3 2932
1a13852e
MR
2933 if (SELECTED_FRAME () != f)
2934 {
2935 record_unwind_protect (select_frame_norecord, Fselected_frame ());
2936 select_frame_norecord (frame);
2937 }
2938
6a44ffb3
SM
2939 /* Look for buffer-local values. */
2940 {
2941 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
2942 for (; CONSP (windows); windows = XCDR (windows))
2943 {
2944 Lisp_Object window = XCAR (windows);
2945 Lisp_Object buffer = Fwindow_buffer (window);
2946 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
2947 buffer)))
2948 {
d311d28c 2949 ptrdiff_t inner_count = SPECPDL_INDEX ();
6a44ffb3
SM
2950 record_unwind_protect (select_window_norecord, Fselected_window ());
2951 select_window_norecord (window);
2952 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
2953 buffer));
46a4ce9e 2954 unbind_to (inner_count, Qnil);
fec89261 2955 }
6a44ffb3
SM
2956 }
2957 }
047aaeb9 2958
6a44ffb3
SM
2959 run_funs (global_wcch);
2960 unbind_to (count, Qnil);
ef264c42
SM
2961}
2962
1a13852e
MR
2963DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
2964 Srun_window_configuration_change_hook, 1, 1, 0,
2965 doc: /* Run `window-configuration-change-hook' for FRAME. */)
2966 (Lisp_Object frame)
2967{
2968 CHECK_LIVE_FRAME (frame);
2969 run_window_configuration_change_hook (XFRAME (frame));
2970 return Qnil;
2971}
2972
5500c422
GM
2973/* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2974 means it's allowed to run hooks. See make_frame for a case where
949cf20f
KS
2975 it's not allowed. KEEP_MARGINS_P non-zero means that the current
2976 margins, fringes, and scroll-bar settings of the window are not
2977 reset from the buffer's local settings. */
7ab12479 2978
5500c422 2979void
971de7fb 2980set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int keep_margins_p)
5500c422
GM
2981{
2982 struct window *w = XWINDOW (window);
2983 struct buffer *b = XBUFFER (buffer);
d311d28c 2984 ptrdiff_t count = SPECPDL_INDEX ();
c3b232e4 2985 int samebuf = EQ (buffer, w->buffer);
7ab12479
JB
2986
2987 w->buffer = buffer;
86e48436
RS
2988
2989 if (EQ (window, selected_window))
4b4deea2 2990 BVAR (b, last_selected_window) = window;
beb4e312 2991
c49a0495
KS
2992 /* Let redisplay errors through. */
2993 b->display_error_modiff = 0;
2994
beb4e312 2995 /* Update time stamps of buffer display. */
4b4deea2
TT
2996 if (INTEGERP (BVAR (b, display_count)))
2997 XSETINT (BVAR (b, display_count), XINT (BVAR (b, display_count)) + 1);
2998 BVAR (b, display_time) = Fcurrent_time ();
86e48436 2999
d834a2e9 3000 XSETFASTINT (w->window_end_pos, 0);
5500c422 3001 XSETFASTINT (w->window_end_vpos, 0);
72af86bd 3002 memset (&w->last_cursor, 0, sizeof w->last_cursor);
5a41ab94 3003 w->window_end_valid = Qnil;
c3b232e4 3004 if (!(keep_margins_p && samebuf))
23fe745a 3005 { /* If we're not actually changing the buffer, don't reset hscroll and
c3b232e4
SM
3006 vscroll. This case happens for example when called from
3007 change_frame_size_1, where we use a dummy call to
3008 Fset_window_buffer on the frame's selected window (and no other)
3009 just in order to run window-configuration-change-hook.
3010 Resetting hscroll and vscroll here is problematic for things like
3011 image-mode and doc-view-mode since it resets the image's position
3012 whenever we resize the frame. */
80b00b08 3013 w->hscroll = w->min_hscroll = 0;
c3b232e4
SM
3014 w->vscroll = 0;
3015 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3016 set_marker_restricted (w->start,
3017 make_number (b->last_window_start),
3018 buffer);
c98ff5dd
DA
3019 w->start_at_line_beg = 0;
3020 w->force_start = 0;
80b00b08
DA
3021 w->last_modified = 0;
3022 w->last_overlay_modified = 0;
c3b232e4
SM
3023 }
3024 /* Maybe we could move this into the `if' but it's not obviously safe and
3025 I doubt it's worth the trouble. */
7ab12479 3026 windows_or_buffers_changed++;
5b03d3c0 3027
da39107c 3028 /* We must select BUFFER for running the window-scroll-functions. */
5b03d3c0
RS
3029 /* We can't check ! NILP (Vwindow_scroll_functions) here
3030 because that might itself be a local variable. */
da39107c 3031 if (window_initialized)
5b03d3c0 3032 {
da39107c 3033 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
5b03d3c0
RS
3034 Fset_buffer (buffer);
3035 }
3036
a1562258
SM
3037 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3038
949cf20f
KS
3039 if (!keep_margins_p)
3040 {
3041 /* Set left and right marginal area width etc. from buffer. */
3042
79fd290e 3043 /* This may call adjust_window_margins three times, so
949cf20f 3044 temporarily disable window margins. */
6b61353c
KH
3045 Lisp_Object save_left = w->left_margin_cols;
3046 Lisp_Object save_right = w->right_margin_cols;
3047
949cf20f
KS
3048 w->left_margin_cols = w->right_margin_cols = Qnil;
3049
3050 Fset_window_fringes (window,
4b4deea2
TT
3051 BVAR (b, left_fringe_width), BVAR (b, right_fringe_width),
3052 BVAR (b, fringes_outside_margins));
949cf20f
KS
3053
3054 Fset_window_scroll_bars (window,
4b4deea2
TT
3055 BVAR (b, scroll_bar_width),
3056 BVAR (b, vertical_scroll_bar_type), Qnil);
949cf20f 3057
6b61353c
KH
3058 w->left_margin_cols = save_left;
3059 w->right_margin_cols = save_right;
3060
949cf20f 3061 Fset_window_margins (window,
4b4deea2 3062 BVAR (b, left_margin_cols), BVAR (b, right_margin_cols));
949cf20f 3063 }
7ab12479 3064
5500c422
GM
3065 if (run_hooks_p)
3066 {
3067 if (! NILP (Vwindow_scroll_functions))
3068 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3069 Fmarker_position (w->start));
ef264c42 3070 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
5500c422 3071 }
543f5fb1 3072
5b03d3c0 3073 unbind_to (count, Qnil);
5500c422 3074}
5b03d3c0 3075
a7ca3326 3076DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
d653c8cc 3077 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
9397e56f
MR
3078WINDOW has to be a live window and defaults to the selected one.
3079BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3080
3081Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3082display margins, fringe widths, and scroll bar settings are preserved;
3083the default is to reset these from the local settings for BUFFER-OR-NAME
3084or the frame defaults. Return nil.
d653c8cc 3085
7bfac547
MR
3086This function throws an error when WINDOW is strongly dedicated to its
3087buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3088already display BUFFER-OR-NAME.
6cb4a892 3089
8fef9de1
MR
3090This function runs `window-scroll-functions' before running
3091`window-configuration-change-hook'. */)
5842a27b 3092 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
5500c422 3093{
d653c8cc 3094 register Lisp_Object tem, buffer;
5500c422 3095 register struct window *w = decode_window (window);
5500c422 3096
bed0c171 3097 XSETWINDOW (window, w);
d653c8cc 3098 buffer = Fget_buffer (buffer_or_name);
b7826503 3099 CHECK_BUFFER (buffer);
4b4deea2 3100 if (NILP (BVAR (XBUFFER (buffer), name)))
5500c422
GM
3101 error ("Attempt to display deleted buffer");
3102
3103 tem = w->buffer;
aac0c6e3
MR
3104 if (NILP (tem))
3105 error ("Window is deleted");
3106 else if (!EQ (tem, Qt))
d653c8cc 3107 /* w->buffer is t when the window is first being set up. */
5500c422 3108 {
9397e56f
MR
3109 if (!EQ (tem, buffer))
3110 {
3111 if (EQ (w->dedicated, Qt))
3112 /* WINDOW is strongly dedicated to its buffer, signal an
3113 error. */
3114 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3115 else
3116 /* WINDOW is weakly dedicated to its buffer, reset
e4769531 3117 dedication. */
9397e56f
MR
3118 w->dedicated = Qnil;
3119
3120 call1 (Qrecord_window_buffer, window);
3121 }
5500c422
GM
3122
3123 unshow_buffer (w);
3124 }
3125
949cf20f 3126 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
7ab12479 3127
9397e56f 3128 return Qnil;
c6932ecd 3129}
b7354ddf 3130\f
7e5cf297 3131static Lisp_Object
971de7fb 3132display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
d07f802a 3133{
87478b52 3134 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
d07f802a
RS
3135}
3136
6b61353c
KH
3137DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3138 0, 1, 0,
5a1048a5 3139 doc: /* Force all windows to be updated on next redisplay.
6b61353c 3140If optional arg OBJECT is a window, force redisplay of that window only.
0cc1039f 3141If OBJECT is a buffer or buffer name, force redisplay of all windows
6b61353c 3142displaying that buffer. */)
5842a27b 3143 (Lisp_Object object)
6b61353c
KH
3144{
3145 if (NILP (object))
3146 {
3147 windows_or_buffers_changed++;
3148 update_mode_lines++;
3149 return Qt;
3150 }
3151
3152 if (WINDOWP (object))
3153 {
3154 struct window *w = XWINDOW (object);
3155 mark_window_display_accurate (object, 0);
c98ff5dd 3156 w->update_mode_line = 1;
6b61353c
KH
3157 if (BUFFERP (w->buffer))
3158 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3159 ++update_mode_lines;
3160 return Qt;
3161 }
0cc1039f 3162
6b61353c
KH
3163 if (STRINGP (object))
3164 object = Fget_buffer (object);
4b4deea2 3165 if (BUFFERP (object) && !NILP (BVAR (XBUFFER (object), name)))
6b61353c
KH
3166 {
3167 /* Walk all windows looking for buffer, and force update
3168 of each of those windows. */
3169
3170 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3171 return NILP (object) ? Qnil : Qt;
3172 }
3173
3174 /* If nothing suitable was found, just return.
3175 We could signal an error, but this feature will typically be used
3176 asynchronously in timers or process sentinels, so we don't. */
3177 return Qnil;
3178}
3179
3180
7ab12479 3181void
971de7fb 3182temp_output_buffer_show (register Lisp_Object buf)
7ab12479
JB
3183{
3184 register struct buffer *old = current_buffer;
3185 register Lisp_Object window;
3186 register struct window *w;
3187
4b4deea2 3188 BVAR (XBUFFER (buf), directory) = BVAR (current_buffer, directory);
bccd3dd1 3189
7ab12479 3190 Fset_buffer (buf);
c6367666 3191 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
7ab12479
JB
3192 BEGV = BEG;
3193 ZV = Z;
3194 SET_PT (BEG);
7ab12479
JB
3195 set_buffer_internal (old);
3196
e67a1dea 3197 if (!NILP (Vtemp_buffer_show_function))
7ab12479
JB
3198 call1 (Vtemp_buffer_show_function, buf);
3199 else
3200 {
4ee88440 3201 window = display_buffer (buf, Qnil, Qnil);
7ab12479 3202
1ae1a37d 3203 if (!EQ (XWINDOW (window)->frame, selected_frame))
44fa5b1e 3204 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
7ab12479
JB
3205 Vminibuf_scroll_window = window;
3206 w = XWINDOW (window);
80b00b08
DA
3207 w->hscroll = 0;
3208 w->min_hscroll = 0;
2d0834cc
SM
3209 set_marker_restricted_both (w->start, buf, BEG, BEG);
3210 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
a58ec57d 3211
beb4e312 3212 /* Run temp-buffer-show-hook, with the chosen window selected
a5731348 3213 and its buffer current. */
dee091a3 3214 {
d311d28c 3215 ptrdiff_t count = SPECPDL_INDEX ();
dee091a3
JD
3216 Lisp_Object prev_window, prev_buffer;
3217 prev_window = selected_window;
3218 XSETBUFFER (prev_buffer, old);
3219
3220 /* Select the window that was chosen, for running the hook.
3221 Note: Both Fselect_window and select_window_norecord may
3222 set-buffer to the buffer displayed in the window,
3223 so we need to save the current buffer. --stef */
3224 record_unwind_protect (Fset_buffer, prev_buffer);
3225 record_unwind_protect (select_window_norecord, prev_window);
3226 Fselect_window (window, Qt);
3227 Fset_buffer (w->buffer);
3228 Frun_hooks (1, &Qtemp_buffer_show_hook);
3229 unbind_to (count, Qnil);
3230 }
2cccc823 3231 }
7ab12479 3232}
3e21b6a7
SM
3233
3234DEFUN ("internal-temp-output-buffer-show",
3235 Ftemp_output_buffer_show, Stemp_output_buffer_show,
3236 1, 1, 0,
87e68db4 3237 doc: /* Internal function for `with-output-to-temp-buffer'. */)
3e21b6a7
SM
3238 (Lisp_Object buf)
3239{
3240 temp_output_buffer_show (buf);
3241 return Qnil;
3242}
7ab12479 3243\f
1a13852e
MR
3244/* Make new window, have it replace WINDOW in window-tree, and make
3245 WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
3246 horizontal child). */
3247static void
3248make_parent_window (Lisp_Object window, int horflag)
3249{
3250 Lisp_Object parent;
3251 register struct window *o, *p;
1a13852e
MR
3252
3253 o = XWINDOW (window);
3254 p = allocate_window ();
aa754e6a 3255 memcpy ((char *) p + sizeof (struct vectorlike_header),
62efea5e
DA
3256 (char *) o + sizeof (struct vectorlike_header),
3257 sizeof (Lisp_Object) * VECSIZE (struct window));
1a13852e
MR
3258 XSETWINDOW (parent, p);
3259
45942c7d 3260 p->sequence_number = ++sequence_number;
1a13852e
MR
3261
3262 replace_window (window, parent, 1);
3263
3264 o->next = Qnil;
3265 o->prev = Qnil;
3266 o->parent = parent;
3267
3268 p->hchild = horflag ? window : Qnil;
3269 p->vchild = horflag ? Qnil : window;
3270 p->start = Qnil;
3271 p->pointm = Qnil;
3272 p->buffer = Qnil;
b6f67890 3273 p->combination_limit = Qnil;
1a13852e
MR
3274 p->window_parameters = Qnil;
3275}
3276
496e208e
MR
3277/* Make new window from scratch. */
3278Lisp_Object
3279make_window (void)
3280{
3281 Lisp_Object window;
3282 register struct window *w;
3283
3284 w = allocate_window ();
62efea5e
DA
3285 /* Initialize Lisp data. Note that allocate_window initializes all
3286 Lisp data to nil, so do it only for slots which should not be nil. */
496e208e
MR
3287 XSETFASTINT (w->left_col, 0);
3288 XSETFASTINT (w->top_line, 0);
3289 XSETFASTINT (w->total_lines, 0);
3290 XSETFASTINT (w->total_cols, 0);
3291 w->normal_lines = make_float (1.0);
3292 w->normal_cols = make_float (1.0);
3293 XSETFASTINT (w->new_total, 0);
3294 XSETFASTINT (w->new_normal, 0);
496e208e
MR
3295 w->start = Fmake_marker ();
3296 w->pointm = Fmake_marker ();
496e208e 3297 w->vertical_scroll_bar_type = Qt;
496e208e
MR
3298 XSETFASTINT (w->window_end_pos, 0);
3299 XSETFASTINT (w->window_end_vpos, 0);
62efea5e
DA
3300
3301 /* Initialize non-Lisp data. Note that allocate_window zeroes out all
3302 non-Lisp data, so do it only for slots which should not be zero. */
496e208e 3303 w->nrows_scale_factor = w->ncols_scale_factor = 1;
496e208e
MR
3304 w->phys_cursor_type = -1;
3305 w->phys_cursor_width = -1;
45942c7d 3306 w->sequence_number = ++sequence_number;
62efea5e 3307
496e208e
MR
3308 /* Reset window_list. */
3309 Vwindow_list = Qnil;
3310 /* Return window. */
3311 XSETWINDOW (window, w);
3312 return window;
3313}
3314\f
3315DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3316 doc: /* Set new total size of WINDOW to SIZE.
3317Return SIZE.
3318
3319Optional argument ADD non-nil means add SIZE to the new total size of
3320WINDOW and return the sum.
3321
be7f5545 3322Note: This function does not operate on any child windows of WINDOW. */)
496e208e
MR
3323 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3324{
3325 struct window *w = decode_any_window (window);
3326
3327 CHECK_NUMBER (size);
3328 if (NILP (add))
3329 XSETINT (w->new_total, XINT (size));
3330 else
3331 XSETINT (w->new_total, XINT (w->new_total) + XINT (size));
3332
3333 return w->new_total;
3334}
3335
3336DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3337 doc: /* Set new normal size of WINDOW to SIZE.
3338Return SIZE.
3339
be7f5545 3340Note: This function does not operate on any child windows of WINDOW. */)
496e208e
MR
3341 (Lisp_Object window, Lisp_Object size)
3342{
3343 struct window *w = decode_any_window (window);
3344
3345 w->new_normal = size;
3346 return w->new_normal;
7ab12479
JB
3347}
3348
1a13852e
MR
3349/* Return 1 if setting w->total_lines (w->total_cols if HORFLAG is
3350 non-zero) to w->new_total would result in correct heights (widths)
be7f5545 3351 for window W and recursively all child windows of W.
1a13852e
MR
3352
3353 Note: This function does not check any of `window-fixed-size-p',
3354 `window-min-height' or `window-min-width'. It does check that window
3355 sizes do not drop below one line (two columns). */
4b66faf3 3356static int
d615d6d2 3357window_resize_check (struct window *w, int horflag)
1a13852e
MR
3358{
3359 struct window *c;
3360
3361 if (!NILP (w->vchild))
3362 /* W is a vertical combination. */
3363 {
3364 c = XWINDOW (w->vchild);
3365 if (horflag)
be7f5545 3366 /* All child windows of W must have the same width as W. */
1a13852e
MR
3367 {
3368 while (c)
3369 {
3370 if ((XINT (c->new_total) != XINT (w->new_total))
d615d6d2 3371 || !window_resize_check (c, horflag))
1a13852e
MR
3372 return 0;
3373 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3374 }
3375 return 1;
3376 }
3377 else
be7f5545
MR
3378 /* The sum of the heights of the child windows of W must equal
3379 W's height. */
1a13852e
MR
3380 {
3381 int sum_of_sizes = 0;
3382 while (c)
3383 {
d615d6d2 3384 if (!window_resize_check (c, horflag))
1a13852e
MR
3385 return 0;
3386 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3387 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3388 }
3389 return (sum_of_sizes == XINT (w->new_total));
3390 }
3391 }
3392 else if (!NILP (w->hchild))
3393 /* W is a horizontal combination. */
3394 {
3395 c = XWINDOW (w->hchild);
3396 if (horflag)
be7f5545 3397 /* The sum of the widths of the child windows of W must equal W's
1a13852e
MR
3398 width. */
3399 {
3400 int sum_of_sizes = 0;
3401 while (c)
3402 {
d615d6d2 3403 if (!window_resize_check (c, horflag))
1a13852e
MR
3404 return 0;
3405 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3406 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3407 }
3408 return (sum_of_sizes == XINT (w->new_total));
3409 }
3410 else
be7f5545 3411 /* All child windows of W must have the same height as W. */
1a13852e
MR
3412 {
3413 while (c)
3414 {
3415 if ((XINT (c->new_total) != XINT (w->new_total))
d615d6d2 3416 || !window_resize_check (c, horflag))
1a13852e
MR
3417 return 0;
3418 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3419 }
3420 return 1;
3421 }
3422 }
3423 else
3424 /* A leaf window. Make sure it's not too small. The following
3425 hardcodes the values of `window-safe-min-width' (2) and
3426 `window-safe-min-height' (1) which are defined in window.el. */
3427 return XINT (w->new_total) >= (horflag ? 2 : 1);
3428}
3429
3430/* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
be7f5545
MR
3431 w->new_total for window W and recursively all child windows of W.
3432 Also calculate and assign the new vertical (horizontal) start
3433 positions of each of these windows.
1a13852e
MR
3434
3435 This function does not perform any error checks. Make sure you have
d615d6d2 3436 run window_resize_check on W before applying this function. */
440a42e3 3437static void
d615d6d2 3438window_resize_apply (struct window *w, int horflag)
1a13852e 3439{
46a4ce9e 3440 struct window *c;
1a13852e
MR
3441 int pos;
3442
3443 /* Note: Assigning new_normal requires that the new total size of the
3444 parent window has been set *before*. */
3445 if (horflag)
3446 {
3447 w->total_cols = w->new_total;
3448 if (NUMBERP (w->new_normal))
3449 w->normal_cols = w->new_normal;
3450
3451 pos = XINT (w->left_col);
3452 }
3453 else
3454 {
3455 w->total_lines = w->new_total;
3456 if (NUMBERP (w->new_normal))
3457 w->normal_lines = w->new_normal;
3458
3459 pos = XINT (w->top_line);
3460 }
3461
3462 if (!NILP (w->vchild))
3463 /* W is a vertical combination. */
3464 {
3465 c = XWINDOW (w->vchild);
3466 while (c)
3467 {
3468 if (horflag)
3469 XSETFASTINT (c->left_col, pos);
3470 else
3471 XSETFASTINT (c->top_line, pos);
d615d6d2 3472 window_resize_apply (c, horflag);
1a13852e
MR
3473 if (!horflag)
3474 pos = pos + XINT (c->total_lines);
3475 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3476 }
3477 }
3478 else if (!NILP (w->hchild))
3479 /* W is a horizontal combination. */
3480 {
3481 c = XWINDOW (w->hchild);
3482 while (c)
3483 {
3484 if (horflag)
3485 XSETFASTINT (c->left_col, pos);
3486 else
3487 XSETFASTINT (c->top_line, pos);
d615d6d2 3488 window_resize_apply (c, horflag);
1a13852e
MR
3489 if (horflag)
3490 pos = pos + XINT (c->total_cols);
3491 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3492 }
3493 }
3494
3495 /* Clear out some redisplay caches. */
80b00b08
DA
3496 w->last_modified = 0;
3497 w->last_overlay_modified = 0;
1a13852e
MR
3498}
3499
3500
d615d6d2 3501DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 1, 2, 0,
1a13852e
MR
3502 doc: /* Apply requested size values for window-tree of FRAME.
3503Optional argument HORIZONTAL omitted or nil means apply requested height
3504values. HORIZONTAL non-nil means apply requested width values.
3505
3506This function checks whether the requested values sum up to a valid
be7f5545
MR
3507window layout, recursively assigns the new sizes of all child windows
3508and calculates and assigns the new start positions of these windows.
1a13852e
MR
3509
3510Note: This function does not check any of `window-fixed-size-p',
3511`window-min-height' or `window-min-width'. All these checks have to
3512be applied on the Elisp level. */)
3513 (Lisp_Object frame, Lisp_Object horizontal)
3514{
3515 struct frame *f;
3516 struct window *r;
3517 int horflag = !NILP (horizontal);
3518
3519 if (NILP (frame))
3520 frame = selected_frame;
3521 CHECK_LIVE_FRAME (frame);
3522
3523 f = XFRAME (frame);
3524 r = XWINDOW (FRAME_ROOT_WINDOW (f));
3525
d615d6d2 3526 if (!window_resize_check (r, horflag)
1a13852e
MR
3527 || ! EQ (r->new_total, (horflag ? r->total_cols : r->total_lines)))
3528 return Qnil;
3529
3530 BLOCK_INPUT;
d615d6d2 3531 window_resize_apply (r, horflag);
1a13852e
MR
3532
3533 windows_or_buffers_changed++;
3534 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3535
3536 adjust_glyphs (f);
3537 UNBLOCK_INPUT;
3538
3539 run_window_configuration_change_hook (f);
3540
3541 return Qt;
3542}
3543
3544
3545/* Resize frame F's windows when number of lines of F is set to SIZE.
3546 HORFLAG 1 means resize windows when number of columns of F is set to
3547 SIZE.
3548
3549 This function can delete all windows but the selected one in order to
3550 satisfy the request. The result will be meaningful if and only if
3551 F's windows have meaningful sizes when you call this. */
3552void
3553resize_frame_windows (struct frame *f, int size, int horflag)
3554{
3555 Lisp_Object root = f->root_window;
3556 struct window *r = XWINDOW (root);
3557 Lisp_Object mini = f->minibuffer_window;
3558 struct window *m;
3559 /* new_size is the new size of the frame's root window. */
3560 int new_size = (horflag
3561 ? size
3562 : (size
3563 - FRAME_TOP_MARGIN (f)
3564 - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3565 ? 1 : 0)));
3566
3567 XSETFASTINT (r->top_line, FRAME_TOP_MARGIN (f));
3568 if (NILP (r->vchild) && NILP (r->hchild))
3569 /* For a leaf root window just set the size. */
3570 if (horflag)
3571 XSETFASTINT (r->total_cols, new_size);
3572 else
3573 XSETFASTINT (r->total_lines, new_size);
3574 else
3575 {
3576 /* old_size is the old size of the frame's root window. */
3577 int old_size = XFASTINT (horflag ? r->total_cols : r->total_lines);
3578 Lisp_Object delta;
3579
3580 XSETINT (delta, new_size - old_size);
3581 /* Try a "normal" resize first. */
3582 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil);
d615d6d2
MR
3583 if (window_resize_check (r, horflag) && new_size == XINT (r->new_total))
3584 window_resize_apply (r, horflag);
1a13852e
MR
3585 else
3586 {
3587 /* Try with "reasonable" minimum sizes next. */
3588 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt);
d615d6d2 3589 if (window_resize_check (r, horflag)
1a13852e 3590 && new_size == XINT (r->new_total))
d615d6d2 3591 window_resize_apply (r, horflag);
1a13852e
MR
3592 else
3593 {
3594 /* Finally, try with "safe" minimum sizes. */
3595 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe);
d615d6d2 3596 if (window_resize_check (r, horflag)
1a13852e 3597 && new_size == XINT (r->new_total))
d615d6d2 3598 window_resize_apply (r, horflag);
1a13852e
MR
3599 else
3600 {
3601 /* We lost. Delete all windows but the frame's
3602 selected one. */
3603 root = f->selected_window;
3604 Fdelete_other_windows_internal (root, Qnil);
3605 if (horflag)
3606 XSETFASTINT (XWINDOW (root)->total_cols, new_size);
3607 else
3608 XSETFASTINT (XWINDOW (root)->total_lines, new_size);
3609 }
3610 }
3611 }
3612 }
3613
3614 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3615 {
3616 m = XWINDOW (mini);
3617 if (horflag)
3618 XSETFASTINT (m->total_cols, size);
3619 else
3620 {
3621 /* Are we sure we always want 1 line here? */
3622 XSETFASTINT (m->total_lines, 1);
3623 XSETFASTINT (m->top_line, XINT (r->top_line) + XINT (r->total_lines));
3624 }
3625 }
3626}
3627
3628
3629DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
3630 doc: /* Split window OLD.
3631Second argument TOTAL-SIZE specifies the number of lines or columns of the
9397e56f 3632new window. In any case TOTAL-SIZE must be a positive integer.
1a13852e
MR
3633
3634Third argument SIDE nil (or `below') specifies that the new window shall
3635be located below WINDOW. SIDE `above' means the new window shall be
3636located above WINDOW. In both cases TOTAL-SIZE specifies the number of
3637lines of the new window including space reserved for the mode and/or
3638header line.
3639
3640SIDE t (or `right') specifies that the new window shall be located on
3641the right side of WINDOW. SIDE `left' means the new window shall be
3642located on the left of WINDOW. In both cases TOTAL-SIZE specifies the
3643number of columns of the new window including space reserved for fringes
3644and the scrollbar or a divider column.
3645
3646Fourth argument NORMAL-SIZE specifies the normal size of the new window
3647according to the SIDE argument.
3648
3649The new total and normal sizes of all involved windows must have been
3650set correctly. See the code of `split-window' for how this is done. */)
3651 (Lisp_Object old, Lisp_Object total_size, Lisp_Object side, Lisp_Object normal_size)
3652{
3653 /* OLD (*o) is the window we have to split. (*p) is either OLD's
3654 parent window or an internal window we have to install as OLD's new
3655 parent. REFERENCE (*r) must denote a live window, or is set to OLD
3656 provided OLD is a leaf window, or to the frame's selected window.
3657 NEW (*n) is the new window created with some parameters taken from
3658 REFERENCE (*r). */
3659 register Lisp_Object new, frame, reference;
3660 register struct window *o, *p, *n, *r;
3661 struct frame *f;
3662 int horflag
3663 /* HORFLAG is 1 when we split side-by-side, 0 otherwise. */
3664 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
b6f67890 3665 int combination_limit = 0;
1a13852e
MR
3666
3667 CHECK_WINDOW (old);
3668 o = XWINDOW (old);
3669 frame = WINDOW_FRAME (o);
3670 f = XFRAME (frame);
3671
3672 CHECK_NUMBER (total_size);
3673
b6f67890
MR
3674 /* Set combination_limit to 1 if we have to make a new parent window.
3675 We do that if either `window-combination-limit' is t, or OLD has no
3676 parent, or OLD is ortho-combined. */
3677 combination_limit =
3678 !NILP (Vwindow_combination_limit)
1a13852e
MR
3679 || NILP (o->parent)
3680 || NILP (horflag
3681 ? (XWINDOW (o->parent)->hchild)
3682 : (XWINDOW (o->parent)->vchild));
3683
3684 /* We need a live reference window to initialize some parameters. */
3685 if (WINDOW_LIVE_P (old))
3686 /* OLD is live, use it as reference window. */
3687 reference = old;
3688 else
3689 /* Use the frame's selected window as reference window. */
3690 reference = FRAME_SELECTED_WINDOW (f);
3691 r = XWINDOW (reference);
3692
3693 /* The following bugs are caught by `split-window'. */
3694 if (MINI_WINDOW_P (o))
3695 error ("Attempt to split minibuffer window");
3696 else if (XINT (total_size) < (horflag ? 2 : 1))
3697 error ("Size of new window too small (after split)");
a0c2d0ae
MR
3698 else if (!combination_limit && !NILP (Vwindow_combination_resize))
3699 /* `window-combination-resize' non-nil means try to resize OLD's siblings
1a13852e
MR
3700 proportionally. */
3701 {
3702 p = XWINDOW (o->parent);
3703 /* Temporarily pretend we split the parent window. */
3704 XSETINT (p->new_total,
3705 XINT (horflag ? p->total_cols : p->total_lines)
3706 - XINT (total_size));
d615d6d2 3707 if (!window_resize_check (p, horflag))
1a13852e
MR
3708 error ("Window sizes don't fit");
3709 else
3710 /* Undo the temporary pretension. */
3711 p->new_total = horflag ? p->total_cols : p->total_lines;
3712 }
3713 else
3714 {
d615d6d2 3715 if (!window_resize_check (o, horflag))
1a13852e
MR
3716 error ("Resizing old window failed");
3717 else if (XINT (total_size) + XINT (o->new_total)
3718 != XINT (horflag ? o->total_cols : o->total_lines))
3719 error ("Sum of sizes of old and new window don't fit");
3720 }
3721
3722 /* This is our point of no return. */
b6f67890 3723 if (combination_limit)
1a13852e
MR
3724 {
3725 /* Save the old value of o->normal_cols/lines. It gets corrupted
3726 by make_parent_window and we need it below for assigning it to
3727 p->new_normal. */
3728 Lisp_Object new_normal = horflag ? o->normal_cols : o->normal_lines;
3729
3730 make_parent_window (old, horflag);
3731 p = XWINDOW (o->parent);
b6f67890
MR
3732 /* Store value of `window-combination-limit' in new parent's
3733 combination_limit slot. */
3734 p->combination_limit = Vwindow_combination_limit;
1a13852e
MR
3735 /* These get applied below. */
3736 p->new_total = horflag ? o->total_cols : o->total_lines;
3737 p->new_normal = new_normal;
3738 }
3739 else
3740 p = XWINDOW (o->parent);
3741
3742 windows_or_buffers_changed++;
3743 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3744 new = make_window ();
3745 n = XWINDOW (new);
3746 n->frame = frame;
3747 n->parent = o->parent;
3748 n->vchild = n->hchild = Qnil;
3749
3750 if (EQ (side, Qabove) || EQ (side, Qleft))
3751 {
3752 n->prev = o->prev;
3753 if (NILP (n->prev))
3754 if (horflag)
3755 p->hchild = new;
3756 else
3757 p->vchild = new;
3758 else
3759 XWINDOW (n->prev)->next = new;
3760 n->next = old;
3761 o->prev = new;
3762 }
3763 else
3764 {
3765 n->next = o->next;
3766 if (!NILP (n->next))
3767 XWINDOW (n->next)->prev = new;
3768 n->prev = old;
3769 o->next = new;
3770 }
3771
3772 n->buffer = Qt;
3773 n->window_end_valid = Qnil;
3774 memset (&n->last_cursor, 0, sizeof n->last_cursor);
3775
3776 /* Get special geometry settings from reference window. */
3777 n->left_margin_cols = r->left_margin_cols;
3778 n->right_margin_cols = r->right_margin_cols;
3779 n->left_fringe_width = r->left_fringe_width;
3780 n->right_fringe_width = r->right_fringe_width;
3781 n->fringes_outside_margins = r->fringes_outside_margins;
3782 n->scroll_bar_width = r->scroll_bar_width;
3783 n->vertical_scroll_bar_type = r->vertical_scroll_bar_type;
3784
1a13852e
MR
3785 /* Directly assign orthogonal coordinates and sizes. */
3786 if (horflag)
3787 {
3788 n->top_line = o->top_line;
3789 n->total_lines = o->total_lines;
3790 }
3791 else
3792 {
3793 n->left_col = o->left_col;
3794 n->total_cols = o->total_cols;
3795 }
3796
d615d6d2 3797 /* Iso-coordinates and sizes are assigned by window_resize_apply,
1a13852e
MR
3798 get them ready here. */
3799 n->new_total = total_size;
3800 n->new_normal = normal_size;
3801
3802 BLOCK_INPUT;
d615d6d2 3803 window_resize_apply (p, horflag);
1a13852e
MR
3804 adjust_glyphs (f);
3805 /* Set buffer of NEW to buffer of reference window. Don't run
3806 any hooks. */
3807 set_window_buffer (new, r->buffer, 0, 1);
3808 UNBLOCK_INPUT;
3809
3810 /* Maybe we should run the scroll functions in Elisp (which already
3811 runs the configuration change hook). */
3812 if (! NILP (Vwindow_scroll_functions))
3813 run_hook_with_args_2 (Qwindow_scroll_functions, new,
3814 Fmarker_position (n->start));
3815 /* Return NEW. */
3816 return new;
3817}
3818
3819
3820DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
3821 doc: /* Remove WINDOW from its frame.
87e68db4
JB
3822WINDOW defaults to the selected window. Return nil.
3823Signal an error when WINDOW is the only window on its frame. */)
1a13852e
MR
3824 (register Lisp_Object window)
3825{
3826 register Lisp_Object parent, sibling, frame, root;
3827 struct window *w, *p, *s, *r;
3828 struct frame *f;
3829 int horflag;
3830 int before_sibling = 0;
3831
3832 w = decode_any_window (window);
3833 XSETWINDOW (window, w);
3834 if (NILP (w->buffer) && NILP (w->hchild) && NILP (w->vchild))
3835 /* It's a no-op to delete an already deleted window. */
3836 return Qnil;
3837
3838 parent = w->parent;
3839 if (NILP (parent))
3840 /* Never delete a minibuffer or frame root window. */
3841 error ("Attempt to delete minibuffer or sole ordinary window");
3842 else if (NILP (w->prev) && NILP (w->next))
3843 /* Rather bow out here, this case should be handled on the Elisp
3844 level. */
3845 error ("Attempt to delete sole window of parent");
3846
3847 p = XWINDOW (parent);
3848 horflag = NILP (p->vchild);
3849
3850 frame = WINDOW_FRAME (w);
3851 f = XFRAME (frame);
3852
3853 root = FRAME_ROOT_WINDOW (f);
3854 r = XWINDOW (root);
3855
3856 /* Unlink WINDOW from window tree. */
3857 if (NILP (w->prev))
3858 /* Get SIBLING below (on the right of) WINDOW. */
3859 {
3860 /* before_sibling 1 means WINDOW is the first child of its
3861 parent and thus before the sibling. */
3862 before_sibling = 1;
3863 sibling = w->next;
3864 s = XWINDOW (sibling);
3865 s->prev = Qnil;
3866 if (horflag)
3867 p->hchild = sibling;
3868 else
3869 p->vchild = sibling;
3870 }
3871 else
3872 /* Get SIBLING above (on the left of) WINDOW. */
3873 {
3874 sibling = w->prev;
3875 s = XWINDOW (sibling);
3876 s->next = w->next;
562dd5e9
MR
3877 if (!NILP (s->next))
3878 XWINDOW (s->next)->prev = sibling;
7ab12479
JB
3879 }
3880
d615d6d2 3881 if (window_resize_check (r, horflag)
562dd5e9
MR
3882 && EQ (r->new_total, (horflag ? r->total_cols : r->total_lines)))
3883 /* We can delete WINDOW now. */
3884 {
95986d52 3885
562dd5e9
MR
3886 /* Block input. */
3887 BLOCK_INPUT;
d615d6d2 3888 window_resize_apply (p, horflag);
0d384044 3889
95986d52
CY
3890 /* If this window is referred to by the dpyinfo's mouse
3891 highlight, invalidate that slot to be safe (Bug#9904). */
4c5501e9
EZ
3892 if (!FRAME_INITIAL_P (f))
3893 {
3894 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
3895
3896 if (EQ (hlinfo->mouse_face_window, window))
3897 hlinfo->mouse_face_window = Qnil;
3898 }
95986d52 3899
562dd5e9
MR
3900 windows_or_buffers_changed++;
3901 Vwindow_list = Qnil;
3902 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
0d384044 3903
562dd5e9
MR
3904 w->next = Qnil; /* Don't delete w->next too. */
3905 free_window_matrices (w);
bd99e242 3906
562dd5e9 3907 if (!NILP (w->vchild))
0d384044 3908 {
be7f5545 3909 delete_all_child_windows (w->vchild);
562dd5e9 3910 w->vchild = Qnil;
0d384044 3911 }
562dd5e9 3912 else if (!NILP (w->hchild))
bd99e242 3913 {
be7f5545 3914 delete_all_child_windows (w->hchild);
562dd5e9 3915 w->hchild = Qnil;
bd99e242 3916 }
562dd5e9 3917 else if (!NILP (w->buffer))
bd99e242 3918 {
562dd5e9
MR
3919 unshow_buffer (w);
3920 unchain_marker (XMARKER (w->pointm));
3921 unchain_marker (XMARKER (w->start));
3922 w->buffer = Qnil;
bd99e242
RS
3923 }
3924
562dd5e9
MR
3925 if (NILP (s->prev) && NILP (s->next))
3926 /* A matrjoshka where SIBLING has become the only child of
3927 PARENT. */
c32de52a 3928 {
562dd5e9
MR
3929 /* Put SIBLING into PARENT's place. */
3930 replace_window (parent, sibling, 0);
3931 /* Have SIBLING inherit the following three slot values from
b6f67890 3932 PARENT (the combination_limit slot is not inherited). */
562dd5e9
MR
3933 s->normal_cols = p->normal_cols;
3934 s->normal_lines = p->normal_lines;
562dd5e9
MR
3935 /* Mark PARENT as deleted. */
3936 p->vchild = p->hchild = Qnil;
3937 /* Try to merge SIBLING into its new parent. */
3938 recombine_windows (sibling);
c32de52a
RS
3939 }
3940
562dd5e9
MR
3941 adjust_glyphs (f);
3942
3943 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
3944 /* We deleted the frame's selected window. */
0d384044 3945 {
562dd5e9
MR
3946 /* Use the frame's first window as fallback ... */
3947 Lisp_Object new_selected_window = Fframe_first_window (frame);
3948 /* ... but preferably use its most recently used window. */
3949 Lisp_Object mru_window;
0d384044 3950
562dd5e9
MR
3951 /* `get-mru-window' might fail for some reason so play it safe
3952 - promote the first window _without recording it_ first. */
3953 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
3954 Fselect_window (new_selected_window, Qt);
3955 else
3956 FRAME_SELECTED_WINDOW (f) = new_selected_window;
0d384044 3957
562dd5e9 3958 UNBLOCK_INPUT;
0d384044 3959
562dd5e9
MR
3960 /* Now look whether `get-mru-window' gets us something. */
3961 mru_window = call1 (Qget_mru_window, frame);
3962 if (WINDOW_LIVE_P (mru_window)
3963 && EQ (XWINDOW (mru_window)->frame, frame))
3964 new_selected_window = mru_window;
bd99e242 3965
562dd5e9
MR
3966 /* If all ended up well, we now promote the mru window. */
3967 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
3968 Fselect_window (new_selected_window, Qnil);
3969 else
3970 FRAME_SELECTED_WINDOW (f) = new_selected_window;
0d384044
RS
3971 }
3972 else
562dd5e9 3973 UNBLOCK_INPUT;
0d384044 3974
562dd5e9
MR
3975 /* Must be run by the caller:
3976 run_window_configuration_change_hook (f); */
0d384044 3977 }
562dd5e9
MR
3978 else
3979 /* We failed: Relink WINDOW into window tree. */
0d384044 3980 {
562dd5e9
MR
3981 if (before_sibling)
3982 {
3983 s->prev = window;
3984 if (horflag)
3985 p->hchild = window;
3986 else
3987 p->vchild = window;
3988 }
3989 else
3990 {
3991 s->next = window;
3992 if (!NILP (w->next))
3993 XWINDOW (w->next)->prev = window;
3994 }
3995 error ("Deletion failed");
0d384044
RS
3996 }
3997
0d384044
RS
3998 return Qnil;
3999}
f984d4fc
GM
4000\f
4001/***********************************************************************
4002 Resizing Mini-Windows
4003 ***********************************************************************/
4004
562dd5e9
MR
4005/* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4006 can. */
4007void
4008grow_mini_window (struct window *w, int delta)
f984d4fc 4009{
562dd5e9
MR
4010 struct frame *f = XFRAME (w->frame);
4011 struct window *r;
4012 Lisp_Object root, value;
f984d4fc 4013
a54e2c05
DA
4014 eassert (MINI_WINDOW_P (w));
4015 eassert (delta >= 0);
f984d4fc 4016
562dd5e9
MR
4017 root = FRAME_ROOT_WINDOW (f);
4018 r = XWINDOW (root);
5386012d
MR
4019 value = call2 (Qwindow_resize_root_window_vertically,
4020 root, make_number (- delta));
d615d6d2 4021 if (INTEGERP (value) && window_resize_check (r, 0))
f984d4fc 4022 {
562dd5e9 4023 BLOCK_INPUT;
d615d6d2 4024 window_resize_apply (r, 0);
f984d4fc 4025
562dd5e9
MR
4026 /* Grow the mini-window. */
4027 XSETFASTINT (w->top_line, XFASTINT (r->top_line) + XFASTINT (r->total_lines));
4028 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - XINT (value));
80b00b08
DA
4029 w->last_modified = 0;
4030 w->last_overlay_modified = 0;
f984d4fc 4031
562dd5e9
MR
4032 adjust_glyphs (f);
4033 UNBLOCK_INPUT;
f984d4fc
GM
4034 }
4035}
4036
4037
562dd5e9
MR
4038/* Shrink mini-window W. */
4039void
4040shrink_mini_window (struct window *w)
f984d4fc 4041{
562dd5e9
MR
4042 struct frame *f = XFRAME (w->frame);
4043 struct window *r;
4044 Lisp_Object root, value;
4045 EMACS_INT size;
43b4a21f 4046
a54e2c05 4047 eassert (MINI_WINDOW_P (w));
177c0ea7 4048
562dd5e9
MR
4049 size = XINT (w->total_lines);
4050 if (size > 1)
4051 {
4052 root = FRAME_ROOT_WINDOW (f);
4053 r = XWINDOW (root);
5386012d 4054 value = call2 (Qwindow_resize_root_window_vertically,
562dd5e9 4055 root, make_number (size - 1));
d615d6d2 4056 if (INTEGERP (value) && window_resize_check (r, 0))
f984d4fc 4057 {
562dd5e9 4058 BLOCK_INPUT;
d615d6d2 4059 window_resize_apply (r, 0);
43b4a21f 4060
562dd5e9
MR
4061 /* Shrink the mini-window. */
4062 XSETFASTINT (w->top_line, XFASTINT (r->top_line) + XFASTINT (r->total_lines));
4063 XSETFASTINT (w->total_lines, 1);
43b4a21f 4064
80b00b08
DA
4065 w->last_modified = 0;
4066 w->last_overlay_modified = 0;
43b4a21f 4067
562dd5e9
MR
4068 adjust_glyphs (f);
4069 UNBLOCK_INPUT;
f984d4fc 4070 }
562dd5e9
MR
4071 /* If the above failed for whatever strange reason we must make a
4072 one window frame here. The same routine will be needed when
4073 shrinking the frame (and probably when making the initial
4074 *scratch* window). For the moment leave things as they are. */
f984d4fc
GM
4075 }
4076}
4077
562dd5e9
MR
4078DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4079 doc: /* Resize minibuffer window WINDOW. */)
4080 (Lisp_Object window)
f984d4fc 4081{
562dd5e9
MR
4082 struct window *w = XWINDOW (window);
4083 struct window *r;
4084 struct frame *f;
4085 int height;
177c0ea7 4086
562dd5e9
MR
4087 CHECK_WINDOW (window);
4088 f = XFRAME (w->frame);
177c0ea7 4089
562dd5e9
MR
4090 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4091 error ("Not a valid minibuffer window");
4092 else if (FRAME_MINIBUF_ONLY_P (f))
4093 error ("Cannot resize a minibuffer-only frame");
177c0ea7 4094
562dd5e9
MR
4095 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4096 height = XINT (r->total_lines) + XINT (w->total_lines);
d615d6d2 4097 if (window_resize_check (r, 0)
562dd5e9
MR
4098 && XINT (w->new_total) > 0
4099 && height == XINT (r->new_total) + XINT (w->new_total))
f984d4fc 4100 {
562dd5e9 4101 BLOCK_INPUT;
d615d6d2 4102 window_resize_apply (r, 0);
f984d4fc 4103
562dd5e9
MR
4104 w->total_lines = w->new_total;
4105 XSETFASTINT (w->top_line, XINT (r->top_line) + XINT (r->total_lines));
177c0ea7 4106
562dd5e9
MR
4107 windows_or_buffers_changed++;
4108 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
f984d4fc 4109 adjust_glyphs (f);
562dd5e9 4110 UNBLOCK_INPUT;
f984d4fc 4111
562dd5e9
MR
4112 run_window_configuration_change_hook (f);
4113 return Qt;
86c8e823 4114 }
562dd5e9 4115 else error ("Failed to resize minibuffer window");
f984d4fc 4116}
562dd5e9 4117\f
5500c422
GM
4118/* Mark window cursors off for all windows in the window tree rooted
4119 at W by setting their phys_cursor_on_p flag to zero. Called from
4120 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4121 the frame are cleared. */
4122
4123void
971de7fb 4124mark_window_cursors_off (struct window *w)
5500c422
GM
4125{
4126 while (w)
4127 {
4128 if (!NILP (w->hchild))
4129 mark_window_cursors_off (XWINDOW (w->hchild));
4130 else if (!NILP (w->vchild))
4131 mark_window_cursors_off (XWINDOW (w->vchild));
4132 else
4133 w->phys_cursor_on_p = 0;
4134
4135 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4136 }
4137}
4138
4139
e9c195b1 4140/* Return number of lines of text (not counting mode lines) in W. */
7ab12479
JB
4141
4142int
971de7fb 4143window_internal_height (struct window *w)
7ab12479 4144{
949cf20f 4145 int ht = XFASTINT (w->total_lines);
7ab12479 4146
e9c195b1
GM
4147 if (!MINI_WINDOW_P (w))
4148 {
4149 if (!NILP (w->parent)
4150 || !NILP (w->vchild)
4151 || !NILP (w->hchild)
4152 || !NILP (w->next)
4153 || !NILP (w->prev)
4154 || WINDOW_WANTS_MODELINE_P (w))
4155 --ht;
7ab12479 4156
e9c195b1
GM
4157 if (WINDOW_WANTS_HEADER_LINE_P (w))
4158 --ht;
4159 }
7ab12479
JB
4160
4161 return ht;
4162}
5500c422
GM
4163\f
4164/************************************************************************
4165 Window Scrolling
4166 ***********************************************************************/
535e0b8e 4167
5500c422 4168/* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
d4e7cf01 4169 N screen-fulls, which is defined as the height of the window minus
5500c422
GM
4170 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4171 instead. Negative values of N mean scroll down. NOERROR non-zero
4172 means don't signal an error if we try to move over BEGV or ZV,
4173 respectively. */
7ab12479 4174
101d1605 4175static void
d311d28c 4176window_scroll (Lisp_Object window, EMACS_INT n, int whole, int noerror)
5500c422 4177{
cba59f77 4178 immediate_quit = 1;
d311d28c 4179 n = clip_to_bounds (INT_MIN, n, INT_MAX);
cba59f77 4180
5500c422
GM
4181 /* If we must, use the pixel-based version which is much slower than
4182 the line-based one but can handle varying line heights. */
4183 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4184 window_scroll_pixel_based (window, n, whole, noerror);
4185 else
4186 window_scroll_line_based (window, n, whole, noerror);
cba59f77
RS
4187
4188 immediate_quit = 0;
5500c422
GM
4189}
4190
4191
4192/* Implementation of window_scroll that works based on pixel line
4193 heights. See the comment of window_scroll for parameter
4194 descriptions. */
4195
4196static void
971de7fb 4197window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
5500c422
GM
4198{
4199 struct it it;
4200 struct window *w = XWINDOW (window);
4201 struct text_pos start;
5500c422 4202 int this_scroll_margin;
9d14503e 4203 /* True if we fiddled the window vscroll field without really scrolling. */
5cdb3cf3 4204 int vscrolled = 0;
5a857365 4205 int x, y, rtop, rbot, rowh, vpos;
57b3e30b 4206 void *itdata = NULL;
5500c422
GM
4207
4208 SET_TEXT_POS_FROM_MARKER (start, w->start);
f0ee99a0
EZ
4209 /* Scrolling a minibuffer window via scroll bar when the echo area
4210 shows long text sometimes resets the minibuffer contents behind
4211 our backs. */
4212 if (CHARPOS (start) > ZV)
4213 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
177c0ea7 4214
5500c422 4215 /* If PT is not visible in WINDOW, move back one half of
288d4e06
GM
4216 the screen. Allow PT to be partially visible, otherwise
4217 something like (scroll-down 1) with PT in the line before
4218 the partially visible one would recenter. */
5a857365
KS
4219
4220 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
5500c422 4221 {
57b3e30b 4222 itdata = bidi_shelve_cache ();
5500c422
GM
4223 /* Move backward half the height of the window. Performance note:
4224 vmotion used here is about 10% faster, but would give wrong
4225 results for variable height lines. */
4226 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4227 it.current_y = it.last_visible_y;
f204989e 4228 move_it_vertically_backward (&it, window_box_height (w) / 2);
177c0ea7 4229
5500c422
GM
4230 /* The function move_iterator_vertically may move over more than
4231 the specified y-distance. If it->w is small, e.g. a
4232 mini-buffer window, we may end up in front of the window's
4233 display area. This is the case when Start displaying at the
4234 start of the line containing PT in this case. */
4235 if (it.current_y <= 0)
4236 {
4237 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
f204989e 4238 move_it_vertically_backward (&it, 0);
5500c422
GM
4239 it.current_y = 0;
4240 }
4241
4242 start = it.current.pos;
35928349 4243 bidi_unshelve_cache (itdata, 0);
5500c422 4244 }
e56263e5
KS
4245 else if (auto_window_vscroll_p)
4246 {
5a857365 4247 if (rtop || rbot) /* partially visible */
e56263e5
KS
4248 {
4249 int px;
4250 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4251 if (whole)
e856c216
KS
4252 dy = max ((window_box_height (w)
4253 - next_screen_context_lines * dy),
4254 dy);
e56263e5
KS
4255 dy *= n;
4256
5a857365 4257 if (n < 0)
e56263e5 4258 {
5a857365
KS
4259 /* Only vscroll backwards if already vscrolled forwards. */
4260 if (w->vscroll < 0 && rtop > 0)
4261 {
4262 px = max (0, -w->vscroll - min (rtop, -dy));
4263 Fset_window_vscroll (window, make_number (px), Qt);
4264 return;
4265 }
e56263e5 4266 }
5a857365 4267 if (n > 0)
e56263e5 4268 {
5a857365
KS
4269 /* Do vscroll if already vscrolled or only display line. */
4270 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4271 {
4272 px = max (0, -w->vscroll + min (rbot, dy));
4273 Fset_window_vscroll (window, make_number (px), Qt);
4274 return;
4275 }
4276
4277 /* Maybe modify window start instead of scrolling. */
4278 if (rbot > 0 || w->vscroll < 0)
4279 {
d311d28c 4280 ptrdiff_t spos;
5a857365
KS
4281
4282 Fset_window_vscroll (window, make_number (0), Qt);
4283 /* If there are other text lines above the current row,
4284 move window start to current row. Else to next row. */
4285 if (rbot > 0)
4286 spos = XINT (Fline_beginning_position (Qnil));
4287 else
4288 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4289 set_marker_restricted (w->start, make_number (spos),
4290 w->buffer);
c98ff5dd
DA
4291 w->start_at_line_beg = 1;
4292 w->update_mode_line = 1;
80b00b08
DA
4293 w->last_modified = 0;
4294 w->last_overlay_modified = 0;
5a857365
KS
4295 /* Set force_start so that redisplay_window will run the
4296 window-scroll-functions. */
c98ff5dd 4297 w->force_start = 1;
5a857365
KS
4298 return;
4299 }
e56263e5
KS
4300 }
4301 }
5a857365 4302 /* Cancel previous vscroll. */
e56263e5
KS
4303 Fset_window_vscroll (window, make_number (0), Qt);
4304 }
5500c422 4305
57b3e30b 4306 itdata = bidi_shelve_cache ();
d0c38d63 4307 /* If scroll_preserve_screen_position is non-nil, we try to set
5500c422
GM
4308 point in the same window line as it is now, so get that line. */
4309 if (!NILP (Vscroll_preserve_screen_position))
4310 {
c525d842 4311 /* We preserve the goal pixel coordinate across consecutive
a4b000fb
JL
4312 calls to scroll-up, scroll-down and other commands that
4313 have the `scroll-command' property. This avoids the
c525d842
CY
4314 possibility of point becoming "stuck" on a tall line when
4315 scrolling by one line. */
66fe93d1 4316 if (window_scroll_pixel_based_preserve_y < 0
1344aad4
TT
4317 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4318 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
c525d842
CY
4319 {
4320 start_display (&it, w, start);
4321 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
66fe93d1 4322 window_scroll_pixel_based_preserve_y = it.current_y;
c876b227 4323 window_scroll_pixel_based_preserve_x = it.current_x;
c525d842 4324 }
5500c422
GM
4325 }
4326 else
c876b227
SM
4327 window_scroll_pixel_based_preserve_y
4328 = window_scroll_pixel_based_preserve_x = -1;
5500c422
GM
4329
4330 /* Move iterator it from start the specified distance forward or
4331 backward. The result is the new window start. */
4332 start_display (&it, w, start);
4333 if (whole)
4334 {
d311d28c 4335 ptrdiff_t start_pos = IT_CHARPOS (it);
e856c216
KS
4336 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4337 dy = max ((window_box_height (w)
4338 - next_screen_context_lines * dy),
4339 dy) * n;
d72340d4
GM
4340
4341 /* Note that move_it_vertically always moves the iterator to the
4342 start of a line. So, if the last line doesn't have a newline,
4343 we would end up at the start of the line ending at ZV. */
4344 if (dy <= 0)
e856c216
KS
4345 {
4346 move_it_vertically_backward (&it, -dy);
5a857365 4347 /* Ensure we actually do move, e.g. in case we are currently
e856c216
KS
4348 looking at an image that is taller that the window height. */
4349 while (start_pos == IT_CHARPOS (it)
4350 && start_pos > BEGV)
e4cc2dfc 4351 move_it_by_lines (&it, -1);
e856c216 4352 }
d72340d4 4353 else if (dy > 0)
bed83ee4 4354 {
bed83ee4
KS
4355 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4356 MOVE_TO_POS | MOVE_TO_Y);
5a857365 4357 /* Ensure we actually do move, e.g. in case we are currently
bed83ee4
KS
4358 looking at an image that is taller that the window height. */
4359 while (start_pos == IT_CHARPOS (it)
4360 && start_pos < ZV)
e4cc2dfc 4361 move_it_by_lines (&it, 1);
bed83ee4 4362 }
5500c422
GM
4363 }
4364 else
e4cc2dfc 4365 move_it_by_lines (&it, n);
5500c422 4366
96ae58c8
RS
4367 /* We failed if we find ZV is already on the screen (scrolling up,
4368 means there's nothing past the end), or if we can't start any
4369 earlier (scrolling down, means there's nothing past the top). */
5500c422 4370 if ((n > 0 && IT_CHARPOS (it) == ZV)
96ae58c8 4371 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
5500c422 4372 {
5cdb3cf3
MB
4373 if (IT_CHARPOS (it) == ZV)
4374 {
07ce8b53
RS
4375 if (it.current_y < it.last_visible_y
4376 && (it.current_y + it.max_ascent + it.max_descent
3f489dc7 4377 > it.last_visible_y))
a74eca50
GM
4378 {
4379 /* The last line was only partially visible, make it fully
4380 visible. */
4381 w->vscroll = (it.last_visible_y
4382 - it.current_y + it.max_ascent + it.max_descent);
4383 adjust_glyphs (it.f);
4384 }
5cdb3cf3 4385 else
57b3e30b 4386 {
35928349 4387 bidi_unshelve_cache (itdata, 0);
57b3e30b
EZ
4388 if (noerror)
4389 return;
4390 else if (n < 0) /* could happen with empty buffers */
4391 xsignal0 (Qbeginning_of_buffer);
4392 else
4393 xsignal0 (Qend_of_buffer);
4394 }
5cdb3cf3 4395 }
5500c422 4396 else
5cdb3cf3
MB
4397 {
4398 if (w->vscroll != 0)
4399 /* The first line was only partially visible, make it fully
4400 visible. */
4401 w->vscroll = 0;
5cdb3cf3 4402 else
57b3e30b 4403 {
35928349 4404 bidi_unshelve_cache (itdata, 0);
57b3e30b
EZ
4405 if (noerror)
4406 return;
4407 else
4408 xsignal0 (Qbeginning_of_buffer);
4409 }
5cdb3cf3
MB
4410 }
4411
4412 /* If control gets here, then we vscrolled. */
4413
4414 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4415
4416 /* Don't try to change the window start below. */
4417 vscrolled = 1;
5500c422
GM
4418 }
4419
5cdb3cf3
MB
4420 if (! vscrolled)
4421 {
d311d28c
PE
4422 ptrdiff_t pos = IT_CHARPOS (it);
4423 ptrdiff_t bytepos;
e68def1e
AS
4424
4425 /* If in the middle of a multi-glyph character move forward to
4426 the next character. */
4427 if (in_display_vector_p (&it))
4428 {
4429 ++pos;
4430 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4431 }
4432
5cdb3cf3 4433 /* Set the window start, and set up the window for redisplay. */
dad67609 4434 set_marker_restricted (w->start, make_number (pos),
5cdb3cf3 4435 w->buffer);
dad67609 4436 bytepos = XMARKER (w->start)->bytepos;
c98ff5dd
DA
4437 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
4438 w->update_mode_line = 1;
80b00b08
DA
4439 w->last_modified = 0;
4440 w->last_overlay_modified = 0;
5cdb3cf3
MB
4441 /* Set force_start so that redisplay_window will run the
4442 window-scroll-functions. */
c98ff5dd 4443 w->force_start = 1;
5cdb3cf3 4444 }
177c0ea7 4445
dc297565
RS
4446 /* The rest of this function uses current_y in a nonstandard way,
4447 not including the height of the header line if any. */
5500c422 4448 it.current_y = it.vpos = 0;
177c0ea7 4449
940f53e5
RS
4450 /* Move PT out of scroll margins.
4451 This code wants current_y to be zero at the window start position
4452 even if there is a header line. */
4453 this_scroll_margin = max (0, scroll_margin);
4454 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4455 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4456
4457 if (n > 0)
5500c422 4458 {
940f53e5
RS
4459 /* We moved the window start towards ZV, so PT may be now
4460 in the scroll margin at the top. */
4461 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
bdf4ec93
RS
4462 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
4463 && (NILP (Vscroll_preserve_screen_position)
4464 || EQ (Vscroll_preserve_screen_position, Qt)))
940f53e5
RS
4465 /* We found PT at a legitimate height. Leave it alone. */
4466 ;
66fe93d1 4467 else if (window_scroll_pixel_based_preserve_y >= 0)
940f53e5 4468 {
fa3c3426
RS
4469 /* If we have a header line, take account of it.
4470 This is necessary because we set it.current_y to 0, above. */
c876b227
SM
4471 move_it_to (&it, -1,
4472 window_scroll_pixel_based_preserve_x,
66fe93d1
LT
4473 window_scroll_pixel_based_preserve_y
4474 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
c876b227 4475 -1, MOVE_TO_Y | MOVE_TO_X);
940f53e5
RS
4476 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4477 }
4478 else
5500c422 4479 {
5500c422 4480 while (it.current_y < this_scroll_margin)
e9b2c961
RS
4481 {
4482 int prev = it.current_y;
e4cc2dfc 4483 move_it_by_lines (&it, 1);
e9b2c961
RS
4484 if (prev == it.current_y)
4485 break;
4486 }
5500c422
GM
4487 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4488 }
940f53e5
RS
4489 }
4490 else if (n < 0)
4491 {
d311d28c 4492 ptrdiff_t charpos, bytepos;
aed328bf 4493 int partial_p;
940f53e5 4494
66fe93d1
LT
4495 /* Save our position, for the
4496 window_scroll_pixel_based_preserve_y case. */
940f53e5
RS
4497 charpos = IT_CHARPOS (it);
4498 bytepos = IT_BYTEPOS (it);
5cdb3cf3 4499
940f53e5
RS
4500 /* We moved the window start towards BEGV, so PT may be now
4501 in the scroll margin at the bottom. */
4502 move_it_to (&it, PT, -1,
7ad53239
RS
4503 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
4504 - this_scroll_margin - 1),
4505 -1,
940f53e5
RS
4506 MOVE_TO_POS | MOVE_TO_Y);
4507
aed328bf
KS
4508 /* Save our position, in case it's correct. */
4509 charpos = IT_CHARPOS (it);
4510 bytepos = IT_BYTEPOS (it);
4511
4512 /* See if point is on a partially visible line at the end. */
4513 if (it.what == IT_EOB)
4514 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
4515 else
4516 {
e4cc2dfc 4517 move_it_by_lines (&it, 1);
aed328bf
KS
4518 partial_p = it.current_y > it.last_visible_y;
4519 }
4520
bdf4ec93
RS
4521 if (charpos == PT && !partial_p
4522 && (NILP (Vscroll_preserve_screen_position)
4523 || EQ (Vscroll_preserve_screen_position, Qt)))
940f53e5
RS
4524 /* We found PT before we found the display margin, so PT is ok. */
4525 ;
66fe93d1 4526 else if (window_scroll_pixel_based_preserve_y >= 0)
940f53e5
RS
4527 {
4528 SET_TEXT_POS_FROM_MARKER (start, w->start);
4529 start_display (&it, w, start);
c525d842
CY
4530 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
4531 here because we called start_display again and did not
4532 alter it.current_y this time. */
c876b227
SM
4533 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
4534 window_scroll_pixel_based_preserve_y, -1,
4535 MOVE_TO_Y | MOVE_TO_X);
940f53e5
RS
4536 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4537 }
4538 else
4539 {
aed328bf 4540 if (partial_p)
5cdb3cf3
MB
4541 /* The last line was only partially visible, so back up two
4542 lines to make sure we're on a fully visible line. */
4543 {
e4cc2dfc 4544 move_it_by_lines (&it, -2);
5cdb3cf3
MB
4545 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4546 }
4547 else
4548 /* No, the position we saved is OK, so use it. */
4549 SET_PT_BOTH (charpos, bytepos);
5500c422
GM
4550 }
4551 }
35928349 4552 bidi_unshelve_cache (itdata, 0);
5500c422
GM
4553}
4554
4555
4556/* Implementation of window_scroll that works based on screen lines.
4557 See the comment of window_scroll for parameter descriptions. */
4558
4559static void
971de7fb 4560window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
7ab12479
JB
4561{
4562 register struct window *w = XWINDOW (window);
03ab8921
EZ
4563 /* Fvertical_motion enters redisplay, which can trigger
4564 fontification, which in turn can modify buffer text (e.g., if the
4565 fontification functions replace escape sequences with faces, as
4566 in `grep-mode-font-lock-keywords'). So we use a marker to record
4567 the old point position, to prevent crashes in SET_PT_BOTH. */
4568 Lisp_Object opoint_marker = Fpoint_marker ();
d311d28c 4569 register ptrdiff_t pos, pos_byte;
7ab12479
JB
4570 register int ht = window_internal_height (w);
4571 register Lisp_Object tem;
4572 int lose;
5500c422 4573 Lisp_Object bolp;
d311d28c 4574 ptrdiff_t startpos;
c876b227 4575 Lisp_Object original_pos = Qnil;
101d1605 4576
d4e7cf01
GM
4577 /* If scrolling screen-fulls, compute the number of lines to
4578 scroll from the window's height. */
4579 if (whole)
4580 n *= max (1, ht - next_screen_context_lines);
4581
101d1605
RS
4582 startpos = marker_position (w->start);
4583
c876b227
SM
4584 if (!NILP (Vscroll_preserve_screen_position))
4585 {
4586 if (window_scroll_preserve_vpos <= 0
1344aad4
TT
4587 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4588 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
c876b227
SM
4589 {
4590 struct position posit
4591 = *compute_motion (startpos, 0, 0, 0,
4592 PT, ht, 0,
80b00b08 4593 -1, w->hscroll,
c876b227
SM
4594 0, w);
4595 window_scroll_preserve_vpos = posit.vpos;
80b00b08 4596 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
c876b227
SM
4597 }
4598
4599 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
4600 make_number (window_scroll_preserve_vpos));
4601 }
0a1f771a 4602
d834a2e9 4603 XSETFASTINT (tem, PT);
6ffdb539 4604 tem = Fpos_visible_in_window_p (tem, window, Qnil);
7ab12479 4605
265a9e55 4606 if (NILP (tem))
7ab12479 4607 {
cd2be1dd 4608 Fvertical_motion (make_number (- (ht / 2)), window);
345d45b2 4609 startpos = PT;
7ab12479
JB
4610 }
4611
345d45b2 4612 SET_PT (startpos);
5ce7b543 4613 lose = n < 0 && PT == BEGV;
540b6aa0 4614 Fvertical_motion (make_number (n), window);
5ce7b543 4615 pos = PT;
b73ea88e 4616 pos_byte = PT_BYTE;
7ab12479 4617 bolp = Fbolp ();
03ab8921
EZ
4618 SET_PT_BOTH (marker_position (opoint_marker),
4619 marker_byte_position (opoint_marker));
7ab12479
JB
4620
4621 if (lose)
f8026fd8
JB
4622 {
4623 if (noerror)
4624 return;
4625 else
ba96a5cf 4626 xsignal0 (Qbeginning_of_buffer);
f8026fd8 4627 }
7ab12479
JB
4628
4629 if (pos < ZV)
7ab12479 4630 {
0c7da84e 4631 /* Don't use a scroll margin that is negative or too large. */
71f02bc5
PE
4632 int this_scroll_margin =
4633 max (0, min (scroll_margin, XINT (w->total_lines) / 4));
0c7da84e 4634
b73ea88e 4635 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
c98ff5dd
DA
4636 w->start_at_line_beg = !NILP (bolp);
4637 w->update_mode_line = 1;
80b00b08
DA
4638 w->last_modified = 0;
4639 w->last_overlay_modified = 0;
345d45b2
RS
4640 /* Set force_start so that redisplay_window will run
4641 the window-scroll-functions. */
c98ff5dd 4642 w->force_start = 1;
0c7da84e 4643
bdf4ec93
RS
4644 if (!NILP (Vscroll_preserve_screen_position)
4645 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
0c7da84e 4646 {
b73ea88e 4647 SET_PT_BOTH (pos, pos_byte);
c876b227 4648 Fvertical_motion (original_pos, window);
0c7da84e 4649 }
101d1605
RS
4650 /* If we scrolled forward, put point enough lines down
4651 that it is outside the scroll margin. */
4652 else if (n > 0)
0c7da84e 4653 {
101d1605
RS
4654 int top_margin;
4655
4656 if (this_scroll_margin > 0)
4657 {
b73ea88e 4658 SET_PT_BOTH (pos, pos_byte);
101d1605
RS
4659 Fvertical_motion (make_number (this_scroll_margin), window);
4660 top_margin = PT;
4661 }
4662 else
4663 top_margin = pos;
4664
03ab8921
EZ
4665 if (top_margin <= marker_position (opoint_marker))
4666 SET_PT_BOTH (marker_position (opoint_marker),
4667 marker_byte_position (opoint_marker));
5500c422 4668 else if (!NILP (Vscroll_preserve_screen_position))
101d1605 4669 {
b73ea88e 4670 SET_PT_BOTH (pos, pos_byte);
c876b227 4671 Fvertical_motion (original_pos, window);
101d1605 4672 }
9317a85d 4673 else
335406fc 4674 SET_PT (top_margin);
0c7da84e 4675 }
101d1605 4676 else if (n < 0)
7ab12479 4677 {
101d1605
RS
4678 int bottom_margin;
4679
0c7da84e
RS
4680 /* If we scrolled backward, put point near the end of the window
4681 but not within the scroll margin. */
b73ea88e 4682 SET_PT_BOTH (pos, pos_byte);
0c7da84e 4683 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
101d1605
RS
4684 if (XFASTINT (tem) == ht - this_scroll_margin)
4685 bottom_margin = PT;
4686 else
4687 bottom_margin = PT + 1;
4688
03ab8921
EZ
4689 if (bottom_margin > marker_position (opoint_marker))
4690 SET_PT_BOTH (marker_position (opoint_marker),
4691 marker_byte_position (opoint_marker));
7ab12479 4692 else
101d1605 4693 {
5500c422 4694 if (!NILP (Vscroll_preserve_screen_position))
9317a85d 4695 {
b73ea88e 4696 SET_PT_BOTH (pos, pos_byte);
c876b227 4697 Fvertical_motion (original_pos, window);
9317a85d
RS
4698 }
4699 else
4700 Fvertical_motion (make_number (-1), window);
101d1605 4701 }
7ab12479
JB
4702 }
4703 }
4704 else
f8026fd8
JB
4705 {
4706 if (noerror)
4707 return;
4708 else
ba96a5cf 4709 xsignal0 (Qend_of_buffer);
f8026fd8 4710 }
7ab12479 4711}
5500c422
GM
4712
4713
4714/* Scroll selected_window up or down. If N is nil, scroll a
4715 screen-full which is defined as the height of the window minus
4716 next_screen_context_lines. If N is the symbol `-', scroll.
4717 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4718 up. This is the guts of Fscroll_up and Fscroll_down. */
7ab12479
JB
4719
4720static void
971de7fb 4721scroll_command (Lisp_Object n, int direction)
7ab12479 4722{
d311d28c 4723 ptrdiff_t count = SPECPDL_INDEX ();
7ab12479 4724
a54e2c05 4725 eassert (eabs (direction) == 1);
5500c422
GM
4726
4727 /* If selected window's buffer isn't current, make it current for
4728 the moment. But don't screw up if window_scroll gets an error. */
7ab12479 4729 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
4730 {
4731 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4732 Fset_buffer (XWINDOW (selected_window)->buffer);
5500c422
GM
4733
4734 /* Make redisplay consider other windows than just selected_window. */
4735 ++windows_or_buffers_changed;
95605e15 4736 }
7ab12479 4737
265a9e55 4738 if (NILP (n))
d4e7cf01 4739 window_scroll (selected_window, direction, 1, 0);
7ab12479 4740 else if (EQ (n, Qminus))
d4e7cf01 4741 window_scroll (selected_window, -direction, 1, 0);
7ab12479
JB
4742 else
4743 {
4744 n = Fprefix_numeric_value (n);
101d1605 4745 window_scroll (selected_window, XINT (n) * direction, 0, 0);
7ab12479 4746 }
95605e15
JB
4747
4748 unbind_to (count, Qnil);
7ab12479
JB
4749}
4750
e0965597 4751DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
12bb3111 4752 doc: /* Scroll text of selected window upward ARG lines.
a0a37a6f 4753If ARG is omitted or nil, scroll upward by a near full screen.
fdb82f93
PJ
4754A near full screen is `next-screen-context-lines' less than a full screen.
4755Negative ARG means scroll downward.
4756If ARG is the atom `-', scroll downward by nearly full screen.
4757When calling from a program, supply as argument a number, nil, or `-'. */)
5842a27b 4758 (Lisp_Object arg)
7ab12479 4759{
413430c5 4760 scroll_command (arg, 1);
7ab12479
JB
4761 return Qnil;
4762}
4763
e0965597 4764DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
12bb3111 4765 doc: /* Scroll text of selected window down ARG lines.
a0a37a6f 4766If ARG is omitted or nil, scroll down by a near full screen.
fdb82f93
PJ
4767A near full screen is `next-screen-context-lines' less than a full screen.
4768Negative ARG means scroll upward.
4769If ARG is the atom `-', scroll upward by nearly full screen.
4770When calling from a program, supply as argument a number, nil, or `-'. */)
5842a27b 4771 (Lisp_Object arg)
7ab12479 4772{
413430c5 4773 scroll_command (arg, -1);
7ab12479
JB
4774 return Qnil;
4775}
ccd0664b
RS
4776\f
4777DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
fdb82f93 4778 doc: /* Return the other window for \"other window scroll\" commands.
fdb82f93 4779If `other-window-scroll-buffer' is non-nil, a window
a0a37a6f
LT
4780showing that buffer is used.
4781If in the minibuffer, `minibuffer-scroll-window' if non-nil
4782specifies the window. This takes precedence over
4783`other-window-scroll-buffer'. */)
5842a27b 4784 (void)
7ab12479 4785{
ccd0664b 4786 Lisp_Object window;
7ab12479
JB
4787
4788 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 4789 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
4790 window = Vminibuf_scroll_window;
4791 /* If buffer is specified, scroll that buffer. */
265a9e55 4792 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
4793 {
4794 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 4795 if (NILP (window))
87478b52 4796 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
7ab12479
JB
4797 }
4798 else
dbc4e1c1
JB
4799 {
4800 /* Nothing specified; look for a neighboring window on the same
4801 frame. */
4802 window = Fnext_window (selected_window, Qnil, Qnil);
4803
4804 if (EQ (window, selected_window))
4805 /* That didn't get us anywhere; look for a window on another
4806 visible frame. */
4807 do
4808 window = Fnext_window (window, Qnil, Qt);
4809 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4810 && ! EQ (window, selected_window));
4811 }
4812
b7826503 4813 CHECK_LIVE_WINDOW (window);
7ab12479
JB
4814
4815 if (EQ (window, selected_window))
4816 error ("There is no other window");
4817
ccd0664b
RS
4818 return window;
4819}
4820
4821DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
fdb82f93
PJ
4822 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4823A near full screen is `next-screen-context-lines' less than a full screen.
4824The next window is the one below the current one; or the one at the top
4825if the current one is at the bottom. Negative ARG means scroll downward.
4826If ARG is the atom `-', scroll downward by nearly full screen.
4827When calling from a program, supply as argument a number, nil, or `-'.
4828
fdb82f93 4829If `other-window-scroll-buffer' is non-nil, scroll the window
a0a37a6f
LT
4830showing that buffer, popping the buffer up if necessary.
4831If in the minibuffer, `minibuffer-scroll-window' if non-nil
4832specifies the window to scroll. This takes precedence over
4833`other-window-scroll-buffer'. */)
5842a27b 4834 (Lisp_Object arg)
ccd0664b 4835{
d4e7cf01
GM
4836 Lisp_Object window;
4837 struct window *w;
d311d28c 4838 ptrdiff_t count = SPECPDL_INDEX ();
ccd0664b
RS
4839
4840 window = Fother_window_for_scrolling ();
7ab12479 4841 w = XWINDOW (window);
7ab12479
JB
4842
4843 /* Don't screw up if window_scroll gets an error. */
4844 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5500c422 4845 ++windows_or_buffers_changed;
7ab12479
JB
4846
4847 Fset_buffer (w->buffer);
4848 SET_PT (marker_position (w->pointm));
4849
413430c5 4850 if (NILP (arg))
d4e7cf01 4851 window_scroll (window, 1, 1, 1);
413430c5 4852 else if (EQ (arg, Qminus))
d4e7cf01 4853 window_scroll (window, -1, 1, 1);
7ab12479
JB
4854 else
4855 {
413430c5
EN
4856 if (CONSP (arg))
4857 arg = Fcar (arg);
b7826503 4858 CHECK_NUMBER (arg);
101d1605 4859 window_scroll (window, XINT (arg), 0, 1);
7ab12479
JB
4860 }
4861
b73ea88e 4862 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
f4e7b2c2 4863 unbind_to (count, Qnil);
7ab12479
JB
4864
4865 return Qnil;
4866}
4867\f
e0965597 4868DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
fdb82f93 4869 doc: /* Scroll selected window display ARG columns left.
2fe41216
EZ
4870Default for ARG is window width minus 2.
4871Value is the total amount of leftward horizontal scrolling in
4872effect after the change.
23fe745a 4873If SET-MINIMUM is non-nil, the new scroll amount becomes the
dc297565 4874lower bound for automatic scrolling, i.e. automatic scrolling
2fe41216 4875will not scroll a window to a column less than the value returned
dc297565 4876by this function. This happens in an interactive call. */)
5842a27b 4877 (register Lisp_Object arg, Lisp_Object set_minimum)
7ab12479 4878{
c67fa410 4879 struct window *w = XWINDOW (selected_window);
aa754e6a
PE
4880 EMACS_INT requested_arg = (NILP (arg)
4881 ? window_body_cols (w) - 2
4882 : XINT (Fprefix_numeric_value (arg)));
24a212eb 4883 Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
c67fa410 4884
dc297565 4885 if (!NILP (set_minimum))
c67fa410
GM
4886 w->min_hscroll = w->hscroll;
4887
4888 return result;
7ab12479
JB
4889}
4890
e0965597 4891DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
fdb82f93 4892 doc: /* Scroll selected window display ARG columns right.
2fe41216
EZ
4893Default for ARG is window width minus 2.
4894Value is the total amount of leftward horizontal scrolling in
4895effect after the change.
23fe745a 4896If SET-MINIMUM is non-nil, the new scroll amount becomes the
dc297565 4897lower bound for automatic scrolling, i.e. automatic scrolling
2fe41216 4898will not scroll a window to a column less than the value returned
dc297565 4899by this function. This happens in an interactive call. */)
5842a27b 4900 (register Lisp_Object arg, Lisp_Object set_minimum)
7ab12479 4901{
c67fa410 4902 struct window *w = XWINDOW (selected_window);
aa754e6a
PE
4903 EMACS_INT requested_arg = (NILP (arg)
4904 ? window_body_cols (w) - 2
4905 : XINT (Fprefix_numeric_value (arg)));
24a212eb 4906 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
177c0ea7 4907
dc297565 4908 if (!NILP (set_minimum))
c67fa410
GM
4909 w->min_hscroll = w->hscroll;
4910
4911 return result;
7ab12479
JB
4912}
4913
fa832261
KS
4914DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
4915 doc: /* Return the window which was selected when entering the minibuffer.
12bb3111 4916Returns nil, if selected window is not a minibuffer window. */)
5842a27b 4917 (void)
fa832261
KS
4918{
4919 if (minibuf_level > 0
4920 && MINI_WINDOW_P (XWINDOW (selected_window))
fa832261
KS
4921 && WINDOW_LIVE_P (minibuf_selected_window))
4922 return minibuf_selected_window;
4923
4924 return Qnil;
4925}
4926
12c8b416
GM
4927/* Value is the number of lines actually displayed in window W,
4928 as opposed to its height. */
4929
4930static int
971de7fb 4931displayed_window_lines (struct window *w)
12c8b416
GM
4932{
4933 struct it it;
4934 struct text_pos start;
4935 int height = window_box_height (w);
4936 struct buffer *old_buffer;
4937 int bottom_y;
57b3e30b 4938 void *itdata = NULL;
12c8b416
GM
4939
4940 if (XBUFFER (w->buffer) != current_buffer)
4941 {
4942 old_buffer = current_buffer;
4943 set_buffer_internal (XBUFFER (w->buffer));
4944 }
4945 else
4946 old_buffer = NULL;
4947
521b203e
GM
4948 /* In case W->start is out of the accessible range, do something
4949 reasonable. This happens in Info mode when Info-scroll-down
4950 calls (recenter -1) while W->start is 1. */
4951 if (XMARKER (w->start)->charpos < BEGV)
4952 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4953 else if (XMARKER (w->start)->charpos > ZV)
4954 SET_TEXT_POS (start, ZV, ZV_BYTE);
4955 else
4956 SET_TEXT_POS_FROM_MARKER (start, w->start);
4957
57b3e30b 4958 itdata = bidi_shelve_cache ();
12c8b416
GM
4959 start_display (&it, w, start);
4960 move_it_vertically (&it, height);
c8bc6f65 4961 bottom_y = line_bottom_y (&it);
35928349 4962 bidi_unshelve_cache (itdata, 0);
12c8b416 4963
1de65f51
RS
4964 /* rms: On a non-window display,
4965 the value of it.vpos at the bottom of the screen
4966 seems to be 1 larger than window_box_height (w).
4967 This kludge fixes a bug whereby (move-to-window-line -1)
4968 when ZV is on the last screen line
4969 moves to the previous screen line instead of the last one. */
4970 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
4971 height++;
4972
12c8b416
GM
4973 /* Add in empty lines at the bottom of the window. */
4974 if (bottom_y < height)
4975 {
949cf20f 4976 int uy = FRAME_LINE_HEIGHT (it.f);
c8bc6f65 4977 it.vpos += (height - bottom_y + uy - 1) / uy;
12c8b416
GM
4978 }
4979
c8bc6f65
GM
4980 if (old_buffer)
4981 set_buffer_internal (old_buffer);
4982
12c8b416
GM
4983 return it.vpos;
4984}
4985
4986
a7ca3326 4987DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
666e158e 4988 doc: /* Center point in selected window and maybe redisplay frame.
fdb82f93 4989With prefix argument ARG, recenter putting point on screen line ARG
12bb3111 4990relative to the selected window. If ARG is negative, it counts up from the
fdb82f93
PJ
4991bottom of the window. (ARG should be less than the height of the window.)
4992
666e158e
MB
4993If ARG is omitted or nil, then recenter with point on the middle line of
4994the selected window; if the variable `recenter-redisplay' is non-nil,
4995also erase the entire frame and redraw it (when `auto-resize-tool-bars'
4996is set to `grow-only', this resets the tool-bar's height to the minimum
4997height needed); if `recenter-redisplay' has the special value `tty',
53524d93 4998then only tty frames are redrawn.
7d1d98ee 4999
fdb82f93
PJ
5000Just C-u as prefix means put point in the center of the window
5001and redisplay normally--don't erase and redraw the frame. */)
5842a27b 5002 (register Lisp_Object arg)
7ab12479 5003{
6df47b59 5004 struct window *w = XWINDOW (selected_window);
478292ed
RS
5005 struct buffer *buf = XBUFFER (w->buffer);
5006 struct buffer *obuf = current_buffer;
6df47b59 5007 int center_p = 0;
d311d28c 5008 ptrdiff_t charpos, bytepos;
71f02bc5 5009 EMACS_INT iarg IF_LINT (= 0);
f6b43440 5010 int this_scroll_margin;
7ab12479 5011
0fa5d25b
RS
5012 /* If redisplay is suppressed due to an error, try again. */
5013 obuf->display_error_modiff = 0;
5014
413430c5 5015 if (NILP (arg))
7ab12479 5016 {
666e158e
MB
5017 if (!NILP (Vrecenter_redisplay)
5018 && (!EQ (Vrecenter_redisplay, Qtty)
5019 || !NILP (Ftty_type (selected_frame))))
5020 {
ebfa62c0 5021 ptrdiff_t i;
f02d6d5c 5022
666e158e
MB
5023 /* Invalidate pixel data calculated for all compositions. */
5024 for (i = 0; i < n_compositions; i++)
5025 composition_table[i]->font = NULL;
7ab12479 5026
666e158e
MB
5027 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5028
5029 Fredraw_frame (WINDOW_FRAME (w));
5030 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5031 }
7d1d98ee 5032
6df47b59 5033 center_p = 1;
7ab12479 5034 }
413430c5 5035 else if (CONSP (arg)) /* Just C-u. */
6df47b59 5036 center_p = 1;
7ab12479
JB
5037 else
5038 {
413430c5 5039 arg = Fprefix_numeric_value (arg);
b7826503 5040 CHECK_NUMBER (arg);
ae12ecd7 5041 iarg = XINT (arg);
7ab12479
JB
5042 }
5043
478292ed 5044 set_buffer_internal (buf);
7ab12479 5045
f6b43440
RS
5046 /* Do this after making BUF current
5047 in case scroll_margin is buffer-local. */
71f02bc5
PE
5048 this_scroll_margin =
5049 max (0, min (scroll_margin, XFASTINT (w->total_lines) / 4));
f6b43440 5050
521b203e 5051 /* Handle centering on a graphical frame specially. Such frames can
6df47b59
GM
5052 have variable-height lines and centering point on the basis of
5053 line counts would lead to strange effects. */
521b203e 5054 if (FRAME_WINDOW_P (XFRAME (w->frame)))
6df47b59 5055 {
6df47b59
GM
5056 if (center_p)
5057 {
521b203e
GM
5058 struct it it;
5059 struct text_pos pt;
57b3e30b 5060 void *itdata = bidi_shelve_cache ();
177c0ea7 5061
521b203e
GM
5062 SET_TEXT_POS (pt, PT, PT_BYTE);
5063 start_display (&it, w, pt);
f204989e 5064 move_it_vertically_backward (&it, window_box_height (w) / 2);
521b203e
GM
5065 charpos = IT_CHARPOS (it);
5066 bytepos = IT_BYTEPOS (it);
35928349 5067 bidi_unshelve_cache (itdata, 0);
6df47b59 5068 }
f6b43440 5069 else if (iarg < 0)
6df47b59 5070 {
521b203e
GM
5071 struct it it;
5072 struct text_pos pt;
5895d7b9 5073 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
f204989e
KS
5074 int extra_line_spacing;
5075 int h = window_box_height (w);
57b3e30b 5076 void *itdata = bidi_shelve_cache ();
177c0ea7 5077
f6b43440
RS
5078 iarg = - max (-iarg, this_scroll_margin);
5079
521b203e
GM
5080 SET_TEXT_POS (pt, PT, PT_BYTE);
5081 start_display (&it, w, pt);
f204989e
KS
5082
5083 /* Be sure we have the exact height of the full line containing PT. */
e4cc2dfc 5084 move_it_by_lines (&it, 0);
521b203e 5085
d466fa4d 5086 /* The amount of pixels we have to move back is the window
521b203e
GM
5087 height minus what's displayed in the line containing PT,
5088 and the lines below. */
f204989e
KS
5089 it.current_y = 0;
5090 it.vpos = 0;
e4cc2dfc 5091 move_it_by_lines (&it, nlines);
d466fa4d 5092
f204989e
KS
5093 if (it.vpos == nlines)
5094 h -= it.current_y;
5095 else
5096 {
5097 /* Last line has no newline */
5098 h -= line_bottom_y (&it);
5099 it.vpos++;
5100 }
5101
5102 /* Don't reserve space for extra line spacing of last line. */
5103 extra_line_spacing = it.max_extra_line_spacing;
d466fa4d
GM
5104
5105 /* If we can't move down NLINES lines because we hit
5106 the end of the buffer, count in some empty lines. */
5107 if (it.vpos < nlines)
f204989e
KS
5108 {
5109 nlines -= it.vpos;
5110 extra_line_spacing = it.extra_line_spacing;
5111 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5112 }
5113 if (h <= 0)
57b3e30b 5114 {
35928349 5115 bidi_unshelve_cache (itdata, 0);
57b3e30b
EZ
5116 return Qnil;
5117 }
201c831a 5118
f204989e 5119 /* Now find the new top line (starting position) of the window. */
521b203e 5120 start_display (&it, w, pt);
f204989e
KS
5121 it.current_y = 0;
5122 move_it_vertically_backward (&it, h);
5123
5124 /* If extra line spacing is present, we may move too far
5125 back. This causes the last line to be only partially
5126 visible (which triggers redisplay to recenter that line
5127 in the middle), so move forward.
5128 But ignore extra line spacing on last line, as it is not
5129 considered to be part of the visible height of the line.
5130 */
5131 h += extra_line_spacing;
5132 while (-it.current_y > h)
e4cc2dfc 5133 move_it_by_lines (&it, 1);
f204989e 5134
521b203e
GM
5135 charpos = IT_CHARPOS (it);
5136 bytepos = IT_BYTEPOS (it);
57b3e30b 5137
35928349 5138 bidi_unshelve_cache (itdata, 0);
6df47b59 5139 }
521b203e
GM
5140 else
5141 {
5142 struct position pos;
f6b43440 5143
f6b43440
RS
5144 iarg = max (iarg, this_scroll_margin);
5145
5146 pos = *vmotion (PT, -iarg, w);
521b203e
GM
5147 charpos = pos.bufpos;
5148 bytepos = pos.bytepos;
5149 }
5150 }
5151 else
5152 {
5153 struct position pos;
5154 int ht = window_internal_height (w);
5155
5156 if (center_p)
a4429c5b 5157 iarg = ht / 2;
f567c488
KS
5158 else if (iarg < 0)
5159 iarg += ht;
f6b43440
RS
5160
5161 /* Don't let it get into the margin at either top or bottom. */
5162 iarg = max (iarg, this_scroll_margin);
5163 iarg = min (iarg, ht - this_scroll_margin - 1);
177c0ea7 5164
f6b43440 5165 pos = *vmotion (PT, - iarg, w);
6df47b59
GM
5166 charpos = pos.bufpos;
5167 bytepos = pos.bytepos;
5168 }
5169
5170 /* Set the new window start. */
5171 set_marker_both (w->start, w->buffer, charpos, bytepos);
2f3cad6c 5172 w->window_end_valid = Qnil;
177c0ea7 5173
c98ff5dd 5174 w->optional_new_start = 1;
95605b1b 5175
c98ff5dd
DA
5176 w->start_at_line_beg = (bytepos == BEGV_BYTE ||
5177 FETCH_BYTE (bytepos - 1) == '\n');
177c0ea7 5178
478292ed 5179 set_buffer_internal (obuf);
7ab12479
JB
5180 return Qnil;
5181}
b7617575 5182
81fe0836 5183DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
fdb82f93
PJ
5184 0, 1, 0,
5185 doc: /* Return the height in lines of the text display area of WINDOW.
105216ed 5186If WINDOW is omitted or nil, it defaults to the selected window.
8fef9de1 5187
105216ed
CY
5188The returned height does not include the mode line, any header line,
5189nor any partial-height lines at the bottom of the text area. */)
5842a27b 5190 (Lisp_Object window)
81fe0836
MB
5191{
5192 struct window *w = decode_window (window);
5193 int pixel_height = window_box_height (w);
949cf20f 5194 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
81fe0836
MB
5195 return make_number (line_height);
5196}
5197
5198
7ab12479
JB
5199\f
5200DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
fdb82f93
PJ
5201 1, 1, "P",
5202 doc: /* Position point relative to window.
87e68db4
JB
5203ARG nil means position point at center of window.
5204Else, ARG specifies vertical position within the window;
fdb82f93 5205zero means top of window, negative means relative to bottom of window. */)
5842a27b 5206 (Lisp_Object arg)
7ab12479 5207{
b7617575
GM
5208 struct window *w = XWINDOW (selected_window);
5209 int lines, start;
540b6aa0 5210 Lisp_Object window;
f6b43440
RS
5211#if 0
5212 int this_scroll_margin;
5213#endif
7ab12479 5214
794b75c7
SM
5215 if (!(BUFFERP (w->buffer)
5216 && XBUFFER (w->buffer) == current_buffer))
5217 /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
5218 when passed below to set_marker_both. */
5219 error ("move-to-window-line called from unrelated buffer");
6dc1d2d3 5220
b7617575 5221 window = selected_window;
7ab12479
JB
5222 start = marker_position (w->start);
5223 if (start < BEGV || start > ZV)
5224 {
b7617575 5225 int height = window_internal_height (w);
cd2be1dd 5226 Fvertical_motion (make_number (- (height / 2)), window);
b73ea88e 5227 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
c98ff5dd
DA
5228 w->start_at_line_beg = !NILP (Fbolp ());
5229 w->force_start = 1;
7ab12479
JB
5230 }
5231 else
b73ea88e 5232 Fgoto_char (w->start);
7ab12479 5233
b7617575 5234 lines = displayed_window_lines (w);
f6b43440
RS
5235
5236#if 0
71f02bc5 5237 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
f6b43440
RS
5238#endif
5239
b7617575
GM
5240 if (NILP (arg))
5241 XSETFASTINT (arg, lines / 2);
5242 else
5243 {
71f02bc5 5244 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
f6b43440
RS
5245
5246 if (iarg < 0)
5247 iarg = iarg + lines;
5248
5249#if 0 /* This code would prevent move-to-window-line from moving point
5250 to a place inside the scroll margins (which would cause the
5251 next redisplay to scroll). I wrote this code, but then concluded
5252 it is probably better not to install it. However, it is here
5253 inside #if 0 so as not to lose it. -- rms. */
5254
5255 /* Don't let it get into the margin at either top or bottom. */
5256 iarg = max (iarg, this_scroll_margin);
5257 iarg = min (iarg, lines - this_scroll_margin - 1);
5258#endif
5259
5260 arg = make_number (iarg);
b7617575
GM
5261 }
5262
c8bc6f65 5263 /* Skip past a partially visible first line. */
163784df 5264 if (w->vscroll)
163784df
MB
5265 XSETINT (arg, XINT (arg) + 1);
5266
540b6aa0 5267 return Fvertical_motion (arg, window);
7ab12479 5268}
5500c422
GM
5269
5270
7ab12479 5271\f
5500c422
GM
5272/***********************************************************************
5273 Window Configuration
5274 ***********************************************************************/
5275
7ab12479
JB
5276struct save_window_data
5277 {
b102ceb1 5278 struct vectorlike_header header;
bdc727bf 5279 Lisp_Object selected_frame;
7ab12479
JB
5280 Lisp_Object current_window;
5281 Lisp_Object current_buffer;
5282 Lisp_Object minibuf_scroll_window;
3f49fddc 5283 Lisp_Object minibuf_selected_window;
7ab12479 5284 Lisp_Object root_window;
bdc727bf 5285 Lisp_Object focus_frame;
cbff28e8
RS
5286 /* A vector, each of whose elements is a struct saved_window
5287 for one window. */
7ab12479 5288 Lisp_Object saved_windows;
b05b4e27
SM
5289
5290 /* All fields above are traced by the GC.
5291 From `fame-cols' down, the fields are ignored by the GC. */
5292
5293 int frame_cols, frame_lines, frame_menu_bar_lines;
5294 int frame_tool_bar_lines;
7ab12479 5295 };
ff06df24 5296
cbff28e8 5297/* This is saved as a Lisp_Vector */
7ab12479 5298struct saved_window
ea68264b 5299{
b102ceb1 5300 struct vectorlike_header header;
496e208e 5301
28545e04 5302 Lisp_Object window, buffer, start, pointm, mark;
949cf20f 5303 Lisp_Object left_col, top_line, total_cols, total_lines;
496e208e 5304 Lisp_Object normal_cols, normal_lines;
949cf20f 5305 Lisp_Object hscroll, min_hscroll;
ea68264b
GM
5306 Lisp_Object parent, prev;
5307 Lisp_Object start_at_line_beg;
5308 Lisp_Object display_table;
949cf20f
KS
5309 Lisp_Object left_margin_cols, right_margin_cols;
5310 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
562dd5e9 5311 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
b6f67890 5312 Lisp_Object combination_limit, window_parameters;
ea68264b
GM
5313};
5314
7ab12479
JB
5315#define SAVED_WINDOW_N(swv,n) \
5316 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5317
5318DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
fdb82f93 5319 doc: /* Return t if OBJECT is a window-configuration object. */)
5842a27b 5320 (Lisp_Object object)
7ab12479 5321{
6ad0381c 5322 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
7ab12479
JB
5323}
5324
3f8ab7bd 5325DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
fdb82f93 5326 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5842a27b 5327 (Lisp_Object config)
3f8ab7bd
RS
5328{
5329 register struct save_window_data *data;
5330 struct Lisp_Vector *saved_windows;
5331
663fbbba 5332 CHECK_WINDOW_CONFIGURATION (config);
3f8ab7bd
RS
5333
5334 data = (struct save_window_data *) XVECTOR (config);
5335 saved_windows = XVECTOR (data->saved_windows);
5336 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5337}
5338
a7ca3326 5339DEFUN ("set-window-configuration", Fset_window_configuration,
fdb82f93
PJ
5340 Sset_window_configuration, 1, 1, 0,
5341 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5342CONFIGURATION must be a value previously returned
5343by `current-window-configuration' (which see).
5344If CONFIGURATION was made from a frame that is now deleted,
5345only frame-independent values can be restored. In this case,
5346the return value is nil. Otherwise the value is t. */)
5842a27b 5347 (Lisp_Object configuration)
7ab12479 5348{
7ab12479
JB
5349 register struct save_window_data *data;
5350 struct Lisp_Vector *saved_windows;
7ab12479 5351 Lisp_Object new_current_buffer;
fd482be5 5352 Lisp_Object frame;
6198ccd0 5353 Lisp_Object auto_buffer_name;
44fa5b1e 5354 FRAME_PTR f;
d311d28c 5355 ptrdiff_t old_point = -1;
7ab12479 5356
663fbbba 5357 CHECK_WINDOW_CONFIGURATION (configuration);
7ab12479 5358
2f83aebe 5359 data = (struct save_window_data *) XVECTOR (configuration);
7ab12479
JB
5360 saved_windows = XVECTOR (data->saved_windows);
5361
7ab12479 5362 new_current_buffer = data->current_buffer;
4b4deea2 5363 if (NILP (BVAR (XBUFFER (new_current_buffer), name)))
7ab12479 5364 new_current_buffer = Qnil;
72695e47 5365 else
73cadfc1
DK
5366 {
5367 if (XBUFFER (new_current_buffer) == current_buffer)
e67a1dea
SM
5368 /* The code further down "preserves point" by saving here PT in
5369 old_point and then setting it later back into PT. When the
5370 current-selected-window and the final-selected-window both show
5371 the current buffer, this suffers from the problem that the
5372 current PT is the window-point of the current-selected-window,
5373 while the final PT is the point of the final-selected-window, so
5374 this copy from one PT to the other would end up moving the
5375 window-point of the final-selected-window to the window-point of
5376 the current-selected-window. So we have to be careful which
5377 point of the current-buffer we copy into old_point. */
5378 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5379 && WINDOWP (selected_window)
5380 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
5381 && !EQ (selected_window, data->current_window))
5382 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5383 else
5384 old_point = PT;
73cadfc1 5385 else
203eb0aa
SM
5386 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5387 point in new_current_buffer as of the last time this buffer was
5388 used. This can be non-deterministic since it can be changed by
5389 things like jit-lock by mere temporary selection of some random
5390 window that happens to show this buffer.
5391 So if possible we want this arbitrary choice of "which point" to
5392 be the one from the to-be-selected-window so as to prevent this
5393 window's cursor from being copied from another window. */
5394 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5395 /* If current_window = selected_window, its point is in BUF_PT. */
5396 && !EQ (selected_window, data->current_window))
5397 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5398 else
5399 old_point = BUF_PT (XBUFFER (new_current_buffer));
73cadfc1 5400 }
7ab12479 5401
fd482be5
JB
5402 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5403 f = XFRAME (frame);
177c0ea7 5404
fd482be5
JB
5405 /* If f is a dead frame, don't bother rebuilding its window tree.
5406 However, there is other stuff we should still try to do below. */
5407 if (FRAME_LIVE_P (f))
7ab12479 5408 {
6198ccd0
MR
5409 Lisp_Object window;
5410 Lisp_Object dead_windows = Qnil;
6a6ee00d 5411 register Lisp_Object tem, par, pers;
fd482be5
JB
5412 register struct window *w;
5413 register struct saved_window *p;
5500c422
GM
5414 struct window *root_window;
5415 struct window **leaf_windows;
5416 int n_leaf_windows;
71f02bc5
PE
5417 ptrdiff_t k;
5418 int i, n;
fd482be5
JB
5419
5420 /* If the frame has been resized since this window configuration was
5421 made, we change the frame to the size specified in the
5422 configuration, restore the configuration, and then resize it
5423 back. We keep track of the prevailing height in these variables. */
949cf20f
KS
5424 int previous_frame_lines = FRAME_LINES (f);
5425 int previous_frame_cols = FRAME_COLS (f);
8f6ea2e9 5426 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
9ea173e8 5427 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
fd482be5 5428
d2b35234
RS
5429 /* The mouse highlighting code could get screwed up
5430 if it runs during this. */
5431 BLOCK_INPUT;
5432
b05b4e27
SM
5433 if (data->frame_lines != previous_frame_lines
5434 || data->frame_cols != previous_frame_cols)
5435 change_frame_size (f, data->frame_lines,
5436 data->frame_cols, 0, 0, 0);
e3678b64 5437#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
b05b4e27 5438 if (data->frame_menu_bar_lines
8f6ea2e9 5439 != previous_frame_menu_bar_lines)
b05b4e27
SM
5440 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
5441 make_number (0));
4314246f 5442#ifdef HAVE_WINDOW_SYSTEM
b05b4e27 5443 if (data->frame_tool_bar_lines
9ea173e8 5444 != previous_frame_tool_bar_lines)
b05b4e27
SM
5445 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
5446 make_number (0));
4314246f 5447#endif
217f2871 5448#endif
fd482be5 5449
a46c0153
RS
5450 /* "Swap out" point from the selected window's buffer
5451 into the window itself. (Normally the pointm of the selected
5452 window holds garbage.) We do this now, before
719eaeb1
GM
5453 restoring the window contents, and prevent it from
5454 being done later on when we select a new window. */
596ae0cf
RS
5455 if (! NILP (XWINDOW (selected_window)->buffer))
5456 {
5457 w = XWINDOW (selected_window);
5458 set_marker_both (w->pointm,
5459 w->buffer,
5460 BUF_PT (XBUFFER (w->buffer)),
5461 BUF_PT_BYTE (XBUFFER (w->buffer)));
5462 }
5463
fd482be5 5464 windows_or_buffers_changed++;
29aeee73 5465 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
fd482be5 5466
5500c422 5467 /* Problem: Freeing all matrices and later allocating them again
177c0ea7 5468 is a serious redisplay flickering problem. What we would
5500c422 5469 really like to do is to free only those matrices not reused
9d14503e 5470 below. */
5500c422 5471 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
38182d90
PE
5472 leaf_windows = alloca (count_windows (root_window)
5473 * sizeof *leaf_windows);
5500c422
GM
5474 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5475
fd482be5
JB
5476 /* Kludge Alert!
5477 Mark all windows now on frame as "deleted".
5478 Restoring the new configuration "undeletes" any that are in it.
37962e60 5479
fd482be5
JB
5480 Save their current buffers in their height fields, since we may
5481 need it later, if a buffer saved in the configuration is now
5482 dead. */
be7f5545 5483 delete_all_child_windows (FRAME_ROOT_WINDOW (f));
fd482be5 5484
eab3844f 5485 for (k = 0; k < saved_windows->header.size; k++)
fd482be5
JB
5486 {
5487 p = SAVED_WINDOW_N (saved_windows, k);
6198ccd0
MR
5488 window = p->window;
5489 w = XWINDOW (window);
fd482be5 5490 w->next = Qnil;
7ab12479 5491
fd482be5
JB
5492 if (!NILP (p->parent))
5493 w->parent = SAVED_WINDOW_N (saved_windows,
5494 XFASTINT (p->parent))->window;
5495 else
5496 w->parent = Qnil;
7ab12479 5497
fd482be5 5498 if (!NILP (p->prev))
7ab12479 5499 {
fd482be5
JB
5500 w->prev = SAVED_WINDOW_N (saved_windows,
5501 XFASTINT (p->prev))->window;
5502 XWINDOW (w->prev)->next = p->window;
5503 }
5504 else
5505 {
5506 w->prev = Qnil;
5507 if (!NILP (w->parent))
5508 {
949cf20f 5509 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
fd482be5
JB
5510 {
5511 XWINDOW (w->parent)->vchild = p->window;
5512 XWINDOW (w->parent)->hchild = Qnil;
5513 }
5514 else
5515 {
5516 XWINDOW (w->parent)->hchild = p->window;
5517 XWINDOW (w->parent)->vchild = Qnil;
5518 }
5519 }
5520 }
5521
5522 /* If we squirreled away the buffer in the window's height,
5523 restore it now. */
949cf20f
KS
5524 if (BUFFERP (w->total_lines))
5525 w->buffer = w->total_lines;
5526 w->left_col = p->left_col;
5527 w->top_line = p->top_line;
5528 w->total_cols = p->total_cols;
5529 w->total_lines = p->total_lines;
496e208e
MR
5530 w->normal_cols = p->normal_cols;
5531 w->normal_lines = p->normal_lines;
80b00b08
DA
5532 w->hscroll = XFASTINT (p->hscroll);
5533 w->min_hscroll = XFASTINT (p->min_hscroll);
fd482be5 5534 w->display_table = p->display_table;
949cf20f
KS
5535 w->left_margin_cols = p->left_margin_cols;
5536 w->right_margin_cols = p->right_margin_cols;
5537 w->left_fringe_width = p->left_fringe_width;
5538 w->right_fringe_width = p->right_fringe_width;
2af3565e 5539 w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
949cf20f
KS
5540 w->scroll_bar_width = p->scroll_bar_width;
5541 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
6ad0381c 5542 w->dedicated = p->dedicated;
b6f67890 5543 w->combination_limit = p->combination_limit;
6a6ee00d
MR
5544 /* Restore any window parameters that have been saved.
5545 Parameters that have not been saved are left alone. */
5546 for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
5547 {
5548 pers = XCAR (tem);
5549 if (CONSP (pers))
5550 {
5551 if (NILP (XCDR (pers)))
5552 {
5553 par = Fassq (XCAR (pers), w->window_parameters);
5554 if (CONSP (par) && !NILP (XCDR (par)))
5555 /* Reset a parameter to nil if and only if it
5556 has a non-nil association. Don't make new
5557 associations. */
5558 Fsetcdr (par, Qnil);
5559 }
5560 else
5561 /* Always restore a non-nil value. */
5562 Fset_window_parameter (window, XCAR (pers), XCDR (pers));
5563 }
5564 }
5565
80b00b08
DA
5566 w->last_modified = 0;
5567 w->last_overlay_modified = 0;
fd482be5
JB
5568
5569 /* Reinstall the saved buffer and pointers into it. */
5570 if (NILP (p->buffer))
6198ccd0 5571 /* An internal window. */
fd482be5 5572 w->buffer = p->buffer;
6198ccd0
MR
5573 else if (!NILP (BVAR (XBUFFER (p->buffer), name)))
5574 /* If saved buffer is alive, install it. */
5575 {
5576 w->buffer = p->buffer;
c98ff5dd 5577 w->start_at_line_beg = !NILP (p->start_at_line_beg);
6198ccd0
MR
5578 set_marker_restricted (w->start, p->start, w->buffer);
5579 set_marker_restricted (w->pointm, p->pointm, w->buffer);
5580 Fset_marker (BVAR (XBUFFER (w->buffer), mark),
5581 p->mark, w->buffer);
5582
5583 /* As documented in Fcurrent_window_configuration, don't
5584 restore the location of point in the buffer which was
5585 current when the window configuration was recorded. */
5586 if (!EQ (p->buffer, new_current_buffer)
5587 && XBUFFER (p->buffer) == current_buffer)
5588 Fgoto_char (w->pointm);
5589 }
5590 else if (!NILP (w->buffer) && !NILP (BVAR (XBUFFER (w->buffer), name)))
5591 /* Keep window's old buffer; make sure the markers are
5592 real. */
5593 {
5594 /* Set window markers at start of visible range. */
5595 if (XMARKER (w->start)->buffer == 0)
5596 set_marker_restricted (w->start, make_number (0),
5597 w->buffer);
5598 if (XMARKER (w->pointm)->buffer == 0)
5599 set_marker_restricted_both (w->pointm, w->buffer,
5600 BUF_PT (XBUFFER (w->buffer)),
5601 BUF_PT_BYTE (XBUFFER (w->buffer)));
c98ff5dd 5602 w->start_at_line_beg = 1;
6198ccd0
MR
5603 }
5604 else if (STRINGP (auto_buffer_name =
5605 Fwindow_parameter (window, Qauto_buffer_name))
5606 && SCHARS (auto_buffer_name) != 0
5607 && !NILP (w->buffer = Fget_buffer_create (auto_buffer_name)))
5608 {
5609 set_marker_restricted (w->start, make_number (0), w->buffer);
5610 set_marker_restricted (w->pointm, make_number (0), w->buffer);
c98ff5dd 5611 w->start_at_line_beg = 1;
6198ccd0 5612 }
fd482be5 5613 else
6198ccd0 5614 /* Window has no live buffer, get one. */
fd482be5 5615 {
6198ccd0
MR
5616 /* Get the buffer via other_buffer_safely in order to
5617 avoid showing an unimportant buffer and, if necessary, to
5618 recreate *scratch* in the course (part of Juanma's bs-show
5619 scenario from March 2011). */
5620 w->buffer = other_buffer_safely (Fcurrent_buffer ());
5621 /* This will set the markers to beginning of visible
5622 range. */
5623 set_marker_restricted (w->start, make_number (0), w->buffer);
5624 set_marker_restricted (w->pointm, make_number (0), w->buffer);
c98ff5dd 5625 w->start_at_line_beg = 1;
6198ccd0
MR
5626 if (!NILP (w->dedicated))
5627 /* Record this window as dead. */
5628 dead_windows = Fcons (window, dead_windows);
5629 /* Make sure window is no more dedicated. */
5630 w->dedicated = Qnil;
7ab12479
JB
5631 }
5632 }
9ace597f 5633
fd482be5 5634 FRAME_ROOT_WINDOW (f) = data->root_window;
a46c0153
RS
5635 /* Arrange *not* to restore point in the buffer that was
5636 current when the window configuration was saved. */
243a5ce6
RS
5637 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5638 set_marker_restricted (XWINDOW (data->current_window)->pointm,
18787f5e 5639 make_number (old_point),
243a5ce6 5640 XWINDOW (data->current_window)->buffer);
177c0ea7 5641
6198ccd0
MR
5642 /* In the following call to `select-window', prevent "swapping out
5643 point" in the old selected window using the buffer that has
5644 been restored into it. We already swapped out that point from
5645 that window's old buffer. */
e6b84b30 5646 select_window (data->current_window, Qnil, 1);
4b4deea2 5647 BVAR (XBUFFER (XWINDOW (selected_window)->buffer), last_selected_window)
396a830c 5648 = selected_window;
7ab12479 5649
db269683 5650 if (NILP (data->focus_frame)
017b2bad 5651 || (FRAMEP (data->focus_frame)
db269683
JB
5652 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5653 Fredirect_frame_focus (frame, data->focus_frame);
7ab12479 5654
fd482be5 5655 /* Set the screen height to the value it had before this function. */
949cf20f
KS
5656 if (previous_frame_lines != FRAME_LINES (f)
5657 || previous_frame_cols != FRAME_COLS (f))
5658 change_frame_size (f, previous_frame_lines, previous_frame_cols,
2b653806 5659 0, 0, 0);
e3678b64 5660#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9 5661 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
f8ad443a
AS
5662 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5663 make_number (0));
4314246f 5664#ifdef HAVE_WINDOW_SYSTEM
9ea173e8
GM
5665 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5666 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5667 make_number (0));
4314246f 5668#endif
217f2871 5669#endif
d2b35234 5670
5500c422 5671 /* Now, free glyph matrices in windows that were not reused. */
c4280705
GM
5672 for (i = n = 0; i < n_leaf_windows; ++i)
5673 {
5674 if (NILP (leaf_windows[i]->buffer))
5675 {
5676 /* Assert it's not reused as a combination. */
a54e2c05 5677 eassert (NILP (leaf_windows[i]->hchild)
c4280705
GM
5678 && NILP (leaf_windows[i]->vchild));
5679 free_window_matrices (leaf_windows[i]);
c4280705
GM
5680 }
5681 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5682 ++n;
5683 }
177c0ea7 5684
5500c422 5685 adjust_glyphs (f);
d2b35234 5686 UNBLOCK_INPUT;
756b6edc 5687
6198ccd0
MR
5688 /* Scan dead buffer windows. */
5689 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
5690 {
5691 window = XCAR (dead_windows);
5692 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
5693 delete_deletable_window (window);
5694 }
5695
478292ed
RS
5696 /* Fselect_window will have made f the selected frame, so we
5697 reselect the proper frame here. Fhandle_switch_frame will change the
5698 selected window too, but that doesn't make the call to
5699 Fselect_window above totally superfluous; it still sets f's
5700 selected window. */
5701 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
c6932ecd 5702 do_switch_frame (data->selected_frame, 0, 0, Qnil);
478292ed 5703
eeca6f6f 5704 run_window_configuration_change_hook (f);
478292ed 5705 }
bdc727bf
JB
5706
5707 if (!NILP (new_current_buffer))
243a5ce6 5708 Fset_buffer (new_current_buffer);
bdc727bf 5709
478292ed 5710 Vminibuf_scroll_window = data->minibuf_scroll_window;
3dbab091 5711 minibuf_selected_window = data->minibuf_selected_window;
543f5fb1 5712
3f8ab7bd 5713 return (FRAME_LIVE_P (f) ? Qt : Qnil);
7ab12479
JB
5714}
5715
562dd5e9 5716
be7f5545
MR
5717/* Recursively delete all child windows reachable via the next, vchild,
5718 and hchild slots of WINDOW. */
fd482be5 5719void
be7f5545 5720delete_all_child_windows (Lisp_Object window)
7ab12479 5721{
fa8a67e6
MR
5722 register struct window *w;
5723
5724 w = XWINDOW (window);
5725
265a9e55 5726 if (!NILP (w->next))
fa8a67e6 5727 /* Delete WINDOW's siblings (we traverse postorderly). */
be7f5545 5728 delete_all_child_windows (w->next);
605be8af 5729
949cf20f 5730 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
605be8af 5731
fa8a67e6
MR
5732 if (!NILP (w->vchild))
5733 {
be7f5545 5734 delete_all_child_windows (w->vchild);
fa8a67e6
MR
5735 w->vchild = Qnil;
5736 }
5737 else if (!NILP (w->hchild))
5738 {
be7f5545 5739 delete_all_child_windows (w->hchild);
fa8a67e6
MR
5740 w->hchild = Qnil;
5741 }
5742 else if (!NILP (w->buffer))
5743 {
5744 unshow_buffer (w);
5745 unchain_marker (XMARKER (w->pointm));
5746 unchain_marker (XMARKER (w->start));
5747 w->buffer = Qnil;
5748 }
acf70840
GM
5749
5750 Vwindow_list = Qnil;
7ab12479
JB
5751}
5752\f
5753static int
971de7fb 5754count_windows (register struct window *window)
7ab12479
JB
5755{
5756 register int count = 1;
265a9e55 5757 if (!NILP (window->next))
7ab12479 5758 count += count_windows (XWINDOW (window->next));
265a9e55 5759 if (!NILP (window->vchild))
7ab12479 5760 count += count_windows (XWINDOW (window->vchild));
265a9e55 5761 if (!NILP (window->hchild))
7ab12479
JB
5762 count += count_windows (XWINDOW (window->hchild));
5763 return count;
5764}
5765
5500c422 5766
177c0ea7 5767/* Fill vector FLAT with leaf windows under W, starting at index I.
5500c422 5768 Value is last index + 1. */
5500c422 5769static int
971de7fb 5770get_leaf_windows (struct window *w, struct window **flat, int i)
5500c422
GM
5771{
5772 while (w)
5773 {
5774 if (!NILP (w->hchild))
5775 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5776 else if (!NILP (w->vchild))
5777 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
177c0ea7 5778 else
5500c422
GM
5779 flat[i++] = w;
5780
5781 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5782 }
5783
5784 return i;
5785}
5786
5787
5788/* Return a pointer to the glyph W's physical cursor is on. Value is
c80e3b4a 5789 null if W's current matrix is invalid, so that no meaningful glyph
5500c422 5790 can be returned. */
5500c422 5791struct glyph *
971de7fb 5792get_phys_cursor_glyph (struct window *w)
5500c422
GM
5793{
5794 struct glyph_row *row;
5795 struct glyph *glyph;
f8fe6f96 5796 int hpos = w->phys_cursor.hpos;
5500c422 5797
f8fe6f96
EZ
5798 if (!(w->phys_cursor.vpos >= 0
5799 && w->phys_cursor.vpos < w->current_matrix->nrows))
5800 return NULL;
5801
5802 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5803 if (!row->enabled_p)
5804 return NULL;
5805
80b00b08 5806 if (w->hscroll)
f8fe6f96
EZ
5807 {
5808 /* When the window is hscrolled, cursor hpos can legitimately be
5809 out of bounds, but we draw the cursor at the corresponding
5810 window margin in that case. */
5811 if (!row->reversed_p && hpos < 0)
5812 hpos = 0;
5813 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
5814 hpos = row->used[TEXT_AREA] - 1;
5815 }
5500c422 5816
f8fe6f96
EZ
5817 if (row->used[TEXT_AREA] > hpos
5818 && 0 <= hpos)
5819 glyph = row->glyphs[TEXT_AREA] + hpos;
5500c422
GM
5820 else
5821 glyph = NULL;
5822
5823 return glyph;
5824}
5825
5826
7ab12479 5827static int
971de7fb 5828save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
7ab12479
JB
5829{
5830 register struct saved_window *p;
5831 register struct window *w;
6a6ee00d 5832 register Lisp_Object tem, pers, par;
7ab12479 5833
265a9e55 5834 for (;!NILP (window); window = w->next)
7ab12479
JB
5835 {
5836 p = SAVED_WINDOW_N (vector, i);
5837 w = XWINDOW (window);
5838
2a1893f4 5839 XSETFASTINT (w->temslot, i); i++;
7ab12479
JB
5840 p->window = window;
5841 p->buffer = w->buffer;
949cf20f
KS
5842 p->left_col = w->left_col;
5843 p->top_line = w->top_line;
5844 p->total_cols = w->total_cols;
5845 p->total_lines = w->total_lines;
496e208e
MR
5846 p->normal_cols = w->normal_cols;
5847 p->normal_lines = w->normal_lines;
80b00b08
DA
5848 XSETFASTINT (p->hscroll, w->hscroll);
5849 XSETFASTINT (p->min_hscroll, w->min_hscroll);
7ab12479 5850 p->display_table = w->display_table;
949cf20f
KS
5851 p->left_margin_cols = w->left_margin_cols;
5852 p->right_margin_cols = w->right_margin_cols;
5853 p->left_fringe_width = w->left_fringe_width;
5854 p->right_fringe_width = w->right_fringe_width;
2af3565e 5855 p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
949cf20f
KS
5856 p->scroll_bar_width = w->scroll_bar_width;
5857 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6ad0381c 5858 p->dedicated = w->dedicated;
b6f67890 5859 p->combination_limit = w->combination_limit;
6a6ee00d
MR
5860 p->window_parameters = Qnil;
5861
5862 if (!NILP (Vwindow_persistent_parameters))
5863 {
5864 /* Run cycle detection on Vwindow_persistent_parameters. */
5865 Lisp_Object tortoise, hare;
5866
5867 hare = tortoise = Vwindow_persistent_parameters;
5868 while (CONSP (hare))
5869 {
5870 hare = XCDR (hare);
5871 if (!CONSP (hare))
5872 break;
5873
5874 hare = XCDR (hare);
5875 tortoise = XCDR (tortoise);
5876
5877 if (EQ (hare, tortoise))
5878 /* Reset Vwindow_persistent_parameters to Qnil. */
5879 {
5880 Vwindow_persistent_parameters = Qnil;
5881 break;
5882 }
5883 }
5884
5885 for (tem = Vwindow_persistent_parameters; CONSP (tem);
5886 tem = XCDR (tem))
5887 {
5888 pers = XCAR (tem);
34a02f46
MR
5889 /* Save values for persistent window parameters. */
5890 if (CONSP (pers) && !NILP (XCDR (pers)))
6a6ee00d
MR
5891 {
5892 par = Fassq (XCAR (pers), w->window_parameters);
5893 if (NILP (par))
5894 /* If the window has no value for the parameter,
5895 make one. */
5896 p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
5897 p->window_parameters);
5898 else
5899 /* If the window has a value for the parameter,
5900 save it. */
5901 p->window_parameters = Fcons (Fcons (XCAR (par),
5902 XCDR (par)),
5903 p->window_parameters);
5904 }
5905 }
5906 }
5907
265a9e55 5908 if (!NILP (w->buffer))
7ab12479 5909 {
6a6ee00d
MR
5910 /* Save w's value of point in the window configuration. If w
5911 is the selected window, then get the value of point from
5912 the buffer; pointm is garbage in the selected window. */
7ab12479
JB
5913 if (EQ (window, selected_window))
5914 {
5915 p->pointm = Fmake_marker ();
b73ea88e
RS
5916 set_marker_both (p->pointm, w->buffer,
5917 BUF_PT (XBUFFER (w->buffer)),
5918 BUF_PT_BYTE (XBUFFER (w->buffer)));
7ab12479
JB
5919 }
5920 else
eeb82665 5921 p->pointm = Fcopy_marker (w->pointm, Qnil);
de8c03dc
SM
5922 XMARKER (p->pointm)->insertion_type
5923 = !NILP (Vwindow_point_insertion_type);
7ab12479 5924
eeb82665 5925 p->start = Fcopy_marker (w->start, Qnil);
c98ff5dd 5926 p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
7ab12479 5927
4b4deea2 5928 tem = BVAR (XBUFFER (w->buffer), mark);
eeb82665 5929 p->mark = Fcopy_marker (tem, Qnil);
7ab12479
JB
5930 }
5931 else
5932 {
5933 p->pointm = Qnil;
5934 p->start = Qnil;
5935 p->mark = Qnil;
5936 p->start_at_line_beg = Qnil;
5937 }
5938
265a9e55 5939 if (NILP (w->parent))
7ab12479
JB
5940 p->parent = Qnil;
5941 else
5942 p->parent = XWINDOW (w->parent)->temslot;
5943
265a9e55 5944 if (NILP (w->prev))
7ab12479
JB
5945 p->prev = Qnil;
5946 else
5947 p->prev = XWINDOW (w->prev)->temslot;
5948
265a9e55 5949 if (!NILP (w->vchild))
7ab12479 5950 i = save_window_save (w->vchild, vector, i);
265a9e55 5951 if (!NILP (w->hchild))
7ab12479
JB
5952 i = save_window_save (w->hchild, vector, i);
5953 }
5954
5955 return i;
5956}
5957
a7ca3326 5958DEFUN ("current-window-configuration", Fcurrent_window_configuration,
fdb82f93
PJ
5959 Scurrent_window_configuration, 0, 1, 0,
5960 doc: /* Return an object representing the current window configuration of FRAME.
5961If FRAME is nil or omitted, use the selected frame.
5962This describes the number of windows, their sizes and current buffers,
5963and for each displayed buffer, where display starts, and the positions of
5964point and mark. An exception is made for point in the current buffer:
5965its value is -not- saved.
5966This also records the currently selected frame, and FRAME's focus
34a02f46
MR
5967redirection (see `redirect-frame-focus'). The variable
5968`window-persistent-parameters' specifies which window parameters are
5969saved by this function. */)
5842a27b 5970 (Lisp_Object frame)
7ab12479
JB
5971{
5972 register Lisp_Object tem;
5973 register int n_windows;
5974 register struct save_window_data *data;
5975 register int i;
44fa5b1e 5976 FRAME_PTR f;
43bad991 5977
44fa5b1e 5978 if (NILP (frame))
1ae1a37d 5979 frame = selected_frame;
b7826503 5980 CHECK_LIVE_FRAME (frame);
1ae1a37d 5981 f = XFRAME (frame);
7ab12479 5982
44fa5b1e 5983 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
b05b4e27
SM
5984 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
5985 PVEC_WINDOW_CONFIGURATION);
5986
5987 data->frame_cols = FRAME_COLS (f);
5988 data->frame_lines = FRAME_LINES (f);
5989 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5990 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
1ae1a37d 5991 data->selected_frame = selected_frame;
44fa5b1e 5992 data->current_window = FRAME_SELECTED_WINDOW (f);
74112613 5993 XSETBUFFER (data->current_buffer, current_buffer);
3f49fddc 5994 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
3dbab091 5995 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
44fa5b1e 5996 data->root_window = FRAME_ROOT_WINDOW (f);
bdc727bf 5997 data->focus_frame = FRAME_FOCUS_FRAME (f);
7ab12479
JB
5998 tem = Fmake_vector (make_number (n_windows), Qnil);
5999 data->saved_windows = tem;
6000 for (i = 0; i < n_windows; i++)
28be1ada
DA
6001 ASET (tem, i,
6002 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
a1d58e5b 6003 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
74112613 6004 XSETWINDOW_CONFIGURATION (tem, data);
7ab12479
JB
6005 return (tem);
6006}
5500c422
GM
6007\f
6008/***********************************************************************
6009 Marginal Areas
6010 ***********************************************************************/
6011
6012DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
a7bdfc08 6013 2, 3, 0,
fdb82f93 6014 doc: /* Set width of marginal areas of window WINDOW.
6b61353c
KH
6015If WINDOW is nil, set margins of the currently selected window.
6016Second arg LEFT-WIDTH specifies the number of character cells to
6017reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6018does the same for the right marginal area. A nil width parameter
6019means no margin. */)
5842a27b 6020 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
5500c422
GM
6021{
6022 struct window *w = decode_window (window);
5500c422 6023
6b61353c
KH
6024 /* Translate negative or zero widths to nil.
6025 Margins that are too wide have to be checked elsewhere. */
949cf20f 6026
c10ce82e 6027 if (!NILP (left_width))
6b61353c 6028 {
c10ce82e
JB
6029 CHECK_NUMBER (left_width);
6030 if (XINT (left_width) <= 0)
6031 left_width = Qnil;
6b61353c 6032 }
5500c422 6033
c10ce82e 6034 if (!NILP (right_width))
6b61353c 6035 {
c10ce82e
JB
6036 CHECK_NUMBER (right_width);
6037 if (XINT (right_width) <= 0)
6038 right_width = Qnil;
6b61353c 6039 }
5500c422 6040
c10ce82e
JB
6041 if (!EQ (w->left_margin_cols, left_width)
6042 || !EQ (w->right_margin_cols, right_width))
949cf20f 6043 {
c10ce82e
JB
6044 w->left_margin_cols = left_width;
6045 w->right_margin_cols = right_width;
949cf20f
KS
6046
6047 adjust_window_margins (w);
6048
6049 ++windows_or_buffers_changed;
6050 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6051 }
5500c422 6052
5500c422
GM
6053 return Qnil;
6054}
6055
6056
6057DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6058 0, 1, 0,
fdb82f93 6059 doc: /* Get width of marginal areas of window WINDOW.
49745b39 6060If WINDOW is omitted or nil, it defaults to the selected window.
fdb82f93
PJ
6061Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6062If a marginal area does not exist, its width will be returned
6063as nil. */)
5842a27b 6064 (Lisp_Object window)
5500c422
GM
6065{
6066 struct window *w = decode_window (window);
949cf20f
KS
6067 return Fcons (w->left_margin_cols, w->right_margin_cols);
6068}
6069
6070
6071\f
6072/***********************************************************************
6073 Fringes
6074 ***********************************************************************/
6075
a7ca3326 6076DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
949cf20f 6077 2, 4, 0,
6b61353c
KH
6078 doc: /* Set the fringe widths of window WINDOW.
6079If WINDOW is nil, set the fringe widths of the currently selected
6080window.
6081Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6082the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6083fringe width. If a fringe width arg is nil, that means to use the
6084frame's default fringe width. Default fringe widths can be set with
6085the command `set-fringe-style'.
6086If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6087outside of the display margins. By default, fringes are drawn between
6088display marginal areas and the text area. */)
5842a27b 6089 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width, Lisp_Object outside_margins)
949cf20f
KS
6090{
6091 struct window *w = decode_window (window);
2af3565e 6092 int outside = !NILP (outside_margins);
949cf20f 6093
c10ce82e
JB
6094 if (!NILP (left_width))
6095 CHECK_NATNUM (left_width);
6096 if (!NILP (right_width))
6097 CHECK_NATNUM (right_width);
5a857365 6098
017e297e 6099 /* Do nothing on a tty. */
d46c6df5
NR
6100 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6101 && (!EQ (w->left_fringe_width, left_width)
6102 || !EQ (w->right_fringe_width, right_width)
2af3565e 6103 || w->fringes_outside_margins != outside))
949cf20f 6104 {
c10ce82e
JB
6105 w->left_fringe_width = left_width;
6106 w->right_fringe_width = right_width;
2af3565e 6107 w->fringes_outside_margins = outside;
949cf20f
KS
6108
6109 adjust_window_margins (w);
6110
6111 clear_glyph_matrix (w->current_matrix);
6112 w->window_end_valid = Qnil;
6113
6114 ++windows_or_buffers_changed;
6115 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6116 }
6117
6118 return Qnil;
6119}
6120
6121
6122DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6123 0, 1, 0,
6124 doc: /* Get width of fringes of window WINDOW.
49745b39 6125If WINDOW is omitted or nil, it defaults to the selected window.
6b61353c 6126Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
5842a27b 6127 (Lisp_Object window)
949cf20f
KS
6128{
6129 struct window *w = decode_window (window);
d46c6df5 6130
949cf20f
KS
6131 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6132 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
d46c6df5
NR
6133 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6134 ? Qt : Qnil), Qnil)));
949cf20f
KS
6135}
6136
6137
6138\f
6139/***********************************************************************
6140 Scroll bars
6141 ***********************************************************************/
6142
a7ca3326 6143DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
16a97296 6144 Sset_window_scroll_bars, 2, 4, 0,
949cf20f
KS
6145 doc: /* Set width and type of scroll bars of window WINDOW.
6146If window is nil, set scroll bars of the currently selected window.
6147Second parameter WIDTH specifies the pixel width for the scroll bar;
6148this is automatically adjusted to a multiple of the frame column width.
6149Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6150bar: left, right, or nil.
6b61353c 6151If WIDTH is nil, use the frame's scroll-bar width.
a53d44a8
JB
6152If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6153Fourth parameter HORIZONTAL-TYPE is currently unused. */)
5842a27b 6154 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, Lisp_Object horizontal_type)
949cf20f
KS
6155{
6156 struct window *w = decode_window (window);
6157
6158 if (!NILP (width))
0f8fe9a2 6159 {
af5a5a98 6160 CHECK_RANGED_INTEGER (width, 0, INT_MAX);
949cf20f 6161
0f8fe9a2
SM
6162 if (XINT (width) == 0)
6163 vertical_type = Qnil;
6164 }
949cf20f 6165
413a79ad 6166 if (!(NILP (vertical_type)
0cc1039f 6167 || EQ (vertical_type, Qleft)
6b61353c
KH
6168 || EQ (vertical_type, Qright)
6169 || EQ (vertical_type, Qt)))
6170 error ("Invalid type of vertical scroll bar");
6171
949cf20f
KS
6172 if (!EQ (w->scroll_bar_width, width)
6173 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6174 {
6175 w->scroll_bar_width = width;
6176 w->vertical_scroll_bar_type = vertical_type;
6177
6178 adjust_window_margins (w);
6179
6180 clear_glyph_matrix (w->current_matrix);
6181 w->window_end_valid = Qnil;
6182
6183 ++windows_or_buffers_changed;
6184 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6185 }
6186
6187 return Qnil;
6188}
6189
6190
6191DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6192 0, 1, 0,
6193 doc: /* Get width and type of scroll bars of window WINDOW.
49745b39 6194If WINDOW is omitted or nil, it defaults to the selected window.
6b61353c
KH
6195Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6196If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6197value. */)
5842a27b 6198 (Lisp_Object window)
949cf20f
KS
6199{
6200 struct window *w = decode_window (window);
6201 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6202 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6203 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6204 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6205 Fcons (w->vertical_scroll_bar_type,
6206 Fcons (Qnil, Qnil))));
5500c422
GM
6207}
6208
6209
7ab12479 6210\f
5500c422
GM
6211/***********************************************************************
6212 Smooth scrolling
6213 ***********************************************************************/
6214
0cc1039f 6215DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
fdb82f93 6216 doc: /* Return the amount by which WINDOW is scrolled vertically.
49745b39 6217If WINDOW is omitted or nil, it defaults to the selected window.
0cc1039f 6218Normally, value is a multiple of the canonical character height of WINDOW;
8cd0d661 6219optional second arg PIXELS-P means value is measured in pixels. */)
5842a27b 6220 (Lisp_Object window, Lisp_Object pixels_p)
5500c422 6221{
47004952 6222 Lisp_Object result;
5500c422
GM
6223 struct frame *f;
6224 struct window *w;
177c0ea7 6225
5500c422
GM
6226 if (NILP (window))
6227 window = selected_window;
47004952 6228 else
b7826503 6229 CHECK_WINDOW (window);
5500c422
GM
6230 w = XWINDOW (window);
6231 f = XFRAME (w->frame);
177c0ea7 6232
5500c422 6233 if (FRAME_WINDOW_P (f))
0cc1039f
KS
6234 result = (NILP (pixels_p)
6235 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6236 : make_number (-w->vscroll));
5500c422 6237 else
47004952
GM
6238 result = make_number (0);
6239 return result;
5500c422
GM
6240}
6241
6242
6243DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
0cc1039f 6244 2, 3, 0,
fdb82f93 6245 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
0cc1039f
KS
6246WINDOW nil means use the selected window. Normally, VSCROLL is a
6247non-negative multiple of the canonical character height of WINDOW;
8cd0d661 6248optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
a0a37a6f
LT
6249If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6250corresponds to an integral number of pixels. The return value is the
6251result of this rounding.
6252If PIXELS-P is non-nil, the return value is VSCROLL. */)
5842a27b 6253 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
5500c422
GM
6254{
6255 struct window *w;
6256 struct frame *f;
177c0ea7 6257
5500c422
GM
6258 if (NILP (window))
6259 window = selected_window;
47004952 6260 else
b7826503
PJ
6261 CHECK_WINDOW (window);
6262 CHECK_NUMBER_OR_FLOAT (vscroll);
177c0ea7 6263
5500c422
GM
6264 w = XWINDOW (window);
6265 f = XFRAME (w->frame);
6266
6267 if (FRAME_WINDOW_P (f))
6268 {
6269 int old_dy = w->vscroll;
177c0ea7 6270
0cc1039f
KS
6271 w->vscroll = - (NILP (pixels_p)
6272 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6273 : XFLOATINT (vscroll));
47004952 6274 w->vscroll = min (w->vscroll, 0);
5500c422 6275
e56263e5
KS
6276 if (w->vscroll != old_dy)
6277 {
6278 /* Adjust glyph matrix of the frame if the virtual display
6279 area becomes larger than before. */
6280 if (w->vscroll < 0 && w->vscroll < old_dy)
6281 adjust_glyphs (f);
177c0ea7 6282
e56263e5
KS
6283 /* Prevent redisplay shortcuts. */
6284 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6285 }
5500c422 6286 }
177c0ea7 6287
0cc1039f 6288 return Fwindow_vscroll (window, pixels_p);
5500c422 6289}
177c0ea7 6290
7bbb5782
GM
6291\f
6292/* Call FN for all leaf windows on frame F. FN is called with the
6293 first argument being a pointer to the leaf window, and with
f95464e4 6294 additional argument USER_DATA. Stops when FN returns 0. */
7bbb5782 6295
2f7c71a1
AS
6296static void
6297foreach_window (struct frame *f, int (*fn) (struct window *, void *),
6298 void *user_data)
7bbb5782 6299{
56f2de10 6300 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
76fb556f
YM
6301 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6302 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
7bbb5782
GM
6303}
6304
6305
6306/* Helper function for foreach_window. Call FN for all leaf windows
6307 reachable from W. FN is called with the first argument being a
f95464e4 6308 pointer to the leaf window, and with additional argument USER_DATA.
67492200 6309 Stop when FN returns 0. Value is 0 if stopped by FN. */
7bbb5782 6310
67492200 6311static int
971de7fb 6312foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
7bbb5782 6313{
67492200 6314 int cont;
177c0ea7 6315
67492200 6316 for (cont = 1; w && cont;)
7bbb5782
GM
6317 {
6318 if (!NILP (w->hchild))
f95464e4 6319 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
7bbb5782 6320 else if (!NILP (w->vchild))
f95464e4 6321 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
177c0ea7 6322 else
0f532a9a 6323 cont = fn (w, user_data);
177c0ea7 6324
7bbb5782
GM
6325 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6326 }
67492200
GM
6327
6328 return cont;
7bbb5782
GM
6329}
6330
6331
6d194a45 6332/* Freeze or unfreeze the window start of W unless it is a
f95464e4 6333 mini-window or the selected window. FREEZE_P non-null means freeze
7bbb5782
GM
6334 the window start. */
6335
67492200 6336static int
971de7fb 6337freeze_window_start (struct window *w, void *freeze_p)
7bbb5782 6338{
08c1d235
SM
6339 if (MINI_WINDOW_P (w)
6340 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
6341 && (w == XWINDOW (selected_window)
6342 || (MINI_WINDOW_P (XWINDOW (selected_window))
6343 && ! NILP (Vminibuf_scroll_window)
6344 && w == XWINDOW (Vminibuf_scroll_window)))))
f95464e4 6345 freeze_p = NULL;
177c0ea7 6346
f95464e4 6347 w->frozen_window_start_p = freeze_p != NULL;
67492200 6348 return 1;
7bbb5782
GM
6349}
6350
6351
6352/* Freeze or unfreeze the window starts of all leaf windows on frame
6353 F, except the selected window and a mini-window. FREEZE_P non-zero
6354 means freeze the window start. */
6355
6356void
971de7fb 6357freeze_window_starts (struct frame *f, int freeze_p)
7bbb5782 6358{
cbccabec 6359 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
7bbb5782 6360}
5500c422
GM
6361
6362\f
6363/***********************************************************************
6364 Initialization
6365 ***********************************************************************/
6366
6198ccd0
MR
6367/* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
6368 describe the same state of affairs. This is used by Fequal.
6369
6370 ignore_positions non-zero means ignore non-matching scroll positions
6371 and the like.
6372
e4769531 6373 This ignores a couple of things like the dedication status of
b6f67890
MR
6374 window, combination_limit and the like. This might have to be
6375 fixed. */
cbff28e8
RS
6376
6377int
6198ccd0 6378compare_window_configurations (Lisp_Object configuration1, Lisp_Object configuration2, int ignore_positions)
cbff28e8
RS
6379{
6380 register struct save_window_data *d1, *d2;
6198ccd0 6381 struct Lisp_Vector *sws1, *sws2;
71f02bc5 6382 ptrdiff_t i;
cbff28e8 6383
6198ccd0
MR
6384 CHECK_WINDOW_CONFIGURATION (configuration1);
6385 CHECK_WINDOW_CONFIGURATION (configuration2);
6386
6387 d1 = (struct save_window_data *) XVECTOR (configuration1);
6388 d2 = (struct save_window_data *) XVECTOR (configuration2);
6389 sws1 = XVECTOR (d1->saved_windows);
6390 sws2 = XVECTOR (d2->saved_windows);
6391
6392 /* Frame settings must match. */
6393 if (d1->frame_cols != d2->frame_cols
6394 || d1->frame_lines != d2->frame_lines
6395 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
6396 || !EQ (d1->selected_frame, d2->selected_frame)
6397 || !EQ (d1->current_buffer, d2->current_buffer)
6398 || (!ignore_positions
6399 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
6400 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
6401 || !EQ (d1->focus_frame, d2->focus_frame)
6402 /* Verify that the two configurations have the same number of windows. */
6403 || sws1->header.size != sws2->header.size)
cbff28e8 6404 return 0;
cbff28e8 6405
6198ccd0 6406 for (i = 0; i < sws1->header.size; i++)
cbff28e8 6407 {
6198ccd0 6408 struct saved_window *sw1, *sw2;
cbff28e8 6409
6198ccd0
MR
6410 sw1 = SAVED_WINDOW_N (sws1, i);
6411 sw2 = SAVED_WINDOW_N (sws2, i);
6412
6413 if (
6414 /* The "current" windows in the two configurations must
6415 correspond to each other. */
6416 EQ (d1->current_window, sw1->window)
6417 != EQ (d2->current_window, sw2->window)
6418 /* Windows' buffers must match. */
6419 || !EQ (sw1->buffer, sw2->buffer)
6420 || !EQ (sw1->left_col, sw2->left_col)
6421 || !EQ (sw1->top_line, sw2->top_line)
6422 || !EQ (sw1->total_cols, sw2->total_cols)
6423 || !EQ (sw1->total_lines, sw2->total_lines)
6424 || !EQ (sw1->display_table, sw2->display_table)
6425 /* The next two disjuncts check the window structure for
6426 equality. */
6427 || !EQ (sw1->parent, sw2->parent)
6428 || !EQ (sw1->prev, sw2->prev)
6429 || (!ignore_positions
6430 && (!EQ (sw1->hscroll, sw2->hscroll)
6431 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
6432 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
6433 || NILP (Fequal (sw1->start, sw2->start))
6434 || NILP (Fequal (sw1->pointm, sw2->pointm))
6435 || NILP (Fequal (sw1->mark, sw2->mark))))
6436 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
6437 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
6438 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
6439 || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
6440 || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
6441 || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
6442 || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
949cf20f 6443 return 0;
cbff28e8
RS
6444 }
6445
6446 return 1;
6447}
2f8274be
RS
6448
6449DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6450 Scompare_window_configurations, 2, 2, 0,
fdb82f93
PJ
6451 doc: /* Compare two window configurations as regards the structure of windows.
6452This function ignores details such as the values of point and mark
6453and scrolling positions. */)
5842a27b 6454 (Lisp_Object x, Lisp_Object y)
2f8274be
RS
6455{
6456 if (compare_window_configurations (x, y, 1))
6457 return Qt;
6458 return Qnil;
6459}
cbff28e8 6460\f
dfcf069d 6461void
971de7fb 6462init_window_once (void)
7ab12479 6463{
3224dac1 6464 struct frame *f = make_initial_frame ();
1ae1a37d
GM
6465 XSETFRAME (selected_frame, f);
6466 Vterminal_frame = selected_frame;
6467 minibuf_window = f->minibuffer_window;
6468 selected_window = f->selected_window;
6469 last_nonminibuf_frame = f;
5b03d3c0
RS
6470
6471 window_initialized = 1;
7ab12479
JB
6472}
6473
67492200 6474void
971de7fb 6475init_window (void)
67492200
GM
6476{
6477 Vwindow_list = Qnil;
6478}
6479
dfcf069d 6480void
971de7fb 6481syms_of_window (void)
7ab12479 6482{
cd3520a4
JB
6483 DEFSYM (Qscroll_up, "scroll-up");
6484 DEFSYM (Qscroll_down, "scroll-down");
6485 DEFSYM (Qscroll_command, "scroll-command");
a4b000fb
JL
6486
6487 Fput (Qscroll_up, Qscroll_command, Qt);
6488 Fput (Qscroll_down, Qscroll_command, Qt);
6489
cd3520a4
JB
6490 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
6491 DEFSYM (Qwindowp, "windowp");
6492 DEFSYM (Qwindow_configuration_p, "window-configuration-p");
6493 DEFSYM (Qwindow_live_p, "window-live-p");
6494 DEFSYM (Qwindow_deletable_p, "window-deletable-p");
6495 DEFSYM (Qdelete_window, "delete-window");
5386012d
MR
6496 DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
6497 DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
cd3520a4
JB
6498 DEFSYM (Qsafe, "safe");
6499 DEFSYM (Qdisplay_buffer, "display-buffer");
6500 DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
6501 DEFSYM (Qrecord_window_buffer, "record-window-buffer");
6502 DEFSYM (Qget_mru_window, "get-mru-window");
6503 DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6504 DEFSYM (Qabove, "above");
6505 DEFSYM (Qbelow, "below");
6506 DEFSYM (Qauto_buffer_name, "auto-buffer-name");
6a6ee00d 6507 DEFSYM (Qclone_of, "clone-of");
b9e809c2 6508
67492200 6509 staticpro (&Vwindow_list);
8bfb170b
KS
6510
6511 minibuf_selected_window = Qnil;
3dbab091 6512 staticpro (&minibuf_selected_window);
67492200 6513
c876b227 6514 window_scroll_pixel_based_preserve_x = -1;
66fe93d1 6515 window_scroll_pixel_based_preserve_y = -1;
c876b227
SM
6516 window_scroll_preserve_hpos = -1;
6517 window_scroll_preserve_vpos = -1;
66d43aea 6518
29208e82 6519 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
fdb82f93
PJ
6520 doc: /* Non-nil means call as function to display a help buffer.
6521The function is called with one argument, the buffer to be displayed.
6522Used by `with-output-to-temp-buffer'.
6523If this function is used, then it must do the entire job of showing
6524the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7ab12479 6525 Vtemp_buffer_show_function = Qnil;
e10ac9f1 6526
29208e82 6527 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
fdb82f93 6528 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7ab12479
JB
6529 Vminibuf_scroll_window = Qnil;
6530
29208e82 6531 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
26124d5e 6532 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
cc91894c
KS
6533If the minibuffer is active, the `minibuffer-scroll-window' mode line
6534is displayed in the `mode-line' face. */);
6535 mode_line_in_non_selected_windows = 1;
26124d5e 6536
29208e82 6537 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
fdb82f93 6538 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7ab12479
JB
6539 Vother_window_scroll_buffer = Qnil;
6540
29208e82 6541 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
e10ac9f1 6542 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
e56263e5
KS
6543 auto_window_vscroll_p = 1;
6544
29208e82 6545 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
e10ac9f1 6546 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
7ab12479
JB
6547 next_screen_context_lines = 2;
6548
5500c422 6549 DEFVAR_LISP ("scroll-preserve-screen-position",
29208e82 6550 Vscroll_preserve_screen_position,
e10ac9f1 6551 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
bdf4ec93
RS
6552A value of nil means point does not keep its screen position except
6553at the scroll margin or window boundary respectively.
6554A value of t means point keeps its screen position if the scroll
6555command moved it vertically out of the window, e.g. when scrolling
6556by full screens.
9013a7f8 6557Any other value means point always keeps its screen position.
a4b000fb
JL
6558Scroll commands should have the `scroll-command' property
6559on their symbols to be controlled by this variable. */);
5500c422 6560 Vscroll_preserve_screen_position = Qnil;
9317a85d 6561
29208e82 6562 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
a1562258
SM
6563 doc: /* Type of marker to use for `window-point'. */);
6564 Vwindow_point_insertion_type = Qnil;
6565
543f5fb1 6566 DEFVAR_LISP ("window-configuration-change-hook",
29208e82 6567 Vwindow_configuration_change_hook,
fdb82f93 6568 doc: /* Functions to call when window configuration changes.
6a44ffb3
SM
6569The buffer-local part is run once per window, with the relevant window
6570selected; while the global part is run only once for the modified frame,
6571with the relevant frame selected. */);
543f5fb1
RS
6572 Vwindow_configuration_change_hook = Qnil;
6573
29208e82 6574 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
61d4b438
MR
6575 doc: /* Non-nil means `recenter' redraws entire frame.
6576If this option is non-nil, then the `recenter' command with a nil
6577argument will redraw the entire frame; the special value `tty' causes
6578the frame to be redrawn only if it is a tty frame. */);
666e158e
MB
6579 Vrecenter_redisplay = Qtty;
6580
a0c2d0ae 6581 DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
454592a6 6582 doc: /* If t, resize window combinations proportionally.
1a13852e 6583If this variable is nil, splitting a window gets the entire screen space
a0c2d0ae 6584for displaying the new window from the window to split. Deleting and
df85d315 6585resizing a window preferably resizes one adjacent window only.
a0c2d0ae 6586
454592a6 6587If this variable is t, splitting a window tries to get the space
a0c2d0ae
MR
6588proportionally from all windows in the same combination. This also
6589allows to split a window that is otherwise too small or of fixed size.
6590Resizing and deleting a window proportionally resize all windows in the
6591same combination.
1a13852e 6592
454592a6
MR
6593Other values are reserved for future use.
6594
b6f67890 6595This variable takes no effect if `window-combination-limit' is non-nil. */);
a0c2d0ae 6596 Vwindow_combination_resize = Qnil;
1a13852e 6597
b6f67890 6598 DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
454592a6 6599 doc: /* If t, splitting a window makes a new parent window.
1a13852e
MR
6600If this variable is nil, splitting a window will create a new parent
6601window only if the window has no parent window or the window shall
58179cce 6602become a combination orthogonal to the one it is part of.
1a13852e 6603
b6f67890
MR
6604If this variable is t, splitting a window always creates a new parent
6605window. If all splits behave this way, each frame's window tree is a
6606binary tree and every window but the frame's root window has exactly one
6607sibling.
1a13852e 6608
b6f67890 6609Other values are reserved for future use.
1a13852e 6610
d2999b1a
MR
6611The value of this variable is also assigned to the combination limit of
6612the new parent window. The combination limit of a window can be
6613retrieved via the function `window-combination-limit' and altered by the
6614function `set-window-combination-limit'. */);
b6f67890 6615 Vwindow_combination_limit = Qnil;
666e158e 6616
6a6ee00d
MR
6617 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
6618 doc: /* Alist of persistent window parameters.
34a02f46
MR
6619This alist specifies which window parameters shall get saved by
6620`current-window-configuration' and `window-state-get' and subsequently
6621restored to their previous values by `set-window-configuration' and
6622`window-state-put'.
6a6ee00d
MR
6623
6624The car of each entry of this alist is the symbol specifying the
6625parameter. The cdr is one of the following:
6626
34a02f46
MR
6627nil means the parameter is neither saved by `window-state-get' nor by
6628`current-window-configuration'.
6a6ee00d 6629
34a02f46
MR
6630t means the parameter is saved by `current-window-configuration' and,
6631provided its WRITABLE argument is nil, by `window-state-get'.
6a6ee00d 6632
34a02f46
MR
6633The symbol `writable' means the parameter is saved unconditionally by
6634both `current-window-configuration' and `window-state-get'. Do not use
6635this value for parameters without read syntax (like windows or frames).
6a6ee00d
MR
6636
6637Parameters not saved by `current-window-configuration' or
6638`window-state-get' are left alone by `set-window-configuration'
6639respectively are not installed by `window-state-put'. */);
34a02f46 6640 Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
6a6ee00d 6641
7ab12479
JB
6642 defsubr (&Sselected_window);
6643 defsubr (&Sminibuffer_window);
6644 defsubr (&Swindow_minibuffer_p);
6645 defsubr (&Swindowp);
806b4d9b 6646 defsubr (&Swindow_live_p);
727e958e
MR
6647 defsubr (&Swindow_frame);
6648 defsubr (&Sframe_root_window);
6649 defsubr (&Sframe_first_window);
6650 defsubr (&Sframe_selected_window);
6651 defsubr (&Sset_frame_selected_window);
7ab12479 6652 defsubr (&Spos_visible_in_window_p);
536833ab 6653 defsubr (&Swindow_line_height);
7ab12479 6654 defsubr (&Swindow_buffer);
bf60a96b 6655 defsubr (&Swindow_parent);
d68443dc
MR
6656 defsubr (&Swindow_top_child);
6657 defsubr (&Swindow_left_child);
6658 defsubr (&Swindow_next_sibling);
6659 defsubr (&Swindow_prev_sibling);
b6f67890
MR
6660 defsubr (&Swindow_combination_limit);
6661 defsubr (&Sset_window_combination_limit);
abde8f8c
MR
6662 defsubr (&Swindow_use_time);
6663 defsubr (&Swindow_top_line);
6664 defsubr (&Swindow_left_column);
105216ed
CY
6665 defsubr (&Swindow_total_height);
6666 defsubr (&Swindow_total_width);
496e208e
MR
6667 defsubr (&Swindow_normal_size);
6668 defsubr (&Swindow_new_total);
6669 defsubr (&Swindow_new_normal);
6670 defsubr (&Sset_window_new_total);
6671 defsubr (&Sset_window_new_normal);
d615d6d2 6672 defsubr (&Swindow_resize_apply);
105216ed
CY
6673 defsubr (&Swindow_body_height);
6674 defsubr (&Swindow_body_width);
7ab12479
JB
6675 defsubr (&Swindow_hscroll);
6676 defsubr (&Sset_window_hscroll);
190eb263
RS
6677 defsubr (&Swindow_redisplay_end_trigger);
6678 defsubr (&Sset_window_redisplay_end_trigger);
7ab12479 6679 defsubr (&Swindow_edges);
c99a9eb3 6680 defsubr (&Swindow_pixel_edges);
9d5405ec 6681 defsubr (&Swindow_absolute_pixel_edges);
c99a9eb3
RS
6682 defsubr (&Swindow_inside_edges);
6683 defsubr (&Swindow_inside_pixel_edges);
9d5405ec 6684 defsubr (&Swindow_inside_absolute_pixel_edges);
d5783c40
JB
6685 defsubr (&Scoordinates_in_window_p);
6686 defsubr (&Swindow_at);
7ab12479
JB
6687 defsubr (&Swindow_point);
6688 defsubr (&Swindow_start);
6689 defsubr (&Swindow_end);
6690 defsubr (&Sset_window_point);
6691 defsubr (&Sset_window_start);
6692 defsubr (&Swindow_dedicated_p);
d207b766 6693 defsubr (&Sset_window_dedicated_p);
7ab12479
JB
6694 defsubr (&Swindow_display_table);
6695 defsubr (&Sset_window_display_table);
6696 defsubr (&Snext_window);
6697 defsubr (&Sprevious_window);
7ab12479 6698 defsubr (&Sget_buffer_window);
1a13852e
MR
6699 defsubr (&Sdelete_other_windows_internal);
6700 defsubr (&Sdelete_window_internal);
6701 defsubr (&Sresize_mini_window_internal);
7ab12479 6702 defsubr (&Sset_window_buffer);
1a13852e 6703 defsubr (&Srun_window_configuration_change_hook);
7ab12479 6704 defsubr (&Sselect_window);
6b61353c 6705 defsubr (&Sforce_window_update);
3e21b6a7 6706 defsubr (&Stemp_output_buffer_show);
1a13852e 6707 defsubr (&Ssplit_window_internal);
7ab12479
JB
6708 defsubr (&Sscroll_up);
6709 defsubr (&Sscroll_down);
6710 defsubr (&Sscroll_left);
6711 defsubr (&Sscroll_right);
ccd0664b 6712 defsubr (&Sother_window_for_scrolling);
7ab12479 6713 defsubr (&Sscroll_other_window);
fa832261 6714 defsubr (&Sminibuffer_selected_window);
7ab12479 6715 defsubr (&Srecenter);
81fe0836 6716 defsubr (&Swindow_text_height);
7ab12479
JB
6717 defsubr (&Smove_to_window_line);
6718 defsubr (&Swindow_configuration_p);
3f8ab7bd 6719 defsubr (&Swindow_configuration_frame);
7ab12479
JB
6720 defsubr (&Sset_window_configuration);
6721 defsubr (&Scurrent_window_configuration);
5500c422
GM
6722 defsubr (&Sset_window_margins);
6723 defsubr (&Swindow_margins);
949cf20f
KS
6724 defsubr (&Sset_window_fringes);
6725 defsubr (&Swindow_fringes);
6726 defsubr (&Sset_window_scroll_bars);
6727 defsubr (&Swindow_scroll_bars);
5500c422
GM
6728 defsubr (&Swindow_vscroll);
6729 defsubr (&Sset_window_vscroll);
2f8274be 6730 defsubr (&Scompare_window_configurations);
67492200 6731 defsubr (&Swindow_list);
abde8f8c 6732 defsubr (&Swindow_list_1);
496e208e
MR
6733 defsubr (&Swindow_prev_buffers);
6734 defsubr (&Sset_window_prev_buffers);
6735 defsubr (&Swindow_next_buffers);
6736 defsubr (&Sset_window_next_buffers);
cfbb2395
JB
6737 defsubr (&Swindow_parameters);
6738 defsubr (&Swindow_parameter);
6739 defsubr (&Sset_window_parameter);
7ab12479
JB
6740}
6741
dfcf069d 6742void
971de7fb 6743keys_of_window (void)
7ab12479 6744{
7ab12479
JB
6745 initial_define_key (control_x_map, '<', "scroll-left");
6746 initial_define_key (control_x_map, '>', "scroll-right");
6747
32129746 6748 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
7ab12479 6749 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
32129746 6750 initial_define_key (meta_map, 'v', "scroll-down-command");
7ab12479 6751}