mirrored from git://git.sv.gnu.org/emacs.git
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
window.c
7913 lines (6836 loc) · 257 KB
/
window.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* Window creation, deletion and examination for GNU Emacs.
Does not include redisplay.
Copyright (C) 1985-1987, 1993-1998, 2000-2019 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
#include "lisp.h"
#include "buffer.h"
#include "keyboard.h"
#include "keymap.h"
#include "frame.h"
#include "window.h"
#include "commands.h"
#include "indent.h"
#include "termchar.h"
#include "disptab.h"
#include "dispextern.h"
#include "blockinput.h"
#include "termhooks.h" /* For FRAME_TERMINAL. */
#include "xwidget.h"
#ifdef HAVE_WINDOW_SYSTEM
#include TERM_HEADER
#endif /* HAVE_WINDOW_SYSTEM */
#ifdef MSDOS
#include "msdos.h"
#endif
static ptrdiff_t count_windows (struct window *);
static ptrdiff_t get_leaf_windows (struct window *, struct window **,
ptrdiff_t);
static void window_scroll_pixel_based (Lisp_Object, int, bool, bool);
static void window_scroll_line_based (Lisp_Object, int, bool, bool);
static void foreach_window (struct frame *,
bool (* fn) (struct window *, void *),
void *);
static bool foreach_window_1 (struct window *,
bool (* fn) (struct window *, void *),
void *);
static bool window_resize_check (struct window *, bool);
static void window_resize_apply (struct window *, bool);
static void select_window_1 (Lisp_Object, bool);
static void run_window_configuration_change_hook (struct frame *);
static struct window *set_window_fringes (struct window *, Lisp_Object,
Lisp_Object, Lisp_Object);
static struct window *set_window_margins (struct window *, Lisp_Object,
Lisp_Object);
static struct window *set_window_scroll_bars (struct window *, Lisp_Object,
Lisp_Object, Lisp_Object,
Lisp_Object);
static void apply_window_adjustment (struct window *);
/* This is the window in which the terminal's cursor should
be left when nothing is being done with it. This must
always be a leaf window, and its buffer is selected by
the top level editing loop at the end of each command.
This value is always the same as
FRAME_SELECTED_WINDOW (selected_frame). */
Lisp_Object selected_window;
/* A list of all windows for use by next_window and Fwindow_list.
Functions creating or deleting windows should invalidate this cache
by setting it to nil. */
Lisp_Object Vwindow_list;
/* The mini-buffer window of the selected frame.
Note that you cannot test for mini-bufferness of an arbitrary window
by comparing against this; but you can test for mini-bufferness of
the selected window. */
Lisp_Object minibuf_window;
/* Non-nil means it is the window whose mode line should be
shown as the selected window when the minibuffer is selected. */
Lisp_Object minibuf_selected_window;
/* Incremented for each window created. */
static EMACS_INT sequence_number;
/* Used by the function window_scroll_pixel_based. */
static int window_scroll_pixel_based_preserve_x;
static int window_scroll_pixel_based_preserve_y;
/* Same for window_scroll_line_based. */
static EMACS_INT window_scroll_preserve_hpos;
static EMACS_INT window_scroll_preserve_vpos;
static void
CHECK_WINDOW_CONFIGURATION (Lisp_Object x)
{
CHECK_TYPE (WINDOW_CONFIGURATIONP (x), Qwindow_configuration_p, x);
}
/* These setters are used only in this file, so they can be private. */
static void
wset_combination_limit (struct window *w, Lisp_Object val)
{
w->combination_limit = val;
}
static void
wset_dedicated (struct window *w, Lisp_Object val)
{
w->dedicated = val;
}
static void
wset_display_table (struct window *w, Lisp_Object val)
{
w->display_table = val;
}
static void
wset_new_normal (struct window *w, Lisp_Object val)
{
w->new_normal = val;
}
static void
wset_new_total (struct window *w, Lisp_Object val)
{
w->new_total = val;
}
static void
wset_normal_cols (struct window *w, Lisp_Object val)
{
w->normal_cols = val;
}
static void
wset_normal_lines (struct window *w, Lisp_Object val)
{
w->normal_lines = val;
}
static void
wset_parent (struct window *w, Lisp_Object val)
{
w->parent = val;
}
static void
wset_pointm (struct window *w, Lisp_Object val)
{
w->pointm = val;
}
static void
wset_old_pointm (struct window *w, Lisp_Object val)
{
w->old_pointm = val;
}
static void
wset_start (struct window *w, Lisp_Object val)
{
w->start = val;
}
static void
wset_temslot (struct window *w, Lisp_Object val)
{
w->temslot = val;
}
static void
wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
{
w->vertical_scroll_bar_type = val;
}
static void
wset_window_parameters (struct window *w, Lisp_Object val)
{
w->window_parameters = val;
}
static void
wset_combination (struct window *w, bool horflag, Lisp_Object val)
{
/* Since leaf windows never becomes non-leaf, there should
be no buffer and markers in start and pointm fields of W. */
eassert (!BUFFERP (w->contents) && NILP (w->start) && NILP (w->pointm));
w->contents = val;
/* When an internal window is deleted and VAL is nil, HORFLAG
is meaningless. */
if (!NILP (val))
w->horizontal = horflag;
}
static void
wset_update_mode_line (struct window *w)
{
/* If this window is the selected window on its frame, set the
global variable update_mode_lines, so that x_consider_frame_title
will consider this frame's title for redisplay. */
Lisp_Object fselected_window = XFRAME (WINDOW_FRAME (w))->selected_window;
if (WINDOWP (fselected_window) && XWINDOW (fselected_window) == w)
update_mode_lines = 42;
else
w->update_mode_line = true;
}
/* True if leaf window W doesn't reflect the actual state
of displayed buffer due to its text or overlays change. */
bool
window_outdated (struct window *w)
{
struct buffer *b = XBUFFER (w->contents);
return (w->last_modified < BUF_MODIFF (b)
|| w->last_overlay_modified < BUF_OVERLAY_MODIFF (b));
}
struct window *
decode_live_window (register Lisp_Object window)
{
if (NILP (window))
return XWINDOW (selected_window);
CHECK_LIVE_WINDOW (window);
return XWINDOW (window);
}
struct window *
decode_any_window (register Lisp_Object window)
{
struct window *w;
if (NILP (window))
return XWINDOW (selected_window);
CHECK_WINDOW (window);
w = XWINDOW (window);
return w;
}
static struct window *
decode_valid_window (register Lisp_Object window)
{
struct window *w;
if (NILP (window))
return XWINDOW (selected_window);
CHECK_VALID_WINDOW (window);
w = XWINDOW (window);
return w;
}
/* Called when W's buffer slot is changed. ARG -1 means that W is about to
cease its buffer, and 1 means that W is about to set up the new one. */
static void
adjust_window_count (struct window *w, int arg)
{
eassert (eabs (arg) == 1);
if (BUFFERP (w->contents))
{
struct buffer *b = XBUFFER (w->contents);
if (b->base_buffer)
b = b->base_buffer;
b->window_count += arg;
eassert (b->window_count >= 0);
/* These should be recalculated by redisplay code. */
w->window_end_valid = false;
w->base_line_pos = 0;
}
}
/* Set W's buffer slot to VAL and recompute number
of windows showing VAL if it is a buffer. */
void
wset_buffer (struct window *w, Lisp_Object val)
{
adjust_window_count (w, -1);
if (BUFFERP (val))
/* Make sure that we do not assign the buffer
to an internal window. */
eassert (MARKERP (w->start) && MARKERP (w->pointm));
w->contents = val;
adjust_window_count (w, 1);
}
DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
doc: /* Return t if OBJECT is a window and nil otherwise. */)
(Lisp_Object object)
{
return WINDOWP (object) ? Qt : Qnil;
}
DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
doc: /* Return t if OBJECT is a valid window and nil otherwise.
A valid window is either a window that displays a buffer or an internal
window. Windows that have been deleted are not valid. */)
(Lisp_Object object)
{
return WINDOW_VALID_P (object) ? Qt : Qnil;
}
DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
doc: /* Return t if OBJECT is a live window and nil otherwise.
A live window is a window that displays a buffer.
Internal windows and deleted windows are not live. */)
(Lisp_Object object)
{
return WINDOW_LIVE_P (object) ? Qt : Qnil;
}
/* Frames and windows. */
DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
doc: /* Return the frame that window WINDOW is on.
WINDOW must be a valid window and defaults to the selected one. */)
(Lisp_Object window)
{
return decode_valid_window (window)->frame;
}
DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
doc: /* Return the root window of FRAME-OR-WINDOW.
If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
With a frame argument, return that frame's root window.
With a window argument, return the root window of that window's frame. */)
(Lisp_Object frame_or_window)
{
Lisp_Object window;
if (NILP (frame_or_window))
window = SELECTED_FRAME ()->root_window;
else if (WINDOW_VALID_P (frame_or_window))
window = XFRAME (XWINDOW (frame_or_window)->frame)->root_window;
else
{
CHECK_LIVE_FRAME (frame_or_window);
window = XFRAME (frame_or_window)->root_window;
}
return window;
}
DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
doc: /* Return the minibuffer window for frame FRAME.
If FRAME is omitted or nil, it defaults to the selected frame. */)
(Lisp_Object frame)
{
return FRAME_MINIBUF_WINDOW (decode_live_frame (frame));
}
DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
Swindow_minibuffer_p, 0, 1, 0,
doc: /* Return non-nil if WINDOW is a minibuffer window.
WINDOW must be a valid window and defaults to the selected one. */)
(Lisp_Object window)
{
return MINI_WINDOW_P (decode_valid_window (window)) ? Qt : Qnil;
}
/* Don't move this to window.el - this must be a safe routine. */
DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
Else if FRAME-OR-WINDOW denotes a valid window, return the first window
of that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
the first window of that frame. */)
(Lisp_Object frame_or_window)
{
Lisp_Object window;
if (NILP (frame_or_window))
window = SELECTED_FRAME ()->root_window;
else if (WINDOW_VALID_P (frame_or_window))
window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
else
{
CHECK_LIVE_FRAME (frame_or_window);
window = XFRAME (frame_or_window)->root_window;
}
while (WINDOWP (XWINDOW (window)->contents))
window = XWINDOW (window)->contents;
return window;
}
DEFUN ("frame-selected-window", Fframe_selected_window,
Sframe_selected_window, 0, 1, 0,
doc: /* Return the selected window of FRAME-OR-WINDOW.
If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
Else if FRAME-OR-WINDOW denotes a valid window, return the selected
window of that window's frame. If FRAME-OR-WINDOW denotes a live frame,
return the selected window of that frame. */)
(Lisp_Object frame_or_window)
{
Lisp_Object window;
if (NILP (frame_or_window))
window = SELECTED_FRAME ()->selected_window;
else if (WINDOW_VALID_P (frame_or_window))
window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
else
{
CHECK_LIVE_FRAME (frame_or_window);
window = XFRAME (frame_or_window)->selected_window;
}
return window;
}
DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
Sset_frame_selected_window, 2, 3, 0,
doc: /* Set selected window of FRAME to WINDOW.
FRAME must be a live frame and defaults to the selected one. If FRAME
is the selected frame, this makes WINDOW the selected window. Optional
argument NORECORD non-nil means to neither change the order of recently
selected windows nor the buffer list. WINDOW must denote a live window.
Return WINDOW. */)
(Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
{
if (NILP (frame))
frame = selected_frame;
CHECK_LIVE_FRAME (frame);
CHECK_LIVE_WINDOW (window);
if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
error ("In `set-frame-selected-window', WINDOW is not on FRAME");
if (EQ (frame, selected_frame))
return Fselect_window (window, norecord);
else
{
fset_selected_window (XFRAME (frame), window);
return window;
}
}
DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
doc: /* Return the selected window.
The selected window is the window in which the standard cursor for
selected windows appears and to which many commands apply. */)
(void)
{
return selected_window;
}
EMACS_INT window_select_count;
/* If select_window is called with inhibit_point_swap true it will
not store point of the old selected window's buffer back into that
window's pointm slot. This is needed by Fset_window_configuration to
avoid that the display routine is called with selected_window set to
Qnil causing a subsequent crash. */
static Lisp_Object
select_window (Lisp_Object window, Lisp_Object norecord,
bool inhibit_point_swap)
{
struct window *w;
struct frame *sf;
CHECK_LIVE_WINDOW (window);
w = XWINDOW (window);
/* Make the selected window's buffer current. */
Fset_buffer (w->contents);
if (EQ (window, selected_window) && !inhibit_point_swap)
/* `switch-to-buffer' uses (select-window (selected-window)) as a "clever"
way to call record_buffer from Elisp, so it's important that we call
record_buffer before returning here. */
goto record_and_return;
if (NILP (norecord) || EQ (norecord, Qmark_for_redisplay))
{ /* Mark the window for redisplay since the selected-window has
a different mode-line. */
wset_redisplay (XWINDOW (selected_window));
wset_redisplay (w);
}
else
redisplay_other_windows ();
sf = SELECTED_FRAME ();
if (XFRAME (WINDOW_FRAME (w)) != sf)
{
fset_selected_window (XFRAME (WINDOW_FRAME (w)), window);
/* Use this rather than Fhandle_switch_frame
so that FRAME_FOCUS_FRAME is moved appropriately as we
move around in the state where a minibuffer in a separate
frame is active. */
Fselect_frame (WINDOW_FRAME (w), norecord);
/* Fselect_frame called us back so we've done all the work already. */
eassert (EQ (window, selected_window));
return window;
}
else
fset_selected_window (sf, window);
select_window_1 (window, inhibit_point_swap);
bset_last_selected_window (XBUFFER (w->contents), window);
record_and_return:
/* record_buffer can call maybe_quit, so make sure it is run only
after we have re-established the invariant between
selected_window and selected_frame, otherwise the temporary
broken invariant might "escape" (Bug#14161). */
if (NILP (norecord))
{
w->use_time = ++window_select_count;
record_buffer (w->contents);
}
return window;
}
/* Select window with a minimum of fuss, i.e. don't record the change anywhere
(not even for redisplay's benefit), and assume that the window's frame is
already selected. */
static void
select_window_1 (Lisp_Object window, bool inhibit_point_swap)
{
/* Store the old selected window's buffer's point in pointm of the old
selected window. It belongs to that window, and when the window is
not selected, must be in the window. */
if (!inhibit_point_swap)
{
struct window *ow = XWINDOW (selected_window);
if (BUFFERP (ow->contents))
set_marker_both (ow->pointm, ow->contents,
BUF_PT (XBUFFER (ow->contents)),
BUF_PT_BYTE (XBUFFER (ow->contents)));
}
selected_window = window;
/* Go to the point recorded in the window.
This is important when the buffer is in more
than one window. It also matters when
redisplay_window has altered point after scrolling,
because it makes the change only in the window. */
set_point_from_marker (XWINDOW (window)->pointm);
}
DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
doc: /* Select WINDOW which must be a live window.
Also make WINDOW's frame the selected frame and WINDOW that frame's
selected window. In addition, make WINDOW's buffer current and set its
buffer's value of `point' to the value of WINDOW's `window-point'.
Return WINDOW.
Optional second arg NORECORD non-nil means do not put this buffer at the
front of the buffer list and do not make this window the most recently
selected one. Also, do not mark WINDOW for redisplay unless NORECORD
equals the special symbol `mark-for-redisplay'.
Run `buffer-list-update-hook' unless NORECORD is non-nil. Note that
applications and internal routines often select a window temporarily for
various purposes; mostly, to simplify coding. As a rule, such
selections should be not recorded and therefore will not pollute
`buffer-list-update-hook'. Selections that "really count" are those
causing a visible change in the next redisplay of WINDOW's frame and
should be always recorded. So if you think of running a function each
time a window gets selected put it on `buffer-list-update-hook'.
Also note that the main editor command loop sets the current buffer to
the buffer of the selected window before each command. */)
(Lisp_Object window, Lisp_Object norecord)
{
return select_window (window, norecord, false);
}
DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
doc: /* Return the buffer displayed in window WINDOW.
If WINDOW is omitted or nil, it defaults to the selected window.
Return nil for an internal window or a deleted window. */)
(Lisp_Object window)
{
struct window *w = decode_any_window (window);
return WINDOW_LEAF_P (w) ? w->contents : Qnil;
}
DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
doc: /* Return the parent window of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
Return nil for a window with no parent (e.g. a root window). */)
(Lisp_Object window)
{
return decode_valid_window (window)->parent;
}
DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 0, 1, 0,
doc: /* Return the topmost child window of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
Return nil if WINDOW is a live window (live windows have no children).
Return nil if WINDOW is an internal window whose children form a
horizontal combination. */)
(Lisp_Object window)
{
struct window *w = decode_valid_window (window);
return WINDOW_VERTICAL_COMBINATION_P (w) ? w->contents : Qnil;
}
DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
doc: /* Return the leftmost child window of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
Return nil if WINDOW is a live window (live windows have no children).
Return nil if WINDOW is an internal window whose children form a
vertical combination. */)
(Lisp_Object window)
{
struct window *w = decode_valid_window (window);
return WINDOW_HORIZONTAL_COMBINATION_P (w) ? w->contents : Qnil;
}
DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
doc: /* Return the next sibling window of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
Return nil if WINDOW has no next sibling. */)
(Lisp_Object window)
{
return decode_valid_window (window)->next;
}
DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
doc: /* Return the previous sibling window of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
Return nil if WINDOW has no previous sibling. */)
(Lisp_Object window)
{
return decode_valid_window (window)->prev;
}
DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
doc: /* Return combination limit of window WINDOW.
WINDOW must be a valid window used in horizontal or vertical combination.
If the return value is nil, child windows of WINDOW can be recombined with
WINDOW's siblings. A return value of t means that child windows of
WINDOW are never (re-)combined with WINDOW's siblings. */)
(Lisp_Object window)
{
struct window *w;
CHECK_VALID_WINDOW (window);
w = XWINDOW (window);
if (WINDOW_LEAF_P (w))
error ("Combination limit is meaningful for internal windows only");
return w->combination_limit;
}
DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
WINDOW must be a valid window used in horizontal or vertical combination.
If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
siblings. LIMIT t means that child windows of WINDOW are never
\(re-)combined with WINDOW's siblings. Other values are reserved for
future use. */)
(Lisp_Object window, Lisp_Object limit)
{
struct window *w;
CHECK_VALID_WINDOW (window);
w = XWINDOW (window);
if (WINDOW_LEAF_P (w))
error ("Combination limit is meaningful for internal windows only");
wset_combination_limit (w, limit);
return limit;
}
DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
doc: /* Return the use time of window WINDOW.
WINDOW must be a live window and defaults to the selected one.
The window with the highest use time is the most recently selected
one. The window with the lowest use time is the least recently
selected one. */)
(Lisp_Object window)
{
return make_number (decode_live_window (window)->use_time);
}
DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0,
doc: /* Return the width of window WINDOW in pixels.
WINDOW must be a valid window and defaults to the selected one.
The return value includes the fringes and margins of WINDOW as well as
any vertical dividers or scroll bars belonging to WINDOW. If WINDOW is
an internal window, its pixel width is the width of the screen areas
spanned by its children. */)
(Lisp_Object window)
{
return make_number (decode_valid_window (window)->pixel_width);
}
DEFUN ("window-pixel-height", Fwindow_pixel_height, Swindow_pixel_height, 0, 1, 0,
doc: /* Return the height of window WINDOW in pixels.
WINDOW must be a valid window and defaults to the selected one.
The return value includes the mode line and header line and the bottom
divider, if any. If WINDOW is an internal window, its pixel height is
the height of the screen areas spanned by its children. */)
(Lisp_Object window)
{
return make_number (decode_valid_window (window)->pixel_height);
}
DEFUN ("window-pixel-width-before-size-change",
Fwindow_pixel_width_before_size_change,
Swindow_pixel_width_before_size_change, 0, 1, 0,
doc: /* Return pixel width of window WINDOW before last size changes.
WINDOW must be a valid window and defaults to the selected one.
The return value is the pixel width of WINDOW at the last time
`window-size-change-functions' was run. It's zero if WINDOW was made
after that. */)
(Lisp_Object window)
{
return (make_number
(decode_valid_window (window)->pixel_width_before_size_change));
}
DEFUN ("window-pixel-height-before-size-change",
Fwindow_pixel_height_before_size_change,
Swindow_pixel_height_before_size_change, 0, 1, 0,
doc: /* Return pixel height of window WINDOW before last size changes.
WINDOW must be a valid window and defaults to the selected one.
The return value is the pixel height of WINDOW at the last time
`window-size-change-functions' was run. It's zero if WINDOW was made
after that. */)
(Lisp_Object window)
{
return (make_number
(decode_valid_window (window)->pixel_height_before_size_change));
}
DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0,
doc: /* Return the height of window WINDOW in lines.
WINDOW must be a valid window and defaults to the selected one.
The return value includes the heights of WINDOW's mode and header line
and its bottom divider, if any. If WINDOW is an internal window, the
total height is the height of the screen areas spanned by its children.
If WINDOW's pixel height is not an integral multiple of its frame's
character height, the number of lines occupied by WINDOW is rounded
internally. This is done in a way such that, if WINDOW is a parent
window, the sum of the total heights of all its children internally
equals the total height of WINDOW.
If the optional argument ROUND is `ceiling', return the smallest integer
larger than WINDOW's pixel height divided by the character height of
WINDOW's frame. ROUND `floor' means to return the largest integer
smaller than WINDOW's pixel height divided by the character height of
WINDOW's frame. Any other value of ROUND means to return the internal
total height of WINDOW. */)
(Lisp_Object window, Lisp_Object round)
{
struct window *w = decode_valid_window (window);
if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
return make_number (w->total_lines);
else
{
int unit = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
return make_number (EQ (round, Qceiling)
? ((w->pixel_height + unit - 1) /unit)
: (w->pixel_height / unit));
}
}
DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 2, 0,
doc: /* Return the total width of window WINDOW in columns.
WINDOW must be a valid window and defaults to the selected one.
The return value includes the widths of WINDOW's fringes, margins,
scroll bars and its right divider, if any. If WINDOW is an internal
window, the total width is the width of the screen areas spanned by its
children.
If WINDOW's pixel width is not an integral multiple of its frame's
character width, the number of lines occupied by WINDOW is rounded
internally. This is done in a way such that, if WINDOW is a parent
window, the sum of the total widths of all its children internally
equals the total width of WINDOW.
If the optional argument ROUND is `ceiling', return the smallest integer
larger than WINDOW's pixel width divided by the character width of
WINDOW's frame. ROUND `floor' means to return the largest integer
smaller than WINDOW's pixel width divided by the character width of
WINDOW's frame. Any other value of ROUND means to return the internal
total width of WINDOW. */)
(Lisp_Object window, Lisp_Object round)
{
struct window *w = decode_valid_window (window);
if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
return make_number (w->total_cols);
else
{
int unit = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
return make_number (EQ (round, Qceiling)
? ((w->pixel_width + unit - 1) /unit)
: (w->pixel_width / unit));
}
}
DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
doc: /* Return the new total size of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
The new total size of WINDOW is the value set by the last call of
`set-window-new-total' for WINDOW. If it is valid, it will be shortly
installed as WINDOW's total height (see `window-total-height') or total
width (see `window-total-width'). */)
(Lisp_Object window)
{
return decode_valid_window (window)->new_total;
}
DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
doc: /* Return the normal height of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
If HORIZONTAL is non-nil, return the normal width of WINDOW.
The normal height of a frame's root window or a window that is
horizontally combined (a window that has a left or right sibling) is
1.0. The normal height of a window that is vertically combined (has a
sibling above or below) is the fraction of the window's height with
respect to its parent. The sum of the normal heights of all windows in a
vertical combination equals 1.0.
Similarly, the normal width of a frame's root window or a window that is
vertically combined equals 1.0. The normal width of a window that is
horizontally combined is the fraction of the window's width with respect
to its parent. The sum of the normal widths of all windows in a
horizontal combination equals 1.0.
The normal sizes of windows are used to restore the proportional sizes
of windows after they have been shrunk to their minimum sizes; for
example when a frame is temporarily made very small and afterwards gets
re-enlarged to its previous size. */)
(Lisp_Object window, Lisp_Object horizontal)
{
struct window *w = decode_valid_window (window);
return NILP (horizontal) ? w->normal_lines : w->normal_cols;
}
DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
doc: /* Return new normal size of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
The new normal size of WINDOW is the value set by the last call of
`set-window-new-normal' for WINDOW. If valid, it will be shortly
installed as WINDOW's normal size (see `window-normal-size'). */)
(Lisp_Object window)
{
return decode_valid_window (window)->new_normal;
}
DEFUN ("window-new-pixel", Fwindow_new_pixel, Swindow_new_pixel, 0, 1, 0,
doc: /* Return new pixel size of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
The new pixel size of WINDOW is the value set by the last call of
`set-window-new-pixel' for WINDOW. If it is valid, it will be shortly
installed as WINDOW's pixel height (see `window-pixel-height') or pixel
width (see `window-pixel-width'). */)
(Lisp_Object window)
{
return decode_valid_window (window)->new_pixel;
}
DEFUN ("window-pixel-left", Fwindow_pixel_left, Swindow_pixel_left, 0, 1, 0,
doc: /* Return left pixel edge of window WINDOW.
WINDOW must be a valid window and defaults to the selected one. */)
(Lisp_Object window)
{
return make_number (decode_valid_window (window)->pixel_left);
}
DEFUN ("window-pixel-top", Fwindow_pixel_top, Swindow_pixel_top, 0, 1, 0,
doc: /* Return top pixel edge of window WINDOW.
WINDOW must be a valid window and defaults to the selected one. */)
(Lisp_Object window)
{
return make_number (decode_valid_window (window)->pixel_top);
}
DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
doc: /* Return left column of window WINDOW.
This is the distance, in columns, between the left edge of WINDOW and
the left edge of the frame's window area. For instance, the return
value is 0 if there is no window to the left of WINDOW.
WINDOW must be a valid window and defaults to the selected one. */)
(Lisp_Object window)
{
return make_number (decode_valid_window (window)->left_col);
}
DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
doc: /* Return top line of window WINDOW.
This is the distance, in lines, between the top of WINDOW and the top
of the frame's window area. For instance, the return value is 0 if
there is no window above WINDOW.
WINDOW must be a valid window and defaults to the selected one. */)
(Lisp_Object window)
{
return make_number (decode_valid_window (window)->top_line);
}
/* Return the number of lines/pixels of W's body. Don't count any mode
or header line or horizontal divider of W. Rounds down to nearest
integer when not working pixelwise. */
static int
window_body_height (struct window *w, bool pixelwise)
{
int height = (w->pixel_height
- WINDOW_HEADER_LINE_HEIGHT (w)
- (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
? WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
: 0)
- WINDOW_MODE_LINE_HEIGHT (w)
- WINDOW_BOTTOM_DIVIDER_WIDTH (w));
/* Don't return a negative value. */
return max (pixelwise
? height
: height / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)),
0);
}
/* Return the number of columns/pixels of W's body. Don't count columns
occupied by the scroll bar or the divider/vertical bar separating W
from its right sibling or margins. On window-systems don't count
fringes either. Round down to nearest integer when not working
pixelwise. */
int
window_body_width (struct window *w, bool pixelwise)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
int width = (w->pixel_width
- WINDOW_RIGHT_DIVIDER_WIDTH (w)
- (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
? WINDOW_SCROLL_BAR_AREA_WIDTH (w)
: (/* A vertical bar is either 1 or 0. */
!FRAME_WINDOW_P (f)
&& !WINDOW_RIGHTMOST_P (w)
&& !WINDOW_RIGHT_DIVIDER_WIDTH (w)))
- WINDOW_MARGINS_WIDTH (w)
- (FRAME_WINDOW_P (f)
? WINDOW_FRINGES_WIDTH (w)
: 0));
/* Don't return a negative value. */
return max (pixelwise
? width
: width / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)),
0);
}
DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
doc: /* Return the height of WINDOW's text area.
WINDOW must be a live window and defaults to the selected one. Optional
argument PIXELWISE non-nil means return the height of WINDOW's text area
in pixels. The return value does not include the mode line or header
line or any horizontal divider.
If PIXELWISE is nil, return the largest integer smaller than WINDOW's
pixel height divided by the character height of WINDOW's frame. This
means that if a line at the bottom of the text area is only partially
visible, that line is not counted. */)
(Lisp_Object window, Lisp_Object pixelwise)
{
return make_number (window_body_height (decode_live_window (window),