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