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