Mercurial > emacs
annotate lisp/windmove.el @ 112453:06719a229a46 default tip
* calc/calc.el (calc-default-power-reference-level)
(calc-default-field-reference-level): New variables.
* calc/calc-units.el (math-standard-units): Add dB and Np.
(math-logunits): New variable.
(math-extract-logunits, math-logcombine, calcFunc-luplus)
(calcFunc-luminus, calc-luplus, calc-luminus, math-logunit-level)
(calcFunc-fieldlevel, calcFunc-powerlevel, calc-level): New
functions.
(math-find-base-units-rec): Add entry for ln(10).
* calc/calc-help.el (calc-u-prefix-help): Add logarithmic help.
(calc-ul-prefix-help): New function.
* calc/calc-ext.el (calc-init-extensions): Autoload new units
functions. Add keybindings for new units functions.
| author | Jay Belanger <jay.p.belanger@gmail.com> |
|---|---|
| date | Sun, 23 Jan 2011 23:08:04 -0600 |
| parents | ef719132ddfa |
| children |
| rev | line source |
|---|---|
|
38436
b174db545cfd
Some fixes to follow coding conventions.
Pavel Jan?k <Pavel@Janik.cz>
parents:
30892
diff
changeset
|
1 ;;; windmove.el --- directional window-selection routines |
| 27545 | 2 ;; |
| 74442 | 3 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, |
|
112218
376148b31b5e
Add 2011 to FSF/AIST copyright years.
Glenn Morris <rgm@gnu.org>
parents:
106815
diff
changeset
|
4 ;; 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. |
| 27545 | 5 ;; |
| 6 ;; Author: Hovav Shacham (hovav@cs.stanford.edu) | |
| 7 ;; Created: 17 October 1998 | |
|
30892
495502641770
(windmove) <defgroup>: Add :version.
Dave Love <fx@gnu.org>
parents:
27545
diff
changeset
|
8 ;; Keywords: window, movement, convenience |
| 27545 | 9 ;; |
| 10 ;; This file is part of GNU Emacs. | |
| 11 ;; | |
|
94678
ee5932bf781d
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
93975
diff
changeset
|
12 ;; GNU Emacs is free software: you can redistribute it and/or modify |
| 27545 | 13 ;; it under the terms of the GNU General Public License as published by |
|
94678
ee5932bf781d
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
93975
diff
changeset
|
14 ;; the Free Software Foundation, either version 3 of the License, or |
|
ee5932bf781d
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
93975
diff
changeset
|
15 ;; (at your option) any later version. |
|
ee5932bf781d
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
93975
diff
changeset
|
16 |
| 27545 | 17 ;; GNU Emacs is distributed in the hope that it will be useful, |
| 18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 20 ;; GNU General Public License for more details. | |
|
94678
ee5932bf781d
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
93975
diff
changeset
|
21 |
| 27545 | 22 ;; You should have received a copy of the GNU General Public License |
|
94678
ee5932bf781d
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
93975
diff
changeset
|
23 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
| 27545 | 24 ;; |
| 25 ;; -------------------------------------------------------------------- | |
| 26 | |
| 27 ;;; Commentary: | |
| 28 ;; | |
| 29 ;; This package defines a set of routines, windmove-{left,up,right, | |
| 30 ;; down}, for selection of windows in a frame geometrically. For | |
| 31 ;; example, `windmove-right' selects the window immediately to the | |
| 32 ;; right of the currently-selected one. This functionality is similar | |
| 33 ;; to the window-selection controls of the BRIEF editor of yore. | |
| 34 ;; | |
| 35 ;; One subtle point is what happens when the window to the right has | |
| 36 ;; been split vertically; for example, consider a call to | |
| 37 ;; `windmove-right' in this setup: | |
| 38 ;; | |
| 39 ;; ------------- | |
| 40 ;; | | A | | |
| 41 ;; | | | | |
| 42 ;; | |----- | |
| 43 ;; | * | | (* is point in the currently | |
| 44 ;; | | B | selected window) | |
| 45 ;; | | | | |
| 46 ;; ------------- | |
| 47 ;; | |
| 48 ;; There are (at least) three reasonable things to do: | |
| 49 ;; (1) Always move to the window to the right of the top edge of the | |
| 50 ;; selected window; in this case, this policy selects A. | |
| 51 ;; (2) Always move to the window to the right of the bottom edge of | |
| 52 ;; the selected window; in this case, this policy selects B. | |
|
30892
495502641770
(windmove) <defgroup>: Add :version.
Dave Love <fx@gnu.org>
parents:
27545
diff
changeset
|
53 ;; (3) Move to the window to the right of point in the selected |
| 27545 | 54 ;; window. This may select either A or B, depending on the |
| 55 ;; position of point; in the illustrated example, it would select | |
| 56 ;; B. | |
| 57 ;; | |
| 58 ;; Similar issues arise for all the movement functions. Windmove | |
| 59 ;; resolves this problem by allowing the user to specify behavior | |
| 60 ;; through a prefix argument. The cases are thus: | |
| 61 ;; * if no argument is given to the movement functions, or the | |
| 62 ;; argument given is zero, movement is relative to point; | |
| 63 ;; * if a positive argument is given, movement is relative to the top | |
| 64 ;; or left edge of the selected window, depending on whether the | |
| 65 ;; movement is to be horizontal or vertical; | |
| 66 ;; * if a negative argument is given, movement is relative to the | |
| 67 ;; bottom or right edge of the selected window, depending on whether | |
| 68 ;; the movement is to be horizontal or vertical. | |
| 69 ;; | |
| 70 ;; | |
| 71 ;; Another feature enables wrap-around mode when the variable | |
| 72 ;; `windmove-wrap-around' is set to a non-nil value. In this mode, | |
| 73 ;; movement that falls off the edge of the frame will wrap around to | |
| 74 ;; find the window on the opposite side of the frame. Windmove does | |
| 75 ;; the Right Thing about the minibuffer; for example, consider: | |
| 76 ;; | |
| 77 ;; ------------- | |
| 78 ;; | * | | |
| 79 ;; |-----------| | |
| 80 ;; | A | | |
| 81 ;; |-----------| (* is point in the currently | |
| 82 ;; | B | C | selected window) | |
| 83 ;; | | | | |
| 84 ;; ------------- | |
| 85 ;; | |
| 86 ;; With wraparound enabled, windmove-down will move to A, while | |
| 87 ;; windmove-up will move to the minibuffer if it is active, or to | |
| 88 ;; either B or C depending on the prefix argument. | |
| 89 ;; | |
| 90 ;; | |
| 91 ;; A set of default keybindings is supplied: shift-{left,up,right,down} | |
| 92 ;; invoke the corresponding Windmove function. See the installation | |
| 93 ;; section if you wish to use these keybindings. | |
| 94 | |
| 95 | |
| 96 ;; Installation: | |
| 97 ;; | |
| 98 ;; Put the following line in your `.emacs' file: | |
| 99 ;; | |
|
45166
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
100 ;; (windmove-default-keybindings) ; shifted arrow keys |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
101 ;; |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
102 ;; or |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
103 ;; |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
104 ;; (windmove-default-keybindings 'hyper) ; etc. |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
105 ;; |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
106 ;; to use another modifier key. |
| 27545 | 107 ;; |
| 108 ;; | |
| 109 ;; If you wish to enable wrap-around, also add a line like: | |
| 110 ;; | |
| 111 ;; (setq windmove-wrap-around t) | |
| 112 ;; | |
| 113 ;; | |
| 114 ;; Note: If you have an Emacs that manifests a bug that sometimes | |
| 115 ;; causes the occasional creation of a "lost column" between windows, | |
| 116 ;; so that two adjacent windows do not actually touch, you may want to | |
| 117 ;; increase the value of `windmove-window-distance-delta' to 2 or 3: | |
|
45166
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
118 ;; |
| 27545 | 119 ;; (setq windmove-window-distance-delta 2) |
| 120 ;; | |
| 121 | |
| 122 ;; Acknowledgements: | |
| 123 ;; | |
| 124 ;; Special thanks to Julian Assange (proff@iq.org), whose | |
| 125 ;; change-windows-intuitively.el predates Windmove, and provided the | |
| 126 ;; inspiration for it. Kin Cho (kin@symmetrycomm.com) was the first | |
| 127 ;; to suggest wrap-around behavior. Thanks also to Gerd Moellmann | |
| 128 ;; (gerd@gnu.org) for his comments and suggestions. | |
| 129 | |
| 130 ;;; Code: | |
| 131 | |
| 132 | |
| 133 ;; User configurable variables: | |
| 134 | |
| 135 ;; For customize ... | |
| 136 (defgroup windmove nil | |
| 137 "Directional selection of windows in a frame." | |
| 138 :prefix "windmove-" | |
|
30892
495502641770
(windmove) <defgroup>: Add :version.
Dave Love <fx@gnu.org>
parents:
27545
diff
changeset
|
139 :version "21.1" |
| 27545 | 140 :group 'windows |
| 141 :group 'convenience) | |
| 142 | |
| 143 | |
| 144 (defcustom windmove-wrap-around nil | |
| 145 "Whether movement off the edge of the frame wraps around. | |
| 146 If this variable is set to t, moving left from the leftmost window in | |
| 147 a frame will find the rightmost one, and similarly for the other | |
| 148 directions. The minibuffer is skipped over in up/down movements if it | |
| 149 is inactive." | |
| 150 :type 'boolean | |
| 151 :group 'windmove) | |
| 152 | |
| 153 ;; If your Emacs sometimes places an empty column between two adjacent | |
| 154 ;; windows, you may wish to set this delta to 2. | |
| 155 (defcustom windmove-window-distance-delta 1 | |
| 156 "How far away from the current window to look for an adjacent window. | |
| 157 Measured in characters either horizontally or vertically; setting this | |
| 158 to a value larger than 1 may be useful in getting around window- | |
| 159 placement bugs in old versions of Emacs." | |
| 160 :type 'number | |
| 161 :group 'windmove) | |
| 162 | |
| 163 | |
| 164 | |
| 165 ;; Implementation overview: | |
| 166 ;; | |
| 167 ;; The conceptual framework behind this code is all fairly simple. We | |
| 168 ;; are on one window; we wish to move to another. The correct window | |
| 169 ;; to move to is determined by the position of point in the current | |
| 170 ;; window as well as the overall window setup. | |
| 171 ;; | |
| 172 ;; Early on, I made the decision to base my implementation around the | |
| 173 ;; built-in function `window-at'. This function takes a frame-based | |
| 174 ;; coordinate, and returns the window that contains it. Using this | |
| 175 ;; function, the job of the various top-level windmove functions can | |
| 176 ;; be decomposed: first, find the current frame-based location of | |
| 177 ;; point; second, manipulate it in some way to give a new location, | |
| 178 ;; that hopefully falls in the window immediately at left (or right, | |
| 179 ;; etc.); third, use `window-at' and `select-window' to select the | |
| 180 ;; window at that new location. | |
| 181 ;; | |
| 182 ;; This is probably not the only possible architecture, and it turns | |
| 183 ;; out to have some inherent cruftiness. (Well, okay, the third step | |
| 184 ;; is pretty clean....) We will consider each step in turn. | |
| 185 ;; | |
| 186 ;; A quick digression about coordinate frames: most of the functions | |
| 187 ;; in the windmove package deal with screen coordinates in one way or | |
| 188 ;; another. These coordinates are always relative to some reference | |
| 189 ;; points. Window-based coordinates have their reference point in the | |
| 190 ;; upper-left-hand corner of whatever window is being talked about; | |
| 191 ;; frame-based coordinates have their reference point in the | |
| 192 ;; upper-left-hand corner of the entire frame (of which the current | |
| 193 ;; window is a component). | |
| 194 ;; | |
| 195 ;; All coordinates are zero-based, which simply means that the | |
| 196 ;; reference point (whatever it is) is assigned the value (x=0, y=0). | |
| 197 ;; X-coordinates grow down the screen, and Y-coordinates grow towards | |
| 198 ;; the right of the screen. | |
| 199 ;; | |
| 200 ;; Okay, back to work. The first step is to gather information about | |
| 201 ;; the frame-based coordinates of point, or rather, the reference | |
| 202 ;; location. The reference location can be point, or the upper-left, | |
| 203 ;; or the lower-right corner of the window; the particular one used is | |
| 204 ;; controlled by the prefix argument to `windmove-left' and all the | |
| 205 ;; rest. | |
| 206 ;; | |
| 207 ;; This work is done by `windmove-reference-loc'. It can figure out | |
|
65018
6c1c6712bea9
(windmove-coordinates-of-position): Remove.
Kim F. Storm <storm@cua.dk>
parents:
64762
diff
changeset
|
208 ;; the locations of the corners by calling `window-edges' combined |
|
6c1c6712bea9
(windmove-coordinates-of-position): Remove.
Kim F. Storm <storm@cua.dk>
parents:
64762
diff
changeset
|
209 ;; with the result of `posn-at-point'. |
| 27545 | 210 ;; |
| 211 ;; The second step is more messy. Conceptually, it is fairly simple: | |
| 212 ;; if we know the reference location, and the coordinates of the | |
| 213 ;; current window, we can "throw" our reference point just over the | |
| 214 ;; appropriate edge of the window, and see what other window is | |
| 215 ;; there. More explicitly, consider this example from the user | |
| 216 ;; documentation above. | |
| 217 ;; | |
| 218 ;; ------------- | |
| 219 ;; | | A | | |
| 220 ;; | | | | |
| 221 ;; | |----- | |
| 222 ;; | * | | (* is point in the currently | |
| 223 ;; | | B | selected window) | |
| 224 ;; | | | | |
| 225 ;; ------------- | |
| 226 ;; | |
| 227 ;; The asterisk marks the reference point; we wish to move right. | |
| 228 ;; Since we are moving horizontally, the Y coordinate of the new | |
| 229 ;; location will be the same. The X coordinate can be such that it is | |
| 230 ;; just past the edge of the present window. Obviously, the new point | |
| 231 ;; will be inside window B. This in itself is fairly simple: using | |
| 232 ;; the result of `windmove-reference-loc' and `window-edges', all the | |
| 233 ;; necessary math can be performed. (Having said that, there is a | |
| 234 ;; good deal of room for off-by-one errors, and Emacs 19.34, at least, | |
| 235 ;; sometimes manifests a bug where two windows don't actually touch, | |
| 236 ;; so a larger skip is required.) The actual math here is done by | |
| 237 ;; `windmove-other-window-loc'. | |
| 238 ;; | |
| 239 ;; But we can't just pass the result of `windmove-other-window-loc' to | |
| 240 ;; `window-at' directly. Why not? Suppose a move would take us off | |
| 241 ;; the edge of the screen, say to the left. We want to give a | |
| 242 ;; descriptive error message to the user. Or, suppose that a move | |
| 243 ;; would place us in the minibuffer. What if the minibuffer is | |
| 244 ;; inactive? | |
| 245 ;; | |
| 246 ;; Actually, the whole subject of the minibuffer edge of the frame is | |
| 247 ;; rather messy. It turns out that with a sufficiently large delta, | |
| 248 ;; we can fly off the bottom edge of the frame and miss the minibuffer | |
| 249 ;; altogther. This, I think, is never right: if there's a minibuffer | |
| 250 ;; and you're not in it, and you move down, the minibuffer should be | |
| 251 ;; in your way. | |
| 252 ;; | |
| 253 ;; (By the way, I'm not totally sure that the code does the right | |
| 254 ;; thing in really weird cases, like a frame with no minibuffer.) | |
| 255 ;; | |
| 256 ;; So, what we need is some ways to do constraining and such. The | |
| 257 ;; early versions of windmove took a fairly simplistic approach to all | |
| 258 ;; this. When I added the wrap-around option, those internals had to | |
| 259 ;; be rewritten. After a *lot* of futzing around, I came up with a | |
| 260 ;; two-step process that I think is general enough to cover the | |
| 261 ;; relevant cases. (I'm not totally happy with having to pass the | |
| 262 ;; window variable as deep as I do, but we can't have everything.) | |
| 263 ;; | |
| 264 ;; In the first phase, we make sure that the new location is sane. | |
| 265 ;; "Sane" means that we can only fall of the edge of the frame in the | |
| 266 ;; direction we're moving in, and that we don't miss the minibuffer if | |
|
30892
495502641770
(windmove) <defgroup>: Add :version.
Dave Love <fx@gnu.org>
parents:
27545
diff
changeset
|
267 ;; we're moving down and not already in the minibuffer. The function |
| 27545 | 268 ;; `windmove-constrain-loc-for-movement' takes care of all this. |
| 269 ;; | |
| 270 ;; Then, we handle the wraparound, if it's enabled. The function | |
| 271 ;; `windmove-wrap-loc-for-movement' takes coordinate values (both X | |
| 272 ;; and Y) that fall off the edge of the frame, and replaces them with | |
| 273 ;; values on the other side of the frame. It also has special | |
| 274 ;; minibuffer-handling code again, because we want to wrap through the | |
| 275 ;; minibuffer if it's not enabled. | |
| 276 ;; | |
| 277 ;; So, that's it. Seems to work. All of this work is done by the fun | |
| 278 ;; function `windmove-find-other-window'. | |
| 279 ;; | |
| 280 ;; So, now we have a window to move to (or nil if something's gone | |
| 281 ;; wrong). The function `windmove-do-window-select' is the main | |
| 282 ;; driver function: it actually does the `select-window'. It is | |
| 283 ;; called by four little convenience wrappers, `windmove-left', | |
| 284 ;; `windmove-up', `windmove-right', and `windmove-down', which make | |
| 285 ;; for convenient keybinding. | |
| 286 | |
| 287 | |
| 288 ;; Quick & dirty utility function to add two (x . y) coords. | |
| 289 (defun windmove-coord-add (coord1 coord2) | |
| 290 "Add the two coordinates. | |
| 291 Both COORD1 and COORD2 are coordinate cons pairs, (HPOS . VPOS). The | |
| 292 result is another coordinate cons pair." | |
| 293 (cons (+ (car coord1) (car coord2)) | |
| 294 (+ (cdr coord1) (cdr coord2)))) | |
| 295 | |
| 296 | |
| 297 (defun windmove-constrain-to-range (n min-n max-n) | |
| 298 "Ensure that N is between MIN-N and MAX-N inclusive by constraining. | |
| 299 If N is less than MIN-N, return MIN-N; if greater than MAX-N, return | |
| 300 MAX-N." | |
| 301 (max min-n (min n max-n))) | |
| 302 | |
| 303 (defun windmove-constrain-around-range (n min-n max-n) | |
| 304 "Ensure that N is between MIN-N and MAX-N inclusive by wrapping. | |
| 305 If N is less than MIN-N, return MAX-N; if greater than MAX-N, return | |
| 306 MIN-N." | |
| 307 (cond | |
| 308 ((< n min-n) max-n) | |
| 309 ((> n max-n) min-n) | |
| 310 (t n))) | |
| 311 | |
| 312 (defun windmove-frame-edges (window) | |
| 313 "Return (X-MIN Y-MIN X-MAX Y-MAX) for the frame containing WINDOW. | |
| 314 If WINDOW is nil, return the edges for the selected frame. | |
| 39588 | 315 \(X-MIN, Y-MIN) is the zero-based coordinate of the top-left corner |
| 27545 | 316 of the frame; (X-MAX, Y-MAX) is the zero-based coordinate of the |
| 317 bottom-right corner of the frame. | |
| 318 For example, if a frame has 76 rows and 181 columns, the return value | |
| 319 from `windmove-frame-edges' will be the list (0 0 180 75)." | |
|
51424
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
320 (let* ((frame (if window |
|
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
321 (window-frame window) |
|
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
322 (selected-frame))) |
|
57092
5f904f95d7fd
(windmove-frame-edges): Report coordinates of
Eli Zaretskii <eliz@gnu.org>
parents:
56587
diff
changeset
|
323 (top-left (window-edges (frame-first-window frame))) |
|
51424
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
324 (x-min (nth 0 top-left)) |
|
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
325 (y-min (nth 1 top-left)) |
|
57092
5f904f95d7fd
(windmove-frame-edges): Report coordinates of
Eli Zaretskii <eliz@gnu.org>
parents:
56587
diff
changeset
|
326 (x-max (1- (frame-width frame))) ; 1- for last row & col |
|
5f904f95d7fd
(windmove-frame-edges): Report coordinates of
Eli Zaretskii <eliz@gnu.org>
parents:
56587
diff
changeset
|
327 (y-max (1- (frame-height frame)))) |
|
51424
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
328 (list x-min y-min x-max y-max))) |
| 27545 | 329 |
| 330 ;; it turns out that constraining is always a good thing, even when | |
| 331 ;; wrapping is going to happen. this is because: | |
| 332 ;; first, since we disallow exotic diagonal-around-a-corner type | |
| 333 ;; movements, so we can always fix the unimportant direction (the one | |
| 334 ;; we're not moving in). | |
| 335 ;; second, if we're moving down and we're not in the minibuffer, then | |
| 336 ;; constraining the y coordinate to max-y is okay, because if that | |
| 337 ;; falls in the minibuffer and the minibuffer isn't active, that y | |
| 338 ;; coordinate will still be off the bottom of the frame as the | |
| 339 ;; wrapping function sees it and so will get wrapped around anyway. | |
| 340 (defun windmove-constrain-loc-for-movement (coord window dir) | |
| 341 "Constrain COORD so that it is reasonable for the given movement. | |
| 342 This involves two things: first, make sure that the \"off\" coordinate | |
| 343 -- the one not being moved on, e.g., y for horizontal movement -- is | |
| 344 within frame boundaries; second, if the movement is down and we're not | |
| 345 moving from the minibuffer, make sure that the y coordinate does not | |
| 346 exceed the frame max-y, so that we don't overshoot the minibuffer | |
| 347 accidentally. WINDOW is the window that movement is relative to; DIR | |
| 348 is the direction of the movement, one of `left', `up', `right', | |
| 349 or `down'. | |
| 350 Returns the constrained coordinate." | |
| 351 (let ((frame-edges (windmove-frame-edges window)) | |
| 352 (in-minibuffer (window-minibuffer-p window))) | |
| 353 (let ((min-x (nth 0 frame-edges)) | |
| 354 (min-y (nth 1 frame-edges)) | |
| 355 (max-x (nth 2 frame-edges)) | |
| 356 (max-y (nth 3 frame-edges))) | |
| 357 (let ((new-x | |
| 358 (if (memq dir '(up down)) ; vertical movement | |
| 359 (windmove-constrain-to-range (car coord) min-x max-x) | |
| 360 (car coord))) | |
| 361 (new-y | |
| 362 (if (or (memq dir '(left right)) ; horizontal movement | |
| 363 (and (eq dir 'down) | |
| 364 (not in-minibuffer))) ; don't miss minibuffer | |
| 365 ;; (technically, we shouldn't constrain on min-y in the | |
| 366 ;; second case, but this shouldn't do any harm on a | |
| 367 ;; down movement.) | |
| 368 (windmove-constrain-to-range (cdr coord) min-y max-y) | |
| 369 (cdr coord)))) | |
| 370 (cons new-x new-y))))) | |
| 371 | |
| 372 ;; having constrained in the limited sense of windmove-constrain-loc- | |
| 373 ;; for-movement, the wrapping code is actually much simpler than it | |
| 374 ;; otherwise would be. the only complication is that we need to check | |
| 375 ;; if the minibuffer is active, and, if not, pretend that it's not | |
| 376 ;; even part of the frame. | |
| 377 (defun windmove-wrap-loc-for-movement (coord window dir) | |
| 378 "Takes the constrained COORD and wraps it around for the movement. | |
| 379 This makes an out-of-range x or y coordinate and wraps it around the | |
| 380 frame, giving a coordinate (hopefully) in the window on the other edge | |
| 381 of the frame. WINDOW is the window that movement is relative to (nil | |
| 382 means the currently selected window); DIR is the direction of the | |
| 383 movement, one of `left', `up', `right',or `down'. | |
| 384 Returns the wrapped coordinate." | |
| 385 (let* ((frame-edges (windmove-frame-edges window)) | |
| 386 (frame-minibuffer (minibuffer-window (if window | |
| 387 (window-frame window) | |
| 388 (selected-frame)))) | |
| 389 (minibuffer-active (minibuffer-window-active-p | |
| 390 frame-minibuffer))) | |
| 391 (let ((min-x (nth 0 frame-edges)) | |
| 392 (min-y (nth 1 frame-edges)) | |
| 393 (max-x (nth 2 frame-edges)) | |
| 394 (max-y (if (not minibuffer-active) | |
| 395 (- (nth 3 frame-edges) | |
| 396 (window-height frame-minibuffer)) | |
| 397 (nth 3 frame-edges)))) | |
| 398 (cons | |
| 399 (windmove-constrain-around-range (car coord) min-x max-x) | |
| 400 (windmove-constrain-around-range (cdr coord) min-y max-y))))) | |
| 401 | |
| 402 | |
| 403 ;; This calculates the reference location in the current window: the | |
| 404 ;; frame-based (x . y) of either point, the top-left, or the | |
| 405 ;; bottom-right of the window, depending on ARG. | |
| 406 (defun windmove-reference-loc (&optional arg window) | |
| 407 "Return the reference location for directional window selection. | |
| 408 Return a coordinate (HPOS . VPOS) that is frame-based. If ARG is nil | |
| 409 or not supplied, the reference point is the buffer's point in the | |
| 410 currently-selected window, or WINDOW if supplied; otherwise, it is the | |
| 411 top-left or bottom-right corner of the selected window, or WINDOW if | |
| 412 supplied, if ARG is greater or smaller than zero, respectively." | |
| 413 (let ((effective-arg (if (null arg) 0 (prefix-numeric-value arg))) | |
|
51424
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
414 (edges (window-inside-edges window))) |
| 27545 | 415 (let ((top-left (cons (nth 0 edges) |
| 416 (nth 1 edges))) | |
|
51424
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
417 ;; Subtracting 1 converts the edge to the last column or line |
|
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
418 ;; within the window. |
| 27545 | 419 (bottom-right (cons (- (nth 2 edges) 1) |
|
51424
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
420 (- (nth 3 edges) 1)))) |
| 27545 | 421 (cond |
| 422 ((> effective-arg 0) | |
| 423 top-left) | |
| 424 ((< effective-arg 0) | |
| 425 bottom-right) | |
| 426 ((= effective-arg 0) | |
| 427 (windmove-coord-add | |
| 428 top-left | |
|
65018
6c1c6712bea9
(windmove-coordinates-of-position): Remove.
Kim F. Storm <storm@cua.dk>
parents:
64762
diff
changeset
|
429 (let ((col-row |
|
6c1c6712bea9
(windmove-coordinates-of-position): Remove.
Kim F. Storm <storm@cua.dk>
parents:
64762
diff
changeset
|
430 (posn-col-row |
|
6c1c6712bea9
(windmove-coordinates-of-position): Remove.
Kim F. Storm <storm@cua.dk>
parents:
64762
diff
changeset
|
431 (posn-at-point (window-point window) window)))) |
|
6c1c6712bea9
(windmove-coordinates-of-position): Remove.
Kim F. Storm <storm@cua.dk>
parents:
64762
diff
changeset
|
432 (cons (- (car col-row) (window-hscroll window)) |
|
6c1c6712bea9
(windmove-coordinates-of-position): Remove.
Kim F. Storm <storm@cua.dk>
parents:
64762
diff
changeset
|
433 (cdr col-row))))))))) |
| 27545 | 434 |
| 435 ;; This uses the reference location in the current window (calculated | |
| 436 ;; by `windmove-reference-loc' above) to find a reference location | |
| 437 ;; that will hopefully be in the window we want to move to. | |
| 438 (defun windmove-other-window-loc (dir &optional arg window) | |
| 439 "Return a location in the window to be moved to. | |
| 440 Return value is a frame-based (HPOS . VPOS) value that should be moved | |
| 441 to. DIR is one of `left', `up', `right', or `down'; an optional ARG | |
| 442 is handled as by `windmove-reference-loc'; WINDOW is the window that | |
| 443 movement is relative to." | |
| 444 (let ((edges (window-edges window)) ; edges: (x0, y0, x1, y1) | |
| 445 (refpoint (windmove-reference-loc arg window))) ; (x . y) | |
| 446 (cond | |
| 447 ((eq dir 'left) | |
| 448 (cons (- (nth 0 edges) | |
| 449 windmove-window-distance-delta) | |
| 450 (cdr refpoint))) ; (x0-d, y) | |
| 451 ((eq dir 'up) | |
| 452 (cons (car refpoint) | |
| 453 (- (nth 1 edges) | |
| 454 windmove-window-distance-delta))) ; (x, y0-d) | |
| 455 ((eq dir 'right) | |
|
57092
5f904f95d7fd
(windmove-frame-edges): Report coordinates of
Eli Zaretskii <eliz@gnu.org>
parents:
56587
diff
changeset
|
456 (cons (+ (1- (nth 2 edges)) ; -1 to get actual max x |
| 27545 | 457 windmove-window-distance-delta) |
|
57092
5f904f95d7fd
(windmove-frame-edges): Report coordinates of
Eli Zaretskii <eliz@gnu.org>
parents:
56587
diff
changeset
|
458 (cdr refpoint))) ; (x1+d-1, y) |
|
5f904f95d7fd
(windmove-frame-edges): Report coordinates of
Eli Zaretskii <eliz@gnu.org>
parents:
56587
diff
changeset
|
459 ((eq dir 'down) ; -1 to get actual max y |
| 27545 | 460 (cons (car refpoint) |
|
57092
5f904f95d7fd
(windmove-frame-edges): Report coordinates of
Eli Zaretskii <eliz@gnu.org>
parents:
56587
diff
changeset
|
461 (+ (1- (nth 3 edges)) |
|
5f904f95d7fd
(windmove-frame-edges): Report coordinates of
Eli Zaretskii <eliz@gnu.org>
parents:
56587
diff
changeset
|
462 windmove-window-distance-delta))) ; (x, y1+d-1) |
| 27545 | 463 (t (error "Invalid direction of movement: %s" dir))))) |
| 464 | |
| 465 (defun windmove-find-other-window (dir &optional arg window) | |
| 466 "Return the window object in direction DIR. | |
| 467 DIR, ARG, and WINDOW are handled as by `windmove-other-window-loc'." | |
| 468 (let* ((actual-current-window (or window (selected-window))) | |
| 469 (raw-other-window-loc | |
| 470 (windmove-other-window-loc dir arg actual-current-window)) | |
| 471 (constrained-other-window-loc | |
| 472 (windmove-constrain-loc-for-movement raw-other-window-loc | |
| 473 actual-current-window | |
| 474 dir)) | |
| 475 (other-window-loc | |
| 476 (if windmove-wrap-around | |
| 477 (windmove-wrap-loc-for-movement constrained-other-window-loc | |
| 478 actual-current-window | |
| 479 dir) | |
| 480 constrained-other-window-loc))) | |
| 481 (window-at (car other-window-loc) | |
| 482 (cdr other-window-loc)))) | |
| 483 | |
| 484 | |
| 485 ;; Selects the window that's hopefully at the location returned by | |
| 486 ;; `windmove-other-window-loc', or screams if there's no window there. | |
| 487 (defun windmove-do-window-select (dir &optional arg window) | |
|
30892
495502641770
(windmove) <defgroup>: Add :version.
Dave Love <fx@gnu.org>
parents:
27545
diff
changeset
|
488 "Move to the window at direction DIR. |
| 27545 | 489 DIR, ARG, and WINDOW are handled as by `windmove-other-window-loc'. |
| 490 If no window is at direction DIR, an error is signaled." | |
| 491 (let ((other-window (windmove-find-other-window dir arg window))) | |
| 492 (cond ((null other-window) | |
|
51424
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
493 (error "No window %s from selected window" dir)) |
| 27545 | 494 ((and (window-minibuffer-p other-window) |
| 495 (not (minibuffer-window-active-p other-window))) | |
|
51424
26d468be5b3c
(windmove-reference-loc, windmove-frame-edges): Use window-inside-edges.
Richard M. Stallman <rms@gnu.org>
parents:
45166
diff
changeset
|
496 (error "Minibuffer is inactive")) |
| 27545 | 497 (t |
| 498 (select-window other-window))))) | |
| 499 | |
| 500 | |
| 501 ;;; end-user functions | |
| 502 ;; these are all simple interactive wrappers to `windmove-do- | |
| 503 ;; window-select', meant to be bound to keys. | |
| 504 | |
| 505 ;;;###autoload | |
| 506 (defun windmove-left (&optional arg) | |
| 507 "Select the window to the left of the current one. | |
| 508 With no prefix argument, or with prefix argument equal to zero, | |
| 509 \"left\" is relative to the position of point in the window; otherwise | |
| 510 it is relative to the top edge (for positive ARG) or the bottom edge | |
| 39588 | 511 \(for negative ARG) of the current window. |
| 27545 | 512 If no window is at the desired location, an error is signaled." |
| 513 (interactive "P") | |
| 514 (windmove-do-window-select 'left arg)) | |
| 515 | |
| 516 ;;;###autoload | |
| 517 (defun windmove-up (&optional arg) | |
| 518 "Select the window above the current one. | |
| 519 With no prefix argument, or with prefix argument equal to zero, \"up\" | |
| 520 is relative to the position of point in the window; otherwise it is | |
| 521 relative to the left edge (for positive ARG) or the right edge (for | |
| 522 negative ARG) of the current window. | |
| 523 If no window is at the desired location, an error is signaled." | |
| 524 (interactive "P") | |
| 525 (windmove-do-window-select 'up arg)) | |
| 526 | |
| 527 ;;;###autoload | |
| 528 (defun windmove-right (&optional arg) | |
| 529 "Select the window to the right of the current one. | |
| 530 With no prefix argument, or with prefix argument equal to zero, | |
| 531 \"right\" is relative to the position of point in the window; | |
| 532 otherwise it is relative to the top edge (for positive ARG) or the | |
| 533 bottom edge (for negative ARG) of the current window. | |
| 534 If no window is at the desired location, an error is signaled." | |
| 535 (interactive "P") | |
| 536 (windmove-do-window-select 'right arg)) | |
| 537 | |
| 538 ;;;###autoload | |
| 539 (defun windmove-down (&optional arg) | |
| 540 "Select the window below the current one. | |
| 541 With no prefix argument, or with prefix argument equal to zero, | |
| 542 \"down\" is relative to the position of point in the window; otherwise | |
| 543 it is relative to the left edge (for positive ARG) or the right edge | |
| 39588 | 544 \(for negative ARG) of the current window. |
| 27545 | 545 If no window is at the desired location, an error is signaled." |
| 546 (interactive "P") | |
| 547 (windmove-do-window-select 'down arg)) | |
| 548 | |
| 549 | |
| 550 ;;; set up keybindings | |
| 551 ;; Idea for this function is from iswitchb.el, by Stephen Eglen | |
| 552 ;; (stephen@cns.ed.ac.uk). | |
| 553 ;; I don't think these bindings will work on non-X terminals; you | |
| 554 ;; probably want to use different bindings in that case. | |
| 555 | |
| 556 ;;;###autoload | |
|
45166
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
557 (defun windmove-default-keybindings (&optional modifier) |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
558 "Set up keybindings for `windmove'. |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
559 Keybindings are of the form MODIFIER-{left,right,up,down}. |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
560 Default MODIFIER is 'shift." |
| 27545 | 561 (interactive) |
|
45166
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
562 (unless modifier (setq modifier 'shift)) |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
563 (global-set-key (vector (list modifier 'left)) 'windmove-left) |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
564 (global-set-key (vector (list modifier 'right)) 'windmove-right) |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
565 (global-set-key (vector (list modifier 'up)) 'windmove-up) |
|
8de5fa67b6cb
(windmove-default-keybindings): Add optional parameter to allow using a
Juanma Barranquero <lekktu@gmail.com>
parents:
39588
diff
changeset
|
566 (global-set-key (vector (list modifier 'down)) 'windmove-down)) |
| 27545 | 567 |
| 568 | |
| 569 (provide 'windmove) | |
| 570 | |
| 571 ;;; windmove.el ends here |
