+ /* If position is above window start or outside buffer boundaries,
+ or if window start is out of range, position is not visible. */
+ if ((EQ (pos, Qt)
+ || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
+ && CHARPOS (top) >= BUF_BEGV (buf)
+ && CHARPOS (top) <= BUF_ZV (buf)
+ && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
+ && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
+ in_window = Qt;
+
+ if (!NILP (in_window) && !NILP (partially))
+ {
+ Lisp_Object part = Qnil;
+ if (!fully_p)
+ part = list4 (make_number (rtop), make_number (rbot),
+ make_number (rowh), make_number (vpos));
+ in_window = Fcons (make_number (x),
+ Fcons (make_number (y), part));
+ }
+
+ return in_window;
+}
+
+DEFUN ("window-line-height", Fwindow_line_height,
+ Swindow_line_height, 0, 2, 0,
+ doc: /* Return height in pixels of text line LINE in window WINDOW.
+WINDOW defaults to the selected window.
+
+Return height of current line if LINE is omitted or nil. Return height of
+header or mode line if LINE is `header-line' or `mode-line'.
+Otherwise, LINE is a text line number starting from 0. A negative number
+counts from the end of the window.
+
+Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
+in pixels of the visible part of the line, VPOS and YPOS are the
+vertical position in lines and pixels of the line, relative to the top
+of the first text line, and OFFBOT is the number of off-window pixels at
+the bottom of the text line. If there are off-window pixels at the top
+of the (first) text line, YPOS is negative.
+
+Return nil if window display is not up-to-date. In that case, use
+`pos-visible-in-window-p' to obtain the information. */)
+ (Lisp_Object line, Lisp_Object window)
+{
+ register struct window *w;
+ register struct buffer *b;
+ struct glyph_row *row, *end_row;
+ int max_y, crop, i, n;
+
+ w = decode_window (window);
+
+ if (noninteractive || w->pseudo_window_p)
+ return Qnil;
+
+ CHECK_BUFFER (w->buffer);
+ b = XBUFFER (w->buffer);
+
+ /* Fail if current matrix is not up-to-date. */
+ if (NILP (w->window_end_valid)
+ || current_buffer->clip_changed
+ || current_buffer->prevent_redisplay_optimizations_p
+ || XFASTINT (w->last_modified) < BUF_MODIFF (b)
+ || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
+ return Qnil;
+
+ if (NILP (line))
+ {
+ i = w->cursor.vpos;
+ if (i < 0 || i >= w->current_matrix->nrows
+ || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
+ return Qnil;
+ max_y = window_text_bottom_y (w);
+ goto found_row;
+ }
+
+ if (EQ (line, Qheader_line))
+ {
+ if (!WINDOW_WANTS_HEADER_LINE_P (w))
+ return Qnil;
+ row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
+ if (!row->enabled_p)
+ return Qnil;
+ return list4 (make_number (row->height),
+ make_number (0), make_number (0),
+ make_number (0));
+ }
+
+ if (EQ (line, Qmode_line))
+ {
+ row = MATRIX_MODE_LINE_ROW (w->current_matrix);
+ if (!row->enabled_p)
+ return Qnil;
+ return list4 (make_number (row->height),
+ make_number (0), /* not accurate */
+ make_number (WINDOW_HEADER_LINE_HEIGHT (w)
+ + window_text_bottom_y (w)),
+ make_number (0));
+ }
+
+ CHECK_NUMBER (line);
+ n = XINT (line);
+
+ row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
+ max_y = window_text_bottom_y (w);
+ i = 0;
+
+ while ((n < 0 || i < n)
+ && row <= end_row && row->enabled_p
+ && row->y + row->height < max_y)
+ row++, i++;
+
+ if (row > end_row || !row->enabled_p)
+ return Qnil;
+
+ if (++n < 0)
+ {
+ if (-n > i)
+ return Qnil;
+ row += n;
+ i += n;
+ }
+
+ found_row:
+ crop = max (0, (row->y + row->height) - max_y);
+ return list4 (make_number (row->height + min (0, row->y) - crop),
+ make_number (i),
+ make_number (row->y),
+ make_number (crop));
+}
+
+DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
+ 0, 1, 0,
+ doc: /* Return non-nil when WINDOW is dedicated to its buffer.
+More precisely, return the value assigned by the last call of
+`set-window-dedicated-p' for WINDOW. Return nil if that function was
+never called with WINDOW as its argument, or the value set by that
+function was internally reset since its last call. WINDOW defaults to
+the selected window.
+
+When a window is dedicated to its buffer, `display-buffer' will refrain
+from displaying another buffer in it. `get-lru-window' and
+`get-largest-window' treat dedicated windows specially.
+`delete-windows-on', `replace-buffer-in-windows', `quit-window' and
+`kill-buffer' can delete a dedicated window and the containing frame.
+
+Functions like `set-window-buffer' may change the buffer displayed by a
+window, unless that window is "strongly" dedicated to its buffer, that
+is the value returned by `window-dedicated-p' is t. */)
+ (Lisp_Object window)
+{
+ return decode_window (window)->dedicated;
+}
+
+DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
+ Sset_window_dedicated_p, 2, 2, 0,
+ doc: /* Mark WINDOW as dedicated according to FLAG.
+WINDOW must be a live window and defaults to the selected one. FLAG
+non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
+mark WINDOW as non-dedicated. Return FLAG.
+
+When a window is dedicated to its buffer, `display-buffer' will refrain
+from displaying another buffer in it. `get-lru-window' and
+`get-largest-window' treat dedicated windows specially.
+`delete-windows-on', `replace-buffer-in-windows', `quit-window',
+`quit-restore-window' and `kill-buffer' can delete a dedicated window
+and the containing frame.
+
+As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
+its buffer. Functions like `set-window-buffer' may change the buffer
+displayed by a window, unless that window is strongly dedicated to its
+buffer. If and when `set-window-buffer' displays another buffer in a
+window, it also makes sure that the window is no more dedicated. */)