diff options
| author | Martin Rudalics | 2008-12-11 17:17:44 +0000 |
|---|---|---|
| committer | Martin Rudalics | 2008-12-11 17:17:44 +0000 |
| commit | f7baca2087406d3d45d2662a8b3fca43f938d537 (patch) | |
| tree | b4bfbabf366e9725b2b816f9c27414dfb077599c | |
| parent | 8ec71e2341172ad01138c2b5c80623eb99a35549 (diff) | |
| download | emacs-f7baca2087406d3d45d2662a8b3fca43f938d537.tar.gz emacs-f7baca2087406d3d45d2662a8b3fca43f938d537.zip | |
(fit-window-to-buffer): Use with-selected-window and
condition-case. Do not delete more windows than necessary in
the shrinking (delta < 0) case. Do not raise an error when the
containing frame is too small to show all of buffer. (Bug#1488)
| -rw-r--r-- | lisp/window.el | 162 |
1 files changed, 88 insertions, 74 deletions
diff --git a/lisp/window.el b/lisp/window.el index 6373185ffaa..6b1cc9a2d4e 100644 --- a/lisp/window.el +++ b/lisp/window.el | |||
| @@ -1294,86 +1294,100 @@ in some window." | |||
| 1294 | 1294 | ||
| 1295 | (defun fit-window-to-buffer (&optional window max-height min-height) | 1295 | (defun fit-window-to-buffer (&optional window max-height min-height) |
| 1296 | "Adjust height of WINDOW to display its buffer's contents exactly. | 1296 | "Adjust height of WINDOW to display its buffer's contents exactly. |
| 1297 | WINDOW defaults to the selected window. | 1297 | WINDOW defaults to the selected window. Return nil. |
| 1298 | Optional argument MAX-HEIGHT specifies the maximum height of the | 1298 | Optional argument MAX-HEIGHT specifies the maximum height of the |
| 1299 | window and defaults to the height of WINDOW's frame. | 1299 | window and defaults to the maximum permissible height of a window |
| 1300 | on WINDOW's frame. | ||
| 1300 | Optional argument MIN-HEIGHT specifies the minimum height of the | 1301 | Optional argument MIN-HEIGHT specifies the minimum height of the |
| 1301 | window and defaults to `window-min-height'. | 1302 | window and defaults to `window-min-height'. |
| 1302 | Both, MAX-HEIGHT and MIN-HEIGHT are specified in lines and | 1303 | Both, MAX-HEIGHT and MIN-HEIGHT are specified in lines and |
| 1303 | include the mode line and header line, if any. | 1304 | include the mode line and header line, if any. |
| 1304 | Always return nil." | ||
| 1305 | (interactive) | ||
| 1306 | 1305 | ||
| 1307 | (when (null window) | 1306 | Caution: This function can delete WINDOW and/or other windows |
| 1308 | (setq window (selected-window))) | 1307 | when their height shrinks to less than MIN-HEIGHT." |
| 1309 | (when (null max-height) | 1308 | (interactive) |
| 1310 | (setq max-height (frame-height (window-frame window)))) | 1309 | ;; Do all the work in WINDOW and its buffer and restore the selected |
| 1311 | 1310 | ;; window and the current buffer when we're done. | |
| 1312 | (let* ((buf | 1311 | (let ((old-buffer (current-buffer))) |
| 1313 | ;; Buffer that is displayed in WINDOW | 1312 | (with-selected-window (or window (setq window (selected-window))) |
| 1314 | (window-buffer window)) | 1313 | (set-buffer (window-buffer)) |
| 1315 | (window-height | 1314 | ;; Use `condition-case' to handle any fixed-size windows and other |
| 1316 | ;; The current height of WINDOW | 1315 | ;; pitfalls nearby. |
| 1317 | (window-height window)) | 1316 | (condition-case nil |
| 1318 | (desired-height | 1317 | (let* (;; MIN-HEIGHT must not be less than 1 and defaults to |
| 1319 | ;; The height necessary to show the buffer displayed by WINDOW | 1318 | ;; `window-min-height'. |
| 1320 | ;; (`count-screen-lines' always works on the current buffer). | 1319 | (min-height (max (or min-height window-min-height) 1)) |
| 1321 | (with-current-buffer buf | 1320 | (max-window-height |
| 1322 | (+ (count-screen-lines) | 1321 | ;; Maximum height of any window on this frame. |
| 1323 | ;; If the buffer is empty, (count-screen-lines) is | 1322 | (min (window-height (frame-root-window)) (frame-height))) |
| 1324 | ;; zero. But, even in that case, we need one text line | 1323 | ;; MAX-HEIGHT must not be larger than max-window-height and |
| 1325 | ;; for cursor. | 1324 | ;; defaults to max-window-height. |
| 1326 | (if (= (point-min) (point-max)) | 1325 | (max-height |
| 1327 | 1 0) | 1326 | (min (or max-height max-window-height) max-window-height)) |
| 1328 | ;; For non-minibuffers, count the mode-line, if any | 1327 | (desired-height |
| 1329 | (if (and (not (window-minibuffer-p window)) | 1328 | ;; The height necessary to show all of WINDOW's buffer, |
| 1330 | mode-line-format) | 1329 | ;; constrained by MIN-HEIGHT and MAX-HEIGHT. |
| 1331 | 1 0) | 1330 | (max |
| 1332 | ;; Count the header-line, if any | 1331 | (min |
| 1333 | (if header-line-format 1 0)))) | 1332 | ;; For an empty buffer `count-screen-lines' returns zero. |
| 1334 | (delta | 1333 | ;; Even in that case we need one line for the cursor. |
| 1335 | ;; Calculate how much the window height has to change to show | 1334 | (+ (max (count-screen-lines) 1) |
| 1336 | ;; desired-height lines, constrained by MIN-HEIGHT and MAX-HEIGHT. | 1335 | ;; For non-minibuffers count the mode line, if any. |
| 1337 | (- (max (min desired-height max-height) | 1336 | (if (and (not (window-minibuffer-p)) mode-line-format) |
| 1338 | (or min-height window-min-height)) | 1337 | 1 0) |
| 1339 | window-height))) | 1338 | ;; Count the header line, if any. |
| 1340 | 1339 | (if header-line-format 1 0)) | |
| 1341 | ;; Don't try to redisplay with the cursor at the end | 1340 | max-height) |
| 1342 | ;; on its own line--that would force a scroll and spoil things. | 1341 | min-height)) |
| 1343 | (when (with-current-buffer buf | 1342 | (delta |
| 1344 | (and (eobp) (bolp) (not (bobp)))) | 1343 | ;; How much the window height has to change. |
| 1345 | (set-window-point window (1- (window-point window)))) | 1344 | (if (= (window-height) (window-height (frame-root-window))) |
| 1346 | 1345 | ;; Don't try to resize a full-height window. | |
| 1347 | (save-selected-window | 1346 | 0 |
| 1348 | (select-window window 'norecord) | 1347 | (- desired-height (window-height)))) |
| 1349 | 1348 | ;; Do something reasonable so `enlarge-window' can make | |
| 1350 | ;; Adjust WINDOW to the nominally correct size (which may actually | 1349 | ;; windows as small as MIN-HEIGHT. |
| 1351 | ;; be slightly off because of variable height text, etc). | 1350 | (window-min-height (min min-height window-min-height))) |
| 1352 | (unless (zerop delta) | 1351 | ;; Don't try to redisplay with the cursor at the end on its |
| 1353 | (enlarge-window delta)) | 1352 | ;; own line--that would force a scroll and spoil things. |
| 1354 | 1353 | (when (and (eobp) (bolp) (not (bobp))) | |
| 1355 | ;; Check if the last line is surely fully visible. If not, | 1354 | (set-window-point window (1- (window-point)))) |
| 1356 | ;; enlarge the window. | 1355 | ;; Adjust WINDOW's height to the nominally correct one |
| 1357 | (let ((end (with-current-buffer buf | 1356 | ;; (which may actually be slightly off because of variable |
| 1358 | (save-excursion | 1357 | ;; height text, etc). |
| 1359 | (goto-char (point-max)) | 1358 | (unless (zerop delta) |
| 1360 | (when (and (bolp) (not (bobp))) | 1359 | (enlarge-window delta)) |
| 1361 | ;; Don't include final newline | 1360 | ;; `enlarge-window' might have deleted WINDOW, so make sure |
| 1362 | (backward-char 1)) | 1361 | ;; WINDOW's still alive for the remainder of this. |
| 1363 | (when truncate-lines | 1362 | ;; Note: Deleting WINDOW is clearly counter-intuitive in |
| 1364 | ;; If line-wrapping is turned off, test the | 1363 | ;; this context, but we can't do much about it given the |
| 1365 | ;; beginning of the last line for visibility | 1364 | ;; current semantics of `enlarge-window'. |
| 1366 | ;; instead of the end, as the end of the line | 1365 | (when (window-live-p window) |
| 1367 | ;; could be invisible by virtue of extending past | 1366 | ;; Check if the last line is surely fully visible. If |
| 1368 | ;; the edge of the window. | 1367 | ;; not, enlarge the window. |
| 1369 | (forward-line 0)) | 1368 | (let ((end (save-excursion |
| 1370 | (point))))) | 1369 | (goto-char (point-max)) |
| 1371 | (set-window-vscroll window 0) | 1370 | (when (and (bolp) (not (bobp))) |
| 1372 | (while (and (< desired-height max-height) | 1371 | ;; Don't include final newline. |
| 1373 | (= desired-height (window-height window)) | 1372 | (backward-char 1)) |
| 1374 | (not (pos-visible-in-window-p end window))) | 1373 | (when truncate-lines |
| 1375 | (enlarge-window 1) | 1374 | ;; If line-wrapping is turned off, test the |
| 1376 | (setq desired-height (1+ desired-height))))))) | 1375 | ;; beginning of the last line for |
| 1376 | ;; visibility instead of the end, as the | ||
| 1377 | ;; end of the line could be invisible by | ||
| 1378 | ;; virtue of extending past the edge of the | ||
| 1379 | ;; window. | ||
| 1380 | (forward-line 0)) | ||
| 1381 | (point)))) | ||
| 1382 | (set-window-vscroll window 0) | ||
| 1383 | (while (and (< desired-height max-height) | ||
| 1384 | (= desired-height (window-height)) | ||
| 1385 | (not (pos-visible-in-window-p end))) | ||
| 1386 | (enlarge-window 1) | ||
| 1387 | (setq desired-height (1+ desired-height)))))) | ||
| 1388 | (error nil))) | ||
| 1389 | (when (buffer-live-p old-buffer) | ||
| 1390 | (set-buffer old-buffer)))) | ||
| 1377 | 1391 | ||
| 1378 | (defun window-safely-shrinkable-p (&optional window) | 1392 | (defun window-safely-shrinkable-p (&optional window) |
| 1379 | "Return t if WINDOW can be shrunk without shrinking other windows. | 1393 | "Return t if WINDOW can be shrunk without shrinking other windows. |