aboutsummaryrefslogtreecommitdiffstats
path: root/src/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c247
1 files changed, 202 insertions, 45 deletions
diff --git a/src/window.c b/src/window.c
index a3e7b93e878..0233c6bf79e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -335,13 +335,16 @@ Return nil if that position is scrolled vertically out of view.
335If a character is only partially visible, nil is returned, unless the 335If a character is only partially visible, nil is returned, unless the
336optional argument PARTIALLY is non-nil. 336optional argument PARTIALLY is non-nil.
337If POS is only out of view because of horizontal scrolling, return non-nil. 337If POS is only out of view because of horizontal scrolling, return non-nil.
338If POS is t, it specifies the position of the last visible glyph in WINDOW.
338POS defaults to point in WINDOW; WINDOW defaults to the selected window. 339POS defaults to point in WINDOW; WINDOW defaults to the selected window.
339 340
340If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil, 341If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
341return value is a list (X Y PARTIAL) where X and Y are the pixel coordinates 342return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
342relative to the top left corner of the window. PARTIAL is nil if the character 343where X and Y are the pixel coordinates relative to the top left corner
343after POS is fully visible; otherwise it is a cons (RTOP . RBOT) where RTOP 344of the window. The remaining elements are omitted if the character after
344and RBOT are the number of pixels invisible at the top and bottom of the row. */) 345POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
346off-window at the top and bottom of the row, ROWH is the height of the
347display row, and VPOS is the row number (0-based) containing POS. */)
345 (pos, window, partially) 348 (pos, window, partially)
346 Lisp_Object pos, window, partially; 349 Lisp_Object pos, window, partially;
347{ 350{
@@ -350,14 +353,16 @@ and RBOT are the number of pixels invisible at the top and bottom of the row. *
350 register struct buffer *buf; 353 register struct buffer *buf;
351 struct text_pos top; 354 struct text_pos top;
352 Lisp_Object in_window = Qnil; 355 Lisp_Object in_window = Qnil;
353 int rtop, rbot, fully_p = 1; 356 int rtop, rbot, rowh, vpos, fully_p = 1;
354 int x, y; 357 int x, y;
355 358
356 w = decode_window (window); 359 w = decode_window (window);
357 buf = XBUFFER (w->buffer); 360 buf = XBUFFER (w->buffer);
358 SET_TEXT_POS_FROM_MARKER (top, w->start); 361 SET_TEXT_POS_FROM_MARKER (top, w->start);
359 362
360 if (!NILP (pos)) 363 if (EQ (pos, Qt))
364 posint = -1;
365 else if (!NILP (pos))
361 { 366 {
362 CHECK_NUMBER_COERCE_MARKER (pos); 367 CHECK_NUMBER_COERCE_MARKER (pos);
363 posint = XINT (pos); 368 posint = XINT (pos);
@@ -369,24 +374,138 @@ and RBOT are the number of pixels invisible at the top and bottom of the row. *
369 374
370 /* If position is above window start or outside buffer boundaries, 375 /* If position is above window start or outside buffer boundaries,
371 or if window start is out of range, position is not visible. */ 376 or if window start is out of range, position is not visible. */
372 if (posint >= CHARPOS (top) 377 if ((EQ (pos, Qt)
373 && posint <= BUF_ZV (buf) 378 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
374 && CHARPOS (top) >= BUF_BEGV (buf) 379 && CHARPOS (top) >= BUF_BEGV (buf)
375 && CHARPOS (top) <= BUF_ZV (buf) 380 && CHARPOS (top) <= BUF_ZV (buf)
376 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, NILP (partially)) 381 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
377 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p))) 382 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
378 in_window = Qt; 383 in_window = Qt;
379 384
380 if (!NILP (in_window) && !NILP (partially)) 385 if (!NILP (in_window) && !NILP (partially))
381 in_window = Fcons (make_number (x), 386 {
382 Fcons (make_number (y), 387 Lisp_Object part = Qnil;
383 Fcons ((fully_p ? Qnil 388 if (!fully_p)
384 : Fcons (make_number (rtop), 389 part = list4 (make_number (rtop), make_number (rbot),
385 make_number (rbot))), 390 make_number (rowh), make_number (vpos));
386 Qnil))); 391 in_window = Fcons (make_number (x),
392 Fcons (make_number (y), part));
393 }
394
387 return in_window; 395 return in_window;
388} 396}
389 397
398DEFUN ("window-line-height", Fwindow_line_height,
399 Swindow_line_height, 0, 2, 0,
400 doc: /* Return height in pixels of text line LINE in window WINDOW.
401If WINDOW is nil or omitted, use selected window.
402
403Return height of current line if LINE is omitted or nil. Return height of
404header or mode line if LINE is `header-line' and `mode-line'.
405Otherwise, LINE is a text line number starting from 0. A negative number
406counts from the end of the window.
407
408Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
409in pixels of the visible part of the line, VPOS and YPOS are the
410vertical position in lines and pixels of the line, relative to the top
411of the first text line, and OFFBOT is the number of off-window pixels at
412the bottom of the text line. If there are off-window pixels at the top
413of the (first) text line, YPOS is negative.
414
415Return nil if window display is not up-to-date. In that case, use
416`pos-visible-in-window-p' to obtain the information. */)
417 (line, window)
418 Lisp_Object line, window;
419{
420 register struct window *w;
421 register struct buffer *b;
422 struct glyph_row *row, *end_row;
423 int max_y, crop, i, n;
424
425 w = decode_window (window);
426
427 if (noninteractive
428 || w->pseudo_window_p)
429 return Qnil;
430
431 CHECK_BUFFER (w->buffer);
432 b = XBUFFER (w->buffer);
433
434 /* Fail if current matrix is not up-to-date. */
435 if (NILP (w->window_end_valid)
436 || current_buffer->clip_changed
437 || current_buffer->prevent_redisplay_optimizations_p
438 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
439 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
440 return Qnil;
441
442 if (NILP (line))
443 {
444 i = w->cursor.vpos;
445 if (i < 0 || i >= w->current_matrix->nrows
446 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
447 return Qnil;
448 max_y = window_text_bottom_y (w);
449 goto found_row;
450 }
451
452 if (EQ (line, Qheader_line))
453 {
454 if (!WINDOW_WANTS_HEADER_LINE_P (w))
455 return Qnil;
456 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
457 if (!row->enabled_p)
458 return Qnil;
459 return list4 (make_number (row->height),
460 make_number (0), make_number (0),
461 make_number (0));
462 }
463
464 if (EQ (line, Qmode_line))
465 {
466 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
467 if (!row->enabled_p)
468 return Qnil;
469 return list4 (make_number (row->height),
470 make_number (0), /* not accurate */
471 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
472 + window_text_bottom_y (w)),
473 make_number (0));
474 }
475
476 CHECK_NUMBER (line);
477 n = XINT (line);
478
479 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
480 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
481 max_y = window_text_bottom_y (w);
482 i = 0;
483
484 while ((n < 0 || i < n)
485 && row <= end_row && row->enabled_p
486 && row->y + row->height < max_y)
487 row++, i++;
488
489 if (row > end_row || !row->enabled_p)
490 return Qnil;
491
492 if (++n < 0)
493 {
494 if (-n > i)
495 return Qnil;
496 row += n;
497 i += n;
498 }
499
500 found_row:
501 crop = max (0, (row->y + row->height) - max_y);
502 return list4 (make_number (row->height + min (0, row->y) - crop),
503 make_number (i),
504 make_number (row->y),
505 make_number (crop));
506}
507
508
390 509
391static struct window * 510static struct window *
392decode_window (window) 511decode_window (window)
@@ -451,7 +570,7 @@ DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
451Return NCOL. NCOL should be zero or positive. 570Return NCOL. NCOL should be zero or positive.
452 571
453Note that if `automatic-hscrolling' is non-nil, you cannot scroll the 572Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
454window so that the location of point becomes invisible. */) 573window so that the location of point moves off-window. */)
455 (window, ncol) 574 (window, ncol)
456 Lisp_Object window, ncol; 575 Lisp_Object window, ncol;
457{ 576{
@@ -1048,9 +1167,11 @@ if it isn't already recorded. */)
1048 Lisp_Object value; 1167 Lisp_Object value;
1049 struct window *w = decode_window (window); 1168 struct window *w = decode_window (window);
1050 Lisp_Object buf; 1169 Lisp_Object buf;
1170 struct buffer *b;
1051 1171
1052 buf = w->buffer; 1172 buf = w->buffer;
1053 CHECK_BUFFER (buf); 1173 CHECK_BUFFER (buf);
1174 b = XBUFFER (buf);
1054 1175
1055#if 0 /* This change broke some things. We should make it later. */ 1176#if 0 /* This change broke some things. We should make it later. */
1056 /* If we don't know the end position, return nil. 1177 /* If we don't know the end position, return nil.
@@ -1063,12 +1184,20 @@ if it isn't already recorded. */)
1063 1184
1064 if (! NILP (update) 1185 if (! NILP (update)
1065 && ! (! NILP (w->window_end_valid) 1186 && ! (! NILP (w->window_end_valid)
1066 && XFASTINT (w->last_modified) >= MODIFF) 1187 && XFASTINT (w->last_modified) >= BUF_MODIFF (b))
1067 && !noninteractive) 1188 && !noninteractive)
1068 { 1189 {
1069 struct text_pos startp; 1190 struct text_pos startp;
1070 struct it it; 1191 struct it it;
1071 struct buffer *old_buffer = NULL, *b = XBUFFER (buf); 1192 struct buffer *old_buffer = NULL;
1193
1194 /* Cannot use Fvertical_motion because that function doesn't
1195 cope with variable-height lines. */
1196 if (b != current_buffer)
1197 {
1198 old_buffer = current_buffer;
1199 set_buffer_internal (b);
1200 }
1072 1201
1073 /* In case W->start is out of the range, use something 1202 /* In case W->start is out of the range, use something
1074 reasonable. This situation occurred when loading a file with 1203 reasonable. This situation occurred when loading a file with
@@ -1082,14 +1211,6 @@ if it isn't already recorded. */)
1082 else 1211 else
1083 SET_TEXT_POS_FROM_MARKER (startp, w->start); 1212 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1084 1213
1085 /* Cannot use Fvertical_motion because that function doesn't
1086 cope with variable-height lines. */
1087 if (b != current_buffer)
1088 {
1089 old_buffer = current_buffer;
1090 set_buffer_internal (b);
1091 }
1092
1093 start_display (&it, w, startp); 1214 start_display (&it, w, startp);
1094 move_it_vertically (&it, window_box_height (w)); 1215 move_it_vertically (&it, window_box_height (w));
1095 if (it.current_y < it.last_visible_y) 1216 if (it.current_y < it.last_visible_y)
@@ -1100,7 +1221,7 @@ if it isn't already recorded. */)
1100 set_buffer_internal (old_buffer); 1221 set_buffer_internal (old_buffer);
1101 } 1222 }
1102 else 1223 else
1103 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos)); 1224 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1104 1225
1105 return value; 1226 return value;
1106} 1227}
@@ -4820,10 +4941,10 @@ window_scroll_pixel_based (window, n, whole, noerror)
4820 struct it it; 4941 struct it it;
4821 struct window *w = XWINDOW (window); 4942 struct window *w = XWINDOW (window);
4822 struct text_pos start; 4943 struct text_pos start;
4823 Lisp_Object tem;
4824 int this_scroll_margin; 4944 int this_scroll_margin;
4825 /* True if we fiddled the window vscroll field without really scrolling. */ 4945 /* True if we fiddled the window vscroll field without really scrolling. */
4826 int vscrolled = 0; 4946 int vscrolled = 0;
4947 int x, y, rtop, rbot, rowh, vpos;
4827 4948
4828 SET_TEXT_POS_FROM_MARKER (start, w->start); 4949 SET_TEXT_POS_FROM_MARKER (start, w->start);
4829 4950
@@ -4831,8 +4952,8 @@ window_scroll_pixel_based (window, n, whole, noerror)
4831 the screen. Allow PT to be partially visible, otherwise 4952 the screen. Allow PT to be partially visible, otherwise
4832 something like (scroll-down 1) with PT in the line before 4953 something like (scroll-down 1) with PT in the line before
4833 the partially visible one would recenter. */ 4954 the partially visible one would recenter. */
4834 tem = Fpos_visible_in_window_p (make_number (PT), window, Qt); 4955
4835 if (NILP (tem)) 4956 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4836 { 4957 {
4837 /* Move backward half the height of the window. Performance note: 4958 /* Move backward half the height of the window. Performance note:
4838 vmotion used here is about 10% faster, but would give wrong 4959 vmotion used here is about 10% faster, but would give wrong
@@ -4857,7 +4978,7 @@ window_scroll_pixel_based (window, n, whole, noerror)
4857 } 4978 }
4858 else if (auto_window_vscroll_p) 4979 else if (auto_window_vscroll_p)
4859 { 4980 {
4860 if (tem = XCAR (XCDR (XCDR (tem))), CONSP (tem)) 4981 if (rtop || rbot) /* partially visible */
4861 { 4982 {
4862 int px; 4983 int px;
4863 int dy = WINDOW_FRAME_LINE_HEIGHT (w); 4984 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
@@ -4867,19 +4988,52 @@ window_scroll_pixel_based (window, n, whole, noerror)
4867 dy); 4988 dy);
4868 dy *= n; 4989 dy *= n;
4869 4990
4870 if (n < 0 && (px = XINT (XCAR (tem))) > 0) 4991 if (n < 0)
4871 { 4992 {
4872 px = max (0, -w->vscroll - min (px, -dy)); 4993 /* Only vscroll backwards if already vscrolled forwards. */
4873 Fset_window_vscroll (window, make_number (px), Qt); 4994 if (w->vscroll < 0 && rtop > 0)
4874 return; 4995 {
4996 px = max (0, -w->vscroll - min (rtop, -dy));
4997 Fset_window_vscroll (window, make_number (px), Qt);
4998 return;
4999 }
4875 } 5000 }
4876 if (n > 0 && (px = XINT (XCDR (tem))) > 0) 5001 if (n > 0)
4877 { 5002 {
4878 px = max (0, -w->vscroll + min (px, dy)); 5003 /* Do vscroll if already vscrolled or only display line. */
4879 Fset_window_vscroll (window, make_number (px), Qt); 5004 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4880 return; 5005 {
5006 px = max (0, -w->vscroll + min (rbot, dy));
5007 Fset_window_vscroll (window, make_number (px), Qt);
5008 return;
5009 }
5010
5011 /* Maybe modify window start instead of scrolling. */
5012 if (rbot > 0 || w->vscroll < 0)
5013 {
5014 int spos;
5015
5016 Fset_window_vscroll (window, make_number (0), Qt);
5017 /* If there are other text lines above the current row,
5018 move window start to current row. Else to next row. */
5019 if (rbot > 0)
5020 spos = XINT (Fline_beginning_position (Qnil));
5021 else
5022 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
5023 set_marker_restricted (w->start, make_number (spos),
5024 w->buffer);
5025 w->start_at_line_beg = Qt;
5026 w->update_mode_line = Qt;
5027 XSETFASTINT (w->last_modified, 0);
5028 XSETFASTINT (w->last_overlay_modified, 0);
5029 /* Set force_start so that redisplay_window will run the
5030 window-scroll-functions. */
5031 w->force_start = Qt;
5032 return;
5033 }
4881 } 5034 }
4882 } 5035 }
5036 /* Cancel previous vscroll. */
4883 Fset_window_vscroll (window, make_number (0), Qt); 5037 Fset_window_vscroll (window, make_number (0), Qt);
4884 } 5038 }
4885 5039
@@ -4920,7 +5074,7 @@ window_scroll_pixel_based (window, n, whole, noerror)
4920 if (dy <= 0) 5074 if (dy <= 0)
4921 { 5075 {
4922 move_it_vertically_backward (&it, -dy); 5076 move_it_vertically_backward (&it, -dy);
4923 /* Ensure we actually does move, e.g. in case we are currently 5077 /* Ensure we actually do move, e.g. in case we are currently
4924 looking at an image that is taller that the window height. */ 5078 looking at an image that is taller that the window height. */
4925 while (start_pos == IT_CHARPOS (it) 5079 while (start_pos == IT_CHARPOS (it)
4926 && start_pos > BEGV) 5080 && start_pos > BEGV)
@@ -4930,7 +5084,7 @@ window_scroll_pixel_based (window, n, whole, noerror)
4930 { 5084 {
4931 move_it_to (&it, ZV, -1, it.current_y + dy, -1, 5085 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4932 MOVE_TO_POS | MOVE_TO_Y); 5086 MOVE_TO_POS | MOVE_TO_Y);
4933 /* Ensure we actually does move, e.g. in case we are currently 5087 /* Ensure we actually do move, e.g. in case we are currently
4934 looking at an image that is taller that the window height. */ 5088 looking at an image that is taller that the window height. */
4935 while (start_pos == IT_CHARPOS (it) 5089 while (start_pos == IT_CHARPOS (it)
4936 && start_pos < ZV) 5090 && start_pos < ZV)
@@ -6658,7 +6812,7 @@ display marginal areas and the text area. */)
6658 CHECK_NATNUM (left_width); 6812 CHECK_NATNUM (left_width);
6659 if (!NILP (right_width)) 6813 if (!NILP (right_width))
6660 CHECK_NATNUM (right_width); 6814 CHECK_NATNUM (right_width);
6661 6815
6662 /* Do nothing on a tty. */ 6816 /* Do nothing on a tty. */
6663 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) 6817 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6664 && (!EQ (w->left_fringe_width, left_width) 6818 && (!EQ (w->left_fringe_width, left_width)
@@ -7292,16 +7446,18 @@ See also `same-window-buffer-names'. */);
7292 next_screen_context_lines = 2; 7446 next_screen_context_lines = 2;
7293 7447
7294 DEFVAR_INT ("split-height-threshold", &split_height_threshold, 7448 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
7295 doc: /* *A window must be at least this tall to be eligible for splitting by `display-buffer'. 7449 doc: /* *A window must be at least this tall to be eligible for splitting
7450by `display-buffer'. The value is in line units.
7296If there is only one window, it is split regardless of this value. */); 7451If there is only one window, it is split regardless of this value. */);
7297 split_height_threshold = 500; 7452 split_height_threshold = 500;
7298 7453
7299 DEFVAR_INT ("window-min-height", &window_min_height, 7454 DEFVAR_INT ("window-min-height", &window_min_height,
7300 doc: /* *Delete any window less than this tall (including its mode line). */); 7455 doc: /* *Delete any window less than this tall (including its mode line).
7456The value is in line units. */);
7301 window_min_height = 4; 7457 window_min_height = 4;
7302 7458
7303 DEFVAR_INT ("window-min-width", &window_min_width, 7459 DEFVAR_INT ("window-min-width", &window_min_width,
7304 doc: /* *Delete any window less than this wide. */); 7460 doc: /* *Delete any window less than this wide (measured in characters). */);
7305 window_min_width = 10; 7461 window_min_width = 10;
7306 7462
7307 DEFVAR_LISP ("scroll-preserve-screen-position", 7463 DEFVAR_LISP ("scroll-preserve-screen-position",
@@ -7327,6 +7483,7 @@ The selected frame is the one whose configuration has changed. */);
7327 defsubr (&Swindowp); 7483 defsubr (&Swindowp);
7328 defsubr (&Swindow_live_p); 7484 defsubr (&Swindow_live_p);
7329 defsubr (&Spos_visible_in_window_p); 7485 defsubr (&Spos_visible_in_window_p);
7486 defsubr (&Swindow_line_height);
7330 defsubr (&Swindow_buffer); 7487 defsubr (&Swindow_buffer);
7331 defsubr (&Swindow_height); 7488 defsubr (&Swindow_height);
7332 defsubr (&Swindow_width); 7489 defsubr (&Swindow_width);