From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: martin rudalics Newsgroups: gmane.emacs.bugs Subject: bug#13399: 24.3.50; Word-wrap can't wrap at zero-width space U-200B Date: Sat, 02 Feb 2013 17:48:42 +0100 Message-ID: <510D436A.1000603@gmx.at> References: <50EE7BE5.2060806@gmx.at> <83hamohmtj.fsf@gnu.org> <50EFCA6D.7090702@gmx.at> <83ip74ume7.fsf@gnu.org> <50EFE99A.5070508@gmx.at> <838v80ugv1.fsf@gnu.org> <50F021EC.4040107@gmx.at> <50F054A0.2040606@gmx.at> <83libztt68.fsf@gnu.org> <83hammu7og.fsf@gnu.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------010408070805070106050800" X-Trace: ger.gmane.org 1359823757 13954 80.91.229.3 (2 Feb 2013 16:49:17 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 2 Feb 2013 16:49:17 +0000 (UTC) Cc: 13399@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Feb 02 17:49:36 2013 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1U1gHY-0001xz-Hb for geb-bug-gnu-emacs@m.gmane.org; Sat, 02 Feb 2013 17:49:36 +0100 Original-Received: from localhost ([::1]:52740 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U1gHG-0003hR-AI for geb-bug-gnu-emacs@m.gmane.org; Sat, 02 Feb 2013 11:49:18 -0500 Original-Received: from eggs.gnu.org ([208.118.235.92]:45530) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U1gHA-0003gT-5d for bug-gnu-emacs@gnu.org; Sat, 02 Feb 2013 11:49:16 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U1gH6-00074K-NG for bug-gnu-emacs@gnu.org; Sat, 02 Feb 2013 11:49:12 -0500 Original-Received: from debbugs.gnu.org ([140.186.70.43]:55844) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U1gH6-00074G-J0 for bug-gnu-emacs@gnu.org; Sat, 02 Feb 2013 11:49:08 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.72) (envelope-from ) id 1U1gHy-0004Nd-A8 for bug-gnu-emacs@gnu.org; Sat, 02 Feb 2013 11:50:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: martin rudalics Original-Sender: debbugs-submit-bounces@debbugs.gnu.org Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 02 Feb 2013 16:50:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 13399 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 13399-submit@debbugs.gnu.org id=B13399.135982379716817 (code B ref 13399); Sat, 02 Feb 2013 16:50:02 +0000 Original-Received: (at 13399) by debbugs.gnu.org; 2 Feb 2013 16:49:57 +0000 Original-Received: from localhost ([127.0.0.1]:33075 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.72) (envelope-from ) id 1U1gHq-0004N5-WB for submit@debbugs.gnu.org; Sat, 02 Feb 2013 11:49:57 -0500 Original-Received: from mout.gmx.net ([212.227.15.18]:58831) by debbugs.gnu.org with esmtp (Exim 4.72) (envelope-from ) id 1U1gHk-0004Mn-Df for 13399@debbugs.gnu.org; Sat, 02 Feb 2013 11:49:52 -0500 Original-Received: from mailout-de.gmx.net ([10.1.76.2]) by mrigmx.server.lan (mrigmx001) with ESMTP (Nemesis) id 0MQ9JV-1U6Mxq0btj-005J57 for <13399@debbugs.gnu.org>; Sat, 02 Feb 2013 17:48:53 +0100 Original-Received: (qmail invoked by alias); 02 Feb 2013 16:48:51 -0000 Original-Received: from 62-47-50-198.adsl.highway.telekom.at (EHLO [62.47.50.198]) [62.47.50.198] by mail.gmx.net (mp002) with SMTP; 02 Feb 2013 17:48:51 +0100 X-Authenticated: #14592706 X-Provags-ID: V01U2FsdGVkX18UlkYyLkwUIjYnIzTL8mSgx6xxA5k1CxwyojXVFW 5jEI+oBRmH36Sj In-Reply-To: <83hammu7og.fsf@gnu.org> X-Y-GMX-Trusted: 0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.13 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:70610 Archived-At: This is a multi-part message in MIME format. --------------010408070805070106050800 Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit > But why would we need that? Most everything we need to know about > display is already tracked by the display iterator, so available even > without generating glyphs, and that's what the move_it_* functions do. > These function do their job by traversing only small portions of the > buffer, just large enough for the job at hand to be done. I rewrote `fit-window-to-buffer' and `fit-frame-to-buffer' using the display iterator. Please have a look at the attached patch. Thanks, martin --------------010408070805070106050800 Content-Type: text/plain; name="fit-window-to-buffer.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="fit-window-to-buffer.diff" =3D=3D=3D modified file 'lisp/window.el' --- lisp/window.el 2013-01-02 16:13:04 +0000 +++ lisp/window.el 2013-02-02 14:58:22 +0000 @@ -6074,211 +6074,428 @@ (eobp) window)))) =20 -;;; Resizing buffers to fit their contents exactly. +;;; Resizing windows and frames to fit their contents exactly. +(defcustom fit-window-to-buffer-horizontally nil + "Non-nil means `fit-window-to-buffer' can resize windows horizontally.= +If this is nil, `fit-window-to-buffer' never resizes windows +horizontally. If this is `only', it can resize windows +horizontally only. Any other value means `fit-window-to-buffer' +can resize windows in both dimensions." + :type 'boolean + :version "24.4" + :group 'help) + (defcustom fit-frame-to-buffer nil - "Non-nil means `fit-window-to-buffer' can resize frames. + "Non-nil means `fit-frame-to-buffer' can resize frames. A frame can be resized if and only if its root window is a live -window. The height of the root window is subject to the values -of `fit-frame-to-buffer-max-height' and `window-min-height'." +window. If this is `horizontally', frames can be resized +horizontally only. If this is `vertically', frames can be +resized vertically only. Any other non-nil value means frames +can be resized in both dimensions. See also +`fit-frame-to-buffer-margins' and `fit-frame-to-buffer-sizes'." :type 'boolean - :version "24.3" + :version "24.4" :group 'help) =20 -(defcustom fit-frame-to-buffer-bottom-margin 4 - "Bottom margin for the command `fit-frame-to-buffer'. -This is the number of lines that function leaves free at the bottom of -the display, in order to not obscure any system task bar or panel. -If you do not have one (or if it is vertical) you might want to -reduce this. If it is thicker, you might want to increase this." - ;; If you set this too small, fit-frame-to-buffer can shift the - ;; frame up to avoid the panel. - :type 'integer - :version "24.3" - :group 'windows) - -(defun fit-frame-to-buffer (&optional frame max-height min-height) +(defcustom fit-frame-to-buffer-margins '(0 0 0 72) + "Margins around frame for `fit-frame-to-buffer'. +This list specifies the numbers of pixels to be left free on the +left, above, the right, and below a frame that shall be fit to +its buffer. The value specified here can be overridden for a +specific frame by that frame's `fit-frame-to-buffer-margins' +parameter, if present. + +On some window systems the calculation of frame sizes can be +incorrect. Increasing the value of the third and/or fourth +element of this variable can fix that. + +See also `fit-frame-to-buffer-sizes'." + :version "24.4" + :type '(list + (integer :tag "Left" :size 5) + (integer :tag " Above" :size 5) + (integer :tag " Right" :size 5) + (integer :tag " Below" :size 5)) + :group 'windows) + +(defcustom fit-frame-to-buffer-sizes '(nil nil nil nil) + "Size boundaries of frame for `fit-frame-to-buffer'. +This list specifies the total maximum and minimum lines and +maximum and minimum columns of the root window of any frame that +shall be fit to its buffer. If any of these values is non-nil, +it will override the value supplied by the respective arguments +of `fit-frame-to-buffer'. + +On window systems where the menubar can wrap, fitting a frame to +its buffer may swallow the last line(s). Specifying an +appropriate minimum width value here can avoid such wrapping. + +See also `fit-frame-to-buffer-margins'." + :version "24.4" + :type '(list + (choice + :tag "Maximum Height" + :value nil + :format "%[MaxHeight%] %v " + (const :tag "None" :format "%t" nil) + (integer :tag "Lines" :size 5)) + (choice + :tag "Minimum Height" + :value nil + :format "%[MinHeight%] %v " + (const :tag "None" :format "%t" nil) + (integer :tag "Lines" :size 5)) + (choice + :tag "Maximum Width" + :value nil + :format "%[MaxWidth%] %v " + (const :tag "None" :format "%t" nil) + (integer :tag "Columns" :size 5)) + (choice + :tag "Minimum Width" + :value nil + :format "%[MinWidth%] %v\n" + (const :tag "None" :format "%t" nil) + (integer :tag "Columns" :size 5))) + :group 'windows) + +(defun window--sanitize-margin (margin left right) + "Return MARGIN if it's a number between LEFT and RIGHT." + (if (and (numberp margin) + (<=3D left (- right margin)) (<=3D margin right)) + margin + 0)) + +(defun fit-frame-to-buffer (&optional frame max-height min-height max-wi= dth min-width) "Adjust height of FRAME to display its buffer contents exactly. FRAME can be any live frame and defaults to the selected one. +MAX-HEIGHT, MIN-HEIGHT, MAX-WIDTH and MIN-WIDTH specify bounds on +the new total size of FRAME's root window. =20 -Optional argument MAX-HEIGHT specifies the maximum height of FRAME. -It defaults to the height of the display below the current -top line of FRAME, minus `fit-frame-to-buffer-bottom-margin'. -Optional argument MIN-HEIGHT specifies the minimum height of FRAME. -The default corresponds to `window-min-height'." +The option `fit-frame-to-buffer' controls whether this function +has any effect. New position and size of FRAME are additionally +determined by the options `fit-frame-to-buffer-sizes' and +`fit-frame-to-buffer-margins' or the corresponding parameters of +FRAME. This function can fail to fit the buffer's height when +`word-wrap' is turned on in that buffer." (interactive) (setq frame (window-normalize-frame frame)) - (let* ((root (frame-root-window frame)) - (frame-min-height - (+ (- (frame-height frame) (window-total-size root)) - window-min-height)) - (frame-top (frame-parameter frame 'top)) - (top (if (consp frame-top) - (funcall (car frame-top) (cadr frame-top)) - frame-top)) - (frame-max-height - (- (/ (- (x-display-pixel-height frame) top) - (frame-char-height frame)) - fit-frame-to-buffer-bottom-margin)) - (compensate 0) - delta) - (when (and (window-live-p root) (not (window-size-fixed-p root))) - (with-selected-window root - (cond - ((not max-height) - (setq max-height frame-max-height)) - ((numberp max-height) - (setq max-height (min max-height frame-max-height))) - (t - (error "%s is an invalid maximum height" max-height))) - (cond - ((not min-height) - (setq min-height frame-min-height)) - ((numberp min-height) - (setq min-height (min min-height frame-min-height))) - (t - (error "%s is an invalid minimum height" min-height))) - ;; When tool-bar-mode is enabled and we have just created a new - ;; frame, reserve lines for toolbar resizing. This is needed - ;; because for reasons unknown to me Emacs (1) reserves one line - ;; for the toolbar when making the initial frame and toolbars - ;; are enabled, and (2) later adds the remaining lines needed. - ;; Our code runs IN BETWEEN (1) and (2). YMMV when you're on a - ;; system that behaves differently. - (let ((quit-restore (window-parameter root 'quit-restore)) - (lines (tool-bar-lines-needed frame))) - (when (and quit-restore (eq (car quit-restore) 'frame) - (not (zerop lines))) - (setq compensate (1- lines)))) - (message "%s" compensate) - (setq delta - ;; Always count a final newline - we don't do any - ;; post-processing, so let's play safe. - (+ (count-screen-lines nil nil t) - (- (window-body-size)) - compensate))) - ;; Move away from final newline. - (when (and (eobp) (bolp) (not (bobp))) - (set-window-point root (line-beginning-position 0))) - (set-window-start root (point-min)) - (set-window-vscroll root 0) - (condition-case nil - (set-frame-height - frame - (min (max (+ (frame-height frame) delta) - min-height) - max-height)) - (error (setq delta nil)))) - delta)) + (when (and (window-live-p (frame-root-window frame)) + fit-frame-to-buffer + (or (not window-size-fixed) + (and (eq window-size-fixed 'height) + (not (eq fit-frame-to-buffer 'vertically))) + (and (eq window-size-fixed 'width) + (not (eq fit-frame-to-buffer 'horizontally))))) + (with-selected-window (frame-root-window frame) + (let* ((window (frame-root-window frame)) + (char-width (frame-char-width)) + (char-height (frame-char-height)) + (display-width (display-pixel-width frame)) + (display-height (display-pixel-height frame)) + ;; Sanitize margins. + (margins (or (frame-parameter frame 'fit-frame-to-buffer-margins) + fit-frame-to-buffer-margins)) + (left-margin (window--sanitize-margin + (nth 0 margins) 0 display-width)) + (top-margin (window--sanitize-margin + (nth 1 margins) 0 display-height)) + (right-margin (window--sanitize-margin + (nth 2 margins) left-margin display-width)) + (bottom-margin (window--sanitize-margin + (nth 3 margins) top-margin display-height)) + ;; The pixel width of FRAME. + (frame-width (frame-pixel-width)) + ;; The difference between FRAME's pixel and parameter + ;; widths. + (frame-extra-width + (- frame-width (* (frame-width) char-width))) + ;; The pixel height of FRAME's window. + (window-body-width (* (window-body-width) char-width)) + ;; The difference in pixels between total and body width of + ;; FRAME's window. + (window-extra-width + (- (* (window-total-width) char-width) window-body-width)) + ;; The difference in pixels between the frame's pixel width + ;; and the window's body width. + (extra-width + (* char-width (- (frame-width) (window-body-width)))) + ;; The maximum width we can use for fitting. + (fit-width + (- display-width (- frame-width window-body-width) + left-margin right-margin)) + ;; The pixel position of FRAME's left border. We usually + ;; try to leave this alone. + (left + (let ((left (frame-parameter nil 'left))) + (if (consp left) + (funcall (car left) (cadr left)) + left))) + ;; The pixel height of FRAME. + (frame-height (frame-pixel-height)) + ;; The difference between FRAME's pixel and parameter + ;; heights. + (frame-extra-height + (- frame-height (* (frame-height) char-height))) + ;; When tool-bar-mode is enabled and we just created a new + ;; frame, reserve lines for toolbar resizing. Needed + ;; because for reasons unknown to me Emacs (1) reserves one + ;; line for the toolbar when making the initial frame and + ;; toolbars are enabled, and (2) later adds the remaining + ;; lines needed. Our code runs IN BETWEEN (1) and (2). + ;; YMMV when you're on a system that behaves differently. + (toolbar-extra-height + (let ((quit-restore (window-parameter window 'quit-restore)) + (lines (tool-bar-lines-needed frame))) + (* char-height + (if (and quit-restore (eq (car quit-restore) 'frame) + (not (zerop lines))) + (1- lines) + 0)))) + ;; The pixel height of FRAME's window. + (window-body-height (* (window-body-height) char-height)) + ;; The difference in pixels between total and body height + ;; of FRAME's window. + (window-extra-height + (- (* (window-total-height) char-height) window-body-height)) + ;; The difference in pixels between the frame's pixel + ;; height and the window's body height. + (extra-height + (* (- (frame-height) (window-body-height)) char-height)) + ;; The maximum height we can use for fitting. + (fit-height + (- display-height (- frame-height window-body-height) + top-margin bottom-margin toolbar-extra-height)) + ;; The pixel position of FRAME's top border. We usually + ;; try to leave this alone. + (top + (let ((top (frame-parameter nil 'top))) + (if (consp top) + (funcall (car top) (cadr top)) + top))) + ;; Sanitize minimum and maximum sizes. + (sizes (or (frame-parameter frame 'fit-frame-to-buffer-sizes) + fit-frame-to-buffer-sizes)) + (max-height + (cond + ((numberp (nth 0 sizes)) + (- (* (nth 0 sizes) char-height) window-extra-height)) + ((numberp max-height) + (- (* max-height char-height) window-extra-height)))) + (min-height + (cond + ((numberp (nth 1 sizes)) + (- (* (nth 1 sizes) char-height) window-extra-height)) + ((numberp min-height) + (- (* min-height char-height) window-extra-height)))) + (max-width + (cond + ((numberp (nth 2 sizes)) + (- (* (nth 2 sizes) char-width) window-extra-width)) + ((numberp max-width) + (- (* max-width char-width) window-extra-width)))) + (min-width + (cond + ((numberp (nth 3 sizes)) + (- (* (nth 3 sizes) char-width) window-extra-width)) + ((numberp min-width) + (- (* min-width char-width) window-extra-width)))) + (value (window-buffer-pixel-size + nil (point-min) (point-max) + display-width display-height)) + (width (car value)) + (height (cdr value)) + remainder) + ;; Round sizes (hopefully we can drop these as soon as we can + ;; resize pixelwise). First add pixels to obtain full last + ;; lines and columns. + (setq remainder (% width char-width)) + (unless (zerop remainder) + (setq width (+ width (- char-width remainder)))) + (setq remainder (% height char-height)) + (setq height (+ height (- char-height remainder))) + ;; Now make sure that we don't get larger than our rounded + ;; maximum lines and columns. + (when (> width fit-width) + (setq width (- fit-width (% fit-width char-width)))) + (when (> height fit-height) + (setq height (- fit-height (% fit-height char-height)))) + ;; Don't change height or width when the window's size is fixed + ;; in either direction. + (cond + ((eq window-size-fixed 'height) + (setq height nil)) + ((eq window-size-fixed 'width) + (setq height nil))) + (when width + ;; Fit to maximum and minimum widths. + (when max-width + (setq width (min width max-width))) + (when min-width + (setq width (max width min-width))) + ;; Add extra width. + (setq width (+ width extra-width)) + ;; Preserve right margin. + (let ((right (+ left width frame-extra-width)) + (max-right (- display-width right-margin))) + (cond + ((> right max-right) + ;; Move FRAME to left. + (setq left (max 0 (- left (- right max-right))))) + ((< left left-margin) + ;; Move frame to right. + (setq left left-margin))))) + (when height + ;; Fit to maximum and minimum heights. + (when max-height + (setq height (min height max-height))) + (when min-height + (setq height (max height min-height))) + ;; Add extra height. + (setq height (+ height extra-height)) + ;; Preserve bottom and top margins. + (let ((bottom (+ top height frame-extra-height)) + (max-bottom (- display-height bottom-margin))) + (cond + ((> bottom max-bottom) + ;; Move FRAME to left. + (setq top (max 0 (- top (- bottom max-bottom))))) + ((< top top-margin) + ;; Move frame down. + (setq top top-margin))))) + ;; Apply changes. + (set-frame-position frame left top) + (set-frame-size + frame + (if width (/ width char-width) (frame-width)) + (if height (/ height char-height) (frame-height))))))) =20 -(defun fit-window-to-buffer (&optional window max-height min-height) - "Adjust height of WINDOW to display its buffer's contents exactly. +(defun fit-window-to-buffer (&optional window max-height min-height max-= width min-width) + "Adjust size of WINDOW to display its buffer's contents exactly. WINDOW must be a live window and defaults to the selected one. =20 -Optional argument MAX-HEIGHT specifies the maximum height of -WINDOW and defaults to the height of WINDOW's frame. Optional -argument MIN-HEIGHT specifies the minimum height of WINDOW and -defaults to `window-min-height'. Both MAX-HEIGHT and MIN-HEIGHT -are specified in lines and include the mode line and header line, -if any. - -If WINDOW is a full height window, then if the option -`fit-frame-to-buffer' is non-nil, this calls the function -`fit-frame-to-buffer' to adjust the frame height. - -Return the number of lines by which WINDOW was enlarged or -shrunk. If an error occurs during resizing, return nil but don't -signal an error. +If WINDOW is part of a vertical combination, adjust WINDOW's +height. The new height is calculated from the number of lines of +the accessible portion of its buffer. The optional argument +MAX-HEIGHT specifies a maximum height and defaults to the height +of WINDOW's frame. The optional argument MIN-HEIGHT specifies a +minimum height and defaults to `window-min-height'. Both +MAX-HEIGHT and MIN-HEIGHT are specified in lines and include the +mode line and header line, if any. + +If WINDOW is part of a horizontal combination and the value of +the option `fit-window-to-buffer-horizontally' is non-nil, adjust +WINDOW's height. The new width of WINDOW is calculated from the +maximum length of its buffer's lines that follow the current +start position of WINDOW. The optional argument MAX-WIDTH +specifies a maximum width and defaults to the width of WINDOW's +frame. The optional argument MIN-WIDTH specifies a minimum width +and defaults to `window-min-width'. Both MAX-WIDTH and MIN-WIDTH +are specified in columns and include fringes, margins and +scrollbars, if any. + +If WINDOW is its frame's root window, then if the option +`fit-frame-to-buffer' is non-nil, call `fit-frame-to-buffer' to +adjust the frame's size. =20 Note that even if this function makes WINDOW large enough to show -_all_ lines of its buffer you might not see the first lines when -WINDOW was scrolled." +_all_ parts of its buffer you might not see the first part when +WINDOW was scrolled. If WINDOW is resized horizontally, you will +not see the top of its buffer unless WINDOW starts at its minimum +accessible position." (interactive) (setq window (window-normalize-window window t)) - (cond - ((window-size-fixed-p window)) - ((window-full-height-p window) - (when fit-frame-to-buffer - (fit-frame-to-buffer (window-frame window)))) - (t + (if (eq window (frame-root-window window)) + (when fit-frame-to-buffer + ;; Fit WINDOW's frame to buffer. + (fit-frame-to-buffer + (window-frame window) max-height min-height max-width min-width)) (with-selected-window window - (let* ((height (window-total-size)) + (let* ((frame (window-frame)) + (char-height (frame-char-height)) + (char-width (frame-char-width)) + (display-height (display-pixel-height)) + (total-height (window-total-height)) + (body-height (window-body-height)) + (body-width (window-body-width)) (min-height - ;; Adjust MIN-HEIGHT. + ;; Sanitize MIN-HEIGHT. (if (numberp min-height) ;; Can't get smaller than `window-safe-min-height'. (max min-height window-safe-min-height) ;; Preserve header and mode line if present. (window-min-size nil nil t))) (max-height - ;; Adjust MAX-HEIGHT. + ;; Sanitize MAX-HEIGHT. (if (numberp max-height) - ;; Can't get larger than height of frame. - (min max-height - (window-total-size (frame-root-window window))) - ;; Don't delete other windows. - (+ height (window-max-delta nil nil window)))) - ;; Make `desired-height' the height necessary to show - ;; all of WINDOW's buffer, constrained by MIN-HEIGHT - ;; and MAX-HEIGHT. - (desired-height - (max - (min - (+ (count-screen-lines) - ;; For non-minibuffers count the mode line, if any. - (if (and (not (window-minibuffer-p window)) - mode-line-format) - 1 - 0) - ;; Count the header line, if any. - (if header-line-format 1 0)) - max-height) - min-height)) - (desired-delta - (- desired-height (window-total-size window))) - (delta - (if (> desired-delta 0) - (min desired-delta - (window-max-delta window nil window)) - (max desired-delta - (- (window-min-delta window nil window)))))) - (condition-case nil - (if (zerop delta) - ;; Return zero if DELTA became zero in the process. - 0 - ;; Don't try to redisplay with the cursor at the end on its - ;; own line--that would force a scroll and spoil things. - (when (and (eobp) (bolp) (not (bobp))) - ;; It's silly to put `point' at the end of the previous - ;; line and so maybe force horizontal scrolling. - (set-window-point window (line-beginning-position 0))) - ;; Call `window-resize' with OVERRIDE argument equal WINDOW. - (window-resize window delta nil window) - ;; Check if the last line is surely fully visible. If - ;; not, enlarge the window. - (let ((end (save-excursion - (goto-char (point-max)) - (when (and (bolp) (not (bobp))) - ;; Don't include final newline. - (backward-char 1)) - (when truncate-lines - ;; If line-wrapping is turned off, test the - ;; beginning of the last line for - ;; visibility instead of the end, as the - ;; end of the line could be invisible by - ;; virtue of extending past the edge of the - ;; window. - (forward-line 0)) - (point)))) - (set-window-vscroll window 0) - ;; This loop might in some rare pathological cases raise - ;; an error - another reason for the `condition-case'. - (while (and (< desired-height max-height) - (=3D desired-height (window-total-size)) - (not (pos-visible-in-window-p end))) - (window-resize window 1 nil window) - (setq desired-height (1+ desired-height))))) - (error (setq delta nil))) - delta))))) + (min (+ total-height (window-max-delta)) max-height) + (+ total-height (window-max-delta)))) + height) + (cond + ;; If WINDOW is vertically combined, try to resize it + ;; vertically. + ((and (not (eq fit-window-to-buffer-horizontally 'only)) + (not (window-size-fixed-p window)) + (window-combined-p)) + ;; Vertically we always want to fit the entire buffer. + ;; WINDOW'S height can't get larger than its frame's pixel + ;; height. Its width remains fixed. + (setq height (cdr (window-buffer-pixel-size + nil (point-min) (point-max) + (* body-width char-width) + (frame-pixel-height)))) + ;; Round height. + (setq height (+ (/ height char-height) + (if (zerop (% height char-height)) 0 1))) + (unless (=3D height body-height) + (window-resize-no-error + window + (- (max min-height + (min max-height + (+ total-height (- height body-height)))) + total-height) + nil window))) + ;; If WINDOW is horizontally combined, try to resize it + ;; horizontally. + ((and fit-window-to-buffer-horizontally + (not (window-size-fixed-p window t)) + (window-combined-p nil t)) + (let* ((display-width (display-pixel-width)) + (total-width (window-total-width)) + (min-width + ;; Sanitize MIN-WIDTH. + (if (numberp min-width) + ;; Can't get smaller than `window-safe-min-width'. + (max min-width window-safe-min-width) + ;; Preserve fringes, margines, scrollbars if present. + (window-min-size nil nil t))) + (max-width + ;; Sanitize MAX-WIDTH. + (if (numberp max-width) + (min (+ total-width (window-max-delta nil t)) max-width) + (+ total-width (window-max-delta nil t)))) + ;; When fitting vertically, assume that WINDOW's start + ;; position remains unaltered. WINDOW can't get wider + ;; than its frame's pixel width, its height remains + ;; unaltered. + (width (car (window-buffer-pixel-size + nil (window-start) (point-max) + (frame-pixel-width) + ;; Add one char-height to assure that + ;; we're on the safe side. This + ;; overshoots when the first line below + ;; the bottom is wider than the window. + (* body-height char-height))))) + (setq width (+ (/ width char-width) + (if (zerop (% width char-width)) 0 1))) + (unless (=3D width body-width) + (window-resize-no-error + window + (- (max min-width + (min max-width + (+ total-width (- width body-width)))) + total-width) + t window))))))))) =20 (defun window-safely-shrinkable-p (&optional window) "Return t if WINDOW can be shrunk without shrinking other windows. =3D=3D=3D modified file 'src/dispextern.h' --- src/dispextern.h 2013-01-02 16:13:04 +0000 +++ src/dispextern.h 2013-02-02 14:56:54 +0000 @@ -2489,6 +2489,9 @@ pixel_width with each call to produce_glyphs. */ int current_x; =20 + /* Maximum x pixel position encountered within a display line. */ + int max_current_x; + /* Accumulated width of continuation lines. If > 0, this means we are currently in a continuation line. This is initially zero and incremented/reset by display_line, move_it_to etc. */ =3D=3D=3D modified file 'src/xdisp.c' --- src/xdisp.c 2013-01-05 21:18:01 +0000 +++ src/xdisp.c 2013-02-02 14:56:32 +0000 @@ -2996,7 +2996,7 @@ =20 it->current_y =3D first_y; it->vpos =3D 0; - it->current_x =3D it->hpos =3D 0; + it->current_x =3D it->max_current_x =3D it->hpos =3D 0; } } } @@ -8814,7 +8814,10 @@ =20 /* If TO_CHARPOS is reached or ZV, we don't have to do more. */ if (skip =3D=3D MOVE_POS_MATCH_OR_ZV) - reached =3D 5; + { + it->max_current_x =3D max (it->current_x, it->max_current_x); + reached =3D 5; + } else if (skip =3D=3D MOVE_X_REACHED) { /* If TO_X was reached, we want to know whether TO_Y is @@ -8883,6 +8886,8 @@ skip =3D move_it_in_display_line_to (it, -1, prev_x, MOVE_TO_X); } + + it->max_current_x =3D max (it->current_x, it->max_current_x); reached =3D 6; } } @@ -8908,15 +8913,18 @@ switch (skip) { case MOVE_POS_MATCH_OR_ZV: + it->max_current_x =3D max (it->current_x, it->max_current_x); reached =3D 8; goto out; =20 case MOVE_NEWLINE_OR_CR: + it->max_current_x =3D max (it->current_x, it->max_current_x); set_iterator_to_next (it, 1); it->continuation_lines_width =3D 0; break; =20 case MOVE_LINE_TRUNCATED: + it->max_current_x =3D it->last_visible_x; it->continuation_lines_width =3D 0; reseat_at_next_visible_line_start (it, 0); if ((op & MOVE_TO_POS) !=3D 0 @@ -8928,6 +8936,7 @@ break; =20 case MOVE_LINE_CONTINUED: + it->max_current_x =3D it->last_visible_x; /* For continued lines ending in a tab, some of the glyphs associated with the tab are displayed on the current line. Since it->current_x does not include these glyphs, @@ -9326,6 +9335,93 @@ && it->dpvec + it->current.dpvec_index !=3D it->dpend); } =20 +DEFUN ("window-buffer-pixel-size", Fwindow_buffer_pixel_size, Swindow_bu= ffer_pixel_size, 0, 5, 0, + doc: /* Return size of WINDOW's buffer in pixels. +WINDOW must be a live window and defaults to the selected one. The +return value is a cons of the maximum pixel-width of any line and the +maximum pixel-height of all lines. + +The optional argument X_LIMIT, if non-nil, specifies the maximum +pixel-width that can be returned. X_LIMIT nil or omitted, means to use +the pixel-width of WINDOW's body; use this if you do not intend to +change the width of WINDOW. Use the maximum width WINDOW can be +expanded to if you intend to change WINDOW's width. + +The optional argument Y_LIMIT, if non-nil, specifies the maximum +pixel-height to scan. Lines starting below Y_LIMIT are not scanned. +Since calculating the pixel-height of a large buffer can take some time,= +it makes sense to specify this argument if the size of the buffer is +unknown. */) + (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_l= imit, Lisp_Object y_limit) +{ + struct window *w =3D decode_live_window (window); + Lisp_Object buf, value; + struct buffer *b; + struct it it; + struct buffer *old_buffer =3D NULL; + ptrdiff_t start, end; + struct text_pos startp, endp; + void *itdata =3D NULL; + int max_y =3D -1; + + buf =3D w->buffer; + CHECK_BUFFER (buf); + b =3D XBUFFER (buf); + + if (NILP (from)) + start =3D BEGV; + else + { + CHECK_NUMBER_COERCE_MARKER (from); + start =3D min (max (XINT (from), BEGV), ZV); + } + + if (NILP (to)) + end =3D ZV; + else + { + CHECK_NUMBER_COERCE_MARKER (to); + end =3D max (start, min (XINT (to), ZV)); + } + + if (b !=3D current_buffer) + { + old_buffer =3D current_buffer; + set_buffer_internal (b); + } + + if (!NILP (y_limit)) + { + CHECK_NUMBER (y_limit); + max_y =3D XINT (y_limit); + } + + itdata =3D bidi_shelve_cache (); + SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start)); + start_display (&it, w, startp); + + if (!NILP (x_limit)) + { + CHECK_NUMBER (x_limit); + it.last_visible_x =3D XINT (x_limit); + } + + /* Actually, we never want move_it_to stop at to_x. But to make sure + that move_it_in_display_line_to always moves far enough, we set it + to MOST_POSITIVE_FIXNUM and specify MOVE_TO_X. */ + move_it_to (&it, end, MOST_POSITIVE_FIXNUM, max_y, -1, + MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); + last_height =3D 0; + value =3D Fcons (make_number (it.max_current_x), + make_number (it.current_y)); +/** make_number (line_bottom_y (&it))); **/ + bidi_unshelve_cache (itdata, 0); + + if (old_buffer) + set_buffer_internal (old_buffer); + + return value; +} =0C /***********************************************************************= Messages @@ -28808,6 +28904,7 @@ defsubr (&Sformat_mode_line); defsubr (&Sinvisible_p); defsubr (&Scurrent_bidi_paragraph_direction); + defsubr (&Swindow_buffer_pixel_size); =20 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook"); DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map= "); --------------010408070805070106050800--