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