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