root/trunk/lisp/emulation/cua-rect.el

Revision 4220, 51.2 kB (checked in by miyoshi, 9 months ago)

Sync up with Emacs22.2.

Line 
1 ;;; cua-rect.el --- CUA unified rectangle support
2
3 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 ;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5
6 ;; Author: Kim F. Storm <storm@cua.dk>
7 ;; Keywords: keyboard emulations convenience CUA
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25
26 ;;; Acknowledgements
27
28 ;; The rectangle handling and display code borrows from the standard
29 ;; GNU emacs rect.el package and the rect-mark.el package by Rick
30 ;; Sladkey <jrs@world.std.com>.
31
32 ;;; Commentary:
33
34 ;;; Code:
35
36 (provide 'cua-rect)
37
38 (eval-when-compile
39   (require 'cua-base)
40   (require 'cua-gmrk)
41 )
42
43 ;;; Rectangle support
44
45 (require 'rect)
46
47 ;; If non-nil, restrict current region to this rectangle.
48 ;; Value is a vector [top bot left right corner ins virt select].
49 ;; CORNER specifies currently active corner 0=t/l 1=t/r 2=b/l 3=b/r.
50 ;; INS specifies whether to insert on left(nil) or right(t) side.
51 ;; If VIRT is non-nil, virtual straight edges are enabled.
52 ;; If SELECT is a regexp, only lines starting with that regexp are affected.")
53 (defvar cua--rectangle nil)
54 (make-variable-buffer-local 'cua--rectangle)
55
56 ;; Most recent rectangle geometry.  Note: car is buffer.
57 (defvar cua--last-rectangle nil)
58
59 ;; Rectangle restored by undo.
60 (defvar cua--restored-rectangle nil)
61
62 ;; Last rectangle copied/killed; nil if last kill was not a rectangle.
63 (defvar cua--last-killed-rectangle nil)
64
65 ;; List of overlays used to display current rectangle.
66 (defvar cua--rectangle-overlays nil)
67 (make-variable-buffer-local 'cua--rectangle-overlays)
68 (put 'cua--rectangle-overlays 'permanent-local t)
69
70 (defvar cua--overlay-keymap
71   (let ((map (make-sparse-keymap)))
72     (define-key map "\r" 'cua-rotate-rectangle)))
73
74 (defvar cua--virtual-edges-debug nil)
75
76 ;; Undo rectangle commands.
77
78 (defvar cua--rect-undo-set-point nil)
79
80 (defun cua--rectangle-undo-boundary ()
81   (when (listp buffer-undo-list)
82     (let ((s (cua--rect-start-position))
83           (e (cua--rect-end-position)))
84       (undo-boundary)
85       (push (list 'apply 0 s e
86                   'cua--rect-undo-handler
87                   (copy-sequence cua--rectangle) t s e)
88           buffer-undo-list))))
89
90 (defun cua--rect-undo-handler (rect on s e)
91   (if (setq on (not on))
92       (setq cua--rect-undo-set-point s)
93     (setq cua--restored-rectangle (copy-sequence rect))
94     (setq cua--buffer-and-point-before-command nil))
95   (push (list 'apply 0 s (if on e s)
96               'cua--rect-undo-handler rect on s e)
97         buffer-undo-list))
98
99 ;;; Rectangle geometry
100
101 (defun cua--rectangle-top (&optional val)
102   ;; Top of CUA rectangle (buffer position on first line).
103   (if (not val)
104       (aref cua--rectangle 0)
105     (setq val (line-beginning-position))
106     (if (<= val (aref cua--rectangle 1))
107         (aset cua--rectangle 0 val)
108       (aset cua--rectangle 1 val)
109       (cua--rectangle-corner 2))))
110
111 (defun cua--rectangle-bot (&optional val)
112   ;; Bot of CUA rectangle (buffer position on last line).
113   (if (not val)
114       (aref cua--rectangle 1)
115     (setq val (line-end-position))
116     (if (>= val (aref cua--rectangle 0))
117         (aset cua--rectangle 1 val)
118       (aset cua--rectangle 0 val)
119       (cua--rectangle-corner 2))))
120
121 (defun cua--rectangle-left (&optional val)
122   ;; Left column of CUA rectangle.
123   (if (integerp val)
124       (if (<= val (aref cua--rectangle 3))
125           (aset cua--rectangle 2 val)
126         (aset cua--rectangle 3 val)
127         (cua--rectangle-corner (if (cua--rectangle-right-side) -1 1)))
128     (aref cua--rectangle 2)))
129
130 (defun cua--rectangle-right (&optional val)
131   ;; Right column of CUA rectangle.
132   (if (integerp val)
133       (if (>= val (aref cua--rectangle 2))
134           (aset cua--rectangle 3 val)
135         (aset cua--rectangle 2 val)
136         (cua--rectangle-corner (if (cua--rectangle-right-side) -1 1)))
137     (aref cua--rectangle 3)))
138
139 (defun cua--rectangle-corner (&optional advance)
140   ;; Currently active corner of rectangle.
141   (let ((c (aref cua--rectangle 4)))
142     (if (not (integerp advance))
143         c
144       (aset cua--rectangle 4
145             (if (= advance 0)
146                 (- 3 c) ; opposite corner
147               (mod (+ c 4 advance) 4)))
148       (aset cua--rectangle 5 0))))
149
150 (defun cua--rectangle-right-side (&optional topbot)
151   ;; t if point is on right side of rectangle.
152   (if (and topbot (= (cua--rectangle-left) (cua--rectangle-right)))
153       (< (cua--rectangle-corner) 2)
154     (= (mod (cua--rectangle-corner) 2) 1)))
155
156 (defun cua--rectangle-column ()
157   (if (cua--rectangle-right-side)
158       (cua--rectangle-right)
159     (cua--rectangle-left)))
160
161 (defun cua--rectangle-insert-col (&optional col)
162   ;; Currently active corner of rectangle.
163   (if (integerp col)
164       (aset cua--rectangle 5 col)
165     (if (cua--rectangle-right-side t)
166         (if (= (aref cua--rectangle 5) 0)
167             (1+ (cua--rectangle-right))
168           (aref cua--rectangle 5))
169       (cua--rectangle-left))))
170
171 (defun cua--rectangle-virtual-edges (&optional set val)
172   ;; Current setting of rectangle virtual-edges
173   (if set
174       (aset cua--rectangle 6 val))
175   (and ;(not buffer-read-only)
176        (aref cua--rectangle 6)))
177
178 (defun cua--rectangle-restriction (&optional val bounded negated)
179   ;; Current rectangle restriction
180   (if val
181       (aset cua--rectangle 7
182             (and (stringp val)
183              (> (length val) 0)
184              (list val bounded negated)))
185     (aref cua--rectangle 7)))
186
187 (defun cua--rectangle-assert ()
188   (message "%S (%d)" cua--rectangle (point))
189   (if (< (cua--rectangle-right) (cua--rectangle-left))
190       (message "rectangle right < left"))
191   (if (< (cua--rectangle-bot) (cua--rectangle-top))
192       (message "rectangle bot < top")))
193
194 (defun cua--rectangle-get-corners ()
195   ;; Calculate the rectangular region represented by point and mark,
196   ;; putting start in the upper left corner and end in the
197   ;; bottom right corner.
198   (let ((top (point)) (bot (mark)) r l corner)
199     (save-excursion
200       (goto-char top)
201       (setq l (current-column))
202       (goto-char bot)
203       (setq r (current-column))
204       (if (<= top bot)
205           (setq corner (if (<= l r) 0 1))
206         (setq top (prog1 bot (setq bot top)))
207         (setq corner (if (<= l r) 2 3)))
208       (if (<= l r)
209           (if (< l r)
210               (setq r (1- r)))
211         (setq l (prog1 r (setq r l)))
212         (goto-char top)
213         (move-to-column l)
214         (setq top (point))
215         (goto-char bot)
216         (move-to-column r)
217         (setq bot (point))))
218     (vector top bot l r corner 0 cua-virtual-rectangle-edges nil)))
219
220 (defun cua--rectangle-set-corners ()
221   ;; Set mark and point in opposite corners of current rectangle.
222   (let (pp pc mp mc (c (cua--rectangle-corner)))
223     (cond
224      ((= c 0)  ; top/left -> bot/right
225       (setq pp (cua--rectangle-top) pc (cua--rectangle-left)
226             mp (cua--rectangle-bot) mc (cua--rectangle-right)))
227      ((= c 1)  ; top/right -> bot/left
228       (setq pp (cua--rectangle-top) pc (cua--rectangle-right)
229             mp (cua--rectangle-bot) mc (cua--rectangle-left)))
230      ((= c 2)  ; bot/left -> top/right
231       (setq pp (cua--rectangle-bot) pc (cua--rectangle-left)
232             mp (cua--rectangle-top) mc (cua--rectangle-right)))
233      ((= c 3)  ; bot/right -> top/left
234       (setq pp (cua--rectangle-bot) pc (cua--rectangle-right)
235             mp (cua--rectangle-top) mc (cua--rectangle-left))))
236     (goto-char mp)
237     (move-to-column mc)
238     (set-mark (point))
239     (goto-char pp)
240     ;; Move cursor inside rectangle, except if char at rigth edge is a tab.
241     (if (and (if (cua--rectangle-right-side)
242                  (and (= (move-to-column pc) (- pc tab-width))
243                       (not (eolp)))
244                (> (move-to-column pc) pc))
245              (not (bolp)))
246         (backward-char 1))
247     ))
248
249 (defun cua--rect-start-position ()
250   ;; Return point of top left corner
251   (save-excursion
252     (goto-char (cua--rectangle-top))
253     (and (> (move-to-column (cua--rectangle-left))
254             (cua--rectangle-left))
255          (not (bolp))
256          (backward-char 1))
257     (point)))
258
259 (defun cua--rect-end-position ()
260   ;; Return point of bottom right cornet
261   (save-excursion
262     (goto-char (cua--rectangle-bot))
263     (and (= (move-to-column (cua--rectangle-right))
264             (- (cua--rectangle-right) tab-width))
265          (not (eolp))
266          (not (bolp))
267          (backward-char 1))
268     (point)))
269
270 ;;; Rectangle resizing
271
272 (defun cua--forward-line (n)
273   ;; Move forward/backward one line.  Returns t if movement.
274   (let ((pt (point)))
275     (and (= (forward-line n) 0)
276          ;; Deal with end of buffer
277          (or (not (eobp))
278              (goto-char pt)))))
279
280 (defun cua--rectangle-resized ()
281   ;; Refresh state after resizing rectangle
282   (setq cua--buffer-and-point-before-command nil)
283   (cua--rectangle-insert-col 0)
284   (cua--rectangle-set-corners)
285   (cua--keep-active))
286
287 (defun cua-resize-rectangle-right (n)
288   "Resize rectangle to the right."
289   (interactive "p")
290   (let ((resized (> n 0)))
291     (while (> n 0)
292       (setq n (1- n))
293       (cond
294        ((cua--rectangle-right-side)
295         (cua--rectangle-right (1+ (cua--rectangle-right)))
296         (move-to-column (cua--rectangle-right)))
297        (t
298         (cua--rectangle-left (1+ (cua--rectangle-left)))
299         (move-to-column (cua--rectangle-right)))))
300     (if resized
301         (cua--rectangle-resized))))
302
303 (defun cua-resize-rectangle-left (n)
304   "Resize rectangle to the left."
305   (interactive "p")
306   (let (resized)
307     (while (> n 0)
308       (setq n (1- n))
309       (if (or (= (cua--rectangle-right) 0)
310               (and (not (cua--rectangle-right-side)) (= (cua--rectangle-left) 0)))
311           (setq n 0)
312         (cond
313          ((cua--rectangle-right-side)
314           (cua--rectangle-right (1- (cua--rectangle-right)))
315           (move-to-column (cua--rectangle-right)))
316          (t
317           (cua--rectangle-left (1- (cua--rectangle-left)))
318           (move-to-column (cua--rectangle-right))))
319         (setq resized t)))
320     (if resized
321         (cua--rectangle-resized))))
322
323 (defun cua-resize-rectangle-down (n)
324   "Resize rectangle downwards."
325   (interactive "p")
326   (let (resized)
327     (while (> n 0)
328       (setq n (1- n))
329       (cond
330        ((>= (cua--rectangle-corner) 2)
331         (goto-char (cua--rectangle-bot))
332         (when (cua--forward-line 1)
333           (move-to-column (cua--rectangle-column))
334           (cua--rectangle-bot t)
335           (setq resized t)))
336        (t
337         (goto-char (cua--rectangle-top))
338         (when (cua--forward-line 1)
339           (move-to-column (cua--rectangle-column))
340           (cua--rectangle-top t)
341           (setq resized t)))))
342     (if resized
343         (cua--rectangle-resized))))
344
345 (defun cua-resize-rectangle-up (n)
346   "Resize rectangle upwards."
347   (interactive "p")
348   (let (resized)
349     (while (> n 0)
350       (setq n (1- n))
351       (cond
352        ((>= (cua--rectangle-corner) 2)
353         (goto-char (cua--rectangle-bot))
354         (when (cua--forward-line -1)
355           (move-to-column (cua--rectangle-column))
356           (cua--rectangle-bot t)
357           (setq resized t)))
358        (t
359         (goto-char (cua--rectangle-top))
360         (when (cua--forward-line -1)
361           (move-to-column (cua--rectangle-column))
362           (cua--rectangle-top t)
363           (setq resized t)))))
364     (if resized
365         (cua--rectangle-resized))))
366
367 (defun cua-resize-rectangle-eol ()
368   "Resize rectangle to end of line."
369   (interactive)
370   (unless (eolp)
371     (end-of-line)
372     (if (> (current-column) (cua--rectangle-right))
373         (cua--rectangle-right (current-column)))
374     (if (not (cua--rectangle-right-side))
375         (cua--rectangle-corner 1))
376     (cua--rectangle-resized)))
377
378 (defun cua-resize-rectangle-bol ()
379   "Resize rectangle to beginning of line."
380   (interactive)
381   (unless (bolp)
382     (beginning-of-line)
383     (cua--rectangle-left (current-column))
384     (if (cua--rectangle-right-side)
385         (cua--rectangle-corner -1))
386     (cua--rectangle-resized)))
387
388 (defun cua-resize-rectangle-bot ()
389   "Resize rectangle to bottom of buffer."
390   (interactive)
391   (goto-char (point-max))
392   (move-to-column (cua--rectangle-column))
393   (cua--rectangle-bot t)
394   (cua--rectangle-resized))
395
396 (defun cua-resize-rectangle-top ()
397   "Resize rectangle to top of buffer."
398   (interactive)
399   (goto-char (point-min))
400   (move-to-column (cua--rectangle-column))
401   (cua--rectangle-top t)
402   (cua--rectangle-resized))
403
404 (defun cua-resize-rectangle-page-up ()
405   "Resize rectangle upwards by one scroll page."
406   (interactive)
407   (scroll-down)
408   (move-to-column (cua--rectangle-column))
409   (if (>= (cua--rectangle-corner) 2)
410       (cua--rectangle-bot t)
411     (cua--rectangle-top t))
412   (cua--rectangle-resized))
413
414 (defun cua-resize-rectangle-page-down ()
415   "Resize rectangle downwards by one scroll page."
416   (interactive)
417   (scroll-up)
418   (move-to-column (cua--rectangle-column))
419   (if (>= (cua--rectangle-corner) 2)
420       (cua--rectangle-bot t)
421     (cua--rectangle-top t))
422   (cua--rectangle-resized))
423
424 ;;; Mouse support
425
426 ;; This is pretty simplistic, but it does the job...
427
428 (defun cua-mouse-resize-rectangle (event)
429   "Set rectangle corner at mouse click position."
430   (interactive "e")
431   (mouse-set-point event)
432   ;; FIX ME -- need to calculate virtual column.
433   (if (cua--rectangle-virtual-edges)
434       (move-to-column (car (posn-col-row (event-end event))) t))
435   (if (cua--rectangle-right-side)
436       (cua--rectangle-right (current-column))
437     (cua--rectangle-left (current-column)))
438   (if (>= (cua--rectangle-corner) 2)
439       (cua--rectangle-bot t)
440     (cua--rectangle-top t))
441   (cua--rectangle-resized))
442
443 (defvar cua--mouse-last-pos nil)
444
445 (defun cua-mouse-set-rectangle-mark (event)
446   "Start rectangle at mouse click position."
447   (interactive "e")
448   (when cua--rectangle
449     (cua--deactivate-rectangle)
450     (cua--deactivate t))
451   (setq cua--last-rectangle nil)
452   (mouse-set-point event)
453   ;; FIX ME -- need to calculate virtual column.
454   (cua-set-rectangle-mark)
455   (setq cua--buffer-and-point-before-command nil)
456   (setq cua--mouse-last-pos nil))
457
458 (defun cua-mouse-save-then-kill-rectangle (event arg)
459   "Expand rectangle to mouse click position and copy rectangle.
460 If command is repeated at same position, delete the rectangle."
461   (interactive "e\nP")
462   (if (and (eq this-command last-command)
463            (eq (point) (car-safe cua--mouse-last-pos))
464            (eq cua--last-killed-rectangle (cdr-safe cua--mouse-last-pos)))
465       (progn
466         (unless buffer-read-only
467           (cua--delete-rectangle))
468         (cua--deactivate))
469     (cua-mouse-resize-rectangle event)
470     (let ((cua-keep-region-after-copy t))
471       (cua-copy-rectangle arg)
472       (setq cua--mouse-last-pos (cons (point) cua--last-killed-rectangle)))))
473
474 (defun cua--mouse-ignore (event)
475   (interactive "e")
476   (setq this-command last-command))
477
478 (defun cua--rectangle-move (dir)
479   (let ((moved t)
480         (top (cua--rectangle-top))
481         (bot (cua--rectangle-bot))
482         (l (cua--rectangle-left))
483         (r (cua--rectangle-right)))
484     (cond
485      ((eq dir 'up)
486       (goto-char top)
487       (when (cua--forward-line -1)
488         (cua--rectangle-top t)
489         (goto-char bot)
490         (forward-line -1)
491         (cua--rectangle-bot t)))
492      ((eq dir 'down)
493       (goto-char bot)
494       (when (cua--forward-line 1)
495         (cua--rectangle-bot t)
496         (goto-char top)
497         (cua--forward-line 1)
498         (cua--rectangle-top t)))
499      ((eq dir 'left)
500       (when (> l 0)
501         (cua--rectangle-left (1- l))
502         (cua--rectangle-right (1- r))))
503      ((eq dir 'right)
504       (cua--rectangle-right (1+ r))
505       (cua--rectangle-left (1+ l)))
506      (t
507       (setq moved nil)))
508     (when moved
509       (setq cua--buffer-and-point-before-command nil)
510       (cua--rectangle-set-corners)
511       (cua--keep-active))))
512
513
514 ;;; Operations on current rectangle
515
516 (defun cua--tabify-start (start end)
517   ;; Return position where auto-tabify should start (or nil if not required).
518   (save-excursion
519     (save-restriction
520       (widen)
521       (and (not buffer-read-only)
522            cua-auto-tabify-rectangles
523            (if (or (not (integerp cua-auto-tabify-rectangles))
524                    (= (point-min) (point-max))
525                    (progn
526                      (goto-char (max (point-min)
527                                      (- start cua-auto-tabify-rectangles)))
528                      (search-forward "\t" (min (point-max)
529                                                (+ end cua-auto-tabify-rectangles)) t)))
530                start)))))
531
532 (defun cua--rectangle-operation (keep-clear visible undo pad tabify &optional fct post-fct)
533   ;; Call FCT for each line of region with 4 parameters:
534   ;; Region start, end, left-col, right-col
535   ;; Point is at start when FCT is called
536   ;; Call fct with (s,e) = whole lines if VISIBLE non-nil.
537   ;; Only call fct for visible lines if VISIBLE==t.
538   ;; Set undo boundary if UNDO is non-nil.
539   ;; Rectangle is padded if PAD = t or numeric and (cua--rectangle-virtual-edges)
540   ;; Perform auto-tabify after operation if TABIFY is non-nil.
541   ;; Mark is kept if keep-clear is 'keep and cleared if keep-clear is 'clear.
542   (let* ((inhibit-field-text-motion t)
543          (start (cua--rectangle-top))
544          (end   (cua--rectangle-bot))
545          (l (cua--rectangle-left))
546          (r (1+ (cua--rectangle-right)))
547          (m (make-marker))
548          (tabpad (and (integerp pad) (= pad 2)))
549          (sel (cua--rectangle-restriction))
550          (tabify-start (and tabify (cua--tabify-start start end))))
551     (if undo
552         (cua--rectangle-undo-boundary))
553     (if (integerp pad)
554         (setq pad (cua--rectangle-virtual-edges)))
555     (save-excursion
556       (save-restriction
557         (widen)
558         (when (> (cua--rectangle-corner) 1)
559           (goto-char end)
560           (and (bolp) (not (eolp)) (not (eobp))
561                (setq end (1+ end))))
562         (when (eq visible t)
563           (setq start (max (window-start) start))
564           (setq end   (min (window-end) end)))
565         (goto-char end)
566         (setq end (line-end-position))
567         (if (and visible (bolp) (not (eobp)))
568             (setq end (1+ end)))
569         (goto-char start)
570         (setq start (line-beginning-position))
571         (narrow-to-region start end)
572         (goto-char (point-min))
573         (while (< (point) (point-max))
574           (move-to-column r pad)
575           (and (not pad) (not visible) (> (current-column) r)
576                (backward-char 1))
577           (if (and tabpad (not pad) (looking-at "\t"))
578               (forward-char 1))
579           (set-marker m (point))
580           (move-to-column l pad)
581           (if (and fct (or visible (and (>= (current-column) l) (<= (current-column) r))))
582               (let ((v t) (p (point)))
583                 (when sel
584                   (if (car (cdr sel))
585                       (setq v (looking-at (car sel)))
586                     (setq v (re-search-forward (car sel) m t))
587                     (goto-char p))
588                   (if (car (cdr (cdr sel)))
589                       (setq v (null v))))
590                 (if visible
591                     (funcall fct p m l r v)
592                   (if v
593                       (funcall fct p m l r)))))
594           (set-marker m nil)
595           (forward-line 1))
596         (if (not visible)
597             (cua--rectangle-bot t))
598         (if post-fct
599             (funcall post-fct l r))
600         (when tabify-start
601           (tabify tabify-start (point)))))
602     (cond
603      ((eq keep-clear 'keep)
604       (cua--keep-active))
605      ((eq keep-clear 'clear)
606       (cua--deactivate))
607      ((eq keep-clear 'corners)
608       (cua--rectangle-set-corners)
609       (cua--keep-active)))
610     (setq cua--buffer-and-point-before-command nil)))
611
612 (put 'cua--rectangle-operation 'lisp-indent-function 4)
613
614 (defun cua--delete-rectangle ()
615   (let ((lines 0))
616     (if (not (cua--rectangle-virtual-edges))
617         (cua--rectangle-operation nil nil t 2 t
618           '(lambda (s e l r v)
619              (setq lines (1+ lines))
620              (if (and (> e s) (<= e (point-max)))
621                  (delete-region s e))))
622       (cua--rectangle-operation nil 1 t nil t
623         '(lambda (s e l r v)
624            (setq lines (1+ lines))
625            (when (and (> e s) (<= e (point-max)))
626              (delete-region s e)))))
627     lines))
628
629 (defun cua--extract-rectangle ()
630   (let (rect)
631     (if (not (cua--rectangle-virtual-edges))
632         (cua--rectangle-operation nil nil nil nil nil ; do not tabify
633           '(lambda (s e l r)
634              (setq rect (cons (filter-buffer-substring s e nil t) rect))))
635       (cua--rectangle-operation nil 1 nil nil nil ; do not tabify
636         '(lambda (s e l r v)
637            (let ((copy t) (bs 0) (as 0) row)
638              (if (= s e) (setq e (1+ e)))
639              (goto-char s)
640              (move-to-column l)
641              (if (= (point) (line-end-position))
642                  (setq bs (- r l)
643                        copy nil)
644                (skip-chars-forward "\s\t" e)
645                (setq bs (- (min r (current-column)) l)
646                      s (point))
647                (move-to-column r)
648                (skip-chars-backward "\s\t" s)
649                (setq as (- r (max (current-column) l))
650                      e (point)))
651              (setq row (if (and copy (> e s))
652                            (filter-buffer-substring s e nil t)
653                          ""))
654              (when (> bs 0)
655                (setq row (concat (make-string bs ?\s) row)))
656              (when (> as 0)
657                (setq row (concat row (make-string as ?\s))))
658              (setq rect (cons row rect))))))
659     (nreverse rect)))
660
661 (defun cua--insert-rectangle (rect &optional below paste-column line-count)
662   ;; Insert rectangle as insert-rectangle, but don't set mark and exit with
663   ;; point at either next to top right or below bottom left corner
664   ;; Notice: In overwrite mode, the rectangle is inserted as separate text lines.
665   (if (eq below 'auto)
666       (setq below (and (bolp)
667                        (or (eolp) (eobp) (= (1+ (point)) (point-max))))))
668   (unless paste-column
669     (setq paste-column (current-column)))
670   (let ((lines rect)
671         (first t)
672         (tabify-start (cua--tabify-start (point) (point)))
673         last-column
674         p)
675     (while (or lines below)
676       (or first
677           (if overwrite-mode
678               (insert ?\n)
679             (forward-line 1)
680             (or (bolp) (insert ?\n))))
681       (unless overwrite-mode
682         (move-to-column paste-column t))
683       (if (not lines)
684           (setq below nil)
685         (insert-for-yank (car lines))
686         (unless last-column
687           (setq last-column (current-column)))
688         (setq lines (cdr lines))
689         (and first (not below)
690              (setq p (point))))
691       (setq first nil)
692       (if (and line-count (= (setq line-count (1- line-count)) 0))
693           (setq lines nil)))
694     (when (and line-count last-column (not overwrite-mode))
695       (while (> line-count 0)
696         (forward-line 1)
697         (or (bolp) (insert ?\n))
698         (move-to-column paste-column t)
699         (insert-char ?\s (- last-column paste-column -1))
700         (setq line-count (1- line-count))))
701     (when (and tabify-start
702                (not overwrite-mode))
703       (tabify tabify-start (point)))
704     (and p (not overwrite-mode)
705          (goto-char p))))
706
707 (defun cua--copy-rectangle-as-kill (&optional ring)
708   (if cua--register
709       (set-register cua--register (cua--extract-rectangle))
710     (setq killed-rectangle (cua--extract-rectangle))
711     (setq cua--last-killed-rectangle (cons (and kill-ring (car kill-ring)) killed-rectangle))
712     (if ring
713         (kill-new (mapconcat
714                    (function (lambda (row) (concat row "\n")))
715                    killed-rectangle "")))))
716
717 (defun cua--activate-rectangle ()
718   ;; Turn on rectangular marking mode by disabling transient mark mode
719   ;; and manually handling highlighting from a post command hook.
720   ;; Be careful if we are already marking a rectangle.
721   (setq cua--rectangle
722         (if (and cua--last-rectangle
723                  (eq (car cua--last-rectangle) (current-buffer))
724                  (eq (car (cdr cua--last-rectangle)) (point)))
725             (cdr (cdr cua--last-rectangle))
726           (cua--rectangle-get-corners))
727         cua--status-string (if (cua--rectangle-virtual-edges) " [R]" "")
728         cua--last-rectangle nil))
729
730 ;; (defvar cua-save-point nil)
731
732 (defun cua--deactivate-rectangle ()
733   ;; This is used to clean up after `cua--activate-rectangle'.
734   (mapcar (function delete-overlay) cua--rectangle-overlays)
735   (setq cua--last-rectangle (cons (current-buffer)
736                                   (cons (point) ;; cua-save-point
737                                         cua--rectangle))
738         cua--rectangle nil
739         cua--rectangle-overlays nil
740         cua--status-string nil
741         cua--mouse-last-pos nil))
742
743 (defun cua--highlight-rectangle ()
744   ;; This function is used to highlight the rectangular region.
745   ;; We do this by putting an overlay on each line within the rectangle.
746   ;; Each overlay extends across all the columns of the rectangle.
747   ;; We try to reuse overlays where possible because this is more efficient
748   ;; and results in less flicker.
749   ;; If cua--rectangle-virtual-edges is nil and the buffer contains tabs or short lines,
750   ;; the higlighted region may not be perfectly rectangular.
751   (let ((deactivate-mark deactivate-mark)
752         (old cua--rectangle-overlays)
753         (new nil)
754         (left (cua--rectangle-left))
755         (right (1+ (cua--rectangle-right))))
756     (when (/= left right)
757       (sit-for 0)  ; make window top/bottom reliable
758       (cua--rectangle-operation nil t nil nil nil ; do not tabify
759         '(lambda (s e l r v)
760            (let ((rface (if v 'cua-rectangle 'cua-rectangle-noselect))
761                  overlay bs ms as)
762              (when (cua--rectangle-virtual-edges)
763                (let ((lb (line-beginning-position))
764                      (le (line-end-position))
765                      cl cl0 pl cr cr0 pr)
766                  (goto-char s)
767                  (setq cl (move-to-column l)
768                        pl (point))
769                  (setq cr (move-to-column r)
770                        pr (point))
771                  (if (= lb pl)
772                      (setq cl0 0)
773                    (goto-char (1- pl))
774                    (setq cl0 (current-column)))
775                  (if (= lb le)
776                      (setq cr0 0)
777                    (goto-char (1- pr))
778                    (setq cr0 (current-column)))
779                  (unless (and (= cl l) (= cr r))
780                    (when (/= cl l)
781                      (setq bs (propertize
782                                (make-string
783                                 (- l cl0 (if (and (= le pl) (/= le lb)) 1 0))
784                                 (if cua--virtual-edges-debug ?. ?\s))
785                                'face (or (get-text-property (1- s) 'face) 'default)))
786                      (if (/= pl le)
787                          (setq s (1- s))))
788                    (cond
789                     ((= cr r)
790                      (if (and (/= pr le)
791                               (/= cr0 (1- cr))
792                               (or bs (/= cr0 (- cr tab-width)))
793                               (/= (mod cr tab-width) 0))
794                          (setq e (1- e))))
795                     ((= cr cl)
796                      (setq ms (propertize
797                                (make-string
798                                 (- r l)
799                                 (if cua--virtual-edges-debug ?, ?\s))
800                                'face rface))
801                      (if (cua--rectangle-right-side)
802                          (put-text-property (1- (length ms)) (length ms) 'cursor 2 ms)
803                        (put-text-property 0 1 'cursor 2 ms))
804                      (setq bs (concat bs ms))
805                      (setq rface nil))
806                     (t
807                      (setq as (propertize
808                                (make-string
809                                 (- r cr0 (if (= le pr) 1 0))
810                                 (if cua--virtual-edges-debug ?~ ?\s))
811                                'face rface))
812                      (if (cua--rectangle-right-side)
813                          (put-text-property (1- (length as)) (length as) 'cursor 2 as)
814                        (put-text-property 0 1 'cursor 2 as))
815                      (if (/= pr le)
816                          (setq e (1- e))))))))
817              ;; Trim old leading overlays.
818              (while (and old
819                          (setq overlay (car old))
820                          (< (overlay-start overlay) s)
821                          (/= (overlay-end overlay) e))
822                (delete-overlay overlay)
823                (setq old (cdr old)))
824              ;; Reuse an overlay if possible, otherwise create one.
825              (if (and old
826                       (setq overlay (car old))
827                       (or (= (overlay-start overlay) s)
828                           (= (overlay-end overlay) e)))
829                  (progn
830                    (move-overlay overlay s e)
831                    (setq old (cdr old)))
832                (setq overlay (make-overlay s e)))
833              (overlay-put overlay 'before-string bs)
834              (overlay-put overlay 'after-string as)
835              (overlay-put overlay 'face rface)
836              (overlay-put overlay 'keymap cua--overlay-keymap)
837              (overlay-put overlay 'window (selected-window))
838              (setq new (cons overlay new))))))
839     ;; Trim old trailing overlays.
840     (mapcar (function delete-overlay) old)
841     (setq cua--rectangle-overlays (nreverse new))))
842
843 (defun cua--indent-rectangle (&optional ch to-col clear)
844   ;; Indent current rectangle.
845   (let ((col (cua--rectangle-insert-col))
846         (pad (cua--rectangle-virtual-edges))
847         indent)
848     (cua--rectangle-operation (if clear 'clear 'corners) nil t pad nil
849       '(lambda (s e l r)
850          (move-to-column col pad)
851          (if (and (eolp)
852                   (< (current-column) col))
853              (move-to-column col t))
854          (cond
855           (to-col (indent-to to-col))
856           (ch (insert ch))
857           (t (tab-to-tab-stop)))
858          (if (cua--rectangle-right-side t)
859              (cua--rectangle-insert-col (current-column))
860            (setq indent (- (current-column) l))))
861       '(lambda (l r)
862          (when (and indent (> indent 0))
863            (aset cua--rectangle 2 (+ l indent))
864            (aset cua--rectangle 3 (+ r indent -1)))))))
865
866 ;;
867 ;; rectangle functions / actions
868 ;;
869
870 (defvar cua--rectangle-initialized nil)
871
872 (defun cua-set-rectangle-mark (&optional reopen)
873   "Set mark and start in CUA rectangle mode.
874 With prefix argument, activate previous rectangle if possible."
875   (interactive "P")
876   (unless cua--rectangle-initialized
877     (cua--init-rectangles))
878   (when (not cua--rectangle)
879     (if (and reopen
880              cua--last-rectangle
881              (eq (car cua--last-rectangle) (current-buffer)))
882         (goto-char (car (cdr cua--last-rectangle)))
883       (if (not mark-active)
884           (push-mark nil nil t)))
885     (cua--activate-rectangle)
886     (cua--rectangle-set-corners)
887     (setq mark-active t
888