Mercurial > hg > xemacs-beta
comparison lisp/window.el @ 209:41ff10fd062f r20-4b3
Import from CVS: tag r20-4b3
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:04:58 +0200 |
parents | |
children | 2c611d1463a6 |
comparison
equal
deleted
inserted
replaced
208:f427b8ec4379 | 209:41ff10fd062f |
---|---|
1 ;;; window.el --- XEmacs window commands aside from those written in C. | |
2 | |
3 ;; Copyright (C) 1985, 1989, 1993-94, 1997 Free Software Foundation, Inc. | |
4 ;; Copyright (C) 1995, 1996 Ben Wing. | |
5 | |
6 ;; Maintainer: XEmacs Development Team | |
7 ;; Keywords: frames, extensions, dumped | |
8 | |
9 ;; This file is part of XEmacs. | |
10 | |
11 ;; XEmacs is free software; you can redistribute it and/or modify it | |
12 ;; under the terms of the GNU General Public License as published by | |
13 ;; the Free Software Foundation; either version 2, or (at your option) | |
14 ;; any later version. | |
15 | |
16 ;; XEmacs is distributed in the hope that it will be useful, but | |
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 ;; General Public License for more details. | |
20 | |
21 ;; You should have received a copy of the GNU General Public License | |
22 ;; along with XEmacs; see the file COPYING. If not, write to the | |
23 ;; Free Software Foundation, 59 Temple Place - Suite 330, | |
24 ;; Boston, MA 02111-1307, USA. | |
25 | |
26 ;;; Synched up with: Emacs/Mule zeta. | |
27 | |
28 ;;; Commentary: | |
29 | |
30 ;; This file is dumped with XEmacs. | |
31 | |
32 ;;; Code: | |
33 | |
34 ;;;; Window tree functions. | |
35 | |
36 (defun one-window-p (&optional nomini all-frames device) | |
37 "Returns non-nil if the selected window is the only window (in its frame). | |
38 Optional arg NOMINI non-nil means don't count the minibuffer | |
39 even if it is active. | |
40 | |
41 The optional arg ALL-FRAMES t means count windows on all frames. | |
42 If it is `visible', count windows on all visible frames. | |
43 ALL-FRAMES nil or omitted means count only the selected frame, | |
44 plus the minibuffer it uses (which may be on another frame). | |
45 ALL-FRAMES = 0 means count windows on all visible and iconified frames. | |
46 If ALL-FRAMES is any other value, count only the selected frame. | |
47 | |
48 If optional third argument DEVICE is nil or omitted, count frames | |
49 on all devices. | |
50 If a device, count frames only on that device. | |
51 If a device type, count frames only on devices of that type. | |
52 Otherwise, count frames only on the selected device." | |
53 (let ((base-window (selected-window))) | |
54 (if (and nomini (eq base-window (minibuffer-window))) | |
55 (setq base-window (next-window base-window))) | |
56 (eq base-window | |
57 (next-window base-window (if nomini 'arg) all-frames device)))) | |
58 | |
59 (defun walk-windows (proc &optional minibuf all-frames device) | |
60 "Cycle through all visible windows, calling PROC for each one. | |
61 PROC is called with a window as argument. | |
62 | |
63 Optional second arg MINIBUF t means count the minibuffer window even | |
64 if not active. MINIBUF nil or omitted means count the minibuffer iff | |
65 it is active. MINIBUF neither t nor nil means not to count the | |
66 minibuffer even if it is active. | |
67 | |
68 Several frames may share a single minibuffer; if the minibuffer | |
69 counts, all windows on all frames that share that minibuffer count | |
70 too. Therefore, when a separate minibuffer frame is active, | |
71 `walk-windows' includes the windows in the frame from which you | |
72 entered the minibuffer, as well as the minibuffer window. But if the | |
73 minibuffer does not count, only windows from WINDOW's frame count. | |
74 | |
75 ALL-FRAMES is the optional third argument. | |
76 ALL-FRAMES nil or omitted means cycle within the frames as specified above. | |
77 ALL-FRAMES = `visible' means include windows on all visible frames. | |
78 ALL-FRAMES = 0 means include windows on all visible and iconified frames. | |
79 ALL-FRAMES = t means include windows on all frames including invisible frames. | |
80 Anything else means restrict to WINDOW's frame. | |
81 | |
82 If optional fourth argument DEVICE is nil or omitted, include frames | |
83 on all devices. | |
84 If a device, include frames only on that device. | |
85 If a device type, include frames only on devices of that type. | |
86 Otherwise, include frames only on the selected device." | |
87 ;; If we start from the minibuffer window, don't fail to come back to it. | |
88 (if (window-minibuffer-p (selected-window)) | |
89 (setq minibuf t)) | |
90 ;; Note that, like next-window & previous-window, this behaves a little | |
91 ;; strangely if the selected window is on an invisible frame: it hits | |
92 ;; some of the windows on that frame, and all windows on visible frames. | |
93 (let* ((walk-windows-start (selected-window)) | |
94 (walk-windows-current walk-windows-start)) | |
95 (while (progn | |
96 (setq walk-windows-current | |
97 (next-window walk-windows-current minibuf all-frames | |
98 device)) | |
99 (funcall proc walk-windows-current) | |
100 (not (eq walk-windows-current walk-windows-start)))))) | |
101 ;; The old XEmacs definition of the above clause. It's more correct in | |
102 ;; that it will never hit a window that's already been hit even if you | |
103 ;; do something odd like `delete-other-windows', but has the problem | |
104 ;; that it conses. (This may be called repeatedly, from lazy-lock | |
105 ;; for example.) | |
106 ; (let* ((walk-windows-history nil) | |
107 ; (walk-windows-current (selected-window))) | |
108 ; (while (progn | |
109 ; (setq walk-windows-current | |
110 ; (next-window walk-windows-current minibuf all-frames | |
111 ; device)) | |
112 ; (not (memq walk-windows-current walk-windows-history))) | |
113 ; (setq walk-windows-history (cons walk-windows-current | |
114 ; walk-windows-history)) | |
115 ; (funcall proc walk-windows-current)))) | |
116 | |
117 (defun minibuffer-window-active-p (window) | |
118 "Return t if WINDOW (a minibuffer window) is now active." | |
119 (eq window (active-minibuffer-window))) | |
120 | |
121 (defmacro save-selected-window (&rest body) | |
122 "Execute BODY, then select the window that was selected before BODY." | |
123 (list 'let | |
124 '((save-selected-window-window (selected-window))) | |
125 (list 'unwind-protect | |
126 (cons 'progn body) | |
127 (list 'and ; XEmacs | |
128 (list 'window-live-p 'save-selected-window-window) | |
129 (list 'select-window 'save-selected-window-window))))) | |
130 | |
131 (defun count-windows (&optional minibuf) | |
132 "Returns the number of visible windows. | |
133 Optional arg MINIBUF non-nil means count the minibuffer | |
134 even if it is inactive." | |
135 (let ((count 0)) | |
136 (walk-windows (function (lambda (w) | |
137 (setq count (+ count 1)))) | |
138 minibuf) | |
139 count)) | |
140 | |
141 (defun balance-windows () | |
142 "Makes all visible windows the same height (approximately)." | |
143 (interactive) | |
144 (let ((count -1) levels newsizes size) | |
145 ;FSFmacs | |
146 ;;; Don't count the lines that are above the uppermost windows. | |
147 ;;; (These are the menu bar lines, if any.) | |
148 ;(mbl (nth 1 (window-edges (frame-first-window (selected-frame)))))) | |
149 ;; Find all the different vpos's at which windows start, | |
150 ;; then count them. But ignore levels that differ by only 1. | |
151 (save-window-excursion | |
152 (let (tops (prev-top -2)) | |
153 (walk-windows (function (lambda (w) | |
154 (setq tops (cons (nth 1 (window-pixel-edges w)) | |
155 tops)))) | |
156 'nomini) | |
157 (setq tops (sort tops '<)) | |
158 (while tops | |
159 (if (> (car tops) (1+ prev-top)) | |
160 (setq prev-top (car tops) | |
161 count (1+ count))) | |
162 (setq levels (cons (cons (car tops) count) levels)) | |
163 (setq tops (cdr tops))) | |
164 (setq count (1+ count)))) | |
165 ;; Subdivide the frame into that many vertical levels. | |
166 ;FSFmacs (setq size (/ (- (frame-height) mbl) count)) | |
167 (setq size (/ (window-pixel-height (frame-root-window)) count)) | |
168 (walk-windows (function | |
169 (lambda (w) | |
170 (select-window w) | |
171 (let ((newtop (cdr (assq (nth 1 (window-pixel-edges)) | |
172 levels))) | |
173 (newbot (or (cdr (assq | |
174 (+ (window-pixel-height) | |
175 (nth 1 (window-pixel-edges))) | |
176 levels)) | |
177 count))) | |
178 (setq newsizes | |
179 (cons (cons w (* size (- newbot newtop))) | |
180 newsizes))))) | |
181 'nomini) | |
182 (walk-windows (function (lambda (w) | |
183 (select-window w) | |
184 (let ((newsize (cdr (assq w newsizes)))) | |
185 (enlarge-window | |
186 (/ (- newsize (window-pixel-height)) | |
187 (face-height 'default)))))) | |
188 'nomini))) | |
189 | |
190 ;;; I think this should be the default; I think people will prefer it--rms. | |
191 (defcustom split-window-keep-point t | |
192 "*If non-nil, split windows keeps the original point in both children. | |
193 This is often more convenient for editing. | |
194 If nil, adjust point in each of the two windows to minimize redisplay. | |
195 This is convenient on slow terminals, but point can move strangely." | |
196 :type 'boolean | |
197 :group 'windows) | |
198 | |
199 (defun split-window-vertically (&optional arg) | |
200 "Split current window into two windows, one above the other. | |
201 The uppermost window gets ARG lines and the other gets the rest. | |
202 Negative arg means select the size of the lowermost window instead. | |
203 With no argument, split equally or close to it. | |
204 Both windows display the same buffer now current. | |
205 | |
206 If the variable split-window-keep-point is non-nil, both new windows | |
207 will get the same value of point as the current window. This is often | |
208 more convenient for editing. | |
209 | |
210 Otherwise, we chose window starts so as to minimize the amount of | |
211 redisplay; this is convenient on slow terminals. The new selected | |
212 window is the one that the current value of point appears in. The | |
213 value of point can change if the text around point is hidden by the | |
214 new mode line. | |
215 | |
216 Programs should probably use split-window instead of this." | |
217 (interactive "P") | |
218 (let ((old-w (selected-window)) | |
219 (old-point (point)) | |
220 (size (and arg (prefix-numeric-value arg))) | |
221 (window-full-p nil) | |
222 new-w bottom moved) | |
223 (and size (< size 0) (setq size (+ (window-height) size))) | |
224 (setq new-w (split-window nil size)) | |
225 (or split-window-keep-point | |
226 (progn | |
227 (save-excursion | |
228 (set-buffer (window-buffer)) | |
229 (goto-char (window-start)) | |
230 (setq moved (vertical-motion (window-height))) | |
231 (set-window-start new-w (point)) | |
232 (if (> (point) (window-point new-w)) | |
233 (set-window-point new-w (point))) | |
234 (and (= moved (window-height)) | |
235 (progn | |
236 (setq window-full-p t) | |
237 (vertical-motion -1))) | |
238 (setq bottom (point))) | |
239 (and window-full-p | |
240 (<= bottom (point)) | |
241 (set-window-point old-w (1- bottom))) | |
242 (and window-full-p | |
243 (<= (window-start new-w) old-point) | |
244 (progn | |
245 (set-window-point new-w old-point) | |
246 (select-window new-w))))) | |
247 new-w)) | |
248 | |
249 (defun split-window-horizontally (&optional arg) | |
250 "Split current window into two windows side by side. | |
251 This window becomes the leftmost of the two, and gets ARG columns. | |
252 Negative arg means select the size of the rightmost window instead. | |
253 No arg means split equally." | |
254 (interactive "P") | |
255 (let ((size (and arg (prefix-numeric-value arg)))) | |
256 (and size (< size 0) | |
257 (setq size (+ (window-width) size))) | |
258 (split-window nil size t))) | |
259 | |
260 (defun enlarge-window-horizontally (arg) | |
261 "Make current window ARG columns wider." | |
262 (interactive "p") | |
263 (enlarge-window arg t)) | |
264 | |
265 (defun shrink-window-horizontally (arg) | |
266 "Make current window ARG columns narrower." | |
267 (interactive "p") | |
268 (shrink-window arg t)) | |
269 | |
270 (defun shrink-window-if-larger-than-buffer (&optional window) | |
271 "Shrink the WINDOW to be as small as possible to display its contents. | |
272 Do not shrink to less than `window-min-height' lines. | |
273 Do nothing if the buffer contains more lines than the present window height, | |
274 or if some of the window's contents are scrolled out of view, | |
275 or if the window is not the full width of the frame, | |
276 or if the window is the only window of its frame." | |
277 (interactive) | |
278 (or window (setq window (selected-window))) | |
279 (save-excursion | |
280 (set-buffer (window-buffer window)) | |
281 (let* ((w (selected-window)) ;save-window-excursion can't win | |
282 (buffer-file-name buffer-file-name) | |
283 (p (point)) | |
284 (n 0) | |
285 (ignore-final-newline | |
286 ;; If buffer ends with a newline, ignore it when counting height | |
287 ;; unless point is after it. | |
288 (and (not (eobp)) | |
289 (eq ?\n (char-after (1- (point-max)))))) | |
290 (buffer-read-only nil) | |
291 (modified (buffer-modified-p)) | |
292 (buffer (current-buffer)) | |
293 (mini (frame-property (window-frame window) 'minibuffer)) | |
294 (edges (window-pixel-edges (selected-window)))) | |
295 (if (and (< 1 (let ((frame (selected-frame))) | |
296 (select-frame (window-frame window)) | |
297 (unwind-protect | |
298 (count-windows) | |
299 (select-frame frame)))) | |
300 ;; check to make sure that we don't have horizontally | |
301 ;; split windows | |
302 (eq (frame-highest-window (window-frame window) 0) | |
303 (frame-highest-window (window-frame window) -1)) | |
304 (pos-visible-in-window-p (point-min) window) | |
305 (not (eq mini 'only)) | |
306 (or (not mini) (eq mini t) | |
307 (< (nth 3 edges) | |
308 (nth 1 (window-pixel-edges mini))) | |
309 (> (nth 1 edges) | |
310 ;FSFmacs (frame-property (window-frame window) | |
311 ; 'menu-bar-lines params) | |
312 0))) | |
313 (unwind-protect | |
314 (let ((shrinkee (or window w))) | |
315 (set-buffer (window-buffer shrinkee)) | |
316 (goto-char (point-min)) | |
317 (while (pos-visible-in-window-p | |
318 (- (point-max) | |
319 (if ignore-final-newline 1 0)) | |
320 shrinkee) | |
321 ;; defeat file locking... don't try this at home, kids! | |
322 (setq buffer-file-name nil) | |
323 (insert ?\n) (setq n (1+ n))) | |
324 (if (> n 0) | |
325 (shrink-window (min (1- n) | |
326 (- (window-height shrinkee) | |
327 window-min-height)) | |
328 nil | |
329 shrinkee))) | |
330 (delete-region (point-min) (point)) | |
331 (set-buffer-modified-p modified) | |
332 (goto-char p) | |
333 ;; (select-window w) ; Emacs | |
334 ;; Make sure we unbind buffer-read-only | |
335 ;; with the proper current buffer. | |
336 (set-buffer buffer)))))) | |
337 | |
338 (defun kill-buffer-and-window () | |
339 "Kill the current buffer and delete the selected window." | |
340 (interactive) | |
341 (if (yes-or-no-p (format "Kill buffer `%s'? " (buffer-name))) | |
342 (let ((buffer (current-buffer))) | |
343 (delete-window (selected-window)) | |
344 (kill-buffer buffer)) | |
345 (error "Aborted"))) | |
346 | |
347 ;;; New with XEmacs 20.3 | |
348 ;;; Suggested by Noah Friedman, and tuned by Hrvoje Niksic. | |
349 (defun window-list (&optional minibuf all-frames device) | |
350 "Return a list of existing windows. | |
351 If the optional argument MINIBUF is non-nil, then include minibuffer | |
352 windows in the result. | |
353 | |
354 By default, only the windows in the selected frame are returned. | |
355 The optional argument ALL-FRAMES changes this behavior: | |
356 ALL-FRAMES = `visible' means include windows on all visible frames. | |
357 ALL-FRAMES = 0 means include windows on all visible and iconified frames. | |
358 ALL-FRAMES = t means include windows on all frames including invisible frames. | |
359 Anything else means restrict to the selected frame. | |
360 The optional fourth argument DEVICE further clarifies which frames to | |
361 search as specified by ALL-FRAMES. This value is only meaningful if | |
362 ALL-FRAMES is non-nil. | |
363 If nil or omitted, search only the selected device. | |
364 If a device, search frames only on that device. | |
365 If a device type, search frames only on devices of that type. | |
366 Any other non-nil value means search frames on all devices." | |
367 (let ((wins nil)) | |
368 (walk-windows (lambda (win) | |
369 (push win wins)) | |
370 minibuf all-frames device) | |
371 wins)) | |
372 | |
373 | |
374 ;;; window.el ends here |