diff options
Diffstat (limited to 'src/window.c')
-rw-r--r-- | src/window.c | 213 |
1 files changed, 205 insertions, 8 deletions
diff --git a/src/window.c b/src/window.c index bf89f0e488b..4816bd69909 100644 --- a/src/window.c +++ b/src/window.c @@ -1208,13 +1208,13 @@ coordinates_in_window (register struct window *w, int x, int y) - WINDOW_BOTTOM_DIVIDER_WIDTH (w)))) return ON_HORIZONTAL_SCROLL_BAR; /* On the mode or header line? */ - else if ((WINDOW_WANTS_MODELINE_P (w) + else if ((window_wants_mode_line (w) && y >= (bottom_y - CURRENT_MODE_LINE_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w)) && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w) && (part = ON_MODE_LINE)) - || (WINDOW_WANTS_HEADER_LINE_P (w) + || (window_wants_header_line (w) && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w) && (part = ON_HEADER_LINE))) { @@ -1851,7 +1851,7 @@ Return nil if window display is not up-to-date. In that case, use if (EQ (line, Qheader_line)) { - if (!WINDOW_WANTS_HEADER_LINE_P (w)) + if (!window_wants_header_line (w)) return Qnil; row = MATRIX_HEADER_LINE_ROW (w->current_matrix); return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil; @@ -1898,6 +1898,129 @@ Return nil if window display is not up-to-date. In that case, use return list4i (row->height + min (0, row->y) - crop, i, row->y, crop); } +DEFUN ("window-lines-pixel-dimensions", Fwindow_lines_pixel_dimensions, Swindow_lines_pixel_dimensions, 0, 6, 0, + doc: /* Return pixel dimensions of WINDOW's lines. +The return value is a list of the x- and y-coordinates of the lower +right corner of the last character of each line. Return nil if the +current glyph matrix of WINDOW is not up-to-date. + +Optional argument WINDOW specifies the window whose lines' dimensions +shall be returned. Nil or omitted means to return the dimensions for +the selected window. + +FIRST, if non-nil, specifies the index of the first line whose +dimensions shall be returned. If FIRST is nil and BODY is non-nil, +start with the first text line of WINDOW. Otherwise, start with the +first line of WINDOW. + +LAST, if non-nil, specifies the last line whose dimensions shall be +returned. If LAST is nil and BODY is non-nil, the last line is the last +line of the body (text area) of WINDOW. Otherwise, last is the last +line of WINDOW. + +INVERSE, if nil, means that the y-pixel value returned for a specific +line specifies the distance in pixels from the left edge (body edge if +BODY is non-nil) of WINDOW to the right edge of the last glyph of that +line. INVERSE non-nil means that the y-pixel value returned for a +specific line specifies the distance in pixels from the right edge of +the last glyph of that line to the right edge (body edge if BODY is +non-nil) of WINDOW. + +LEFT non-nil means to return the x- and y-coordinates of the lower left +corner of the leftmost character on each line. This is the value that +should be used for buffers that mostly display text from right to left. + +If LEFT is non-nil and INVERSE is nil, this means that the y-pixel value +returned for a specific line specifies the distance in pixels from the +left edge of the last (leftmost) glyph of that line to the right edge +(body edge if BODY is non-nil) of WINDOW. If LEFT and INVERSE are both +non-nil, the y-pixel value returned for a specific line specifies the +distance in pixels from the left edge (body edge if BODY is non-nil) of +WINDOW to the left edge of the last (leftmost) glyph of that line. + +Normally, the value of this function is not available while Emacs is +busy, for example, when processing a command. It should be retrievable +though when run from an idle timer with a delay of zero seconds. */) + (Lisp_Object window, Lisp_Object first, Lisp_Object last, Lisp_Object body, Lisp_Object inverse, Lisp_Object left) +{ + struct window *w = decode_live_window (window); + struct buffer *b; + struct glyph_row *row, *end_row; + int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w); + Lisp_Object rows = Qnil; + int window_width = NILP (body) ? w->pixel_width : window_body_width (w, true); + int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); + int subtract = NILP (body) ? 0 : header_line_height; + bool invert = !NILP (inverse); + bool left_flag = !NILP (left); + + if (noninteractive || w->pseudo_window_p) + return Qnil; + + CHECK_BUFFER (w->contents); + b = XBUFFER (w->contents); + + /* Fail if current matrix is not up-to-date. */ + if (!w->window_end_valid + || windows_or_buffers_changed + || b->clip_changed + || b->prevent_redisplay_optimizations_p + || window_outdated (w)) + return Qnil; + + if (NILP (first)) + row = (NILP (body) + ? MATRIX_ROW (w->current_matrix, 0) + : MATRIX_FIRST_TEXT_ROW (w->current_matrix)); + else if (NUMBERP (first)) + { + CHECK_RANGED_INTEGER (first, 0, w->current_matrix->nrows); + row = MATRIX_ROW (w->current_matrix, XINT (first)); + } + else + error ("Invalid specification of first line"); + + if (NILP (last)) + + end_row = (NILP (body) + ? MATRIX_ROW (w->current_matrix, w->current_matrix->nrows) + : MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)); + else if (NUMBERP (last)) + { + CHECK_RANGED_INTEGER (last, 0, w->current_matrix->nrows); + end_row = MATRIX_ROW (w->current_matrix, XINT (last)); + } + else + error ("Invalid specification of last line"); + + while (row <= end_row && row->enabled_p + && row->y + row->height < max_y) + { + + if (left_flag) + { + struct glyph *glyph = row->glyphs[TEXT_AREA]; + + rows = Fcons (Fcons (make_number + (invert + ? glyph->pixel_width + : window_width - glyph->pixel_width), + make_number (row->y + row->height - subtract)), + rows); + } + else + rows = Fcons (Fcons (make_number + (invert + ? window_width - row->pixel_width + : row->pixel_width), + make_number (row->y + row->height - subtract)), + rows); + row++; + } + + return Fnreverse (rows); +} + DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p, 0, 1, 0, doc: /* Return non-nil when WINDOW is dedicated to its buffer. @@ -2003,16 +2126,24 @@ return value is a list of elements of the form (PARAMETER . VALUE). */) return Fcopy_alist (decode_valid_window (window)->window_parameters); } +Lisp_Object +window_parameter (struct window *w, Lisp_Object parameter) +{ + Lisp_Object result = Fassq (parameter, w->window_parameters); + + return CDR_SAFE (result); +} + + DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter, 2, 2, 0, doc: /* Return WINDOW's value for PARAMETER. WINDOW can be any window and defaults to the selected one. */) (Lisp_Object window, Lisp_Object parameter) { - Lisp_Object result; + struct window *w = decode_any_window (window); - result = Fassq (parameter, decode_any_window (window)->window_parameters); - return CDR_SAFE (result); + return window_parameter (w, parameter); } DEFUN ("set-window-parameter", Fset_window_parameter, @@ -4740,6 +4871,69 @@ mark_window_cursors_off (struct window *w) } +/** + * window_wants_mode_line: + * + * Return 1 if window W wants a mode line and is high enough to + * accomodate it, 0 otherwise. + * + * W wants a mode line if it's a leaf window and neither a minibuffer + * nor a pseudo window. Moreover, its 'window-mode-line-format' + * parameter must not be 'none' and either that parameter or W's + * buffer's 'mode-line-format' value must be non-nil. Finally, W must + * be higher than its frame's canonical character height. + */ +bool +window_wants_mode_line (struct window *w) +{ + Lisp_Object window_mode_line_format = + window_parameter (w, Qmode_line_format); + + return ((WINDOW_LEAF_P (w) + && !MINI_WINDOW_P (w) + && !WINDOW_PSEUDO_P (w) + && !EQ (window_mode_line_format, Qnone) + && (!NILP (window_mode_line_format) + || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), mode_line_format))) + && WINDOW_PIXEL_HEIGHT (w) > WINDOW_FRAME_LINE_HEIGHT (w)) + ? 1 + : 0); +} + + +/** + * window_wants_header_line: + * + * Return 1 if window W wants a header line and is high enough to + * accomodate it, 0 otherwise. + * + * W wants a header line if it's a leaf window and neither a minibuffer + * nor a pseudo window. Moreover, its 'window-mode-line-format' + * parameter must not be 'none' and either that parameter or W's + * buffer's 'mode-line-format' value must be non-nil. Finally, W must + * be higher than its frame's canonical character height and be able to + * accomodate a mode line too if necessary (the mode line prevails). + */ +bool +window_wants_header_line (struct window *w) +{ + Lisp_Object window_header_line_format = + window_parameter (w, Qheader_line_format); + + return ((WINDOW_LEAF_P (w) + && !MINI_WINDOW_P (w) + && !WINDOW_PSEUDO_P (w) + && !EQ (window_header_line_format, Qnone) + && (!NILP (window_header_line_format) + || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format))) + && (WINDOW_PIXEL_HEIGHT (w) + > (window_wants_mode_line (w) + ? 2 * WINDOW_FRAME_LINE_HEIGHT (w) + : WINDOW_FRAME_LINE_HEIGHT (w)))) + ? 1 + : 0); +} + /* Return number of lines of text (not counting mode lines) in W. */ int @@ -4753,10 +4947,10 @@ window_internal_height (struct window *w) || WINDOWP (w->contents) || !NILP (w->next) || !NILP (w->prev) - || WINDOW_WANTS_MODELINE_P (w)) + || window_wants_mode_line (w)) --ht; - if (WINDOW_WANTS_HEADER_LINE_P (w)) + if (window_wants_header_line (w)) --ht; } @@ -7354,6 +7548,8 @@ syms_of_window (void) DEFSYM (Qfloor, "floor"); DEFSYM (Qceiling, "ceiling"); DEFSYM (Qmark_for_redisplay, "mark-for-redisplay"); + DEFSYM (Qmode_line_format, "mode-line-format"); + DEFSYM (Qheader_line_format, "header-line-format"); staticpro (&Vwindow_list); @@ -7603,6 +7799,7 @@ displayed after a scrolling operation to be somewhat inaccurate. */); defsubr (&Sset_window_point); defsubr (&Sset_window_start); defsubr (&Swindow_dedicated_p); + defsubr (&Swindow_lines_pixel_dimensions); defsubr (&Sset_window_dedicated_p); defsubr (&Swindow_display_table); defsubr (&Sset_window_display_table); |