]> code.delx.au - gnu-emacs/blobdiff - lisp/window.el
Doc fixes for menu-bar.el
[gnu-emacs] / lisp / window.el
index f198d78cc4cc5f3aa072c3db45907f9a4f3adaea..f7a547b915a08a403479f8298b37fda98695def2 100644 (file)
@@ -1,6 +1,6 @@
 ;;; window.el --- GNU Emacs window commands aside from those written in C
 
-;; Copyright (C) 1985, 1989, 1992-1994, 2000-2015 Free Software
+;; Copyright (C) 1985, 1989, 1992-1994, 2000-2016 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -1889,9 +1889,19 @@ the font."
           (ncols (/ window-width font-width)))
       (if (and (display-graphic-p)
               overflow-newline-into-fringe
-              (/= (frame-parameter nil 'left-fringe) 0)
-              (/= (frame-parameter nil 'right-fringe) 0))
+               (not
+                (or (eq left-fringe-width 0)
+                    (and (null left-fringe-width)
+                         (= (frame-parameter nil 'left-fringe) 0))))
+               (not
+                (or (eq right-fringe-width 0)
+                    (and (null right-fringe-width)
+                         (= (frame-parameter nil 'right-fringe) 0)))))
          ncols
+        ;; FIXME: This should remove 1 more column when there are no
+        ;; fringes, lines are truncated, and the window is hscrolled,
+        ;; but EOL is not in the view, because then there are 2
+        ;; truncation glyphs, not one.
        (1- ncols)))))
 
 (defun window-current-scroll-bars (&optional window)
@@ -2005,7 +2015,7 @@ SIDE can be any of the symbols `left', `top', `right' or
 
 ;; Predecessors to the below have been devised by Julian Assange in
 ;; change-windows-intuitively.el and Hovav Shacham in windmove.el.
-;; Neither of these allow to selectively ignore specific windows
+;; Neither of these allow one to selectively ignore specific windows
 ;; (windows whose `no-other-window' parameter is non-nil) as targets of
 ;; the movement.
 (defun window-in-direction (direction &optional window ignore sign wrap mini)
@@ -2034,7 +2044,7 @@ has one, and a window at the bottom of the frame otherwise.
 Optional argument MINI nil means to return the minibuffer window
 if and only if it is currently active.  MINI non-nil means to
 return the minibuffer window even when it's not active.  However,
-if WRAP non-nil, always act as if MINI were nil.
+if WRAP is non-nil, always act as if MINI were nil.
 
 Return nil if no suitable window can be found."
   (setq window (window-normalize-window window t))
@@ -2473,8 +2483,6 @@ windows."
   (when (window-right window)
     (window--resize-reset-1 (window-right window) horizontal)))
 
-;; The following routine is used to manually resize the minibuffer
-;; window and is currently used, for example, by ispell.el.
 (defun window--resize-mini-window (window delta)
   "Resize minibuffer window WINDOW by DELTA pixels.
 If WINDOW cannot be resized by DELTA pixels make it as large (or
@@ -3241,9 +3249,9 @@ move it as far as possible in the desired direction."
        (setq ignore 'preserved)
        (setq right first-right)
        (while (and right
-                   (or (window-size-fixed-p right horizontal 'preserved))
-                   (<= (window-size right horizontal t)
-                       (window-min-size right horizontal 'preserved t)))
+                   (or (window-size-fixed-p right horizontal 'preserved)
+                        (<= (window-size right horizontal t)
+                            (window-min-size right horizontal 'preserved t))))
          (setq right
                (or (window-right right)
                    (progn
@@ -3338,20 +3346,29 @@ negative, shrink selected window by -DELTA lines or columns."
     (cond
      ((zerop delta))
      ((window-size-fixed-p nil horizontal)
-      (error "Selected window has fixed size"))
+      (user-error "Selected window has fixed size"))
      ((window-minibuffer-p)
       (if horizontal
-         (error "Cannot resize minibuffer window horizontally")
-       (window--resize-mini-window (selected-window) delta)))
+         (user-error "Cannot resize minibuffer window horizontally")
+       (window--resize-mini-window
+         (selected-window) (* delta (frame-char-height)))))
      ((and (not horizontal)
           (window-full-height-p)
           (eq (window-frame minibuffer-window) (selected-frame))
           (not resize-mini-windows))
       ;; If the selected window is full height and `resize-mini-windows'
       ;; is nil, resize the minibuffer window.
-      (window--resize-mini-window minibuffer-window (- delta)))
+      (window--resize-mini-window
+       minibuffer-window (* (- delta) (frame-char-height))))
      ((window--resizable-p nil delta horizontal)
       (window-resize nil delta horizontal))
+     ((window--resizable-p nil delta horizontal 'preserved)
+      (window-resize nil delta horizontal 'preserved))
+     ((eq this-command
+         (if horizontal 'enlarge-window-horizontally 'enlarge-window))
+      ;; For backward compatibility don't signal an error unless this
+      ;; command is `enlarge-window(-horizontally)'.
+      (user-error "Cannot enlarge selected window"))
      (t
       (window-resize
        nil (if (> delta 0)
@@ -3364,8 +3381,7 @@ negative, shrink selected window by -DELTA lines or columns."
 Interactively, if no argument is given, make the selected window
 one line smaller.  If optional argument HORIZONTAL is non-nil,
 make selected window narrower by DELTA columns.  If DELTA is
-negative, enlarge selected window by -DELTA lines or columns.
-Also see the `window-min-height' variable."
+negative, enlarge selected window by -DELTA lines or columns."
   (interactive "p")
   (let ((minibuffer-window (minibuffer-window)))
     (when (window-preserved-size nil horizontal)
@@ -3373,20 +3389,29 @@ Also see the `window-min-height' variable."
     (cond
      ((zerop delta))
      ((window-size-fixed-p nil horizontal)
-      (error "Selected window has fixed size"))
+      (user-error "Selected window has fixed size"))
      ((window-minibuffer-p)
       (if horizontal
-         (error "Cannot resize minibuffer window horizontally")
-       (window--resize-mini-window (selected-window) (- delta))))
+         (user-error "Cannot resize minibuffer window horizontally")
+       (window--resize-mini-window
+         (selected-window) (* (- delta) (frame-char-height)))))
      ((and (not horizontal)
           (window-full-height-p)
           (eq (window-frame minibuffer-window) (selected-frame))
           (not resize-mini-windows))
       ;; If the selected window is full height and `resize-mini-windows'
       ;; is nil, resize the minibuffer window.
-      (window--resize-mini-window minibuffer-window delta))
+      (window--resize-mini-window
+       minibuffer-window (* delta (frame-char-height))))
      ((window--resizable-p nil (- delta) horizontal)
       (window-resize nil (- delta) horizontal))
+     ((window--resizable-p nil (- delta) horizontal 'preserved)
+      (window-resize nil (- delta) horizontal 'preserved))
+     ((eq this-command
+         (if horizontal 'shrink-window-horizontally 'shrink-window))
+      ;; For backward compatibility don't signal an error unless this
+      ;; command is `shrink-window(-horizontally)'.
+      (user-error "Cannot shrink selected window"))
      (t
       (window-resize
        nil (if (> delta 0)
@@ -3450,7 +3475,7 @@ in terms of the canonical character width and height of WINDOW's
 frame, rounded if necessary.  PIXELWISE non-nil means to return
 the coordinates in pixels where the values for RIGHT and BOTTOM
 are one more than the actual value of these edges.  Note that if
-ABSOLUTE is non-nil, PIXELWISE is implicily non-nil too."
+ABSOLUTE is non-nil, PIXELWISE is implicitly non-nil too."
   (let* ((window (window-normalize-window window body))
         (frame (window-frame window))
         (border-width (frame-border-width frame))
@@ -3707,7 +3732,7 @@ and no others."
 (defun window-deletable-p (&optional window)
   "Return t if WINDOW can be safely deleted from its frame.
 WINDOW must be a valid window and defaults to the selected one.
-Return 'frame if deleting WINDOW should also delete its frame."
+Return `frame' if deleting WINDOW should also delete its frame."
   (setq window (window-normalize-window window))
 
   (unless (or ignore-window-parameters
@@ -4851,8 +4876,9 @@ frame.  The selected window is not changed by this function."
              (set-window-parameter (window-parent new) 'window-atom t))
            (set-window-parameter new 'window-atom t)))
 
-         ;; Sanitize sizes.
-         (window--sanitize-window-sizes frame horizontal)
+         ;; Sanitize sizes unless SIZE was specified.
+         (unless size
+            (window--sanitize-window-sizes frame horizontal))
 
          (run-window-configuration-change-hook frame)
          (run-window-scroll-functions new)
@@ -5868,7 +5894,7 @@ one of the regular expressions in `special-display-regexps'.
 
 This variable can be set in your init file, like this:
 
-  (setq special-display-frame-alist '((width . 80) (height . 20)))
+  (setq special-display-frame-alist \\='((width . 80) (height . 20)))
 
 These supersede the values given in `default-frame-alist'."
   :type '(repeat (cons :format "%v"
@@ -6491,7 +6517,7 @@ action.  Its form is described below.
 Optional argument FRAME, if non-nil, acts like an additional
 ALIST entry (reusable-frames . FRAME) to the action list of ACTION,
 specifying the frame(s) to search for a window that is already
-displaying the buffer.  See `display-buffer-reuse-window'
+displaying the buffer.  See `display-buffer-reuse-window'.
 
 If ACTION is non-nil, it should have the form (FUNCTION . ALIST),
 where FUNCTION is either a function or a list of functions, and
@@ -6562,9 +6588,9 @@ Recognized alist entries include:
     of not displaying the buffer and FUNCTION can safely return
     a non-window value to suppress displaying.
 
- `preserve-size' -- Value should be either '(t . nil)' to
-    preserve the width of the window, '(nil . t)' to preserve its
-    height or '(t . t)' to preserve both.
+ `preserve-size' -- Value should be either (t . nil) to
+    preserve the width of the window, (nil . t) to preserve its
+    height or (t . t) to preserve both.
 
 The ACTION argument to `display-buffer' can also have a non-nil
 and non-list value.  This means to display the buffer in a window
@@ -6845,7 +6871,7 @@ selected frame."
     (or (and bottom-window-shows-buffer
             (window--display-buffer
              buffer bottom-window 'reuse alist display-buffer-mark-dedicated))
-     (and (not (frame-parameter nil 'unsplittable))
+       (and (not (frame-parameter nil 'unsplittable))
             (let (split-width-threshold)
               (setq window (window--try-to-split-window bottom-window alist)))
             (window--display-buffer
@@ -7868,6 +7894,152 @@ Return non-nil if the window was shrunk, nil otherwise."
        (with-current-buffer buffer-to-kill
         (remove-hook 'kill-buffer-hook delete-window-hook t))))))
 
+\f
+;;;
+;; Groups of windows (Follow Mode).
+;;
+;; This section of functions extends the functionality of some window
+;; manipulating commands to groups of windows cooperatively
+;; displaying a buffer, typically with Follow Mode.
+;;
+;; The xxx-function variables are permanent locals so that their local
+;; status is undone only when explicitly programmed, not when a buffer
+;; is reverted or a mode function is called.
+
+(defvar window-group-start-function nil)
+(make-variable-buffer-local 'window-group-start-function)
+(put 'window-group-start-function 'permanent-local t)
+(defun window-group-start (&optional window)
+  "Return position at which display currently starts in the group of
+windows containing WINDOW.  When a grouping mode (such as Follow Mode)
+is not active, this function is identical to `window-start'.
+
+WINDOW must be a live window and defaults to the selected one.
+This is updated by redisplay or by calling `set-window*-start'."
+  (if (functionp window-group-start-function)
+      (funcall window-group-start-function window)
+    (window-start window)))
+
+(defvar window-group-end-function nil)
+(make-variable-buffer-local 'window-group-end-function)
+(put 'window-group-end-function 'permanent-local t)
+(defun window-group-end (&optional window update)
+  "Return position at which display currently ends in the group of
+windows containing WINDOW.  When a grouping mode (such as Follow Mode)
+is not active, this function is identical to `window-end'.
+
+WINDOW must be a live window and defaults to the selected one.
+This is updated by redisplay, when it runs to completion.
+Simply changing the buffer text or setting `window-group-start'
+does not update this value.
+Return nil if there is no recorded value.  (This can happen if the
+last redisplay of WINDOW was preempted, and did not finish.)
+If UPDATE is non-nil, compute the up-to-date position
+if it isn't already recorded."
+  (if (functionp window-group-end-function)
+      (funcall window-group-end-function window update)
+    (window-end window update)))
+
+(defvar set-window-group-start-function nil)
+(make-variable-buffer-local 'set-window-group-start-function)
+(put 'set-window-group-start-function 'permanent-local t)
+(defun set-window-group-start (window pos &optional noforce)
+  "Make display in the group of windows containing WINDOW start at
+position POS in WINDOW's buffer.  When a grouping mode (such as Follow
+Mode) is not active, this function is identical to `set-window-start'.
+
+WINDOW must be a live window and defaults to the selected one.  Return
+POS.  Optional third arg NOFORCE non-nil inhibits next redisplay from
+overriding motion of point in order to display at this exact start."
+  (if (functionp set-window-group-start-function)
+      (funcall set-window-group-start-function window pos noforce)
+    (set-window-start window pos noforce)))
+
+(defvar recenter-window-group-function nil)
+(make-variable-buffer-local 'recenter-window-group-function)
+(put 'recenter-window-group-function 'permanent-local t)
+(defun recenter-window-group (&optional arg)
+  "Center point in the group of windows containing the selected window
+and maybe redisplay frame.  When a grouping mode (such as Follow Mode)
+is not active, this function is identical to `recenter'.
+
+With a numeric prefix argument ARG, recenter putting point on screen line ARG
+relative to the first window in the selected window group.  If ARG is
+negative, it counts up from the bottom of the last window in the
+group.  (ARG should be less than the total height of the window group.)
+
+If ARG is omitted or nil, then recenter with point on the middle line of
+the selected window group; if the variable `recenter-redisplay' is
+non-nil, also erase the entire frame and redraw it (when
+`auto-resize-tool-bars' is set to `grow-only', this resets the
+tool-bar's height to the minimum height needed); if
+`recenter-redisplay' has the special value `tty', then only tty frames
+are redrawn.
+
+Just C-u as prefix means put point in the center of the window
+and redisplay normally--don't erase and redraw the frame."
+  (if (functionp recenter-window-group-function)
+      (funcall recenter-window-group-function arg)
+    (recenter arg)))
+
+(defvar pos-visible-in-window-group-p-function nil)
+(make-variable-buffer-local 'pos-visible-in-window-group-p-function)
+(put 'pos-visible-in-window-group-p-function 'permanent-local t)
+(defun pos-visible-in-window-group-p (&optional pos window partially)
+  "Return non-nil if position POS is currently on the frame in the
+window group containing WINDOW.  When a grouping mode (such as Follow
+Mode) is not active, this function is identical to
+`pos-visible-in-window-p'.
+
+WINDOW must be a live window and defaults to the selected one.
+
+Return nil if that position is scrolled vertically out of view.  If a
+character is only partially visible, nil is returned, unless the
+optional argument PARTIALLY is non-nil.  If POS is only out of view
+because of horizontal scrolling, return non-nil.  If POS is t, it
+specifies the position of the last visible glyph in the window group.
+POS defaults to point in WINDOW; WINDOW defaults to the selected
+window.
+
+If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
+the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
+where X and Y are the pixel coordinates relative to the top left corner
+of the window.  The remaining elements are omitted if the character after
+POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
+off-window at the top and bottom of the screen line (\"row\") containing
+POS, ROWH is the visible height of that row, and VPOS is the row number
+\(zero-based)."
+  (if (functionp pos-visible-in-window-group-p-function)
+      (funcall pos-visible-in-window-group-p-function pos window partially)
+    (pos-visible-in-window-p pos window partially)))
+
+(defvar selected-window-group-function nil)
+(make-variable-buffer-local 'selected-window-group-function)
+(put 'selected-window-group-function 'permanent-local t)
+(defun selected-window-group ()
+  "Return the list of windows in the group containing the selected window.
+When a grouping mode (such as Follow Mode) is not active, the
+result is a list containing only the selected window."
+  (if (functionp selected-window-group-function)
+      (funcall selected-window-group-function)
+    (list (selected-window))))
+
+(defvar move-to-window-group-line-function nil)
+(make-variable-buffer-local 'move-to-window-group-line-function)
+(put 'move-to-window-group-line-function 'permanent-local t)
+(defun move-to-window-group-line (arg)
+  "Position point relative to the the current group of windows.
+When a grouping mode (such as Follow Mode) is not active, this
+function is identical to `move-to-window-line'.
+
+ARG nil means position point at center of the window group.
+Else, ARG specifies the vertical position within the window
+group; zero means top of first window in the group, negative
+means relative to the bottom of the last window in the group."
+  (if (functionp move-to-window-group-line-function)
+      (funcall move-to-window-group-line-function arg)
+    (move-to-window-line arg)))
+
 \f
 (defvar recenter-last-op nil
   "Indicates the last recenter operation performed.
@@ -8323,10 +8495,10 @@ WINDOWS is a list of windows associated with PROCESS.  REDUCER is
 a two-argument function used to combine the widths and heights of
 the given windows."
   (when windows
-    (let ((width (window-body-width (car windows)))
+    (let ((width (window-max-chars-per-line (car windows)))
           (height (window-body-height (car windows))))
       (dolist (window (cdr windows))
-        (setf width (funcall reducer width (window-body-width window)))
+        (setf width (funcall reducer width (window-max-chars-per-line window)))
         (setf height (funcall reducer height (window-body-height window))))
       (cons width height))))
 
@@ -8348,38 +8520,40 @@ A window is associated with a process if that window is
 displaying that processes's buffer."
   (let ((processes (process-list))
         (process-windows nil))
-    (walk-windows
-     (lambda (window)
-       (let ((buffer (window-buffer window))
-             (iter processes))
-         (while (let ((process (car iter)))
-                  (if (and (process-live-p process)
-                           (eq buffer (process-buffer process)))
-                      (let ((procwin (assq process process-windows)))
-                        ;; Add this window to the list of windows
-                        ;; displaying process.
-                        (if procwin
-                            (push window (cdr procwin))
-                          (push (list process window) process-windows))
-                        ;; We found our process for this window, so
-                        ;; stop iterating over the process list.
-                        nil)
-                    (setf iter (cdr iter)))))))
-     1 t)
+    (if processes
+        (walk-windows
+         (lambda (window)
+           (let ((buffer (window-buffer window))
+                 (iter processes))
+             (while (let ((process (car iter)))
+                      (if (and (process-live-p process)
+                               (eq buffer (process-buffer process)))
+                          (let ((procwin (assq process process-windows)))
+                            ;; Add this window to the list of windows
+                            ;; displaying process.
+                            (if procwin
+                                (push window (cdr procwin))
+                              (push (list process window) process-windows))
+                            ;; We found our process for this window, so
+                            ;; stop iterating over the process list.
+                            nil)
+                        (setf iter (cdr iter)))))))
+         1 t))
     process-windows))
 
 (defun window--adjust-process-windows ()
   "Update process window sizes to match the current window configuration."
-  (dolist (procwin (window--process-window-list))
-    (let ((process (car procwin)))
-      (with-demoted-errors "Error adjusting window size: %S"
-        (with-current-buffer (process-buffer process)
-          (let ((size (funcall
-                       (or (process-get process 'adjust-window-size-function)
-                           window-adjust-process-window-size-function)
-                       process (cdr procwin))))
-            (when size
-              (set-process-window-size process (cdr size) (car size)))))))))
+  (when (fboundp 'process-list)
+    (dolist (procwin (window--process-window-list))
+      (let ((process (car procwin)))
+        (with-demoted-errors "Error adjusting window size: %S"
+          (with-current-buffer (process-buffer process)
+            (let ((size (funcall
+                         (or (process-get process 'adjust-window-size-function)
+                             window-adjust-process-window-size-function)
+                         process (cdr procwin))))
+              (when size
+                (set-process-window-size process (cdr size) (car size))))))))))
 
 (add-hook 'window-configuration-change-hook 'window--adjust-process-windows)