Commit | Line | Data |
---|---|---|
b50c87ee KH |
1 | ;;; pc-select.el --- emulate mark, cut, copy and paste from Motif |
2 | ;;; (or MAC GUI or MS-windoze (bah)) look-and-feel | |
3 | ;;; including key bindings. | |
215e89e5 | 4 | |
e7cec005 | 5 | ;; Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. |
215e89e5 RS |
6 | |
7 | ;; Author: Michael Staats <michael@thp.Uni-Duisburg.DE> | |
de986953 | 8 | ;; Keywords: convenience emulation |
215e89e5 RS |
9 | ;; Created: 26 Sep 1995 |
10 | ||
11 | ;; This file is part of GNU Emacs. | |
12 | ||
13 | ;; GNU Emacs is free software; you can redistribute it and/or modify | |
14 | ;; it under the terms of the GNU General Public License as published by | |
15 | ;; the Free Software Foundation; either version 2, or (at your option) | |
16 | ;; any later version. | |
17 | ||
18 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
19 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | ;; GNU General Public License for more details. | |
22 | ||
23 | ;; You should have received a copy of the GNU General Public License | |
b578f267 EN |
24 | ;; along with GNU Emacs; see the file COPYING. If not, write to the |
25 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
26 | ;; Boston, MA 02111-1307, USA. | |
215e89e5 RS |
27 | |
28 | ;;; Commentary: | |
b578f267 | 29 | |
215e89e5 RS |
30 | ;; This package emulates the mark, copy, cut and paste look-and-feel of motif |
31 | ;; programs (which is the same as the MAC gui and (sorry for that) MS-Windows). | |
32 | ;; It modifies the keybindings of the cursor keys and the next, prior, | |
33 | ;; home and end keys. They will modify mark-active. | |
34 | ;; You can still get the old behaviour of cursor moving with the | |
35 | ;; control sequences C-f, C-b, etc. | |
36 | ;; This package uses transient-mark-mode and | |
37 | ;; delete-selection-mode. | |
38 | ;; | |
13f5a20e | 39 | ;; In addition to that all key-bindings from the pc-mode are |
215e89e5 RS |
40 | ;; done here too (as suggested by RMS). |
41 | ;; | |
42 | ;; As I found out after I finished the first version, s-region.el tries | |
43 | ;; to do the same.... But my code is a little more complete and using | |
44 | ;; delete-selection-mode is very important for the look-and-feel. | |
45 | ;; Pete Forman <pete.forman@airgun.wg.waii.com> provided some motif | |
46 | ;; compliant keybindings which I added. I had to modify them a little | |
47 | ;; to add the -mark and -nomark functionality of cursor moving. | |
48 | ;; | |
49 | ;; Credits: | |
50 | ;; Many thanks to all who made comments. | |
51 | ;; Thanks to RMS and Ralf Muschall <prm@rz.uni-jena.de> for criticism. | |
52 | ;; Kevin Cutts <cutts@ukraine.corp.mot.com> added the beginning-of-buffer | |
53 | ;; and end-of-buffer functions which I modified a little. | |
54 | ;; David Biesack <sasdjb@unx.sas.com> suggested some more cleanup. | |
55 | ;; Thanks to Pete Forman <pete.forman@airgun.wg.waii.com> | |
56 | ;; for additional motif keybindings. | |
14dacacd RS |
57 | ;; Thanks to jvromans@squirrel.nl (Johan Vromans) for a bug report |
58 | ;; concerning setting of this-command. | |
83d1d58c | 59 | ;; Dan Nicolaescu <done@ece.arizona.ro> suggested suppressing the |
20c5a87d | 60 | ;; scroll-up/scroll-down error. |
b50c87ee | 61 | ;; Eli Barzilay (eli@cs.bgu.ac.il) suggested the sexps functions and |
13f5a20e | 62 | ;; keybindings. |
215e89e5 RS |
63 | ;; |
64 | ;; Ok, some details about the idea of pc-selection-mode: | |
65 | ;; | |
66 | ;; o The standard keys for moving around (right, left, up, down, home, end, | |
67 | ;; prior, next, called "move-keys" from now on) will always de-activate | |
68 | ;; the mark. | |
69 | ;; o If you press "Shift" together with the "move-keys", the region | |
70 | ;; you pass along is activated | |
71 | ;; o You have the copy, cut and paste functions (as in many other programs) | |
72 | ;; which will operate on the active region | |
73 | ;; It was not possible to bind them to C-v, C-x and C-c for obvious | |
74 | ;; emacs reasons. | |
75 | ;; They will be bound according to the "old" behaviour to S-delete (cut), | |
76 | ;; S-insert (paste) and C-insert (copy). These keys do the same in many | |
77 | ;; other programs. | |
20c5a87d | 78 | ;; |
215e89e5 | 79 | |
20c5a87d | 80 | ;;;; Customization: |
83d1d58c RS |
81 | (defgroup pc-select nil |
82 | "Emulate pc bindings." | |
83 | :prefix "pc-select" | |
f5f727f8 DN |
84 | :group 'editing-basics |
85 | :group 'convenience) | |
20c5a87d | 86 | |
83d1d58c | 87 | (defcustom pc-select-override-scroll-error t |
20c5a87d RS |
88 | "*Non-nil means don't generate error on scrolling past edge of buffer. |
89 | This variable applies in PC Selection mode only. | |
90 | The scroll commands normally generate an error if you try to scroll | |
91 | past the top or bottom of the buffer. This is annoying when selecting | |
92 | text with these commands. If you set this variable to non-nil, these | |
83d1d58c RS |
93 | errors are suppressed." |
94 | :type 'boolean | |
95 | :group 'pc-select) | |
215e89e5 | 96 | |
83d1d58c | 97 | (defcustom pc-select-selection-keys-only nil |
b50c87ee KH |
98 | "*Non-nil means only bind the basic selection keys when started. |
99 | Other keys that emulate pc-behavior will be untouched. | |
83d1d58c RS |
100 | This gives mostly Emacs-like behaviour with only the selection keys enabled." |
101 | :type 'boolean | |
102 | :group 'pc-select) | |
b50c87ee | 103 | |
83d1d58c RS |
104 | (defcustom pc-select-meta-moves-sexps nil |
105 | "*Non-nil means move sexp-wise with Meta key, otherwise move word-wise." | |
106 | :type 'boolean | |
107 | :group 'pc-select) | |
b50c87ee | 108 | |
215e89e5 RS |
109 | ;;;; |
110 | ;; misc | |
111 | ;;;; | |
112 | ||
113 | (provide 'pc-select) | |
114 | ||
115 | (defun copy-region-as-kill-nomark (beg end) | |
116 | "Save the region as if killed; but don't kill it; deactivate mark. | |
117 | If `interprogram-cut-function' is non-nil, also save the text for a window | |
20c5a87d RS |
118 | system cut and paste. |
119 | ||
215e89e5 RS |
120 | Deactivating mark is to avoid confusion with delete-selection-mode |
121 | and transient-mark-mode." | |
122 | (interactive "r") | |
123 | (copy-region-as-kill beg end) | |
124 | (setq mark-active nil) | |
125 | (message "Region saved")) | |
126 | ||
b50c87ee KH |
127 | (defun exchange-point-and-mark-nomark () |
128 | (interactive) | |
129 | (exchange-point-and-mark) | |
130 | (setq mark-active nil)) | |
131 | ||
215e89e5 RS |
132 | ;;;; |
133 | ;; non-interactive | |
134 | ;;;; | |
135 | (defun ensure-mark() | |
136 | ;; make sure mark is active | |
137 | ;; test if it is active, if it isn't, set it and activate it | |
2a811501 | 138 | (or mark-active (set-mark-command nil))) |
215e89e5 RS |
139 | |
140 | ;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
141 | ;;;;; forward and mark | |
142 | ;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
143 | ||
144 | (defun forward-char-mark (&optional arg) | |
145 | "Ensure mark is active; move point right ARG characters (left if ARG negative). | |
146 | On reaching end of buffer, stop and signal error." | |
147 | (interactive "p") | |
148 | (ensure-mark) | |
149 | (forward-char arg)) | |
150 | ||
151 | (defun forward-word-mark (&optional arg) | |
152 | "Ensure mark is active; move point right ARG words (backward if ARG is negative). | |
153 | Normally returns t. | |
154 | If an edge of the buffer is reached, point is left there | |
155 | and nil is returned." | |
156 | (interactive "p") | |
157 | (ensure-mark) | |
158 | (forward-word arg)) | |
159 | ||
20c5a87d RS |
160 | (defun forward-line-mark (&optional arg) |
161 | "Ensure mark is active; move cursor vertically down ARG lines." | |
162 | (interactive "p") | |
163 | (ensure-mark) | |
164 | (forward-line arg) | |
165 | (setq this-command 'forward-line) | |
166 | ) | |
167 | ||
b50c87ee KH |
168 | (defun forward-sexp-mark (&optional arg) |
169 | "Ensure mark is active; move forward across one balanced expression (sexp). | |
170 | With argument, do it that many times. Negative arg -N means | |
171 | move backward across N balanced expressions." | |
172 | (interactive "p") | |
173 | (ensure-mark) | |
174 | (forward-sexp arg)) | |
175 | ||
215e89e5 RS |
176 | (defun forward-paragraph-mark (&optional arg) |
177 | "Ensure mark is active; move forward to end of paragraph. | |
20c5a87d RS |
178 | With arg N, do it N times; negative arg -N means move backward N paragraphs. |
179 | ||
215e89e5 | 180 | A line which `paragraph-start' matches either separates paragraphs |
14dacacd | 181 | \(if `paragraph-separate' matches it also) or is the first line of a paragraph. |
215e89e5 RS |
182 | A paragraph end is the beginning of a line which is not part of the paragraph |
183 | to which the end of the previous line belongs, or the end of the buffer." | |
184 | (interactive "p") | |
185 | (ensure-mark) | |
186 | (forward-paragraph arg)) | |
20c5a87d | 187 | |
215e89e5 RS |
188 | (defun next-line-mark (&optional arg) |
189 | "Ensure mark is active; move cursor vertically down ARG lines. | |
190 | If there is no character in the target line exactly under the current column, | |
191 | the cursor is positioned after the character in that line which spans this | |
192 | column, or at the end of the line if it is not long enough. | |
193 | If there is no line in the buffer after this one, behavior depends on the | |
194 | value of `next-line-add-newlines'. If non-nil, it inserts a newline character | |
195 | to create a line, and moves the cursor to that line. Otherwise it moves the | |
196 | cursor to the end of the buffer \(if already at the end of the buffer, an error | |
20c5a87d RS |
197 | is signaled). |
198 | ||
215e89e5 RS |
199 | The command C-x C-n can be used to create |
200 | a semipermanent goal column to which this command always moves. | |
201 | Then it does not try to move vertically. This goal column is stored | |
202 | in `goal-column', which is nil when there is none." | |
203 | (interactive "p") | |
204 | (ensure-mark) | |
14dacacd RS |
205 | (next-line arg) |
206 | (setq this-command 'next-line)) | |
215e89e5 RS |
207 | |
208 | (defun end-of-line-mark (&optional arg) | |
209 | "Ensure mark is active; move point to end of current line. | |
210 | With argument ARG not nil or 1, move forward ARG - 1 lines first. | |
211 | If scan reaches end of buffer, stop there without error." | |
212 | (interactive "p") | |
213 | (ensure-mark) | |
14dacacd RS |
214 | (end-of-line arg) |
215 | (setq this-command 'end-of-line)) | |
215e89e5 | 216 | |
20c5a87d RS |
217 | (defun backward-line-mark (&optional arg) |
218 | "Ensure mark is active; move cursor vertically up ARG lines." | |
219 | (interactive "p") | |
220 | (ensure-mark) | |
221 | (if (null arg) | |
222 | (setq arg 1)) | |
223 | (forward-line (- arg)) | |
224 | (setq this-command 'forward-line) | |
225 | ) | |
226 | ||
215e89e5 RS |
227 | (defun scroll-down-mark (&optional arg) |
228 | "Ensure mark is active; scroll down ARG lines; or near full screen if no ARG. | |
229 | A near full screen is `next-screen-context-lines' less than a full screen. | |
230 | Negative ARG means scroll upward. | |
231 | When calling from a program, supply a number as argument or nil." | |
13f5a20e | 232 | (interactive "P") |
215e89e5 | 233 | (ensure-mark) |
2a811501 RS |
234 | (cond (pc-select-override-scroll-error |
235 | (condition-case nil (scroll-down arg) | |
236 | (beginning-of-buffer (goto-char (point-min))))) | |
237 | (t (scroll-down arg)))) | |
215e89e5 RS |
238 | |
239 | (defun end-of-buffer-mark (&optional arg) | |
240 | "Ensure mark is active; move point to the end of the buffer. | |
20c5a87d RS |
241 | With arg N, put point N/10 of the way from the end. |
242 | ||
215e89e5 | 243 | If the buffer is narrowed, this command uses the beginning and size |
20c5a87d RS |
244 | of the accessible part of the buffer. |
245 | ||
215e89e5 RS |
246 | Don't use this command in Lisp programs! |
247 | \(goto-char \(point-max)) is faster and avoids clobbering the mark." | |
248 | (interactive "P") | |
249 | (ensure-mark) | |
250 | (let ((size (- (point-max) (point-min)))) | |
251 | (goto-char (if arg | |
252 | (- (point-max) | |
253 | (if (> size 10000) | |
254 | ;; Avoid overflow for large buffer sizes! | |
255 | (* (prefix-numeric-value arg) | |
256 | (/ size 10)) | |
257 | (/ (* size (prefix-numeric-value arg)) 10))) | |
258 | (point-max)))) | |
259 | ;; If we went to a place in the middle of the buffer, | |
260 | ;; adjust it to the beginning of a line. | |
261 | (if arg (forward-line 1) | |
262 | ;; If the end of the buffer is not already on the screen, | |
263 | ;; then scroll specially to put it near, but not at, the bottom. | |
264 | (if (let ((old-point (point))) | |
265 | (save-excursion | |
266 | (goto-char (window-start)) | |
267 | (vertical-motion (window-height)) | |
268 | (< (point) old-point))) | |
269 | (progn | |
270 | (overlay-recenter (point)) | |
271 | (recenter -3))))) | |
272 | ||
273 | ;;;;;;;;; | |
274 | ;;;;; no mark | |
275 | ;;;;;;;;; | |
276 | ||
277 | (defun forward-char-nomark (&optional arg) | |
278 | "Deactivate mark; move point right ARG characters \(left if ARG negative). | |
279 | On reaching end of buffer, stop and signal error." | |
280 | (interactive "p") | |
281 | (setq mark-active nil) | |
282 | (forward-char arg)) | |
283 | ||
284 | (defun forward-word-nomark (&optional arg) | |
285 | "Deactivate mark; move point right ARG words \(backward if ARG is negative). | |
286 | Normally returns t. | |
287 | If an edge of the buffer is reached, point is left there | |
288 | and nil is returned." | |
289 | (interactive "p") | |
290 | (setq mark-active nil) | |
291 | (forward-word arg)) | |
292 | ||
20c5a87d RS |
293 | (defun forward-line-nomark (&optional arg) |
294 | "Deactivate mark; move cursor vertically down ARG lines." | |
295 | (interactive "p") | |
296 | (setq mark-active nil) | |
297 | (forward-line arg) | |
298 | (setq this-command 'forward-line) | |
299 | ) | |
300 | ||
b50c87ee KH |
301 | (defun forward-sexp-nomark (&optional arg) |
302 | "Deactivate mark; move forward across one balanced expression (sexp). | |
303 | With argument, do it that many times. Negative arg -N means | |
304 | move backward across N balanced expressions." | |
305 | (interactive "p") | |
306 | (setq mark-active nil) | |
307 | (forward-sexp arg)) | |
308 | ||
215e89e5 RS |
309 | (defun forward-paragraph-nomark (&optional arg) |
310 | "Deactivate mark; move forward to end of paragraph. | |
20c5a87d RS |
311 | With arg N, do it N times; negative arg -N means move backward N paragraphs. |
312 | ||
215e89e5 | 313 | A line which `paragraph-start' matches either separates paragraphs |
14dacacd | 314 | \(if `paragraph-separate' matches it also) or is the first line of a paragraph. |
215e89e5 RS |
315 | A paragraph end is the beginning of a line which is not part of the paragraph |
316 | to which the end of the previous line belongs, or the end of the buffer." | |
317 | (interactive "p") | |
318 | (setq mark-active nil) | |
319 | (forward-paragraph arg)) | |
320 | ||
321 | (defun next-line-nomark (&optional arg) | |
322 | "Deactivate mark; move cursor vertically down ARG lines. | |
323 | If there is no character in the target line exactly under the current column, | |
324 | the cursor is positioned after the character in that line which spans this | |
325 | column, or at the end of the line if it is not long enough. | |
326 | If there is no line in the buffer after this one, behavior depends on the | |
327 | value of `next-line-add-newlines'. If non-nil, it inserts a newline character | |
328 | to create a line, and moves the cursor to that line. Otherwise it moves the | |
329 | cursor to the end of the buffer (if already at the end of the buffer, an error | |
20c5a87d RS |
330 | is signaled). |
331 | ||
215e89e5 RS |
332 | The command C-x C-n can be used to create |
333 | a semipermanent goal column to which this command always moves. | |
334 | Then it does not try to move vertically. This goal column is stored | |
335 | in `goal-column', which is nil when there is none." | |
336 | (interactive "p") | |
337 | (setq mark-active nil) | |
14dacacd RS |
338 | (next-line arg) |
339 | (setq this-command 'next-line)) | |
215e89e5 RS |
340 | |
341 | (defun end-of-line-nomark (&optional arg) | |
342 | "Deactivate mark; move point to end of current line. | |
343 | With argument ARG not nil or 1, move forward ARG - 1 lines first. | |
344 | If scan reaches end of buffer, stop there without error." | |
345 | (interactive "p") | |
346 | (setq mark-active nil) | |
14dacacd RS |
347 | (end-of-line arg) |
348 | (setq this-command 'end-of-line)) | |
215e89e5 | 349 | |
20c5a87d RS |
350 | (defun backward-line-nomark (&optional arg) |
351 | "Deactivate mark; move cursor vertically up ARG lines." | |
352 | (interactive "p") | |
353 | (setq mark-active nil) | |
354 | (if (null arg) | |
355 | (setq arg 1)) | |
356 | (forward-line (- arg)) | |
357 | (setq this-command 'forward-line) | |
358 | ) | |
359 | ||
215e89e5 RS |
360 | (defun scroll-down-nomark (&optional arg) |
361 | "Deactivate mark; scroll down ARG lines; or near full screen if no ARG. | |
362 | A near full screen is `next-screen-context-lines' less than a full screen. | |
363 | Negative ARG means scroll upward. | |
364 | When calling from a program, supply a number as argument or nil." | |
365 | (interactive "P") | |
366 | (setq mark-active nil) | |
2a811501 RS |
367 | (cond (pc-select-override-scroll-error |
368 | (condition-case nil (scroll-down arg) | |
369 | (beginning-of-buffer (goto-char (point-min))))) | |
370 | (t (scroll-down arg)))) | |
215e89e5 RS |
371 | |
372 | (defun end-of-buffer-nomark (&optional arg) | |
373 | "Deactivate mark; move point to the end of the buffer. | |
20c5a87d RS |
374 | With arg N, put point N/10 of the way from the end. |
375 | ||
215e89e5 | 376 | If the buffer is narrowed, this command uses the beginning and size |
20c5a87d RS |
377 | of the accessible part of the buffer. |
378 | ||
215e89e5 | 379 | Don't use this command in Lisp programs! |
14dacacd | 380 | \(goto-char (point-max)) is faster and avoids clobbering the mark." |
215e89e5 RS |
381 | (interactive "P") |
382 | (setq mark-active nil) | |
383 | (let ((size (- (point-max) (point-min)))) | |
384 | (goto-char (if arg | |
385 | (- (point-max) | |
386 | (if (> size 10000) | |
387 | ;; Avoid overflow for large buffer sizes! | |
388 | (* (prefix-numeric-value arg) | |
389 | (/ size 10)) | |
390 | (/ (* size (prefix-numeric-value arg)) 10))) | |
391 | (point-max)))) | |
392 | ;; If we went to a place in the middle of the buffer, | |
393 | ;; adjust it to the beginning of a line. | |
394 | (if arg (forward-line 1) | |
395 | ;; If the end of the buffer is not already on the screen, | |
396 | ;; then scroll specially to put it near, but not at, the bottom. | |
397 | (if (let ((old-point (point))) | |
398 | (save-excursion | |
399 | (goto-char (window-start)) | |
400 | (vertical-motion (window-height)) | |
401 | (< (point) old-point))) | |
402 | (progn | |
403 | (overlay-recenter (point)) | |
404 | (recenter -3))))) | |
405 | ||
406 | ||
407 | ;;;;;;;;;;;;;;;;;;;; | |
408 | ;;;;;; backwards and mark | |
409 | ;;;;;;;;;;;;;;;;;;;; | |
410 | ||
411 | (defun backward-char-mark (&optional arg) | |
412 | "Ensure mark is active; move point left ARG characters (right if ARG negative). | |
413 | On attempt to pass beginning or end of buffer, stop and signal error." | |
414 | (interactive "p") | |
415 | (ensure-mark) | |
416 | (backward-char arg)) | |
417 | ||
418 | (defun backward-word-mark (&optional arg) | |
419 | "Ensure mark is active; move backward until encountering the end of a word. | |
420 | With argument, do this that many times." | |
421 | (interactive "p") | |
422 | (ensure-mark) | |
423 | (backward-word arg)) | |
424 | ||
b50c87ee KH |
425 | (defun backward-sexp-mark (&optional arg) |
426 | "Ensure mark is active; move backward across one balanced expression (sexp). | |
427 | With argument, do it that many times. Negative arg -N means | |
428 | move forward across N balanced expressions." | |
429 | (interactive "p") | |
430 | (ensure-mark) | |
431 | (backward-sexp arg)) | |
432 | ||
215e89e5 RS |
433 | (defun backward-paragraph-mark (&optional arg) |
434 | "Ensure mark is active; move backward to start of paragraph. | |
20c5a87d RS |
435 | With arg N, do it N times; negative arg -N means move forward N paragraphs. |
436 | ||
215e89e5 RS |
437 | A paragraph start is the beginning of a line which is a |
438 | `first-line-of-paragraph' or which is ordinary text and follows a | |
439 | paragraph-separating line; except: if the first real line of a | |
440 | paragraph is preceded by a blank line, the paragraph starts at that | |
20c5a87d RS |
441 | blank line. |
442 | ||
215e89e5 RS |
443 | See `forward-paragraph' for more information." |
444 | (interactive "p") | |
445 | (ensure-mark) | |
446 | (backward-paragraph arg)) | |
447 | ||
448 | (defun previous-line-mark (&optional arg) | |
449 | "Ensure mark is active; move cursor vertically up ARG lines. | |
450 | If there is no character in the target line exactly over the current column, | |
451 | the cursor is positioned after the character in that line which spans this | |
20c5a87d RS |
452 | column, or at the end of the line if it is not long enough. |
453 | ||
215e89e5 RS |
454 | The command C-x C-n can be used to create |
455 | a semipermanent goal column to which this command always moves. | |
20c5a87d RS |
456 | Then it does not try to move vertically. |
457 | ||
215e89e5 RS |
458 | If you are thinking of using this in a Lisp program, consider using |
459 | `forward-line' with a negative argument instead. It is usually easier | |
460 | to use and more reliable (no dependence on goal column, etc.)." | |
461 | (interactive "p") | |
462 | (ensure-mark) | |
14dacacd RS |
463 | (previous-line arg) |
464 | (setq this-command 'previous-line)) | |
215e89e5 RS |
465 | |
466 | (defun beginning-of-line-mark (&optional arg) | |
467 | "Ensure mark is active; move point to beginning of current line. | |
468 | With argument ARG not nil or 1, move forward ARG - 1 lines first. | |
469 | If scan reaches end of buffer, stop there without error." | |
470 | (interactive "p") | |
471 | (ensure-mark) | |
472 | (beginning-of-line arg)) | |
473 | ||
474 | ||
475 | (defun scroll-up-mark (&optional arg) | |
476 | "Ensure mark is active; scroll upward ARG lines; or near full screen if no ARG. | |
477 | A near full screen is `next-screen-context-lines' less than a full screen. | |
478 | Negative ARG means scroll downward. | |
479 | When calling from a program, supply a number as argument or nil." | |
480 | (interactive "P") | |
481 | (ensure-mark) | |
2a811501 RS |
482 | (cond (pc-select-override-scroll-error |
483 | (condition-case nil (scroll-up arg) | |
484 | (end-of-buffer (goto-char (point-max))))) | |
485 | (t (scroll-up arg)))) | |
215e89e5 RS |
486 | |
487 | (defun beginning-of-buffer-mark (&optional arg) | |
488 | "Ensure mark is active; move point to the beginning of the buffer. | |
20c5a87d RS |
489 | With arg N, put point N/10 of the way from the beginning. |
490 | ||
215e89e5 | 491 | If the buffer is narrowed, this command uses the beginning and size |
20c5a87d RS |
492 | of the accessible part of the buffer. |
493 | ||
215e89e5 RS |
494 | Don't use this command in Lisp programs! |
495 | \(goto-char (p\oint-min)) is faster and avoids clobbering the mark." | |
496 | (interactive "P") | |
13f5a20e | 497 | (ensure-mark) |
215e89e5 RS |
498 | (let ((size (- (point-max) (point-min)))) |
499 | (goto-char (if arg | |
500 | (+ (point-min) | |
501 | (if (> size 10000) | |
502 | ;; Avoid overflow for large buffer sizes! | |
503 | (* (prefix-numeric-value arg) | |
504 | (/ size 10)) | |
505 | (/ (+ 10 (* size (prefix-numeric-value arg))) 10))) | |
506 | (point-min)))) | |
507 | (if arg (forward-line 1))) | |
508 | ||
509 | ;;;;;;;; | |
510 | ;;; no mark | |
511 | ;;;;;;;; | |
512 | ||
513 | (defun backward-char-nomark (&optional arg) | |
514 | "Deactivate mark; move point left ARG characters (right if ARG negative). | |
515 | On attempt to pass beginning or end of buffer, stop and signal error." | |
516 | (interactive "p") | |
517 | (setq mark-active nil) | |
518 | (backward-char arg)) | |
519 | ||
520 | (defun backward-word-nomark (&optional arg) | |
521 | "Deactivate mark; move backward until encountering the end of a word. | |
522 | With argument, do this that many times." | |
523 | (interactive "p") | |
524 | (setq mark-active nil) | |
525 | (backward-word arg)) | |
526 | ||
b50c87ee KH |
527 | (defun backward-sexp-nomark (&optional arg) |
528 | "Deactivate mark; move backward across one balanced expression (sexp). | |
529 | With argument, do it that many times. Negative arg -N means | |
530 | move forward across N balanced expressions." | |
531 | (interactive "p") | |
532 | (setq mark-active nil) | |
533 | (backward-sexp arg)) | |
534 | ||
215e89e5 RS |
535 | (defun backward-paragraph-nomark (&optional arg) |
536 | "Deactivate mark; move backward to start of paragraph. | |
20c5a87d RS |
537 | With arg N, do it N times; negative arg -N means move forward N paragraphs. |
538 | ||
215e89e5 RS |
539 | A paragraph start is the beginning of a line which is a |
540 | `first-line-of-paragraph' or which is ordinary text and follows a | |
541 | paragraph-separating line; except: if the first real line of a | |
542 | paragraph is preceded by a blank line, the paragraph starts at that | |
20c5a87d RS |
543 | blank line. |
544 | ||
215e89e5 RS |
545 | See `forward-paragraph' for more information." |
546 | (interactive "p") | |
547 | (setq mark-active nil) | |
548 | (backward-paragraph arg)) | |
549 | ||
550 | (defun previous-line-nomark (&optional arg) | |
551 | "Deactivate mark; move cursor vertically up ARG lines. | |
552 | If there is no character in the target line exactly over the current column, | |
553 | the cursor is positioned after the character in that line which spans this | |
20c5a87d RS |
554 | column, or at the end of the line if it is not long enough. |
555 | ||
215e89e5 RS |
556 | The command C-x C-n can be used to create |
557 | a semipermanent goal column to which this command always moves. | |
558 | Then it does not try to move vertically." | |
559 | (interactive "p") | |
560 | (setq mark-active nil) | |
14dacacd RS |
561 | (previous-line arg) |
562 | (setq this-command 'previous-line)) | |
215e89e5 RS |
563 | |
564 | (defun beginning-of-line-nomark (&optional arg) | |
565 | "Deactivate mark; move point to beginning of current line. | |
566 | With argument ARG not nil or 1, move forward ARG - 1 lines first. | |
567 | If scan reaches end of buffer, stop there without error." | |
568 | (interactive "p") | |
569 | (setq mark-active nil) | |
570 | (beginning-of-line arg)) | |
571 | ||
572 | (defun scroll-up-nomark (&optional arg) | |
573 | "Deactivate mark; scroll upward ARG lines; or near full screen if no ARG. | |
574 | A near full screen is `next-screen-context-lines' less than a full screen. | |
575 | Negative ARG means scroll downward. | |
576 | When calling from a program, supply a number as argument or nil." | |
577 | (interactive "P") | |
578 | (setq mark-active nil) | |
2a811501 RS |
579 | (cond (pc-select-override-scroll-error |
580 | (condition-case nil (scroll-up arg) | |
581 | (end-of-buffer (goto-char (point-max))))) | |
582 | (t (scroll-up arg)))) | |
215e89e5 RS |
583 | |
584 | (defun beginning-of-buffer-nomark (&optional arg) | |
585 | "Deactivate mark; move point to the beginning of the buffer. | |
20c5a87d RS |
586 | With arg N, put point N/10 of the way from the beginning. |
587 | ||
215e89e5 | 588 | If the buffer is narrowed, this command uses the beginning and size |
20c5a87d RS |
589 | of the accessible part of the buffer. |
590 | ||
215e89e5 | 591 | Don't use this command in Lisp programs! |
14dacacd | 592 | \(goto-char (point-min)) is faster and avoids clobbering the mark." |
215e89e5 RS |
593 | (interactive "P") |
594 | (setq mark-active nil) | |
595 | (let ((size (- (point-max) (point-min)))) | |
596 | (goto-char (if arg | |
597 | (+ (point-min) | |
598 | (if (> size 10000) | |
599 | ;; Avoid overflow for large buffer sizes! | |
600 | (* (prefix-numeric-value arg) | |
601 | (/ size 10)) | |
602 | (/ (+ 10 (* size (prefix-numeric-value arg))) 10))) | |
603 | (point-min)))) | |
604 | (if arg (forward-line 1))) | |
605 | ||
3eeb7b9f | 606 | ;;;###autoload |
215e89e5 | 607 | (defun pc-selection-mode () |
20c5a87d RS |
608 | "Change mark behaviour to emulate Motif, MAC or MS-Windows cut and paste style. |
609 | ||
610 | This mode enables Delete Selection mode and Transient Mark mode. | |
611 | ||
612 | The arrow keys (and others) are bound to new functions | |
613 | which modify the status of the mark. | |
614 | ||
615 | The ordinary arrow keys disable the mark. | |
616 | The shift-arrow keys move, leaving the mark behind. | |
617 | ||
618 | C-LEFT and C-RIGHT move back or forward one word, disabling the mark. | |
619 | S-C-LEFT and S-C-RIGHT move back or forward one word, leaving the mark behind. | |
620 | ||
b50c87ee KH |
621 | M-LEFT and M-RIGHT move back or forward one word or sexp, disabling the mark. |
622 | S-M-LEFT and S-M-RIGHT move back or forward one word or sexp, leaving the mark | |
623 | behind. To control wether these keys move word-wise or sexp-wise set the | |
624 | variable pc-select-meta-moves-sexps after loading pc-select.el but before | |
625 | turning pc-selection-mode on. | |
626 | ||
20c5a87d RS |
627 | C-DOWN and C-UP move back or forward a paragraph, disabling the mark. |
628 | S-C-DOWN and S-C-UP move back or forward a paragraph, leaving the mark behind. | |
629 | ||
630 | HOME moves to beginning of line, disabling the mark. | |
631 | S-HOME moves to beginning of line, leaving the mark behind. | |
632 | With Ctrl or Meta, these keys move to beginning of buffer instead. | |
633 | ||
634 | END moves to end of line, disabling the mark. | |
635 | S-END moves to end of line, leaving the mark behind. | |
636 | With Ctrl or Meta, these keys move to end of buffer instead. | |
637 | ||
638 | PRIOR or PAGE-UP scrolls and disables the mark. | |
639 | S-PRIOR or S-PAGE-UP scrolls and leaves the mark behind. | |
640 | ||
641 | S-DELETE kills the region (`kill-region'). | |
642 | S-INSERT yanks text from the kill ring (`yank'). | |
643 | C-INSERT copies the region into the kill ring (`copy-region-as-kill'). | |
644 | ||
b50c87ee KH |
645 | In addition, certain other PC bindings are imitated (to avoid this, set |
646 | the variable pc-select-selection-keys-only to t after loading pc-select.el | |
647 | but before calling pc-selection-mode): | |
20c5a87d RS |
648 | |
649 | F6 other-window | |
650 | DELETE delete-char | |
651 | C-DELETE kill-line | |
652 | M-DELETE kill-word | |
653 | C-M-DELETE kill-sexp | |
654 | C-BACKSPACE backward-kill-word | |
655 | M-BACKSPACE undo" | |
656 | ||
215e89e5 RS |
657 | (interactive) |
658 | ;; | |
659 | ;; keybindings | |
660 | ;; | |
661 | ||
662 | ;; This is to avoid confusion with the delete-selection-mode | |
663 | ;; On simple displays you can't see that a region is active and | |
b50c87ee KH |
664 | ;; will be deleted on the next keypress. IMHO especially for |
665 | ;; copy-region-as-kill this is confusing. | |
666 | ;; The same goes for exchange-point-and-mark | |
13f5a20e SS |
667 | (define-key global-map "\M-w" 'copy-region-as-kill-nomark) |
668 | (define-key global-map "\C-x\C-x" 'exchange-point-and-mark-nomark) | |
a7acbbe4 | 669 | ;; The following keybindings are for standard ISO keyboards |
215e89e5 RS |
670 | ;; as they are used with IBM compatible PCs, IBM RS/6000, |
671 | ;; MACs, many X-Stations and probably more | |
672 | (define-key global-map [S-right] 'forward-char-mark) | |
673 | (define-key global-map [right] 'forward-char-nomark) | |
674 | (define-key global-map [C-S-right] 'forward-word-mark) | |
675 | (define-key global-map [C-right] 'forward-word-nomark) | |
b50c87ee KH |
676 | (define-key global-map [S-left] 'backward-char-mark) |
677 | (define-key global-map [left] 'backward-char-nomark) | |
678 | (define-key global-map [C-S-left] 'backward-word-mark) | |
679 | (define-key global-map [C-left] 'backward-word-nomark) | |
680 | (cond (pc-select-meta-moves-sexps | |
681 | (define-key global-map [M-S-right] 'forward-sexp-mark) | |
682 | (define-key global-map [M-right] 'forward-sexp-nomark) | |
683 | (define-key global-map [M-S-left] 'backward-sexp-mark) | |
684 | (define-key global-map [M-left] 'backward-sexp-nomark)) | |
685 | (t | |
686 | (define-key global-map [M-S-right] 'forward-word-mark) | |
687 | (define-key global-map [M-right] 'forward-word-nomark) | |
688 | (define-key global-map [M-S-left] 'backward-word-mark) | |
689 | (define-key global-map [M-left] 'backward-word-nomark))) | |
215e89e5 RS |
690 | |
691 | (define-key global-map [S-down] 'next-line-mark) | |
692 | (define-key global-map [down] 'next-line-nomark) | |
693 | ||
694 | (define-key global-map [S-end] 'end-of-line-mark) | |
695 | (define-key global-map [end] 'end-of-line-nomark) | |
696 | (global-set-key [S-C-end] 'end-of-buffer-mark) | |
697 | (global-set-key [C-end] 'end-of-buffer-nomark) | |
14dacacd RS |
698 | (global-set-key [S-M-end] 'end-of-buffer-mark) |
699 | (global-set-key [M-end] 'end-of-buffer-nomark) | |
215e89e5 RS |
700 | |
701 | (define-key global-map [S-next] 'scroll-up-mark) | |
702 | (define-key global-map [next] 'scroll-up-nomark) | |
703 | ||
215e89e5 RS |
704 | (define-key global-map [S-up] 'previous-line-mark) |
705 | (define-key global-map [up] 'previous-line-nomark) | |
706 | ||
707 | (define-key global-map [S-home] 'beginning-of-line-mark) | |
708 | (define-key global-map [home] 'beginning-of-line-nomark) | |
709 | (global-set-key [S-C-home] 'beginning-of-buffer-mark) | |
710 | (global-set-key [C-home] 'beginning-of-buffer-nomark) | |
14dacacd RS |
711 | (global-set-key [S-M-home] 'beginning-of-buffer-mark) |
712 | (global-set-key [M-home] 'beginning-of-buffer-nomark) | |
215e89e5 | 713 | |
20c5a87d RS |
714 | (define-key global-map [M-S-down] 'forward-line-mark) |
715 | (define-key global-map [M-down] 'forward-line-nomark) | |
716 | (define-key global-map [M-S-up] 'backward-line-mark) | |
717 | (define-key global-map [M-up] 'backward-line-nomark) | |
718 | ||
b50c87ee KH |
719 | (define-key global-map [S-prior] 'scroll-down-mark) |
720 | (define-key global-map [prior] 'scroll-down-nomark) | |
721 | ||
722 | ;; Next four lines are from Pete Forman. | |
723 | (global-set-key [C-down] 'forward-paragraph-nomark) ; KNextPara cDn | |
724 | (global-set-key [C-up] 'backward-paragraph-nomark) ; KPrevPara cUp | |
215e89e5 | 725 | (global-set-key [S-C-down] 'forward-paragraph-mark) |
13f5a20e | 726 | (global-set-key [S-C-up] 'backward-paragraph-mark) |
215e89e5 | 727 | |
b50c87ee | 728 | (or pc-select-selection-keys-only |
13f5a20e | 729 | (progn |
58e4f61d EZ |
730 | ;; We are behaving like normal-erase-is-backspace-mode, so |
731 | ;; say so explicitly. | |
732 | (setq-default normal-erase-is-backspace t) | |
733 | (normal-erase-is-backspace-mode 1) | |
b50c87ee KH |
734 | (define-key global-map [S-insert] 'yank) |
735 | (define-key global-map [C-insert] 'copy-region-as-kill) | |
736 | (define-key global-map [S-delete] 'kill-region) | |
737 | ||
738 | ;; The following bindings are useful on Sun Type 3 keyboards | |
739 | ;; They implement the Get-Delete-Put (copy-cut-paste) | |
740 | ;; functions from sunview on the L6, L8 and L10 keys | |
13f5a20e | 741 | ;; Sam Steingold <sds@gnu.org> says that f16 is copy and f18 is paste. |
b50c87ee KH |
742 | (define-key global-map [f16] 'copy-region-as-kill) |
743 | (define-key global-map [f18] 'yank) | |
744 | (define-key global-map [f20] 'kill-region) | |
745 | ||
746 | ;; The following bindings are from Pete Forman. | |
747 | (global-set-key [f6] 'other-window) ; KNextPane F6 | |
b50c87ee | 748 | (global-set-key [C-delete] 'kill-line) ; KEraseEndLine cDel |
e7cec005 | 749 | (global-set-key "\M-\d" 'undo) ; KUndo aBS |
b50c87ee | 750 | |
58e4f61d | 751 | ;; The following binding is taken from pc-mode.el |
b50c87ee | 752 | ;; as suggested by RMS. |
58e4f61d | 753 | ;; I only used the one that is not covered above. |
b50c87ee | 754 | (global-set-key [C-M-delete] 'kill-sexp) |
b50c87ee KH |
755 | ;; Next line proposed by Eli Barzilay |
756 | (global-set-key [C-escape] 'electric-buffer-list))) | |
13f5a20e | 757 | ;; |
215e89e5 RS |
758 | ;; setup |
759 | ;; | |
b50c87ee KH |
760 | ;; Next line proposed by Eli Barzilay |
761 | (setq highlight-nonselected-windows nil) | |
215e89e5 RS |
762 | (setq transient-mark-mode t) |
763 | (setq mark-even-if-inactive t) | |
20c5a87d | 764 | (delete-selection-mode 1) |
2a811501 | 765 | ) |
83d1d58c RS |
766 | |
767 | ;;;###autoload | |
768 | (defcustom pc-selection-mode nil | |
769 | "Toggle PC Selection mode. | |
770 | Change mark behaviour to emulate Motif, MAC or MS-Windows cut and paste style, | |
771 | and cursor movement commands. | |
772 | This mode enables Delete Selection mode and Transient Mark mode. | |
773 | You must modify via \\[customize] for this variable to have an effect." | |
774 | :set (lambda (symbol value) | |
775 | (if value (pc-selection-mode))) | |
776 | :type 'boolean | |
777 | :group 'pc-select | |
778 | :require 'pc-select) | |
779 | ||
215e89e5 | 780 | ;;; pc-select.el ends here |