changelog shortlog tags changeset files revisions annotate raw

cua.el

changeset 66: 5b737eefe5ea
author: kim.vanwyk
date: Wed Nov 10 15:19:03 2010 +0200 (18 months ago)
permissions: -rw-r--r--
description: Adding CSharp Mode and Google Weather
1;;; cua.el --- emulate CUA key bindings
2
3;; Copyright (C) 1997-2001 Free Software Foundation, Inc.
4
5;; Author: Kim F. Storm <storm@cua.dk>
6;; Maintainer: Kim F. Storm <storm@cua.dk>
7;; Location: http://www.cua.dk/
8;; Keywords: keyboard CUA
9;; Version: 2.10
10
11;; This file is not [yet] part of GNU Emacs, but is distributed under
12;; the same terms.
13
14;; GNU Emacs is free software; you can redistribute it and/or modify
15;; it under the terms of the GNU General Public License as published by
16;; the Free Software Foundation; either version 2, or (at your option)
17;; any later version.
18
19;; GNU Emacs is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
25;; along with GNU Emacs; see the file COPYING. If not, write to the
26;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27;; Boston, MA 02111-1307, USA.
28
29
30;; Note:
31;; This file used to be named cua-mode.el; if you or your users
32;; are using a previous release under that name, you can continue
33;; naming the file cua-mode.el; provided you also continue using
34;; (require 'cua-mode) before activation [see below].
35
36
37;;; Activation:
38
39;; To activate CUA-mode, copy the cua.el file into a directory
40;; on the load-path, byte-compile it (using M-x byte-compile-file),
41;; and place the following lines into your .emacs:
42;;
43;; (require 'cua)
44;; (CUA-mode t)
45;;
46;; If you don't want to modify the bindings of C-z C-x C-c C-v, but still
47;; want the CUA enhanced functionality for the standard emacs bindings of
48;; undo, kill, copy, and yank, use the following lines instead:
49;;
50;; (require 'cua)
51;; (CUA-mode 'emacs)
52;;
53;; If you bind any keys to 'undo or 'advertised-undo in your .emacs file,
54;; CUA-mode should be activated *after* those bindings! Otherwise,
55;; bind the key to CUA-undo
56
57;; You may also use Customize to turn on CUA-mode and control its
58;; features and fine tune its behaviour. You'll find CUA-mode under
59;; the Editing Basics group.
60
61;; Optionally, place this line in your .emacs to turn the numeric
62;; keypad keys into numeric command prefix keys (useful with C-x, C-c
63;; and C-v too to save into and load from registers 1-9):
64;;
65;; (CUA-keypad-mode 'prefix t)
66
67
68;;; Commentary:
69
70;; This is the CUA-mode package which provides a complete emulation of
71;; the standard CUA key bindings (Motif/Windows/Mac GUI) for selecting
72;; and manipulating the region where S-<movement> is used to
73;; highlight & extend the region.
74
75;; This package allow the C-z, C-x, C-c, and C-v keys to be
76;; bound appropriately according to the Motif/Windows GUI, i.e.
77;; C-z -> undo
78;; C-x -> cut
79;; C-c -> copy
80;; C-v -> paste
81;;
82;; The tricky part is the handling of the C-x and C-c keys which
83;; are normally used as prefix keys for most of emacs' built-in
84;; commands. With CUA-mode they still do!!!
85;;
86;; Only when the region is currently active (and highlighted since
87;; transient-mark-mode is used), the C-x and C-c keys will work as CUA
88;; keys
89;; C-x -> cut
90;; C-c -> copy
91;; When the region is not active, C-x and C-c works as prefix keys!
92
93;; This probably sounds strange and difficult to get used to - but
94;; based on my own experience and the feedback from many users of
95;; CUA-mode, it actually works very well and users adapt to it
96;; instantly - or at least very quickly. So give it a try!
97;; ... and in the few cases where you make a mistake and accidentally
98;; delete the region - you just undo the mistake (with C-z).
99
100;; If you really need to perform a command which starts with one of
101;; the prefix keys even when the region is active, you have three options:
102;; - press the prefix key twice very quickly (within 0.2 seconds),
103;; - press the prefix key and the following key within 0.2 seconds), or
104;; - use the SHIFT key with the prefix key, i.e. C-X or C-C
105;;
106;; This behaviour is controlled via the CUA-mode-inhibit-method and
107;; CUA-mode-inhibit-delay variables.
108
109;; In addition to using the shifted movement keys, you can also use
110;; [C-space] to start the region and use unshifted movement keys to extend
111;; it. To cancel the region, use [C-space] or [C-g].
112
113;; If you want to take advantage of CUA-mode's superior rectangle
114;; support and uniform bindings, but prefer to use the standard
115;; emacs cut, copy, paste, and undo bindings, set the variable
116;; CUA-mode-emacs-bindings to t before the call to CUA-mode.
117
118
119;;; New features
120
121;; With release 2 of the CUA-mode package, the CUA commands have been
122;; extended to handle both rectangles and registers in a homogeneous
123;; manner, as well as adding the concept of a "global mark" as
124;; described below.
125
126;;; CUA rectangle support
127
128;; Emacs' normal rectangle support is based on interpreting the region
129;; between the mark and point as a "virtual rectangle", and using a
130;; completely separate set of "rectangle commands" [C-x r ...] on the
131;; region to copy, kill, fill a.s.o. the virtual rectangle.
132;;
133;; CUA-mode's superior rectangle support is based on using a true visual
134;; representation of the selected rectangle. To start a rectangle, use
135;; [S-return] and extend it using the normal movement keys (up, down,
136;; left, right, home, end, C-home, C-end). Once the rectangle has the
137;; desired size, you can cut or copy it using C-x and C-c, and you can
138;; subsequently insert it - as a rectangle - using C-v. So the only new
139;; command you need to know to work with CUA-mode rectangles is S-return!
140;;
141;; Furthermore, CUA-mode's rectangles are not limited to the actual
142;; contents of the buffer, so if the cursor is currently at the end of a
143;; short line, you can still extend the rectangle to include more columns
144;; of longer lines in the same rectangle. Sounds strange? Try it!
145;;
146;; You can enable padding for just this rectangle by pressing [M-p];
147;; this works like entering 'picture mode' where the tabs and spaces
148;; are automatically converted/inserted to make the rectangle truly
149;; rectangular. Or you can do it for all rectangles by setting the
150;; CUA-mode-auto-expand-rectangles variable to 'yes.
151
152;; And there's more: If you want to extend or reduce the size of the
153;; rectangle in one of the other corners of the rectangle, just use
154;; [return] to move the cursor to the "next" corner. Or you can use
155;; the [M-up], [M-down], [M-left], and [M-right] keys to move the
156;; entire rectangle overlay (but not the contents) in the given
157;; direction.
158;;
159;; [S-return] cancels the rectangle
160;; [C-space] activate region bounded by rectangle
161
162;; If you type a normal (self-inserting) character when the rectangle is
163;; active, the character is inserted on the "current side" of every line
164;; of the rectangle. The "current side" is the side on which the cursor
165;; is currently located. If the rectangle is only 1 column wide,
166;; insertion will be performed to the left when the cursor is at the
167;; bottom of the rectangle. So, for example, to comment out an entire
168;; paragraph like this one, just place the cursor on the first character
169;; of the first line, and enter the following:
170;; [S-return] [down].... [;; ] [S-return]
171
172;; CUA-mode's rectangle support also includes all the normal rectangle
173;; functions with easy access:
174;;
175;; [M-a] aligns all words at the left edge of the rectangle
176;; [M-b] fills the rectangle with blanks (tabs and spaces)
177;; [M-c] closes the rectangle by removing all blanks at the left edge
178;; of the rectangle
179;; [M-f] fills the rectangle with a single character (prompt)
180;; [M-F] performs text filling on the rectangle
181;; [M-i] increases the first number found on each line of the rectangle
182;; by the amount given by the numeric prefix argument (default 1)
183;; It recognizes 0x... as hexadecimal numbers
184;; [M-k] kills the rectangle as a normal multi-line text (for paste)
185;; [M-l] downcases the rectangle
186;; [M-m] kills the rectangle as a normal multi-line text (for paste)
187;; [M-n] fills each line of the rectangle with increasing numbers using
188;; a supplied format string (prompt)
189;; [M-o] opens the rectangle by moving the highlighted text to the
190;; right of the rectangle and filling the rectangle with blanks.
191;; [M-p] toggles rectangle padding, i.e. insert tabs and spaces to
192;; make rectangles truly rectangular
193;; [M-r] replaces REGEXP (prompt) by STRING (prompt) in rectangle
194;; [M-R] reverse the lines in the rectangle
195;; [M-s] fills each line of the rectangle with the same STRING (prompt)
196;; [M-t] performs text fill of the rectangle with TEXT (prompt)
197;; [M-u] upcases the rectangle
198;; [M-|] runs shell command on rectangle
199;; [M-'] restricts rectangle to lines with CHAR (prompt) at left column
200;; [M-/] restricts rectangle to lines matching REGEXP (prompt)
201;; [C-?] Shows a brief list of the above commands.
202
203;; [M-C-up] and [M-C-down] scrolls the lines INSIDE the rectangle up
204;; and down; lines scrolled outside the top or bottom of the rectangle
205;; are lost, but can be recovered using [C-z].
206
207
208;;; CUA register support
209
210;; Emacs' standard register support is also based on a separate set of
211;; "register commands".
212;;
213;; CUA-mode's register support is activated by providing a numeric
214;; prefix argument to the C-x, C-c, and C-v commands. For example,
215;; to copy the selected region to register 2, enter [M-2 C-c].
216;; Or if you have activated the keypad prefix mode, enter [kp-2 C-c].
217;;
218;; And CUA-mode will copy and paste normal region as well as rectangles
219;; into the registers, i.e. you use exactly the same command for both.
220;;
221;; In addition, the last highlighted text that is deleted (not copied),
222;; e.g. by typing text over a highlighted region, is automatically saved
223;; in register 0, so you can insert it using [kp-0 C-v].
224
225;;; CUA Global Mark
226
227;; The final feature provided by CUA-mode is the "global mark", which
228;; makes it very easy to copy bits and pieces from the same and other
229;; files into the current text. To enable and cancel the global mark,
230;; use [S-C-space]. The cursor will blink when the global mark
231;; is active. The following commands behave differently when the global
232;; mark is set:
233;; <ch> All characters (including returns) you type are inserted
234;; at the global mark!
235;; [C-x] If you cut a region or rectangle, it is automatically inserted
236;; at the global mark, and the global mark is advanced.
237;; [C-c] If you copy a region or rectangle, it is immediately inserted
238;; at the global mark, and the global mark is advanced.
239;; [C-v] Copies a single character to the global mark.
240;; [C-d] Moves (i.e. deletes and inserts) a single character to the
241;; global mark.
242;; [backspace] deletes the character before the global mark, while
243;; [delete] deltes the character after the global mark.
244
245;; [S-C-space] Jumps to and cancels the global mark.
246;; [C-u S-C-space] Cancels the global mark (stays in current buffer).
247
248;;; CUA mode indications
249
250;; As mentioned above, the cursor will blink when the global mark is
251;; active. In addition, you can choose to let CUA-mode use different
252;; cursor colors to indicate overwrite mode and read-only buffers.
253;; For example, the following setting will use a RED cursor in normal
254;; (insertion) mode in read-write buffers, a YELLOW cursor in
255;; overwrite mode in read-write buffers, and a GREEN cursor read-only
256;; buffers:
257;;
258;; (setq CUA-mode-normal-cursor-color "red")
259;; (setq CUA-mode-overwrite-cursor-color "yellow")
260;; (setq CUA-mode-read-only-cursor-color "green")
261;;
262
263;;; A few more details:
264
265;; * When the region is highlighted, TAB and S-TAB will indent the entire
266;; region by the normal tab-width (or the given prefix argument).
267;;
268;; * C-x C-x (exchange point and mark) no longer activates the mark (i.e.
269;; highlights the region). I found that to be confusing since the
270;; sequence C-x C-x (exchange once) followed by C-x C-x (change back)
271;; would then cut the region! To activate the region in this way,
272;; use C-u C-x C-x.
273;;
274;; * [delete] will delete (not copy) the highlighted region.
275;;
276;; * The highlighted region is automatically deleted if other text is
277;; typed or inserted. The previously highlighted text is saved in
278;; register 0 (if CUA-mode-delete-to-register-0 is non-nil).
279;;
280;; * You may choose to use M-r as a prefix for the register commands
281;; instead of C-x r by setting CUA-mode-register-commands-prefix.
282;; The original binding of M-r (move-to-window-line) is then moved
283;; to M-r M-r.
284;;
285;; * Normally, when you paste a rectangle using C-v, each line of the
286;; rectangle is inserted into the existing lines in the buffer.
287;; However, if overwrite-mode is turned on, the lines of the rectangle
288;; are inserted as a single block of lines at point.
289
290;;; Todo:
291;;
292;; - fix loading of normal cursor color from frame parameters.
293;; - sticky region variable -> unshifted arrow keys deselects region/rectangle.
294;; - more documentation per function / variable
295;; - extended documentation via info would be fine
296;; - rectangle "box" mode
297;; - rectangle "move" mode (eg move all lines up/down)
298;; - insert/delete rectangle shall not modify tabs or eols if padding off.
299
300;;; Implementation details
301
302;; CUA-mode uses a versatile pre-command-hook and post-command-hook
303;; to avoid rebinding any of the cursor movement or scrolling keys.
304;;
305;; The interpretation of C-x and C-c as either emacs prefix keys
306;; or CUA cut/copy keys is handled via GNU emacs' key-translation-map.
307
308;;; Acknowledgements
309
310;; CUA-mode includes code and ideas from several related packages:
311;; pc-selection-mode by Michael Staats <michael@thp.Uni-Duisburg.DE>
312;; s-region by Morten Welinder <terra@diku.dk>
313;; delete-selection-mode by Matthieu Devin <devin@lucid.com>
314;;
315;; The rectangle handling and display code borrows from the standard
316;; GNU emacs rect.el package and the the rect-mark.el package by Rick
317;; Sladkey <jrs@world.std.com>.
318
319
320;;;; Compatibility
321
322;;; Support functions for pre 20.1/20.4 GNU emacsen
323(eval-and-compile
324 (if (fboundp 'unless) nil
325 (defmacro unless (cond &rest body)
326 "(unless COND BODY...): if COND yields nil, do BODY, else return nil."
327 `(if ,cond nil ,@body))
328 (put 'unless 'lisp-indent-function 1)
329 (put 'unless 'edebug-form-spec '(&rest form)))
330
331 (unless (fboundp 'when)
332 (defmacro when (cond &rest body)
333 "(when COND BODY...): if COND yields non-nil, do BODY, else return nil."
334 `(if ,cond (progn ,@body)))
335 (put 'when 'lisp-indent-function 1)
336 (put 'when 'edebug-form-spec '(&rest form)))
337
338 (unless (fboundp 'with-current-buffer)
339 (defmacro with-current-buffer (buffer &rest body)
340 "Execute the forms in BODY with BUFFER as the current buffer."
341 `(save-excursion (set-buffer ,buffer) ,@body))))
342
343(eval-and-compile
344 (condition-case ()
345 (require 'custom)
346 (error nil))
347 (unless (fboundp 'defgroup)
348 (defmacro defgroup (&rest rest) ()))
349 (unless (fboundp 'defcustom)
350 (defmacro defcustom (sym val str &rest rest)
351 `(defvar ,sym ,val ,str)))
352 (unless (fboundp 'defface)
353 (defmacro defface (sym val str &rest rest)
354 `(defvar ,sym (make-face ',sym) ,str))))
355
356(unless (fboundp 'line-beginning-position)
357 (defun line-beginning-position (&optional N)
358 (save-excursion
359 (beginning-of-line N)
360 (point))))
361
362(unless (fboundp 'line-end-position)
363 (defun line-end-position (&optional N)
364 (save-excursion
365 (end-of-line N)
366 (point))))
367
368
369;;;; Customization:
370
371(defgroup CUA-mode nil
372 "Emulate CUA key bindings including C-x and C-c."
373 :prefix "CUA-mode"
374 :group 'editing-basics
375 :group 'convenience
376 :group 'emulations
377 :link '(emacs-commentary-link :tag "Commentary" "cua.el")
378 :link '(emacs-library-link :tag "Lisp File" "cua.el"))
379
380;;;###autoload
381(defcustom CUA-mode nil
382 "Non-nil means that CUA emulation mode is enabled.
383In CUA mode, shifted movement keys highlight and extend the region.
384When a region is highlighted, the binding of the C-x and C-c keys are
385temporarily changed to work as Motif, MAC or MS-Windows cut and paste.
386Also, insertion commands first delete the region and then insert.
387This mode enables Transient Mark mode and it provides a superset of the
388PC Selection Mode and Delete Selection Modes.
389
390Setting this variable directly does not take effect;
391use either \\[customize] or the function `CUA-mode'."
392 :set (lambda (symbol value)
393 (CUA-mode (or value 0)))
394 :initialize 'custom-initialize-default
395 :require 'cua
396 :link '(emacs-commentary-link "cua.el")
397 :version "20.5"
398 :type 'boolean
399 :group 'CUA-mode)
400
401(defcustom CUA-mode-emacs-bindings nil
402 "Non-nil means CUA functionality is enabled without binding CUA keys.
403This causes the normal bindings of kill-region, copy-region-as-kill, yank,
404and undo to behave in the CUA style, but the C-z, C-c, C-x, and
405C-v keys are not rebound.")
406
407(defcustom CUA-mode-remap-cx-shift-only nil
408 "*If non-nil, only remap C-c and C-x if region was marked with S-<move>.
409I.e. if the mark was set using \\[CUA-set-mark], those keys have their
410normal prefix bindings."
411 :type 'boolean
412 :group 'CUA-mode)
413
414(defcustom CUA-mode-highlight-shift-only nil
415 "*If non-nil, only highlight region if marked with S-<move>.
416When this is non-nil, CUA toggles `transient-mark-mode' on when the region
417is marked using shifted movement keys, and off when the mark is cleared.
418But when the mark was set using \\[CUA-set-mark], transient-mark-mode
419is not turned on."
420 :type 'boolean
421 :group 'CUA-mode)
422
423
424(defcustom CUA-mode-inhibit-method
425 (if (memq system-type '(windows-nt ms-dos)) 'shift 'twice)
426 "How to inhibit the CUA interpretation of the next prefix key.
427
428When the region is active, the following methods are available to
429use the normal functionality of the prefix keys:
430delay The interpretation of a prefix keys as a CUA key is delayed
431 for `CUA-mode-inhibit-delay' milliseconds after the prefix
432 key has been typed.
433 If a second key is typed before the delay elapses, the prefix
434 key works as a normal prefix together with the second key.
435twice As delay, but if the second key typed is the same prefix key,
436 the first prefix key is ignored, while the second prefix key
437 will works as a normal prefix key for the following keys.
438shift The Shift key must be used together with the prefix key.
439 (Actually this method always works unless the shifted prefix
440 keys are explicitly bound to a command).
441
442Notice that the delay and twice options only works well on systems
443with a sit-for function supporting fractions of a second delays."
444 :type '(choice (const delay)
445 (const twice)
446 (const shift))
447 :group 'CUA-mode)
448
449(defcustom CUA-mode-inhibit-delay 250
450 "Period during which typing another key inhibits CUA prefix keys.
451Measured in milliseconds.
452Used when `CUA-mode-inhibit-method' is delay or twice."
453 :type 'integer
454 :group 'CUA-mode)
455
456(defcustom CUA-mode-register-commands-prefix nil
457 "Remap register commands [C-x r ...] onto this prefix.
458E.g. to use M-r as register command prefix, use the value [?\\M-r].
459If set to nil, register commands are not remapped.
460Other C-x ? commands can be remapped using CUA-remap-ctl-x-commands"
461 :set (lambda (symbol value)
462 (if value
463 (CUA-remap-ctl-x-commands "r" value)))
464 :type 'sexp
465 :group 'CUA-mode)
466
467(defcustom CUA-mode-keep-region-after-copy nil
468 "If non-nil, don't deselect the region after copying."
469 :type 'boolean
470 :group 'CUA-mode)
471
472(defcustom CUA-mode-auto-expand-rectangles nil
473 "If non-nil, rectangles are padded with spaces to make straight edges.
474This implies modifying buffer contents by expanding tabs and inserting spaces.
475Consequently, this is inhibited in read-only buffers.
476Can be toggled by [M-p] while the rectangle is active,"
477 :type 'boolean
478 :group 'CUA-mode)
479
480(defcustom CUA-mode-global-mark-visible t
481 "If non-nil, always keep global mark visible in other window."
482 :type 'boolean
483 :group 'CUA-mode)
484
485(defcustom CUA-mode-feature-global-mark t
486 "If non-nil, target for kill and copy region is global mark when active.
487When nil, or global mark is not active, target is kill-ring."
488 :type 'boolean
489 :group 'CUA-mode)
490
491(defcustom CUA-mode-feature-registers t
492 "If non-nil, target for kill and copy region is a register if prefix arg.
493When nil, or no prefix arg, target is kill-ring (or global mark)."
494 :type 'boolean
495 :group 'CUA-mode)
496
497(defcustom CUA-mode-delete-to-register-0 t
498 "*If non-nil, save last deleted region or rectangle to register 0."
499 :type 'boolean
500 :group 'CUA-mode)
501
502(defcustom CUA-mode-auto-help t
503 "*If non-nil, automatically show help for region, rectangle and global mark."
504 :type 'boolean
505 :group 'CUA-mode)
506
507(defcustom CUA-mode-use-modeline nil
508 "*If non-nil, use minor-mode hook to show status in mode line."
509 :type 'boolean
510 :group 'CUA-mode)
511
512(defcustom CUA-mode-use-hyper-key nil
513 "*If non-nil, bind rectangle commands to H-? instead of M-?.
514If set to 'also, toggle region command is also on S-return.
515Must be set prior to enabling CUA-mode."
516 :type '(choice (const nil)
517 (const only)
518 (const also))
519 :group 'CUA-mode)
520
521(defcustom CUA-debug nil
522 "*Enable CUA mode debugging."
523 :type 'boolean
524 :group 'CUA-mode)
525
526(defface CUA-rectangle-face 'nil
527 "*Font used by CUA for highlighting the rectangle."
528 :group 'CUA-mode)
529
530(defface CUA-rectangle-noselect-face 'nil
531 "*Font used by CUA for highlighting the non-selected rectangle lines."
532 :group 'CUA-mode)
533
534(defface CUA-global-mark-face '((((class color))
535 (:foreground "black")
536 (:background "yellow"))
537 (t (:bold t)))
538 "*Font used by CUA for highlighting the global mark."
539 :group 'CUA-mode)
540
541(defcustom CUA-mode-use-cursor-colors t
542 "*If non-nil, use different cursor colors for indications."
543 :type 'boolean
544 :group 'CUA-mode)
545
546(defcustom CUA-mode-normal-cursor-color nil
547 "Normal (non-overwrite) cursor color.
548Also used to indicate that rectangle padding is not in effect.
549Automatically loaded from frame parameters, if nil."
550 :initialize (lambda (symbol value)
551 (set symbol (or value
552 (and (boundp 'initial-cursor-color) initial-cursor-color)
553 (and (boundp 'initial-frame-alist)
554 (assoc 'cursor-color initial-frame-alist)
555 (cdr (assoc 'cursor-color initial-frame-alist)))
556 (and (boundp 'default-frame-alist)
557 (assoc 'cursor-color default-frame-alist)
558 (cdr (assoc 'cursor-color default-frame-alist)))
559 (frame-parameter nil 'cursor-color))))
560 :type 'color
561 :group 'CUA-mode)
562
563(defcustom CUA-mode-read-only-cursor-color "darkgreen"
564 "*Cursor color used in read-only buffers, if non-nil."
565 :type 'color
566 :group 'CUA-mode)
567
568(defcustom CUA-mode-overwrite-cursor-color "yellow"
569 "*Cursor color used when overwrite mode is set, if non-nil.
570Also used to indicate that rectangle padding is in effect."
571 :type 'color
572 :group 'CUA-mode)
573
574(defcustom CUA-mode-global-mark-cursor-color "cyan"
575 "*Indication for active global mark.
576Will change cursor color to specified color if string."
577 :type 'color
578 :group 'CUA-mode)
579
580(defcustom CUA-mode-global-mark-cursor-blink t
581 "*If non-nil, use blinking cursor as indication for active global mark."
582 :type 'boolean
583 :group 'CUA-mode)
584
585;;; Code:
586
587;; Basic configuration options
588
589(defvar CUA-prefix-key-mappings
590 '((?\C-x . S-delete)
591 (?\C-c . C-insert)
592;; (?\C-h . "C-?")
593 )
594 "List of prefix keys which are remapped via key-translation-map.
595Each element in the list is a cons of the prefix key and the
596key it is translated into if the region is active.")
597
598(defvar CUA-ctl-x-8-prefix-key nil
599 "*Key which CUA uses in key-translation-map instead of C-x 8 prefix.
600Must be set to a single character. If no set, the first unused key
601among the following list is chosen automatically:
602H-8 (hyper 8), s-8 (super 8), C-H-8, C-H-s-8")
603
604;; Misc variables
605
606(defvar CUA-explicit-region-start nil
607 "Current region was started using set-mark-command.")
608
609(defvar CUA-last-action nil
610 "Action taken by last command.")
611
612(defvar CUA-cur-register nil
613 "Current register selected by prefix arg.")
614
615(defvar CUA-mode-status nil
616 "Modeline status indication.")
617
618(defvar CUA-orig-command nil
619 "The original command before remapping.")
620
621;;; Register support
622
623(defun CUA-register ()
624 (and (not CUA-cur-register)
625 CUA-mode-feature-registers
626 (integerp current-prefix-arg)
627 (>= current-prefix-arg 0) (< current-prefix-arg 10)
628 (setq CUA-cur-register (+ current-prefix-arg ?0)
629 current-prefix-arg nil
630 overriding-terminal-local-map nil))
631 CUA-cur-register)
632
633;;; Rectangle support
634
635(require 'rect)
636
637(defvar CUA-rectangle nil
638 "If non-nil, restrict current region to this rectangle.
639Value is a vector [top bot left right corner ins pad select].
640CORNER specifies currently active corner 0=t/l 1=t/r 2=b/l 3=b/r.
641INS specifies whether to insert on left(nil) or right(t) side.
642If PAD is non-nil, tabs are converted to spaces when necessary.
643If SELECT is a regexp, only lines starting with that regexp are affected.")
644
645(defvar CUA-last-rectangle nil
646 "Most recent rectangle geometry.
647Note: car is buffer.")
648
649;; rectangle restored by undo
650(defvar CUA-next-rectangle nil)
651
652;; buffer + point prior to current command when rectangle is active
653;; checked in post-command hook to see if point was moved
654(defvar CUA-start-point nil)
655
656(defvar CUA-rect-last-killed nil
657 "Last rectangle copied/killed; nil if last kill was not a rectangle.")
658
659(defvar CUA-rect-overlays nil
660 "List of overlays used to display current rectangle.")
661
662(defun CUA-rect-top (&optional val)
663 "Top of CUA rectangle (buffer position on first line)."
664 (if (not val)
665 (aref CUA-rectangle 0)
666 (setq val (line-beginning-position))
667 (if (<= val (aref CUA-rectangle 1))
668 (aset CUA-rectangle 0 val)
669 (aset CUA-rectangle 1 val)
670 (CUA-rect-corner 2))))
671
672(defun CUA-rect-bot (&optional val)
673 "Bot of CUA rectangle (buffer position on last line)."
674 (if (not val)
675 (aref CUA-rectangle 1)
676 (setq val (line-end-position))
677 (if (>= val (aref CUA-rectangle 0))
678 (aset CUA-rectangle 1 val)
679 (aset CUA-rectangle 0 val)
680 (CUA-rect-corner 2))))
681
682(defun CUA-rect-left (&optional val)
683 "Left column of CUA rectangle."
684 (if (integerp val)
685 (if (<= val (aref CUA-rectangle 3))
686 (aset CUA-rectangle 2 val)
687 (aset CUA-rectangle 3 val)
688 (CUA-rect-corner (if (CUA-rect-right-side) -1 1)))
689 (aref CUA-rectangle 2)))
690
691(defun CUA-rect-right (&optional val)
692 "Right column of CUA rectangle."
693 (if (integerp val)
694 (if (>= val (aref CUA-rectangle 2))
695 (aset CUA-rectangle 3 val)
696 (aset CUA-rectangle 2 val)
697 (CUA-rect-corner (if (CUA-rect-right-side) -1 1)))
698 (aref CUA-rectangle 3)))
699
700(defun CUA-rect-corner (&optional advance)
701 "Currently active corner of rectangle."
702 (let ((c (aref CUA-rectangle 4)))
703 (if (not (integerp advance))
704 c
705 (aset CUA-rectangle 4
706 (if (= advance 0)
707 (- 3 c) ; opposite corner
708 (mod (+ c 4 advance) 4)))
709 (aset CUA-rectangle 5 0))))
710
711(defun CUA-rect-right-side (&optional topbot)
712 ;; t if point is on right side of rectangle.
713 (if (and topbot (= (CUA-rect-left) (CUA-rect-right)))
714 (< (CUA-rect-corner) 2)
715 (= (mod (CUA-rect-corner) 2) 1)))
716
717(defun CUA-rect-column ()
718 (if (CUA-rect-right-side)
719 (CUA-rect-right)
720 (CUA-rect-left)))
721
722(defun CUA-rect-insert-col (&optional col)
723 "Currently active corner of rectangle."
724 (if (integerp col)
725 (aset CUA-rectangle 5 col)
726 (if (CUA-rect-right-side t)
727 (if (= (aref CUA-rectangle 5) 0)
728 (1+ (CUA-rect-right))
729 (aref CUA-rectangle 5))
730 (CUA-rect-left))))
731
732(defun CUA-rect-padding (&optional set val)
733 (if set
734 (aset CUA-rectangle 6 val))
735 (and (not buffer-read-only)
736 (aref CUA-rectangle 6)))
737
738(defun CUA-rect-restriction (&optional val bounded negated)
739 (if val
740 (aset CUA-rectangle 7
741 (and (stringp val)
742 (> (length val) 0)
743 (list val bounded negated)))
744 (aref CUA-rectangle 7)))
745
746(defun CUA-rect-assert ()
747 (message "%S (%d)" CUA-rectangle (point))
748 (if (< (CUA-rect-right) (CUA-rect-left))
749 (message "rectangle right < left"))
750 (if (< (CUA-rect-bot) (CUA-rect-top))
751 (message "rectangle bot < top")))
752
753(defun CUA-rect-get-corners (&optional pad)
754 ;; Calculate the rectangular region represented by point and mark,
755 ;; putting start in the upper left corner and end in the
756 ;; bottom right corner.
757 (let ((top (point)) (bot (mark)) r l corner)
758 (save-excursion
759 (goto-char top)
760 (setq l (current-column))
761 (goto-char bot)
762 (setq r (current-column))
763 (if (<= top bot)
764 (setq corner (if (<= l r) 0 1))
765 (setq top (prog1 bot (setq bot top)))
766 (setq corner (if (<= l r) 2 3)))
767 (if (<= l r)
768 (if (< l r)
769 (setq r (1- r)))
770 (setq l (prog1 r (setq r l)))
771 (goto-char top)
772 (move-to-column l pad)
773 (setq top (point))
774 (goto-char bot)
775 (move-to-column r pad)
776 (setq bot (point))))
777 (vector top bot l r corner 0 pad nil)))
778
779(defun CUA-rect-set-corners ()
780 ;; Set mark and point in opposite corners of current rectangle.
781 (let (pp pc mp mc (c (CUA-rect-corner)))
782 (cond
783 ((= c 0) ; top/left -> bot/right
784 (setq pp (CUA-rect-top) pc (CUA-rect-left)
785 mp (CUA-rect-bot) mc (CUA-rect-right)))
786 ((= c 1) ; top/right -> bot/left
787 (setq pp (CUA-rect-top) pc (CUA-rect-right)
788 mp (CUA-rect-bot) mc (CUA-rect-left)))
789 ((= c 2) ; bot/left -> top/right
790 (setq pp (CUA-rect-bot) pc (CUA-rect-left)
791 mp (CUA-rect-top) mc (CUA-rect-right)))
792 ((= c 3) ; bot/right -> top/left
793 (setq pp (CUA-rect-bot) pc (CUA-rect-right)
794 mp (CUA-rect-top) mc (CUA-rect-left))))
795 (goto-char mp)
796 (move-to-column mc (CUA-rect-padding))
797 (set-mark (point))
798 (goto-char pp)
799 (move-to-column pc (CUA-rect-padding))))
800
801(defun CUA-forward-line (n pad)
802 (if (or (not pad) (< n 0))
803 (= (forward-line n) 0)
804 (next-line 1)
805 t))
806
807(defun CUA-rect-resize (command)
808 ;; Adjust rectangle size based on movement command
809 (let ((cmd (or (get command 'CUA-rect) command))
810 (pad (CUA-rect-padding))
811 (resized t))
812 (cond
813 ((eq cmd 'forward-char)
814 (cond
815 ((and (CUA-rect-right-side) (or pad (eolp)))
816 (CUA-rect-right (1+ (CUA-rect-right)))
817 (move-to-column (CUA-rect-right) pad))
818 ((CUA-rect-right-side)
819 (forward-char 1)
820 (CUA-rect-right (current-column)))
821 ((or pad (eolp))
822 (CUA-rect-left (1+ (CUA-rect-left)))
823 (move-to-column (CUA-rect-right) pad))
824 (t
825 (forward-char 1)
826 (CUA-rect-left (current-column)))))
827 ((eq cmd 'backward-char)
828 (cond
829 ((= (CUA-rect-right) 0)
830 nil)
831 ((and (not (CUA-rect-right-side)) (= (CUA-rect-left) 0))
832 nil)
833 ((and (CUA-rect-right-side) (or pad (eolp) (bolp)))
834 (CUA-rect-right (1- (CUA-rect-right)))
835 (move-to-column (CUA-rect-right) pad))
836 ((CUA-rect-right-side)
837 (backward-char 1)
838 (CUA-rect-right (current-column)))
839 ((or pad (eolp) (bolp))
840 (CUA-rect-left (1- (CUA-rect-left)))
841 (move-to-column (CUA-rect-right) pad))
842 (t
843 (backward-char 1)
844 (CUA-rect-left (current-column)))))
845 ((eq cmd 'next-line)
846 (cond
847 ((>= (CUA-rect-corner) 2)
848 (goto-char (CUA-rect-bot))
849 (when (CUA-forward-line 1 pad)
850 (move-to-column (CUA-rect-column) pad)
851 (CUA-rect-bot t)))
852 (t
853 (goto-char (CUA-rect-top))
854 (when (CUA-forward-line 1 pad)
855 (move-to-column (CUA-rect-column) pad)
856 (CUA-rect-top t)))))
857 ((eq cmd 'previous-line)
858 (cond
859 ((>= (CUA-rect-corner) 2)
860 (goto-char (CUA-rect-bot))
861 (when (CUA-forward-line -1 pad)
862 (move-to-column (CUA-rect-column) pad)
863 (CUA-rect-bot t)))
864 (t
865 (goto-char (CUA-rect-top))
866 (when (CUA-forward-line -1 pad)
867 (move-to-column (CUA-rect-column) pad)
868 (CUA-rect-top t)))))
869 ((memq cmd '(end-of-line end-of-line-or-backward-char))
870 (cond
871 ((not (eolp))
872 (end-of-line)
873 (if (> (current-column) (CUA-rect-right))
874 (CUA-rect-right (current-column)))
875 (if (not (CUA-rect-right-side))
876 (CUA-rect-corner 1)))))
877 ((memq cmd '(beginning-of-line beginning-of-line-or-indent))
878 (cond
879 ((not (bolp))
880 (beginning-of-line)
881 (CUA-rect-left (current-column))
882 (if (CUA-rect-right-side)
883 (CUA-rect-corner -1)))))
884 ((eq cmd 'end-of-buffer)
885 (goto-char (point-max))
886 (move-to-column (CUA-rect-column) pad)
887 (CUA-rect-bot t))
888 ((eq cmd 'beginning-of-buffer)
889 (goto-char (point-min))
890 (move-to-column (CUA-rect-column) pad)
891 (CUA-rect-top t))
892 ((memq cmd '(scroll-down scroll-up))
893 (funcall cmd)
894 (move-to-column (CUA-rect-column) pad)
895 (if (>= (CUA-rect-corner) 2)
896 (CUA-rect-bot t)
897 (CUA-rect-top t)))
898 (t
899 (setq resized nil)))
900 (when resized
901 (CUA-pad-rectangle pad)
902 (CUA-rect-insert-col 0)
903 (CUA-rect-set-corners)
904 (CUA-keep-active t))
905 resized))
906
907(defun CUA-rect-move (dir)
908 (let ((pad (CUA-rect-padding))
909 (moved t)
910 (top (CUA-rect-top))
911 (bot (CUA-rect-bot))
912 (l (CUA-rect-left))
913 (r (CUA-rect-right)))
914 (cond
915 ((eq dir 'up)
916 (goto-char top)
917 (when (CUA-forward-line -1 pad)
918 (CUA-rect-top t)
919 (goto-char bot)
920 (forward-line -1)
921 (CUA-rect-bot t)))
922 ((eq dir 'down)
923 (goto-char bot)
924 (when (CUA-forward-line 1 pad)
925 (CUA-rect-bot t)
926 (goto-char top)
927 (CUA-forward-line 1 pad)
928 (CUA-rect-top t)))
929 ((eq dir 'left)
930 (when (> l 0)
931 (CUA-rect-left (1- l))
932 (CUA-rect-right (1- r))))
933 ((eq dir 'right)
934 (CUA-rect-right (1+ r))
935 (CUA-rect-left (1+ l)))
936 (t
937 (setq moved nil)))
938 (when moved
939 (CUA-pad-rectangle)
940 (CUA-rect-set-corners)
941 (CUA-keep-active t))))
942
943(defun CUA-rect-operation (cmd visible undo pad &optional fct post-fct)
944 ;; Call FCT for each line of region with 4 parameters:
945 ;; Region start, end, left-col, right-col
946 ;; Point is at start when FCT is called
947 ;; Rectangle is padded if PAD = t or numeric and (CUA-rect-padding)
948 ;; Mark is kept if keep == t and cleared if keep numeric
949 (let* ((start (CUA-rect-top))
950 (end (CUA-rect-bot))
951 (l (CUA-rect-left))
952 (r (1+ (CUA-rect-right)))
953 (m (make-marker))
954 (tabpad (and (integerp pad) (= pad 2)))
955 (sel (CUA-rect-restriction))
956 (keep-clear (and cmd (get cmd 'CUA-rect))))
957 (if undo
958 (CUA-rect-undo-boundary))
959 (if (integerp pad)
960 (setq pad (CUA-rect-padding)))
961 (save-excursion
962 (save-restriction
963 (widen)
964 (when (> (CUA-rect-corner) 1)
965 (goto-char end)
966 (and (bolp) (not (eolp)) (not (eobp))
967 (setq end (1+ end))))
968 (when visible
969 (setq start (max (window-start) start))
970 (setq end (min (window-end) end)))
971 (goto-char end)
972 (setq end (line-end-position))
973 (goto-char start)
974 (setq start (line-beginning-position))
975 (narrow-to-region start end)
976 (goto-char (point-min))
977 (while (< (point) (point-max))
978 (move-to-column r pad)
979 (and (not pad) (not visible) (> (current-column) r)
980 (backward-char 1))
981 (if (and tabpad (not pad) (looking-at "\t"))
982 (forward-char 1))
983 (set-marker m (point))
984 (move-to-column l pad)
985 (if fct
986 (let ((v t) (p (point)))
987 (when sel
988 (if (car (cdr sel))
989 (setq v (looking-at (car sel)))
990 (setq v (re-search-forward (car sel) m t))
991 (goto-char p))
992 (if (car (cdr (cdr sel)))
993 (setq v (null v))))
994 (if visible
995 (funcall fct p m l r v)
996 (if v
997 (funcall fct p m l r)))))
998 (set-marker m nil)
999 (forward-line 1))
1000 (if (not visible)
1001 (CUA-rect-bot t))
1002 (if post-fct
1003 (funcall post-fct l r))))
1004 (cond
1005 ((eq keep-clear 'keep)
1006 (CUA-keep-active t))
1007 ((eq keep-clear 'clear)
1008 (CUA-keep-active nil))
1009 ((eq keep-clear 'corners)
1010 (CUA-rect-set-corners)
1011 (CUA-keep-active t)))))
1012
1013(put 'CUA-rect-operation 'lisp-indent-function 4)
1014
1015(defun CUA-pad-rectangle (&optional pad)
1016 (if (or pad (CUA-rect-padding))
1017 (CUA-rect-operation nil nil t t)))
1018
1019(defun CUA-delete-rectangle ()
1020 (CUA-rect-operation nil nil t 2
1021 '(lambda (s e l r)
1022 (delete-region s (if (> e s) e (1+ e))))))
1023
1024(defun CUA-extract-rectangle ()
1025 (let (rect)
1026 (CUA-rect-operation nil nil nil 1
1027 '(lambda (s e l r)
1028 (setq rect (cons (buffer-substring-no-properties s e) rect))))
1029 (nreverse rect)))
1030
1031(defun CUA-insert-rectangle (rect &optional below)
1032 ;; Insert rectangle as insert-rectangle, but don't set mark and exit with
1033 ;; point at either next to top right or below bottom left corner
1034 ;; Notice: In overwrite mode, the rectangle is inserted as separate text lines.
1035 (if (and below (eq below 'auto))
1036 (setq below (and (bolp)
1037 (or (eolp) (eobp) (= (1+ (point)) (point-max))))))
1038 (let ((lines rect)
1039 (insertcolumn (current-column))
1040 (first t)
1041 p)
1042 (while (or lines below)
1043 (or first
1044 (if overwrite-mode
1045 (insert ?\n)
1046 (forward-line 1)
1047 (or (bolp) (insert ?\n))
1048 (move-to-column insertcolumn t)))
1049 (if (not lines)
1050 (setq below nil)
1051 (insert (car lines))
1052 (setq lines (cdr lines))
1053 (and first (not below)
1054 (setq p (point))))
1055 (setq first nil))
1056 (and p (not overwrite-mode)
1057 (goto-char p))))
1058
1059(defun CUA-rect-copy-as-kill (&optional ring)
1060 (if (CUA-register)
1061 (set-register (CUA-register) (CUA-extract-rectangle))
1062 (setq killed-rectangle (CUA-extract-rectangle))
1063 (setq CUA-rect-last-killed (cons (and kill-ring (car kill-ring)) killed-rectangle))
1064 (if ring
1065 (kill-new (mapconcat
1066 (function (lambda (row) (concat row "\n")))
1067 killed-rectangle "")))))
1068
1069(defun CUA-rect-activate (&optional force)
1070 ;; Turn on rectangular marking mode by disabling transient mark mode
1071 ;; and manually handling highlighting from a post command hook.
1072 ;; Be careful if we are already marking a rectangle.
1073 (setq CUA-rectangle
1074 (if (and CUA-last-rectangle
1075 (eq (car CUA-last-rectangle) (current-buffer))
1076 (eq (car (cdr CUA-last-rectangle)) (point)))
1077 (cdr (cdr CUA-last-rectangle))
1078 (CUA-rect-get-corners
1079 (and (not buffer-read-only)
1080 (or CUA-mode-auto-expand-rectangles
1081 force
1082 (eq major-mode 'picture-mode)))))
1083 CUA-mode-status (if (CUA-rect-padding) " Pad" "")
1084 CUA-last-rectangle nil))
1085
1086(defvar CUA-save-point nil)
1087
1088(defun CUA-rect-deactivate ()
1089 ;; This is used to clean up after `CUA-rect-activate'.
1090 (mapcar (function delete-overlay) CUA-rect-overlays)
1091 (setq CUA-last-rectangle (cons (current-buffer) (cons CUA-save-point CUA-rectangle))
1092 CUA-rectangle nil
1093 CUA-rect-overlays nil
1094 CUA-mode-status nil))
1095
1096(defun CUA-rect-highlight ()
1097 ;; This function is used to highlight the rectangular region.
1098 ;; We do this by putting an overlay on each line within the rectangle.
1099 ;; Each overlay extends across all the columns of the rectangle.
1100 ;; We try to reuse overlays where possible because this is more efficient
1101 ;; and results in less flicker.
1102 ;; If CUA-rect-padding is nil and the buffer contains tabs or short lines,
1103 ;; the higlighted region may not be perfectly rectangular.
1104 (let ((deactivate-mark deactivate-mark)
1105 (old CUA-rect-overlays)
1106 (new nil)
1107 (left (CUA-rect-left))
1108 (right (1+ (CUA-rect-right))))
1109 (when (/= left right)
1110 (sit-for 0) ; make window top/bottom reliable
1111 (CUA-rect-operation nil t nil nil
1112 '(lambda (s e l r v)
1113 (let ((rface (if v 'CUA-rectangle-face 'CUA-rectangle-noselect-face))
1114 overlay)
1115 ;; Trim old leading overlays.
1116 (while (and old
1117 (setq overlay (car old))
1118 (< (overlay-start overlay) s)
1119 (/= (overlay-end overlay) e))
1120 (delete-overlay overlay)
1121 (setq old (cdr old)))
1122 ;; Reuse an overlay if possible, otherwise create one.
1123 (if (and old
1124 (setq overlay (car old))
1125 (or (= (overlay-start overlay) s)
1126 (= (overlay-end overlay) e)))
1127 (progn
1128 (move-overlay overlay s e)
1129 (setq old (cdr old)))
1130 (setq overlay (make-overlay s e)))
1131 (overlay-put overlay 'face rface)
1132 (setq new (cons overlay new))))))
1133 ;; Trim old trailing overlays.
1134 (mapcar (function delete-overlay) old)
1135 (setq CUA-rect-overlays (nreverse new))))
1136
1137(defun CUA-rect-indent-rectangle (&optional ch)
1138 "Indent current rectangle."
1139 (let ((col (CUA-rect-insert-col))
1140 (pad (CUA-rect-padding))
1141 indent)
1142 (CUA-rect-operation 'CUA-rect-indent-rectangle nil t pad
1143 '(lambda (s e l r)
1144 (move-to-column col pad)
1145 (if (and (eolp)
1146 (< (current-column) col))
1147 (move-to-column col t))
1148 (if ch
1149 (insert ch)
1150 (tab-to-tab-stop))
1151 (if (CUA-rect-right-side t)
1152 (CUA-rect-insert-col (current-column))
1153 (setq indent (- (current-column) l))))
1154 '(lambda (l r)
1155 (when (and indent (> indent 0))
1156 (aset CUA-rectangle 2 (+ l indent))
1157 (aset CUA-rectangle 3 (+ r indent -1)))))))
1158(put 'CUA-rect-indent-rectangle 'CUA-rect 'corners)
1159
1160
1161;;; User functions.
1162
1163;;;###autoload
1164(defun CUA-exchange-point-and-mark (arg)
1165 "Exchanges point and mark, but don't activate the mark.
1166Activates the mark if a prefix argument is given."
1167 (interactive "P")
1168 (if arg
1169 (setq mark-active t)
1170 (let (mark-active)
1171 (exchange-point-and-mark)
1172 (if CUA-rectangle
1173 (CUA-rect-corner 0)))))
1174
1175;;; Global Marker
1176
1177(defvar CUA-global-mark nil
1178 "Global mark position marker.")
1179
1180(defvar CUA-global-mark-overlay nil
1181 "Overlay for global mark position.")
1182
1183(defun CUA-global-mark-active ()
1184 (and (markerp CUA-global-mark) (marker-buffer CUA-global-mark)))
1185
1186(defun CUA-global-mark-deactivate (&optional msg)
1187 (when CUA-global-mark-overlay
1188 (delete-overlay CUA-global-mark-overlay)
1189 (setq CUA-global-mark-overlay nil))
1190 (if (markerp CUA-global-mark)
1191 (move-marker CUA-global-mark nil))
1192 (if msg
1193 (message "Global Mark Cleared")))
1194
1195(defun CUA-global-mark-activate (&optional msg)
1196 (if (not (markerp CUA-global-mark))
1197 (setq CUA-global-mark (make-marker)))
1198 (when (eobp)
1199 (insert " ")
1200 (backward-char 1))
1201 (move-marker CUA-global-mark (point))
1202 (if (overlayp CUA-global-mark-overlay)
1203 (move-overlay CUA-global-mark-overlay (point) (1+ (point)))
1204 (setq CUA-global-mark-overlay
1205 (make-overlay (point) (1+ (point))))
1206 (overlay-put CUA-global-mark-overlay 'face 'CUA-global-mark-face))
1207 (if msg
1208 (message "Global Mark Set")))
1209
1210(defun CUA-cmd-toggle-global-mark (stay)
1211 "Set or cancel the global marker.
1212When the global marker is set, CUA cut and copy commands will automatically
1213insert the deleted or copied text before the global marker, even when the
1214global marker is in another buffer.
1215If the global marker isn't set, set the global marker at point in the current
1216buffer. Otherwise jump to the global marker position and cancel it.
1217With prefix argument, don't jump to global mark when cancelling it."
1218 (interactive "P")
1219 (if (not (CUA-global-mark-active))
1220 (if (not buffer-read-only)
1221 (CUA-global-mark-activate t)
1222 (ding)
1223 (message "Cannot set global mark in read-only buffer."))
1224 (when (not stay)
1225 (pop-to-buffer (marker-buffer CUA-global-mark))
1226 (goto-char CUA-global-mark))
1227 (CUA-global-mark-deactivate t)))
1228
1229(defun CUA-global-mark-insert (str &optional msg)
1230 ;; Insert string at global marker and move marker
1231 (save-excursion
1232 (set-buffer (marker-buffer CUA-global-mark))
1233 (goto-char (marker-position CUA-global-mark))
1234 (insert str)
1235 (CUA-global-mark-activate))
1236 (if msg
1237 (message "%s %d to global mark in %s:%d" msg
1238 (length str)
1239 (buffer-name (marker-buffer CUA-global-mark))
1240 (marker-position CUA-global-mark))))
1241
1242(defun CUA-global-mark-delete-char (arg &optional msg)
1243 ;; Delete chars at global marker
1244 (save-excursion
1245 (set-buffer (marker-buffer CUA-global-mark))
1246 (goto-char (marker-position CUA-global-mark))
1247 (delete-char arg))
1248 (if msg
1249 (message "%s %d chars at global mark in %s:%d" msg arg
1250 (buffer-name (marker-buffer CUA-global-mark))
1251 (marker-position CUA-global-mark))))
1252
1253(defun CUA-global-mark-copy-region (start end)
1254 "Copy region to global mark buffer/position."
1255 (interactive "r")
1256 (if (CUA-global-mark-active)
1257 (let ((src-buf (current-buffer)))
1258 (save-excursion
1259 (if (equal (marker-buffer CUA-global-mark) src-buf)
1260 (let ((text (buffer-substring-no-properties start end)))
1261 (goto-char (marker-position CUA-global-mark))
1262 (insert text))
1263 (set-buffer (marker-buffer CUA-global-mark))
1264 (goto-char (marker-position CUA-global-mark))
1265 (insert-buffer-substring src-buf start end))
1266 (CUA-global-mark-activate)
1267 (message "Copied %d to global mark in %s:%d"
1268 (abs (- end start))
1269 (buffer-name (marker-buffer CUA-global-mark))
1270 (marker-position CUA-global-mark))))
1271 (CUA-global-mark-deactivate)
1272 (message "No Global Mark")))
1273
1274(defun CUA-global-mark-move-region (start end)
1275 "Move region to global buffer/position."
1276 (interactive "r")
1277 (if (CUA-global-mark-active)
1278 (let ((src-buf (current-buffer)))
1279 (save-excursion
1280 (if (equal (marker-buffer CUA-global-mark) src-buf)
1281 (if (and (< start (marker-position CUA-global-mark))
1282 (< (marker-position CUA-global-mark) end))
1283 (message "Can't move region into itself.")
1284 (let ((text (buffer-substring-no-properties start end))
1285 (p1 (copy-marker start))
1286 (p2 (copy-marker end)))
1287 (goto-char (marker-position CUA-global-mark))
1288 (insert text)
1289 (CUA-global-mark-activate)
1290 (delete-region (marker-position p1) (marker-position p2))
1291 (move-marker p1 nil)
1292 (move-marker p2 nil)))
1293 (set-buffer (marker-buffer CUA-global-mark))
1294 (goto-char (marker-position CUA-global-mark))
1295 (insert-buffer-substring src-buf start end)
1296 (message "Moved %d to global mark in %s:%d"
1297 (abs (- end start))
1298 (buffer-name (marker-buffer CUA-global-mark))
1299 (marker-position CUA-global-mark))
1300 (CUA-global-mark-activate)
1301 (set-buffer src-buf)
1302 (delete-region start end))))
1303 (CUA-global-mark-deactivate)
1304 (message "No Global Mark")))
1305
1306(defvar CUA-global-mark-do-rect-as-text nil)
1307
1308(defun CUA-global-mark-copy-rect ()
1309 "Copy rectangle to global mark buffer/position."
1310 (if (CUA-global-mark-active)
1311 (let ((src-buf (current-buffer))
1312 (text (CUA-extract-rectangle)))
1313 (save-excursion
1314 (set-buffer (marker-buffer CUA-global-mark))
1315 (goto-char (marker-position CUA-global-mark))
1316 (if CUA-global-mark-do-rect-as-text
1317 (while text
1318 (insert (car text))
1319 (if (setq text (cdr text))
1320 (insert "\n")))
1321 (CUA-insert-rectangle text 'auto))
1322 (CUA-global-mark-activate)
1323 (message "Copied rectangle to global mark in %s:%d"
1324 (buffer-name (marker-buffer CUA-global-mark))
1325 (marker-position CUA-global-mark))))
1326 (CUA-global-mark-deactivate)
1327 (message "No Global Mark")))
1328
1329(defun CUA-global-mark-move-rect ()
1330 "Move rectangle to global buffer/position."
1331 (if (CUA-global-mark-active)
1332 (let ((src-buf (current-buffer)))
1333 (save-excursion
1334 (if (equal (marker-buffer CUA-global-mark) src-buf)
1335 (let ((olist (overlays-at (marker-position CUA-global-mark)))
1336 in-rect)
1337 (while olist
1338 (if (eq (overlay-get (car olist) 'face) 'CUA-rectangle-face)
1339 (setq in-rect t olist nil)
1340 (setq olist (cdr olist))))
1341 (if in-rect
1342 (message "Can't move rectangle into itself.")
1343 (let ((text (CUA-extract-rectangle)))
1344 (CUA-delete-rectangle)
1345 (goto-char (marker-position CUA-global-mark))
1346 (if CUA-global-mark-do-rect-as-text
1347 (while text
1348 (insert (car text))
1349 (if (setq text (cdr text))
1350 (insert "\n")))
1351 (CUA-insert-rectangle text 'auto))
1352 (CUA-global-mark-activate))))
1353 (let ((text (CUA-extract-rectangle)))
1354 (CUA-delete-rectangle)
1355 (set-buffer (marker-buffer CUA-global-mark))
1356 (goto-char (marker-position CUA-global-mark))
1357 (CUA-insert-rectangle text 'auto))
1358 (message "Moved rectangle to global mark in %s:%d"
1359 (buffer-name (marker-buffer CUA-global-mark))
1360 (marker-position CUA-global-mark))
1361 (CUA-global-mark-activate))))
1362 (CUA-global-mark-deactivate)
1363 (message "No Global Mark")))
1364
1365;;; Enhanced undo - restore rectangle selections
1366
1367(defvar CUA-undo-list nil
1368 "Per-buffer CUA mode undo list.")
1369
1370(defvar CUA-undo-max 64
1371 "*Max no of undoable CUA rectangle changes (including undo).")
1372
1373(defun CUA-rect-undo-boundary ()
1374 (when (listp buffer-undo-list)
1375 (if (> (length CUA-undo-list) CUA-undo-max)
1376 (setcdr (nthcdr (1- CUA-undo-max) CUA-undo-list) nil))
1377 (undo-boundary)
1378 (setq CUA-undo-list
1379 (cons (cons (cdr buffer-undo-list) (copy-sequence CUA-rectangle)) CUA-undo-list))))
1380
1381(defun CUA-undo (&optional arg)
1382 "Undo some previous changes.
1383Knows about CUA rectangle highlighting in addition to standard undo."
1384 (interactive "*P")
1385 (if CUA-rectangle
1386 (CUA-rect-undo-boundary))
1387 (undo arg)
1388 (let ((l CUA-undo-list))
1389 (while l
1390 (if (eq (car (car l)) pending-undo-list)
1391 (setq CUA-next-rectangle
1392 (and (vectorp (cdr (car l))) (cdr (car l)))
1393 l nil)
1394 (setq l (cdr l)))))
1395 (setq CUA-start-point nil))
1396
1397(defvar CUA-tidy-undo-counter 0
1398 "Number of times `CUA-tidy-undo-lists' have run successfully.")
1399
1400(defun CUA-tidy-undo-lists (&optional clean)
1401 (let ((buffers (buffer-list)) (cnt CUA-tidy-undo-counter))
1402 (while (and buffers (or clean (not (input-pending-p))))
1403 (with-current-buffer (car buffers)
1404 (when (local-variable-p 'CUA-undo-list)
1405 (if (or clean (null CUA-undo-list) (eq buffer-undo-list t))
1406 (progn
1407 (kill-local-variable 'CUA-undo-list)
1408 (setq CUA-tidy-undo-counter (1+ CUA-tidy-undo-counter)))
1409 (let* ((bul buffer-undo-list)
1410 (cul (cons nil CUA-undo-list))
1411 (cc (car (car (cdr cul)))))
1412 (while (and bul cc)
1413 (if (setq bul (memq cc bul))
1414 (setq cul (cdr cul)
1415 cc (and (cdr cul) (car (car (cdr cul)))))))
1416 (when cc
1417 (if CUA-debug
1418 (setq cc (length (cdr cul))))
1419 (if (eq (cdr cul) CUA-undo-list)
1420 (setq CUA-undo-list nil)
1421 (setcdr cul nil))
1422 (setq CUA-tidy-undo-counter (1+ CUA-tidy-undo-counter))
1423 (if CUA-debug
1424 (message "Clean undo list in %s (%d)"
1425 (buffer-name) cc)))))))
1426 (setq buffers (cdr buffers)))
1427 (/= cnt CUA-tidy-undo-counter)))
1428
1429;;; Aux functions
1430
1431(defun CUA-indent-active-region (start end backw)
1432 (message "Indenting...")
1433 (let (amount (arg current-prefix-arg))
1434 (save-excursion
1435 (goto-char start)
1436 (setq start (line-beginning-position)))
1437 (if (equal arg '(4))
1438 (indent-region start end nil)
1439 (setq amount (if arg (prefix-numeric-value arg) tab-width))
1440 (indent-rigidly start end (if backw (- amount) amount)))))
1441
1442(defun CUA-set-mark (&optional jump)
1443 "Set mark at where point is, clear mark, or jump to mark.
1444With no prefix argument, set mark, push old mark position on local mark
1445ring, and push mark on global mark ring, or if mark is already set, clear mark.
1446With argument, jump to mark, and pop a new position for mark off the ring."
1447 (interactive "P")
1448 (cond
1449 (jump
1450 (set-mark-command t))
1451 (mark-active
1452 (setq mark-active nil
1453 CUA-explicit-region-start nil)
1454 (message "Mark Cleared"))
1455 (t
1456 (set-mark-command nil)
1457 (setq CUA-explicit-region-start t)
1458 (if CUA-mode-auto-help
1459 (CUA-help-for-region t)))))
1460
1461(defun CUA-keep-active (keep)
1462 (if keep
1463 (setq mark-active t
1464 deactivate-mark nil)
1465 (setq mark-active nil
1466 CUA-explicit-region-start nil)
1467 (run-hooks 'deactivate-mark-hook)))
1468
1469;;
1470;; region functions / actions
1471;;
1472
1473(defun CUA-cmd-copy-region ()
1474 (interactive)
1475 (setq CUA-rect-last-killed nil)
1476 (let ((start (mark)) (end (point)))
1477 (or (<= start end)
1478 (setq start (prog1 end (setq end start))))
1479 (if (CUA-register)
1480 (copy-to-register (CUA-register) start end nil)
1481 (copy-region-as-kill start end))
1482 (CUA-keep-active CUA-mode-keep-region-after-copy)))
1483
1484(defun CUA-cmd-cut-region ()
1485 (interactive)
1486 (setq CUA-rect-last-killed nil)
1487 (if buffer-read-only
1488 (CUA-cmd-copy-region)
1489 (let ((start (mark)) (end (point)))
1490 (or (<= start end)
1491 (setq start (prog1 end (setq end start))))
1492 (if (CUA-register)
1493 (copy-to-register (CUA-register) start end t)
1494 (kill-region start end)))
1495 (CUA-keep-active nil)))
1496
1497(defun CUA-cmd-delete-region ()
1498 (interactive)
1499 (let ((start (mark)) (end (point)))
1500 (or (<= start end)
1501 (setq start (prog1 end (setq end start))))
1502 (if CUA-mode-delete-to-register-0
1503 (copy-to-register ?0 start end nil))
1504 (delete-region start end)
1505 (CUA-keep-active nil)))
1506
1507(defun CUA-cmd-indent-region-left ()
1508 (interactive)
1509 (let ((start (mark)) (end (point)))
1510 (or (<= start end)
1511 (setq start (prog1 end (setq end start))))
1512 (CUA-indent-active-region start end nil)
1513 (CUA-keep-active t)))
1514
1515(defun CUA-cmd-indent-region-right ()
1516 (interactive)
1517 (let ((start (mark)) (end (point)))
1518 (or (<= start end)
1519 (setq start (prog1 end (setq end start))))
1520 (CUA-indent-active-region start end t)
1521 (CUA-keep-active t)))
1522
1523;;
1524;; rectangle functions / actions
1525;;
1526
1527(defun CUA-cmd-begin-rectangle (&optional reopen)
1528 "Set mark and start in CUA rectangle mode.
1529With prefix argument, activate previous rectangle if possible."
1530 (interactive "P")
1531 (when (not CUA-rectangle)
1532 (if (and reopen
1533 CUA-last-rectangle
1534 (eq (car CUA-last-rectangle) (current-buffer)))
1535 (goto-char (car (cdr CUA-last-rectangle)))
1536 (if (not mark-active)
1537 (set-mark-command nil)))
1538 (CUA-rect-activate)
1539 (CUA-rect-set-corners)
1540 (setq mark-active t
1541 CUA-explicit-region-start t)
1542 (if CUA-mode-auto-help
1543 (CUA-help-for-rectangle t))))
1544
1545(defun CUA-cmd-end-rectangle ()
1546 "Cancel current rectangle."
1547 (interactive)
1548 (when CUA-rectangle
1549 (setq mark-active nil
1550 CUA-explicit-region-start nil)
1551 (CUA-rect-deactivate)))
1552
1553(defun CUA-cmd-restrict-regexp-rectangle (arg)
1554 "Restrict rectangle to lines (not) matching REGEXP.
1555With prefix argument, the toggle restriction."
1556 (interactive "P")
1557 (CUA-absorb-prefix-arg)
1558 (let ((r (CUA-rect-restriction)) regexp)
1559 (if (and r (null (car (cdr r))))
1560 (if arg
1561 (CUA-rect-restriction (car r) nil (not (car (cdr (cdr r)))))
1562 (CUA-rect-restriction "" nil nil))
1563 (CUA-rect-restriction
1564 (read-from-minibuffer "Restrict rectangle (regexp): "
1565 nil nil nil nil) nil arg))))
1566
1567(defun CUA-cmd-restrict-prefix-rectangle (arg)
1568 "Restrict rectangle to lines (not) starting with CHAR.
1569With prefix argument, the toggle restriction."
1570 (interactive "P")
1571 (CUA-absorb-prefix-arg)
1572 (let ((r (CUA-rect-restriction)) regexp)
1573 (if (and r (car (cdr r)))
1574 (if arg
1575 (CUA-rect-restriction (car r) t (not (car (cdr (cdr r)))))
1576 (CUA-rect-restriction "" nil nil))
1577 (CUA-rect-restriction
1578 (format "[%c]"
1579 (read-char "Restrictive rectangle (char): ")) t arg))))
1580
1581(defun CUA-cmd-move-rectangle-up ()
1582 (interactive)
1583 (CUA-rect-move 'up))
1584
1585(defun CUA-cmd-move-rectangle-down ()
1586 (interactive)
1587 (CUA-rect-move 'down))
1588
1589(defun CUA-cmd-move-rectangle-left ()
1590 (interactive)
1591 (CUA-rect-move 'left))
1592
1593(defun CUA-cmd-move-rectangle-right ()
1594 (interactive)
1595 (CUA-rect-move 'right))
1596
1597(defun CUA-cmd-copy-rectangle ()
1598 (interactive)
1599 (CUA-rect-copy-as-kill)
1600 (CUA-keep-active CUA-mode-keep-region-after-copy))
1601
1602(defun CUA-cmd-cut-rectangle ()
1603 (interactive)
1604 (if buffer-read-only
1605 (CUA-cmd-copy-rectangle)
1606 (goto-char (min (mark) (point)))
1607 (CUA-rect-copy-as-kill)
1608 (CUA-delete-rectangle))
1609 (CUA-keep-active nil))
1610
1611(defun CUA-cmd-delete-rectangle ()
1612 (interactive)
1613 (goto-char (min (point) (mark)))
1614 (if CUA-mode-delete-to-register-0
1615 (set-register ?0 (CUA-extract-rectangle)))
1616 (CUA-delete-rectangle)
1617 (CUA-keep-active nil))
1618
1619(defun CUA-cmd-toggle-rectangle ()
1620 (interactive)
1621 (if CUA-rectangle
1622 (CUA-rect-deactivate)
1623 (CUA-rect-activate))
1624 (if CUA-mode-auto-help
1625 (if CUA-rectangle
1626 (CUA-help-for-rectangle t)
1627 (CUA-help-for-region t))))
1628
1629(defun CUA-cmd-rotate-rectangle ()
1630 (interactive)
1631 (CUA-rect-corner (if (= (CUA-rect-left) (CUA-rect-right)) 0 1))
1632 (CUA-rect-set-corners))
1633
1634(defun CUA-cmd-toggle-rectangle-padding ()
1635 (interactive)
1636 (if buffer-read-only
1637 (message "Cannot do padding in read-only buffer.")
1638 (CUA-rect-padding t (not (CUA-rect-padding)))
1639 (CUA-pad-rectangle)
1640 (CUA-rect-set-corners))
1641 (setq CUA-mode-status (and (CUA-rect-padding) " Pad"))
1642 (CUA-keep-active t))
1643
1644(defun CUA-cmd-do-rectangle-padding ()
1645 (interactive)
1646 (if buffer-read-only
1647 (message "Cannot do padding in read-only buffer.")
1648 (CUA-pad-rectangle t)
1649 (CUA-rect-set-corners))
1650 (CUA-keep-active t))
1651
1652(defun CUA-cmd-open-rectangle ()
1653 "Blank out CUA rectangle, shifting text right.
1654The text previously in the region is not overwritten by the blanks,
1655but instead winds up to the right of the rectangle."
1656 (interactive)
1657 (CUA-rect-operation 'CUA-cmd-open-rectangle nil t 1
1658 '(lambda (s e l r)
1659 (skip-chars-forward " \t")
1660 (let ((ws (- (current-column) l))
1661 (p (point)))
1662 (skip-chars-backward " \t")
1663 (delete-region (point) p)
1664 (indent-to (+ r ws))))))
1665(put 'CUA-cmd-open-rectangle 'CUA-rect 'corners)
1666
1667(defun CUA-cmd-close-rectangle (arg)
1668 "Delete all whitespace starting at left edge of CUA rectangle.
1669On each line in the rectangle, all continuous whitespace starting
1670at that column is deleted.
1671With prefix arg, also delete whitespace to the left of that column."
1672 (interactive "P")
1673 (CUA-absorb-prefix-arg)
1674 (CUA-rect-operation 'CUA-cmd-close-rectangle nil t 1
1675 '(lambda (s e l r)
1676 (when arg
1677 (skip-syntax-backward " " (line-beginning-position))
1678 (setq s (point)))
1679 (skip-syntax-forward " " (line-end-position))
1680 (delete-region s (point)))))
1681(put 'CUA-cmd-close-rectangle 'CUA-rect 'clear)
1682
1683(defun CUA-cmd-blank-rectangle ()
1684 "Blank out CUA rectangle.
1685The text previously in the rectangle is overwritten by the blanks."
1686 (interactive)
1687 (CUA-rect-operation 'CUA-cmd-blank-rectangle nil nil 1
1688 '(lambda (s e l r)
1689 (goto-char e)
1690 (skip-syntax-forward " " (line-end-position))
1691 (setq e (point))
1692 (let ((column (current-column)))
1693 (goto-char s)
1694 (skip-syntax-backward " " (line-beginning-position))
1695 (delete-region (point) e)
1696 (indent-to column)))))
1697(put 'CUA-cmd-blank-rectangle 'CUA-rect 'keep)
1698
1699(defun CUA-cmd-align-rectangle ()
1700 "Align rectangle lines to left column."
1701 (interactive)
1702 (let (x)
1703 (CUA-rect-operation 'CUA-cmd-align-rectangle nil t t
1704 '(lambda (s e l r)
1705 (let ((b (line-beginning-position)))
1706 (skip-syntax-backward "^ " b)
1707 (skip-syntax-backward " " b)
1708 (setq s (point)))
1709 (skip-syntax-forward " " (line-end-position))
1710 (delete-region s (point))
1711 (indent-to l))
1712 '(lambda (l r)
1713 (move-to-column l)
1714 (setq CUA-save-point (point))))))
1715(put 'CUA-cmd-align-rectangle 'CUA-rect 'clear)
1716
1717(defun CUA-cmd-copy-rectangle-as-text (&optional delete)
1718 "Copy rectangle, but store as normal text."
1719 (interactive)
1720 (if (CUA-global-mark-active)
1721 (let ((CUA-global-mark-do-rect-as-text t))
1722 (if (eq delete 'delete)
1723 (CUA-global-mark-move-rect)
1724 (CUA-global-mark-copy-rect)))
1725 (let* ((rect (CUA-extract-rectangle))
1726 (text (mapconcat
1727 (function (lambda (row) (concat row "\n")))
1728 rect "")))
1729 (if (CUA-register)
1730 (set-register (CUA-register) text)
1731 (kill-new text)))
1732 (if (eq delete 'delete)
1733 (CUA-delete-rectangle))
1734 (CUA-keep-active nil)))
1735
1736(defun CUA-cmd-cut-rectangle-as-text ()
1737 "Kill rectangle, but store as normal text."
1738 (interactive)
1739 (CUA-cmd-copy-rectangle-as-text (or buffer-read-only 'delete)))
1740
1741(defun CUA-cmd-string-rectangle (string)
1742 "Replace CUA rectangle contents with STRING on each line.
1743The length of STRING need not be the same as the rectangle width."
1744 (interactive "sString rectangle: ")
1745 (CUA-rect-operation 'CUA-cmd-string-rectangle nil t t
1746 '(lambda (s e l r)
1747 (delete-region s e)
1748 (skip-chars-forward " \t")
1749 (let ((ws (- (current-column) l)))
1750 (delete-region s (point))
1751 (insert string)
1752 (indent-to (+ (current-column) ws))))
1753 (unless (CUA-rect-restriction)
1754 '(lambda (l r)
1755 (CUA-rect-right (max l (+ l (length string) -1)))))))
1756(put 'CUA-cmd-string-rectangle 'CUA-rect 'keep)
1757
1758(defun CUA-cmd-fill-char-rectangle (ch)
1759 "Replace CUA rectangle contents with CHARACTER."
1760 (interactive "cFill rectangle with character: ")
1761 (CUA-rect-operation 'CUA-cmd-fill-char-rectangle nil t 1
1762 '(lambda (s e l r)
1763 (delete-region s e)
1764 (insert-char ch (- r l)))))
1765(put 'CUA-cmd-fill-char-rectangle 'CUA-rect 'clear)
1766
1767(defun CUA-cmd-replace-in-rectangle (regexp newtext)
1768 "Replace REGEXP with NEWTEXT in each line of CUA rectangle."
1769 (interactive "sReplace regexp: \nsNew text: ")
1770 (if buffer-read-only
1771 (message "Cannot replace in read-only buffer")
1772 (CUA-rect-operation 'CUA-cmd-replace-in-rectangle nil t 1
1773 '(lambda (s e l r)
1774 (if (re-search-forward regexp e t)
1775 (replace-match newtext nil nil))))))
1776(put 'CUA-cmd-replace-in-rectangle 'CUA-rect 'keep)
1777
1778(defun CUA-cmd-incr-rectangle (increment)
1779 "Increment each line of CUA rectangle by prefix amount."
1780 (interactive "p")
1781 (CUA-absorb-prefix-arg)
1782 (CUA-rect-operation 'CUA-cmd-incr-rectangle nil t 1
1783 '(lambda (s e l r)
1784 (cond
1785 ((re-search-forward "0x\\([0-9a-fA-F]+\\)" e t)
1786 (let* ((txt (buffer-substring-no-properties (match-beginning 1) (match-end 1)))
1787 (n (string-to-number txt 16))
1788 (fmt (concat "0x%0" (length txt) "x")))
1789 (replace-match (format fmt (+ n increment)))))
1790 ((re-search-forward "\\( *-?[0-9]+\\)" e t)
1791 (let* ((txt (buffer-substring-no-properties (match-beginning 1) (match-end 1)))
1792 (n (string-to-number txt 10))
1793 (fmt (concat "%" (length txt) "d")))
1794 (replace-match (format fmt (+ n increment)))))
1795 (t nil))))
1796 (CUA-keep-active t))
1797(put 'CUA-cmd-incr-rectangle 'CUA-rect 'clear)
1798
1799(defvar CUA-rect-seq-format "%d"
1800 "Last format used by CUA-cmd-sequence-rectangle.")
1801
1802(defun CUA-cmd-sequence-rectangle (first incr fmt)
1803 "Resequence each line of CUA rectangle starting from FIRST.
1804The numbers are formatted according to the FORMAT string."
1805 (interactive
1806 (list (if current-prefix-arg
1807 (prefix-numeric-value current-prefix-arg)
1808 (string-to-number
1809 (read-string "Start value: (0) " nil nil "0")))
1810 (string-to-number
1811 (read-string "Increment: (1) " nil nil "1"))
1812 (read-string (concat "Format: (" CUA-rect-seq-format ") "))))
1813 (if (= (length fmt) 0)
1814 (setq fmt CUA-rect-seq-format)
1815 (setq CUA-rect-seq-format fmt))
1816 (CUA-rect-operation 'CUA-cmd-sequence-rectangle nil t 1
1817 '(lambda (s e l r)
1818 (delete-region s e)
1819 (insert (format fmt first))
1820 (setq first (+ first incr)))))
1821(put 'CUA-cmd-sequence-rectangle 'CUA-rect 'clear)
1822
1823(defun CUA-cmd-upcase-rectangle ()
1824 "Convert the rectangle to upper case."
1825 (interactive)
1826 (CUA-rect-operation 'CUA-cmd-upcase-rectangle nil nil nil
1827 '(lambda (s e l r)
1828 (upcase-region s e))))
1829(put 'CUA-cmd-upcase-rectangle 'CUA-rect 'clear)
1830
1831(defun CUA-cmd-downcase-rectangle ()
1832 "Convert the rectangle to lower case."
1833 (interactive)
1834 (CUA-rect-operation 'CUA-cmd-downcase-rectangle nil nil nil
1835 '(lambda (s e l r)
1836 (downcase-region s e))))
1837(put 'CUA-cmd-downcase-rectangle 'CUA-rect 'clear)
1838
1839(defun CUA-rect-aux-replace (width adjust keep replace pad format-fct &optional insert-fct)
1840 ;; Process text inserted by calling INSERT-FCT or current rectangle if nil.
1841 ;; Then call FORMAT-FCT on text (if non-nil); takes two args: start and end.
1842 ;; Fill to WIDTH characters if > 0 or fill to current width if == 0.
1843 ;; Don't fill if WIDTH < 0.
1844 ;; Replace current rectangle by filled text if REPLACE is non-nil
1845 (let ((m (get-buffer-create "*CUA temp*"))
1846 (w (- (CUA-rect-right) (CUA-rect-left) -1))
1847 (r (or insert-fct (CUA-extract-rectangle)))
1848 y z)
1849 (if (> width 1)
1850 (setq w width))
1851 (save-excursion
1852 (set-buffer m)
1853 (erase-buffer)
1854 (if insert-fct
1855 (funcall insert-fct)
1856 (CUA-insert-rectangle r))
1857 (if format-fct
1858 (let ((fill-column w))
1859 (funcall format-fct (point-min) (point-max))))
1860 (when replace
1861 (goto-char (point-min))
1862 (while (not (eobp))
1863 (setq z (cons (buffer-substring (point) (line-end-position)) z)
1864 w (if (> (setq y (length (car z))) w) y w))
1865 (forward-line 1))))
1866 (kill-buffer m)
1867 (when replace
1868 (setq z (reverse z))
1869 (CUA-rect-operation nil nil t pad
1870 '(lambda (s e l r)
1871 (let (cc)
1872 (goto-char e)
1873 (skip-chars-forward " \t")
1874 (setq cc (current-column))
1875 (delete-region s e)
1876 (if (not z)
1877 (setq y 0)
1878 (insert (car z))
1879 (setq y (length (car z)))
1880 (setq z (cdr z)))
1881 ;(if(> w y)
1882 ;(insert-char ? (- w y)))
1883 (indent-to cc))))
1884 (if adjust
1885 (CUA-rect-right (+ (CUA-rect-left) w -1)))
1886 (if keep
1887 (CUA-keep-active t)))))
1888
1889(put 'CUA-rect-aux-replace 'lisp-indent-function 4)
1890
1891(defun CUA-cmd-text-fill-rectangle (width text)
1892 "Replace rectagle with filled TEXT read from minibuffer.
1893A numeric prefix argument is used a new width for the filled rectangle."
1894 (interactive (list
1895 (prog1 (prefix-numeric-value current-prefix-arg)
1896 (CUA-absorb-prefix-arg))
1897 (read-from-minibuffer "Enter text: "
1898 nil nil nil nil)))
1899 (CUA-rect-aux-replace width t t t 1
1900 'fill-region
1901 '(lambda () (insert text))))
1902
1903(defun CUA-cmd-self-fill-rectangle (width)
1904 "Fill contents of current rectagle.
1905A numeric prefix argument is used a new width for the filled rectangle."
1906 (interactive "p")
1907 (CUA-absorb-prefix-arg)
1908 (CUA-rect-aux-replace width t t t 1 'fill-region))
1909
1910(defun CUA-cmd-shell-command-on-rectangle (replace command)
1911 "Run shell command on rectangle like `shell-command-on-region'.
1912With prefix arg, replace rectangle with output from command."
1913 (interactive (list
1914 (prog1 current-prefix-arg (CUA-absorb-prefix-arg))
1915 (read-from-minibuffer "Shell command on rectangle: "
1916 nil nil nil
1917 'shell-command-history)))
1918 (CUA-rect-aux-replace -1 t t replace 1
1919 '(lambda (s e)
1920 (shell-command-on-region s e command
1921 replace replace nil))))
1922
1923(defun CUA-cmd-reverse-rectangle ()
1924 "Reverse the lines of the rectangle."
1925 (interactive)
1926 (CUA-rect-aux-replace 0 t t t t 'reverse-region))
1927
1928(defun CUA-cmd-scroll-rectangle-up ()
1929 "Remove the first line of the rectangle and scroll remaining lines up."
1930 (interactive)
1931 (CUA-rect-aux-replace 0 t t t t
1932 '(lambda (s e)
1933 (if (= (forward-line 1) 0)
1934 (delete-region s (point))))))
1935
1936(defun CUA-cmd-scroll-rectangle-down ()
1937 "Insert a blank line at the first line of the rectangle.
1938The remaining lines are scrolled down, losing the last line."
1939 (interactive)
1940 (CUA-rect-aux-replace 0 t t t t
1941 '(lambda (s e)
1942 (goto-char s)
1943 (insert "\n"))))
1944
1945(defun CUA-action-insert-char-rectangle ()
1946 (if buffer-read-only
1947 (ding)
1948 (CUA-rect-indent-rectangle
1949 (aref (this-single-command-keys) 0))
1950 (CUA-keep-active t))
1951 t)
1952
1953(defun CUA-cmd-delete-char-rectangle ()
1954 "Delete char to left or right of rectangle."
1955 (interactive)
1956 (let ((col (CUA-rect-insert-col))
1957 (pad (CUA-rect-padding))
1958 indent)
1959 (CUA-rect-operation 'CUA-cmd-delete-char-rectangle nil t pad
1960 '(lambda (s e l r)
1961 (move-to-column
1962 (if (CUA-rect-right-side t)
1963 (max (1+ r) col) l)
1964 pad)
1965 (if (bolp)
1966 nil
1967 (delete-backward-char 1)
1968 (if (CUA-rect-right-side t)
1969 (CUA-rect-insert-col (current-column))
1970 (setq indent (- l (current-column))))))
1971 '(lambda (l r)
1972 (when (and indent (> indent 0))
1973 (aset CUA-rectangle 2 (- l indent))
1974 (aset CUA-rectangle 3 (- r indent 1)))))))
1975(put 'CUA-cmd-delete-char-rectangle 'CUA-rect 'corners)
1976
1977(defun CUA-cmd-mouse-set-rectangle-corner (event)
1978 "Set rectangle corner at mouse click position."
1979 (interactive "e")
1980 (mouse-set-point event)
1981 (if (CUA-rect-padding)
1982 (move-to-column (car (posn-col-row (event-end event))) t))
1983 (if (CUA-rect-right-side)
1984 (CUA-rect-right (current-column))
1985 (CUA-rect-left (current-column)))
1986 (if (>= (CUA-rect-corner) 2)
1987 (CUA-rect-bot t)
1988 (CUA-rect-top t))
1989 (CUA-pad-rectangle)
1990 (CUA-rect-insert-col 0)
1991 (CUA-rect-set-corners)
1992 (CUA-keep-active t)
1993 (setq CUA-start-point nil))
1994
1995
1996
1997;;
1998;; global mark actions
1999;;
2000(defun CUA-cmd-copy-to-global-mark ()
2001 (interactive)
2002 (setq CUA-rect-last-killed nil)
2003 (if CUA-rectangle
2004 (CUA-global-mark-copy-rect)
2005 (let ((start (mark)) (end (point)))
2006 (or (<= start end)
2007 (setq start (prog1 end (setq end start))))
2008 (CUA-global-mark-copy-region start end))))
2009
2010(defun CUA-cmd-copy1-to-global-mark (n)
2011 (interactive "p")
2012 (CUA-absorb-prefix-arg)
2013 (setq CUA-rect-last-killed nil)
2014 (or (eobp)
2015 (let ((p (point)))
2016 (goto-char (+ p n))
2017 (CUA-global-mark-copy-region p (point)))))
2018
2019(defun CUA-cmd-cut-to-global-mark ()
2020 (interactive)
2021 (if buffer-read-only
2022 (CUA-cmd-copy-to-global-mark)
2023 (setq CUA-rect-last-killed nil)
2024 (if CUA-rectangle
2025 (CUA-global-mark-move-rect)
2026 (let ((start (mark)) (end (point)))
2027 (or (<= start end)
2028 (setq start (prog1 end (setq end start))))
2029 (CUA-global-mark-move-region start end)))))
2030
2031(defun CUA-cmd-cut1-to-global-mark (n)
2032 (interactive "p")
2033 (CUA-absorb-prefix-arg)
2034 (setq CUA-rect-last-killed nil
2035 current-prefix-arg nil
2036 overriding-terminal-local-map nil)
2037 (or (eobp)
2038 (let ((p (point)))
2039 (goto-char (+ p n))
2040 (CUA-global-mark-move-region p (point)))))
2041
2042(defun CUA-cmd-delete-char-at-global-mark (arg)
2043 (interactive "p")
2044 (CUA-absorb-prefix-arg)
2045 (if (window-minibuffer-p)
2046 nil
2047 (CUA-global-mark-delete-char arg "Deleted")
2048 t))
2049
2050(defun CUA-cmd-delete-backward-char-at-global-mark (arg)
2051 (interactive "p")
2052 (CUA-absorb-prefix-arg)
2053 (if (window-minibuffer-p)
2054 nil
2055 (CUA-global-mark-delete-char (- arg) "Deleted backward")
2056 t))
2057
2058(defun CUA-action-insert-char-at-global-mark ()
2059 (if (window-minibuffer-p)
2060 nil
2061 (CUA-global-mark-insert (char-to-string (aref (this-single-command-keys) 0)) "Inserted")
2062 t))
2063
2064(defun CUA-action-insert-newline-at-global-mark ()
2065 (if (window-minibuffer-p)
2066 nil
2067 (CUA-global-mark-insert "\n")
2068 t))
2069
2070
2071(defun CUA-cmd-insert-newline-at-global-mark ()
2072 (interactive)
2073 (if (not (CUA-action-insert-newline-at-global-mark))
2074 (call-interactively CUA-orig-command)))
2075
2076;;
2077;; misc functions
2078;;
2079
2080(defun CUA-cmd-ignore (arg)
2081 (interactive "P")
2082 (CUA-absorb-prefix-arg))
2083(defun CUA-lookup-key (map key)
2084 (let ((k (lookup-key map key)))
2085 (and k
2086 (not (integerp k))
2087 k)))
2088
2089;;
2090;; command specific CUA actions
2091;;
2092
2093(defvar CUA-region-commands
2094 '((CUA-action-delete-before ; delete current region before command
2095 self-insert-command self-insert-iso
2096 insert-register newline-and-indent newline open-line)
2097 (CUA-action-delete ; delete current region and ignore command
2098 delete-backward-char backward-delete-char
2099 backward-delete-char-untabify delete-char)
2100 (CUA-action-cut ; kill region and ignore command
2101 kill-region)
2102 (CUA-action-copy ; copy region and ignore command
2103 copy-region-as-kill kill-ring-save)
2104 (CUA-action-paste ; replace region with rectangle or element on kill ring
2105 yank clipboard-yank)
2106 (CUA-action-paste-pop ; replace current yank with previous kill ring element
2107 yank-pop)
2108 (CUA-action-cancel ; cancel current region
2109 keyboard-escape-quit keyboard-quit))
2110 "Specifies how various editing functions behave in CUA mode.
2111The value is a list of lists. For each element in the list, the
2112first element is an action function and the rest of the list are names of
2113editing commands which shall perform the specified action if the
2114region is active and CUA mode is enabled.
2115Note: These actions are only used if an action is not specified
2116in the state specific CUA keymap for the current command.
2117The action functions are called without arguments, and if they return
2118a non-nil value, the original command is not executed.")
2119
2120(defun CUA-action-move ()
2121 ;; Action handler for cursor movement keys.
2122 ;; If region is not active, region is activated if key is shifted.
2123 ;; If region is active, region is cancelled if key is unshifted (and region not started with C-SPC).
2124 ;; If rectangle is active, expand rectangle in specified direction and ignore the movement.
2125 (if (or CUA-explicit-region-start
2126 CUA-rectangle
2127 (memq 'shift (event-modifiers (aref (this-single-command-keys) 0))))
2128 (and (not mark-active) (set-mark-command nil))
2129 (setq mark-active nil))
2130 (and mark-active CUA-rectangle
2131 (CUA-rect-resize this-command)))
2132
2133(eval-when-compile
2134 (defvar CUA-this-action nil))
2135
2136(defun CUA-action-cancel ()
2137 ;; Action handler which cancels the region.
2138 (setq mark-active nil
2139 CUA-explicit-region-start nil)
2140 (if CUA-rectangle
2141 (CUA-rect-deactivate))
2142 (setq CUA-last-rectangle nil)
2143 (if (CUA-global-mark-active)
2144 (CUA-global-mark-deactivate t)))
2145
2146(defun CUA-action-delete-before ()
2147 ;; Action handler which deletes the region before the command is executed.
2148 (if mark-active
2149 (if CUA-rectangle
2150 (CUA-cmd-delete-rectangle)
2151 (CUA-cmd-delete-region)))
2152 nil)
2153
2154(defun CUA-action-delete ()
2155 ;; Action handler which deletes the region and ignores the command.
2156 (if (not mark-active)
2157 nil
2158 (if CUA-rectangle
2159 (CUA-cmd-delete-rectangle)
2160 (CUA-cmd-delete-region))
2161 t))
2162
2163(defun CUA-action-cut ()
2164 ;; Action handler which cuts the region before executing the command.
2165 ;; If the region is not active, ignore the command.
2166 (if (not mark-active)
2167 t
2168 (setq this-command
2169 (cond ((CUA-global-mark-active) 'CUA-cmd-cut-to-global-mark)
2170 (CUA-rectangle 'CUA-cmd-cut-rectangle)
2171 (t 'CUA-cmd-cut-region)))
2172 nil))
2173
2174(defun CUA-action-copy ()
2175 ;; Action handler which copies the region before executing the command.
2176 ;; If the region is not active, ignore the command.
2177 (if (not mark-active)
2178 t
2179 (setq this-command
2180 (cond ((CUA-global-mark-active) 'CUA-cmd-copy-to-global-mark)
2181 (CUA-rectangle 'CUA-cmd-copy-rectangle)
2182 (t 'CUA-cmd-copy-region)))
2183 nil))
2184
2185(defun CUA-action-paste ()
2186 ;; Action handler which pastes the last cut or copy.
2187 ;; An active region is deleted before executing the command.
2188 (if buffer-read-only
2189 nil ; fall back to original action
2190 ;; Must save register here, since delete may override reg 0.
2191 (let ((reg (and (CUA-register) (get-register (CUA-register)))))
2192 (if mark-active
2193 ;; Before a yank command, make sure we don't yank
2194 ;; the same region that we are going to delete.
2195 ;; That would make yank a no-op.
2196 (if CUA-rectangle
2197 (CUA-cmd-delete-rectangle)
2198 (if (string= (buffer-substring (point) (mark))
2199 (car kill-ring))
2200 (current-kill 1))
2201 (CUA-cmd-delete-region)))
2202 (cond
2203 ((CUA-register)
2204 (cond
2205 ((consp reg) (CUA-insert-rectangle reg))
2206 ((stringp reg) (insert reg))
2207 (t (message "Nothing in register %c" (CUA-register))))
2208 t)
2209 ((and CUA-rect-last-killed (eq (and kill-ring (car kill-ring)) (car CUA-rect-last-killed)))
2210 (when (not (eq buffer-undo-list t))
2211 (setq CUA-this-action 'CUA-action-paste-rect) ;; dynamic binding
2212 (undo-boundary)
2213 (setq buffer-undo-list (cons (point) buffer-undo-list)))
2214 (CUA-insert-rectangle (cdr CUA-rect-last-killed))
2215 t)
2216 ((and (CUA-global-mark-active)
2217 (not (eobp)))
2218 (CUA-global-mark-copy-region (point) (1+ (point)))
2219 (forward-char 1)
2220 t)
2221 (t nil)))))
2222
2223(defun CUA-action-paste-pop ()
2224 (when (eq CUA-last-action 'CUA-action-paste-rect)
2225 (undo)
2226 (setq this-command 'yank))
2227 nil)
2228
2229;;
2230;; CUA state indications
2231;;
2232(defvar CUA-ind-do-initialize t)
2233
2234(defun CUA-ind-init-indications (&optional reset)
2235 (unless (face-background 'CUA-rectangle-face)
2236 (copy-face 'region 'CUA-rectangle-face)
2237 (set-face-background 'CUA-rectangle-face "maroon")
2238 (set-face-foreground 'CUA-rectangle-face "white"))
2239 (unless (face-background 'CUA-rectangle-noselect-face)
2240 (copy-face 'region 'CUA-rectangle-noselect-face)
2241 (set-face-background 'CUA-rectangle-noselect-face "dimgray")
2242 (set-face-foreground 'CUA-rectangle-noselect-face "white"))
2243 (unless (face-background 'CUA-global-mark-face)
2244 (copy-face 'region 'CUA-global-mark-face)
2245 (set-face-foreground 'CUA-global-mark-face "black")
2246 (set-face-background 'CUA-global-mark-face "cyan"))
2247 (setq CUA-ind-do-initialize nil))
2248
2249;; change cursor color according to overwrite-mode...
2250
2251(require 'timer)
2252
2253(defvar CUA-ind-cursor-blink-timer nil)
2254(defvar CUA-ind-cursor-blink-off nil)
2255
2256(defun CUA-ind-cursor-blink-toggle ()
2257 (setq CUA-ind-cursor-blink-off (not CUA-ind-cursor-blink-off))
2258 (let ((cursor
2259 (cond
2260 (CUA-ind-cursor-blink-off
2261 (frame-parameter nil 'foreground-color))
2262 (CUA-rectangle
2263 (if (CUA-rect-padding)
2264 CUA-mode-overwrite-cursor-color
2265 CUA-mode-normal-cursor-color))
2266 (overwrite-mode CUA-mode-overwrite-cursor-color)
2267 (t CUA-mode-normal-cursor-color))))
2268 (if cursor
2269 (set-cursor-color cursor))))
2270
2271(defun CUA-ind-update-indications ()
2272 (if CUA-ind-do-initialize
2273 (CUA-ind-init-indications))
2274 (if CUA-mode-use-cursor-colors
2275 (let ((cursor
2276 (cond
2277 (buffer-read-only CUA-mode-read-only-cursor-color)
2278 (CUA-rectangle
2279 (if (CUA-rect-padding)
2280 CUA-mode-overwrite-cursor-color
2281 CUA-mode-normal-cursor-color))
2282 (overwrite-mode CUA-mode-overwrite-cursor-color)
2283 (t CUA-mode-normal-cursor-color))))
2284 (cond
2285 ((and (CUA-global-mark-active)
2286 (or CUA-mode-global-mark-cursor-blink
2287 CUA-mode-global-mark-cursor-color))
2288 (if CUA-mode-global-mark-cursor-color
2289 (setq cursor CUA-mode-global-mark-cursor-color))
2290 (if (and CUA-mode-global-mark-cursor-blink
2291 cursor (not CUA-ind-cursor-blink-timer))
2292 (setq CUA-ind-cursor-blink-timer
2293 (run-at-time t 0.25 'CUA-ind-cursor-blink-toggle))))
2294 (CUA-ind-cursor-blink-timer
2295 (cancel-timer CUA-ind-cursor-blink-timer)
2296 (setq CUA-ind-cursor-blink-timer nil)
2297 (setq CUA-ind-cursor-blink-off nil)))
2298 (if (and cursor
2299 (not (equal cursor (frame-parameter nil 'cursor-color))))
2300 (set-cursor-color cursor)))))
2301
2302;;
2303;; prefix key handling
2304;;
2305
2306(defun CUA-absorb-prefix-arg ()
2307 ;; If a CUA command has an optional prefix arg, use this command to clear it.
2308 (setq current-prefix-arg nil
2309 overriding-terminal-local-map nil))
2310
2311(defun CUA-kbd-macro-fixup (e1 &optional e2)
2312 (when defining-kbd-macro
2313 (cancel-kbd-macro-events)
2314 (store-kbd-macro-event e1)
2315 (if e2
2316 (store-kbd-macro-event e2)))
2317 nil)
2318
2319(defun CUA-prefix-handler (prompt)
2320 (let ((prefix last-input-char)
2321 (keys (this-command-keys))
2322 ev map)
2323 (if (not
2324 (and
2325 CUA-mode
2326 mark-active
2327 (or CUA-rectangle
2328 transient-mark-mode
2329 (and CUA-mode-highlight-shift-only CUA-explicit-region-start))
2330 (not executing-kbd-macro)
2331 (not (and CUA-mode-remap-cx-shift-only CUA-explicit-region-start))
2332 (or (= (length keys) 1)
2333 (eq (CUA-lookup-key global-map (substring keys 0 -1)) 'digit-argument))
2334 (not (memq this-command '(describe-key describe-key-briefly)))
2335 (or (not (memq CUA-mode-inhibit-method '(delay twice)))
2336 (= CUA-mode-inhibit-delay 0)
2337 (sit-for 0 CUA-mode-inhibit-delay t)
2338 (symbolp (event-basic-type (setq ev (read-event))))
2339 (eq CUA-mode-inhibit-method 'delay)
2340 ;; We got the next key before the timeout.
2341 ;; Don't perform CUA remapping of prefix.
2342 ;; Also, if prefix == ev, drop ev
2343 (and (= prefix ev)
2344 (setq ev (CUA-kbd-macro-fixup prefix))))
2345 (setq map (assq prefix CUA-prefix-key-mappings))))
2346 (if ev
2347 (vector prefix ev)
2348 (vector prefix))
2349 (CUA-kbd-macro-fixup (cdr map) ev)
2350 (if ev
2351 (setq unread-command-events (cons ev unread-command-events)))
2352 (vector (cdr map)))))
2353
2354(defun CUA-ctl-x-8-prefix-handler ()
2355 "Explicit handing of C-x 8 prefix when CUA mode is used.
2356This is necessary since CUA mode installs its own handler for C-x
2357in key-translation-map."
2358 (interactive)
2359 (unless CUA-ctl-x-8-prefix-key
2360 (setq CUA-ctl-x-8-prefix-key
2361 (cond ((not (lookup-key global-map [?\H-8])) ?\H-8)
2362 ((not (lookup-key global-map [?\s-8])) ?\s-8)
2363 ((not (lookup-key global-map [?\C-\H-8])) ?\C-\H-8)
2364 (t ?\C-\s-\H-8)))
2365 (unless (and (boundp 'iso-transl-ctl-x-8-map) (lookup-key iso-transl-ctl-x-8-map [?/ ?o]))
2366 (let ((key-translation-map nil)) ;; Avoid barfing about CUA's C-x binding
2367 (require 'iso-transl))
2368 (define-key key-translation-map (vector CUA-ctl-x-8-prefix-key) 'iso-transl-ctl-x-8-map)))
2369 (setq unread-command-events (cons CUA-ctl-x-8-prefix-key unread-command-events)))
2370
2371(defvar CUA-overriding-region-map nil
2372 "Keymap that overrides other keymaps when region is active.")
2373
2374(defvar CUA-overriding-rectangle-map nil
2375 "Keymap that overrides other keymaps when rectangle is active.")
2376
2377(defvar CUA-overriding-global-mark-map nil
2378 "Keymap that overrides other keymaps when global mark is active.")
2379
2380(defvar CUA-overriding-global-mark-commands
2381 '(self-insert-command self-insert-iso indent-for-tab-command)
2382 "List of commands whose global mapping should override mode specific mappings.")
2383
2384(defun CUA-lookup-overriding-maps (keys &optional command)
2385 (cond
2386 ((and overriding-terminal-local-map
2387 (CUA-lookup-key overriding-terminal-local-map keys))
2388 nil)
2389 ((and (window-minibuffer-p)
2390 (current-local-map)
2391 (CUA-lookup-key (current-local-map) keys))
2392 nil)
2393 (t
2394 (if command
2395 (let ((gcmd (CUA-lookup-key global-map keys)))
2396 (setq keys
2397 (vector
2398 (if (memq gcmd CUA-overriding-global-mark-commands)
2399 gcmd
2400 command)))))
2401 (or (and (CUA-global-mark-active)
2402 (CUA-lookup-key CUA-overriding-global-mark-map keys))
2403 (and CUA-rectangle
2404 (CUA-lookup-key CUA-overriding-rectangle-map keys))
2405 (and mark-active
2406 (CUA-lookup-key CUA-overriding-region-map keys))))))
2407
2408(defun CUA-delete-selection (command)
2409 ;; Convert delete-selection property to corresponding CUA action
2410 (let ((ds (or (get command 'delete-selection) (get command 'pending-delete))))
2411 (and ds
2412 (cond
2413 ((eq ds 'yank) 'CUA-action-paste)
2414 ((eq ds 'kill) 'CUA-action-copy)
2415 ((eq ds 'supersede) 'CUA-action-delete)
2416 (t 'CUA-action-delete-before)))))
2417
2418(defun CUA-pre-hook ()
2419 "Function run prior to command to check for special region handling.
2420If current command is a movement and the key is shifted, set or expand
2421the region."
2422 (condition-case nil
2423 (let* ((keys (this-single-command-raw-keys))
2424 (new-cmd (and (= (length keys) 1)
2425 (CUA-lookup-overriding-maps keys)))
2426 action CUA-this-action ignore)
2427 (setq CUA-save-point (point))
2428 (if new-cmd
2429 (setq CUA-orig-command this-command
2430 this-command new-cmd))
2431 (if (setq action
2432 (and (symbolp this-command)
2433 (or (CUA-lookup-overriding-maps keys this-command)
2434 (get this-command 'CUA)
2435 (CUA-delete-selection this-command))))
2436 (if (and action (fboundp action))
2437 (setq ignore (funcall (setq CUA-this-action action)))
2438 (if action
2439 (message "Unknown function: %S" action)
2440 (setq action nil))))
2441 (setq CUA-last-action CUA-this-action)
2442 (setq CUA-start-point nil)
2443 (if ignore
2444 (setq this-command 'CUA-cmd-ignore
2445 prefix-arg nil
2446 current-prefix-arg nil)
2447 (if CUA-rectangle
2448 (setq CUA-start-point (cons (current-buffer) (point))))))
2449 (error nil)))
2450
2451(defun CUA-post-hook ()
2452 "Function run after command to check for rectangle region handling."
2453 (condition-case nil
2454 (progn
2455 (when (and CUA-mode-global-mark-visible (CUA-global-mark-active))
2456 (sit-for 0)
2457 (if (or (not (eq (current-buffer) (marker-buffer CUA-global-mark)))
2458 (not (pos-visible-in-window-p (marker-position CUA-global-mark))))
2459 (let ((w (selected-window)) (p (point)) h)
2460 ;; The following code is an attempt to keep the global mark visible in
2461 ;; other window -- but it doesn't work.
2462 (switch-to-buffer-other-window (marker-buffer CUA-global-mark) t)
2463 (goto-char (marker-position CUA-global-mark))
2464 (if (not (pos-visible-in-window-p (marker-position CUA-global-mark)))
2465 (recenter (if (> (setq h (- (window-height) 4)) 1) h '(4))))
2466 (select-window w)
2467 (goto-char p))))
2468 (if CUA-next-rectangle
2469 (setq CUA-rectangle CUA-next-rectangle
2470 CUA-next-rectangle nil
2471 mark-active t
2472 deactivate-mark nil)
2473 (when (and CUA-rectangle CUA-start-point
2474 (equal (car CUA-start-point) (current-buffer))
2475 (not (= (cdr CUA-start-point) (point))))
2476 (if (CUA-rect-right-side)
2477 (CUA-rect-right (current-column))
2478 (CUA-rect-left (current-column)))
2479 (if (>= (CUA-rect-corner) 2)
2480 (CUA-rect-bot t)
2481 (CUA-rect-top t))
2482 (if (CUA-rect-padding)
2483 (setq unread-command-events
2484 (cons (if CUA-mode-use-hyper-key ?\H-P ?\M-P) unread-command-events)))))
2485 (setq CUA-start-point nil)
2486 (if CUA-rectangle
2487 (if (and mark-active
2488 (not deactivate-mark))
2489 (CUA-rect-highlight)
2490 (CUA-rect-deactivate)))
2491 (if (or (not mark-active) deactivate-mark)
2492 (setq CUA-explicit-region-start nil))
2493 (if CUA-debug
2494 (cond
2495 (CUA-rectangle (CUA-rect-assert))
2496 (mark-active (message "Mark=%d Point=%d Expl=%s"
2497 (mark) (point) CUA-explicit-region-start))))
2498 ;; Disable transient-mark-mode if rectangle active in current buffer.
2499 (if (not (window-minibuffer-p (selected-window)))
2500 (setq transient-mark-mode (and (not CUA-rectangle)
2501 (if CUA-mode-highlight-shift-only
2502 (not CUA-explicit-region-start)
2503 t))
2504 CUA-cur-register nil))
2505 (CUA-ind-update-indications))
2506 (error nil)))
2507
2508
2509(defvar CUA-movement-keys
2510 '((forward-char right)
2511 (backward-char left)
2512 (next-line down)
2513 (previous-line up)
2514 (forward-word control right)
2515 (backward-word control left)
2516 (end-of-line end)
2517 (beginning-of-line home)
2518 (end-of-buffer control end)
2519 (beginning-of-buffer control home)
2520 (scroll-up next)
2521 (scroll-down prior)
2522 (forward-paragraph control down)
2523 (backward-paragraph control up))
2524 "List of cursor movement functions for which to create CUA key mappings.
2525Each element in the list is a list where the first element is the name of
2526the cursor movement function, and the rest of the list are keys to which
2527the function shall be bound. For each key listed, both the key itself and
2528the shifted version S-key are bound to the specified function.")
2529
2530(defun CUA-help-for-region (&optional help)
2531 (interactive)
2532 (message
2533 (concat (if help "C-?:help " "")
2534 "C-z:undo C-x:cut C-c:copy C-v:paste S-ret:rect")))
2535
2536(defun CUA-help-for-rectangle (&optional help)
2537 (interactive)
2538 (message
2539 (concat (if help "C-?:help " "")
2540 "M-p:pad M-o:open M-c:close M-b:blank M-s:string M-f:fill M-i:incr M-n:seq")))
2541
2542(defun CUA-hyper-key (map key fct &optional other)
2543 (if (eq key 'space) (setq key ? ))
2544 (unless (listp key) (setq key (list key)))
2545 (setq key
2546 (cond
2547 (CUA-mode-use-hyper-key (vector (cons 'hyper key)))
2548 (other other)
2549 (t (vector (cons 'meta key)))))
2550 (define-key map key fct)
2551 (if (and other (eq CUA-mode-use-hyper-key 'also))
2552 (define-key map other fct)))
2553
2554(defun CUA-mode-init-maps (emacs-bindings)
2555 (if (not CUA-overriding-region-map)
2556 (let ((m (make-sparse-keymap)))
2557 (unless emacs-bindings
2558 (define-key m [(control insert)] 'CUA-cmd-copy-region)
2559 (define-key m [(shift delete)] 'CUA-cmd-cut-region))
2560 (CUA-hyper-key m 'space 'CUA-cmd-toggle-rectangle [(shift return)])
2561 (define-key m [(control ?i)] 'CUA-cmd-indent-region-left)
2562 (define-key m [(control shift ?i)] 'CUA-cmd-indent-region-right)
2563 (define-key m [(control ??)] 'CUA-help-for-region)
2564 (setq CUA-overriding-region-map m)))
2565 (if (not CUA-overriding-rectangle-map)
2566 (let ((m (make-keymap)))
2567 (unless emacs-bindings
2568 (define-key m [(control insert)] 'CUA-cmd-copy-rectangle)
2569 (define-key m [(shift delete)] 'CUA-cmd-cut-rectangle))
2570 (define-key m [(control ? )] 'CUA-cmd-toggle-rectangle)
2571 (CUA-hyper-key m 'space 'CUA-cmd-end-rectangle [(shift return)])
2572 (define-key m [return] 'CUA-cmd-rotate-rectangle)
2573 (define-key m "\r" 'CUA-cmd-rotate-rectangle)
2574 (define-key m [mouse-1] 'CUA-cmd-mouse-set-rectangle-corner)
2575 (CUA-hyper-key m 'up 'CUA-cmd-move-rectangle-up)
2576 (CUA-hyper-key m 'down 'CUA-cmd-move-rectangle-down)
2577 (CUA-hyper-key m 'left 'CUA-cmd-move-rectangle-left)
2578 (CUA-hyper-key m 'right 'CUA-cmd-move-rectangle-right)
2579 (CUA-hyper-key m '(control up) 'CUA-cmd-scroll-rectangle-up)
2580 (CUA-hyper-key m '(control down) 'CUA-cmd-scroll-rectangle-down)
2581 (CUA-hyper-key m ?a 'CUA-cmd-align-rectangle)
2582 (CUA-hyper-key m ?b 'CUA-cmd-blank-rectangle)
2583 (CUA-hyper-key m ?c 'CUA-cmd-close-rectangle)
2584 (CUA-hyper-key m ?f 'CUA-cmd-fill-char-rectangle)
2585 (CUA-hyper-key m ?F 'CUA-cmd-self-fill-rectangle)
2586 (CUA-hyper-key m ?i 'CUA-cmd-incr-rectangle)
2587 (CUA-hyper-key m ?k 'CUA-cmd-cut-rectangle-as-text)
2588 (CUA-hyper-key m ?l 'CUA-cmd-downcase-rectangle)
2589 (CUA-hyper-key m ?m 'CUA-cmd-copy-rectangle-as-text)
2590 (CUA-hyper-key m ?n 'CUA-cmd-sequence-rectangle)
2591 (CUA-hyper-key m ?o 'CUA-cmd-open-rectangle)
2592 (CUA-hyper-key m ?p 'CUA-cmd-toggle-rectangle-padding)
2593 (CUA-hyper-key m ?P 'CUA-cmd-do-rectangle-padding)
2594 (CUA-hyper-key m ?r 'CUA-cmd-replace-in-rectangle)
2595 (CUA-hyper-key m ?R 'CUA-cmd-reverse-rectangle)
2596 (CUA-hyper-key m ?s 'CUA-cmd-string-rectangle)
2597 (CUA-hyper-key m ?t 'CUA-cmd-text-fill-rectangle)
2598 (CUA-hyper-key m ?u 'CUA-cmd-upcase-rectangle)
2599 (CUA-hyper-key m ?| 'CUA-cmd-shell-command-on-rectangle)
2600 (CUA-hyper-key m ?' 'CUA-cmd-restrict-prefix-rectangle)
2601 (CUA-hyper-key m ?/ 'CUA-cmd-restrict-regexp-rectangle)
2602 (define-key m [(control ??)] 'CUA-help-for-rectangle)
2603 (define-key m [backspace] 'CUA-cmd-delete-char-rectangle)
2604 (define-key m "\d" 'CUA-cmd-delete-char-rectangle)
2605 (define-key m [self-insert-command] 'CUA-action-insert-char-rectangle)
2606 (define-key m [self-insert-iso] 'CUA-action-insert-char-rectangle)
2607 (define-key m [indent-for-tab-command] 'CUA-action-insert-char-rectangle)
2608 (setq CUA-overriding-rectangle-map m)))
2609 (if (not CUA-overriding-global-mark-map)
2610 (let ((m (make-sparse-keymap)))
2611 (if emacs-bindings
2612 (define-key m [(control ?y)] 'CUA-cmd-copy1-to-global-mark)
2613 (define-key m [(control insert)] 'CUA-cmd-copy-to-global-mark)
2614 (define-key m [(shift delete)] 'CUA-cmd-cut-to-global-mark)
2615 (define-key m [(control ?v)] 'CUA-cmd-copy1-to-global-mark))
2616 (define-key m [(control ?d)] 'CUA-cmd-cut1-to-global-mark)
2617 (define-key m [backspace] 'CUA-cmd-delete-backward-char-at-global-mark)
2618 (define-key m "\d" 'CUA-cmd-delete-backward-char-at-global-mark)
2619 (define-key m [delete] 'CUA-cmd-delete-char-at-global-mark)
2620 (define-key m [self-insert-command] 'CUA-action-insert-char-at-global-mark)
2621 (define-key m [self-insert-iso] 'CUA-action-insert-char-at-global-mark)
2622 (define-key m [newline] 'CUA-action-inset-newline-at-global-mark)
2623 (define-key m [newline-and-indent] 'CUA-action-insert-newline-at-global-mark)
2624 (define-key m [return] 'CUA-cmd-insert-newline-at-global-mark)
2625 (define-key m "\r" 'CUA-cmd-insert-newline-at-global-mark)
2626 (setq CUA-overriding-global-mark-map m)))
2627 (unless (get 'forward-char 'CUA)
2628 (let ((list CUA-region-commands) act l)
2629 (while list
2630 (setq l (car list)
2631 act (car l)
2632 l (cdr l)
2633 list (cdr list))
2634 (while l
2635 (put (car l) 'CUA act)
2636 (setq l (cdr l)))))
2637 (let ((list CUA-movement-keys) cmd)
2638 (while list
2639 (setq cmd (car (car list))
2640 list (cdr list))
2641 (put cmd 'CUA 'CUA-action-move)))))
2642
2643(defun CUA-define-key (map key cmd)
2644 "Like define-key with specific short-cuts for CUA maps.
2645In MAP, define KEY to run command CMD.
2646Special values for MAP are 'region, 'rect, 'gm, and 'all to bind into
2647the CUA maps for the active region, active rectangle, and active
2648global marker resp., or all of them."
2649 (if (symbolp key)
2650 (setq key (vector key)))
2651 (if (memq map '(region all))
2652 (define-key CUA-overriding-region-map key cmd))
2653 (if (memq map '(rect all))
2654 (define-key CUA-overriding-rectangle-map key cmd))
2655 (if (memq map '(gm all))
2656 (define-key CUA-overriding-global-mark-map key cmd)))
2657
2658(defun CUA-define-key-as (map key key2)
2659 "Define a key to run the same CUA command as another key."
2660 (if (symbolp key)
2661 (setq key (vector key)))
2662 (if (symbolp key2)
2663 (setq key2 (vector key2)))
2664 (if (memq map '(region all))
2665 (let ((cmd (CUA-lookup-key CUA-overriding-region-map key2)))
2666 (if cmd
2667 (define-key CUA-overriding-region-map key cmd))))
2668 (if (memq map '(rect all))
2669 (let ((cmd (CUA-lookup-key CUA-overriding-rectangle-map key2)))
2670 (if cmd
2671 (define-key CUA-overriding-rectangle-map key cmd))))
2672 (if (memq map '(gm all))
2673 (let ((cmd (CUA-lookup-key CUA-overriding-global-mark-map key2)))
2674 (if cmd
2675 (define-key CUA-overriding-global-mark-map key cmd)))))
2676
2677;;;###autoload
2678(defun CUA-movement-key (key command)
2679 "Like `global-set-key' but also binds shifted KEY to COMMAND.
2680KEY should be a simple symbol or character, like home or ?\\C-e,
2681or a list like (control home)."
2682 (if (vectorp key)
2683 (setq key (aref key 0)))
2684 (if (not (listp key))
2685 (setq key (list key)))
2686 (global-set-key (vector key) command)
2687 (global-set-key (vector (cons 'shift key)) command)
2688 (put command 'CUA 'CUA-action-move))
2689
2690;;;###autoload
2691(defun CUA-mode-bindings (&optional bind)
2692 "Define even more compatibility bindings.
2693Optional argument BIND identifies what bindings to add."
2694 (cond
2695 ((eq bind 'sun3)
2696 ;; The following bindings are useful on Sun Type 3 keyboards
2697 ;; They implement the Get-Delete-Put (copy-cut-paste)
2698 ;; functions from sunview on the L6, L8 and L10 keys
2699 (define-key global-map [f16] 'yank)
2700 (define-key global-map [f18] 'copy-region-as-kill)
2701 (define-key global-map [f20] 'kill-region))
2702 ((eq bind 'pc-select)
2703 ;; The following bindings are made by pc-select
2704 ;; I [KFS] personally don't like them, so I made them extra.
2705 (global-set-key [f1] 'help) ; KHelp F1
2706 ;; The following bindings are from Pete Forman.
2707 (global-set-key [f6] 'other-window) ; KNextPane F6
2708 (global-set-key [delete] 'delete-char) ; KDelete Del
2709 (global-set-key [(meta backspace)] 'undo) ; KUndo aBS
2710 ;; The following bindings are taken from pc-mode.el as suggested by RMS.
2711 (define-key function-key-map [(meta delete)] [(meta ?d)])
2712 (global-set-key [(control meta delete)] 'kill-sexp)
2713 (global-set-key [(control backspace)] 'backward-kill-word)
2714 ;; Next line proposed by Eli Barzilay
2715 (global-set-key [(control escape)] 'electric-buffer-list))
2716 ((eq bind 'windows-nt)
2717 ;; From: Kari Heinola <kph@dp.com>
2718 (define-key global-map [(control ?a)] 'mark-whole-buffer)
2719 (define-key global-map [(control ?p)] 'print-buffer)
2720 (define-key global-map [(control ?s)] 'save-buffer)
2721 (define-key global-map [(control ?n)] 'find-file)
2722 (if (fboundp 'dlgopen-open-files)
2723 (define-key global-map [(control ?o)] 'dlgopen-open-files)
2724 (define-key global-map [(control ?o)] 'find-file))
2725 (define-key global-map [(control ?f)] 'isearch-forward)
2726 (define-key isearch-mode-map [(control ?f)] 'isearch-repeat-forward)
2727 (define-key global-map [(control ?h)] 'query-replace)
2728 (define-key global-map [f5] 'insert-time-stamp))
2729 ((eq bind 'emacs) ; CUA functionality for normal emacs bindings
2730 (substitute-key-definition 'undo 'CUA-undo global-map)
2731 (substitute-key-definition 'advertised-undo 'CUA-undo global-map)
2732 (define-key global-map [(control delete)] 'kill-word)
2733 (define-key global-map [(control backspace)] 'backward-kill-word)
2734 (define-key global-map [delete] 'delete-char)
2735 (define-key global-map [(control ? )] 'CUA-set-mark)
2736 (define-key global-map [(shift control ? )] 'CUA-cmd-toggle-global-mark)
2737 (CUA-hyper-key global-map 'space 'CUA-cmd-begin-rectangle [(shift return)]))
2738 ((eq bind 'CUA) ; default CUA mappings
2739 ;; Compatibility mappings
2740 ;; Note: These are required since CUA-prefix-key-mappings maps
2741 ;; C-x into S-delete and C-c into C-insert.
2742 (define-key global-map [(control insert)] 'copy-region-as-kill)
2743 (define-key global-map [(shift delete)] 'kill-region)
2744 (define-key global-map [(shift insert)] 'yank)
2745 (define-key global-map [(meta insert)] 'yank-pop)
2746 (define-key global-map [(control delete)] 'kill-word)
2747 (define-key global-map [(control backspace)] 'backward-kill-word)
2748 (define-key global-map [delete] 'delete-char)
2749 (define-key global-map [(control ? )] 'CUA-set-mark)
2750 (define-key global-map [(shift control ? )] 'CUA-cmd-toggle-global-mark)
2751 (CUA-hyper-key global-map 'space 'CUA-cmd-begin-rectangle [(shift return)]))
2752 ((eq bind 'zxcv)
2753 (define-key global-map [(control ?z)] 'CUA-undo)
2754 (define-key ctl-x-map [(control ?x)] 'CUA-exchange-point-and-mark)
2755 (define-key global-map [(control ?v)] 'yank)
2756 (or key-translation-map
2757 (setq key-translation-map (make-sparse-keymap)))
2758 (let ((map CUA-prefix-key-mappings))
2759 (while map
2760 (define-key key-translation-map
2761 (vector (car (car map))) 'CUA-prefix-handler)
2762 (if (stringp (cdr (car map)))
2763 (setcdr (car map) (read-kbd-macro (cdr (car map)))))
2764 (setq map (cdr map))))
2765 (define-key ctl-x-map [?8] 'CUA-ctl-x-8-prefix-handler))
2766 ((eq bind 'shift)
2767 (let ((list CUA-movement-keys) cmd elt key)
2768 (while list
2769 (setq elt (car list)
2770 cmd (car elt)
2771 key (cdr elt)
2772 list (cdr list))
2773 (define-key global-map (vector key) cmd)
2774 (define-key global-map (vector (cons 'shift key)) cmd))))))
2775
2776;;;###autoload
2777(defun CUA-mode (&optional arg extra nobind)
2778 "Toggle CUA keybinding mode.
2779When ON, C-x and C-c will cut and copy the selection if the selection
2780is active (i.e. the region is highlighted), and typed text replaces
2781the active selection. When OFF, typed text is just inserted at point.
2782If non-nil, the optional second argument EXTRA specifies additional
2783key bindings as defined by CUA-mode-bindings.
2784The following key bindings are made unless optional third argument
2785NOBIND is non-nil:
2786 C-z is undo
2787 C-v is yank
2788 C-x C-x is CUA-exchange-point-and-mark which doesn't enable the mark
2789 C-space starts/cancels the normal region
2790 S-C-space sets/cancels the global marker
2791 S-return starts a rectangular region, if repeated toggles between
2792 rectangle and normal region."
2793 (interactive "P")
2794 (setq CUA-mode
2795 (cond
2796 ((null arg) (not CUA-mode))
2797 ((symbolp arg) t)
2798 (t (> (prefix-numeric-value arg) 0))))
2799 (let ((emacs-bindings (or CUA-mode-emacs-bindings (equal arg 'emacs))))
2800 (CUA-mode-init-maps emacs-bindings)
2801 (if emacs-bindings
2802 (CUA-mode-bindings 'emacs)
2803 (CUA-mode-bindings 'CUA)
2804 (CUA-mode-bindings 'zxcv)
2805 (CUA-mode-bindings 'shift))
2806 (if extra
2807 (CUA-mode-bindings extra)))
2808 (setq mark-even-if-inactive t)
2809 (setq highlight-nonselected-windows nil)
2810 (make-variable-buffer-local 'CUA-explicit-region-start)
2811 (make-variable-buffer-local 'CUA-rectangle)
2812 (make-variable-buffer-local 'CUA-rect-overlays)
2813 (make-variable-buffer-local 'CUA-mode-status)
2814 (make-variable-buffer-local 'CUA-undo-list)
2815 (cancel-function-timers 'CUA-tidy-undo-lists)
2816 (if CUA-mode
2817 (progn
2818 (add-hook 'pre-command-hook 'CUA-pre-hook)
2819 (add-hook 'post-command-hook 'CUA-post-hook)
2820 (run-with-idle-timer 10 t 'CUA-tidy-undo-lists)
2821 (if (and CUA-mode-use-modeline (not (assoc 'CUA-mode minor-mode-alist)))
2822 (setq minor-mode-alist (cons '(CUA-mode CUA-mode-status) minor-mode-alist))))
2823 (remove-hook 'pre-command-hook 'CUA-pre-hook)
2824 (remove-hook 'post-command-hook 'CUA-post-hook)
2825 (CUA-tidy-undo-lists t))
2826 (setq transient-mark-mode (and CUA-mode
2827 (if CUA-mode-highlight-shift-only
2828 (not CUA-explicit-region-start)
2829 t))))
2830
2831;;;###autoload
2832(defun CUA-mode-on ()
2833 (interactive)
2834 (CUA-mode t))
2835
2836(defun CUA-debug ()
2837 (interactive)
2838 (setq CUA-debug (not CUA-debug)))
2839
2840;;; Register commands prefix remapping [C-x r ...]
2841
2842(defun CUA-remap-ctl-x-commands (ctl-x-key prefix &optional no-orig)
2843 "Remap ctl-x commands [C-x r ...] onto [PREFIX ...].
2844Unless the optional third arguments NO-ORIG is non-nil, the original
2845binding of [PREFIX] is remapped to [PREFIX PREFIX]."
2846 (let ((org-prefix-cmd (CUA-lookup-key global-map prefix))
2847 (new-prefix-cmd (CUA-lookup-key ctl-x-map ctl-x-key)))
2848 (if new-prefix-cmd
2849 (global-set-key prefix new-prefix-cmd))
2850 (if (and (not no-orig)
2851 new-prefix-cmd org-prefix-cmd
2852 (not (eq new-prefix-cmd org-prefix-cmd)))
2853 (global-set-key (concat prefix prefix) org-prefix-cmd))))
2854
2855;;; KEYPAD REMAPPING
2856
2857(defun CUA-keypad-bind (kp bind)
2858 "Bind the keys in KP list to BIND list in function-key-map.
2859If BIND is 'unbind, all bindings for the keys are removed."
2860 (if (not (boundp 'function-key-map))
2861 (setq function-key-map (make-sparse-keymap)))
2862 (if (eq bind 'unbind)
2863 (while kp
2864 (define-key function-key-map (vector (car kp)) nil)
2865 (setq kp (cdr kp)))
2866 (while (and kp bind)
2867 (define-key function-key-map (vector (car kp)) (vector (car bind)))
2868 (setq kp (cdr kp)
2869 bind (cdr bind)))))
2870
2871
2872;;;###autoload
2873(defun CUA-keypad-mode (mode &optional numlock decimal)
2874 "Set keypad bindings in function-key-map according to MODE.
2875If optional second argument NUMLOCK is non-nil, the NumLock On bindings
2876are changed. Otherwise, the NumLock Off binding are changed.
2877
2878 Mode Binding
2879 -------------------------------------------------------------
2880 'prefix Command prefix argument, i.e. M-0 .. M-9 and M--
2881 'S-cursor Bind shifted keypad keys to the shifted cursor movement keys.
2882 'cursor Bind keypad keys to the cursor movement keys.
2883 'numeric Plain numeric, i.e. 0 .. 9 and . (or DECIMAL arg)
2884 'none Removes all bindings for keypad keys in function-key-map.
2885
2886If mode is 'numeric and the optional third argument DECIMAL is non-nil,
2887the decimal key on the keypad i<s mapped to DECIMAL instead of [.]."
2888 (let ((kp (if numlock
2889 '(kp-decimal kp-0 kp-1 kp-2 kp-3 kp-4 kp-5 kp-6 kp-7 kp-8 kp-9)
2890 '(kp-delete kp-insert kp-end kp-down kp-next kp-left
2891 kp-space kp-right kp-home kp-up kp-prior))))
2892 (CUA-keypad-bind
2893 kp
2894 (cond
2895 ((eq mode 'none)
2896 'unbind)
2897 ((eq mode 'prefix)
2898 '(?\M-- ?\M-0 ?\M-1 ?\M-2 ?\M-3 ?\M-4 ?\M-5 ?\M-6 ?\M-7 ?\M-8 ?\M-9))
2899 ((eq mode 'cursor)
2900 '(delete insert end down next left space right home up prior))
2901 ((eq mode 'S-cursor)
2902 '(S-delete S-insert S-end S-down S-next S-left S-space S-right S-home S-up S-prior))
2903 ((eq mode 'numeric)
2904 (cons (or decimal ?.) '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)))
2905 (t
2906 (signal 'error (list "Unknown keypad mode: " mode)))))))
2907
2908
2909(if CUA-mode
2910 (CUA-mode 1))
2911
2912(provide 'CUA-mode)
2913(provide 'cua-mode)
2914(provide 'cua)
2915
2916;;; cua.el ends here