Mercurial > hg > xemacs-beta
comparison lisp/rect.el @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children | 95016f13131a |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
1 ;;; rect.el --- rectangle functions for XEmacs. | 1 ;;; rect.el --- rectangle functions for XEmacs. |
2 | 2 |
3 ;; Copyright (C) 1985-2000 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1985, 1993, 1994 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Maintainer: Didier Verna <didier@xemacs.org> | 5 ;; Maintainer: FSF |
6 ;; Keywords: internal | 6 ;; Keywords: internal |
7 | 7 |
8 ;; This file is part of XEmacs. | 8 ;; This file is part of XEmacs. |
9 | 9 |
10 ;; XEmacs is free software; you can redistribute it and/or modify it | 10 ;; XEmacs is free software; you can redistribute it and/or modify it |
20 ;; You should have received a copy of the GNU General Public License | 20 ;; You should have received a copy of the GNU General Public License |
21 ;; along with XEmacs; see the file COPYING. If not, write to the Free | 21 ;; along with XEmacs; see the file COPYING. If not, write to the Free |
22 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | 22 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
23 ;; 02111-1307, USA. | 23 ;; 02111-1307, USA. |
24 | 24 |
25 ;;; Synched up with: to be incorporated in a forthcoming GNU Emacs | 25 ;;; Synched up with: FSF 19.34. |
26 | 26 |
27 ;;; Commentary: | 27 ;;; Commentary: |
28 | 28 |
29 ;; This package provides the operations on rectangles that are documented | 29 ;; This package provides the operations on rectangles that are ocumented |
30 ;; in the XEmacs Reference Manual. | 30 ;; in the XEmacs Reference Manual. |
31 | 31 |
32 ;; #### NOTE: this file has been almost completely rewritten by Didier Verna | |
33 ;; <didier@xemacs.org>, Jul 99. The purpose of this rewrite is to be less | |
34 ;; intrusive and fill lines with whitespaces only when needed. A few functions | |
35 ;; are untouched though, as noted above their definition. | |
36 | |
37 | |
38 ;;; Code: | 32 ;;; Code: |
39 | 33 |
40 ;; #### NOTE: this function is untouched, but not used anymore. | |
41 ;; `apply-on-rectangle' is used instead. It's still there because it's | |
42 ;; documented so people might use it in their code, so I've decided not to | |
43 ;; touch it. --dv | |
44 ;; XEmacs: extra-args | 34 ;; XEmacs: extra-args |
45 (defun operate-on-rectangle (function start end coerce-tabs &rest extra-args) | 35 (defun operate-on-rectangle (function start end coerce-tabs &rest extra-args) |
46 "Call FUNCTION for each line of rectangle with corners at START, END. | 36 "Call FUNCTION for each line of rectangle with corners at START, END. |
47 If COERCE-TABS is non-nil, convert multi-column characters | 37 If COERCE-TABS is non-nil, convert multi-column characters |
48 that span the starting or ending columns on any line | 38 that span the starting or ending columns on any line |
52 number of columns that belong to rectangle but are before that position, | 42 number of columns that belong to rectangle but are before that position, |
53 number of columns that belong to rectangle but are after point. | 43 number of columns that belong to rectangle but are after point. |
54 Point is at the end of the segment of this line within the rectangle." | 44 Point is at the end of the segment of this line within the rectangle." |
55 (let (startcol startlinepos endcol endlinepos) | 45 (let (startcol startlinepos endcol endlinepos) |
56 (save-excursion | 46 (save-excursion |
57 (goto-char start) | 47 (goto-char start) |
58 (setq startcol (current-column)) | 48 (setq startcol (current-column)) |
59 (beginning-of-line) | 49 (beginning-of-line) |
60 (setq startlinepos (point))) | 50 (setq startlinepos (point))) |
61 (save-excursion | 51 (save-excursion |
62 (goto-char end) | 52 (goto-char end) |
63 (setq endcol (current-column)) | 53 (setq endcol (current-column)) |
64 (forward-line 1) | 54 (forward-line 1) |
65 (setq endlinepos (point-marker))) | 55 (setq endlinepos (point-marker))) |
66 (if (< endcol startcol) | 56 (if (< endcol startcol) |
67 ;; XEmacs | 57 ;; XEmacs |
68 (let ((tem startcol)) | 58 (let ((tem startcol)) |
69 (setq startcol endcol endcol tem))) | 59 (setq startcol endcol endcol tem))) |
70 (save-excursion | 60 (save-excursion |
82 (if (< endextra 0) (setq endextra 0)) | 72 (if (< endextra 0) (setq endextra 0)) |
83 (apply function startpos begextra endextra extra-args)) | 73 (apply function startpos begextra endextra extra-args)) |
84 (forward-line 1))) | 74 (forward-line 1))) |
85 (- endcol startcol))) | 75 (- endcol startcol))) |
86 | 76 |
87 ;; The replacement for `operate-on-rectangle' -- dv | 77 (defun delete-rectangle-line (startdelpos ignore ignore) |
88 (defun apply-on-rectangle (function start end &rest args) | 78 (delete-region startdelpos (point))) |
89 "Call FUNCTION for each line of rectangle with corners at START and END. | 79 |
90 FUNCTION is called with two arguments: the start and end columns of the | 80 ;; XEmacs: added lines arg |
91 rectangle, plus ARGS extra arguments. Point is at the beginning of line | 81 (defun delete-extract-rectangle-line (startdelpos begextra endextra lines) |
92 when the function is called." | 82 (save-excursion |
93 (let (startcol startpt endcol endpt) | 83 (extract-rectangle-line startdelpos begextra endextra lines)) |
94 (save-excursion | 84 (delete-region startdelpos (point))) |
95 (goto-char start) | 85 |
96 (setq startcol (current-column)) | 86 ;; XEmacs: added lines arg |
97 (beginning-of-line) | 87 (defun extract-rectangle-line (startdelpos begextra endextra lines) |
98 (setq startpt (point)) | 88 (let ((line (buffer-substring startdelpos (point))) |
99 (goto-char end) | 89 (end (point))) |
100 (setq endcol (current-column)) | 90 (goto-char startdelpos) |
101 (forward-line 1) | 91 (while (search-forward "\t" end t) |
102 (setq endpt (point-marker)) | 92 (let ((width (- (current-column) |
103 ;; ensure the start column is the left one. | 93 (save-excursion (forward-char -1) |
104 (if (< endcol startcol) | 94 (current-column))))) |
105 (let ((col startcol)) | 95 (setq line (concat (substring line 0 (- (point) end 1)) |
106 (setq startcol endcol endcol col))) | 96 (spaces-string width) |
107 ;; start looping over lines | 97 (substring line (+ (length line) (- (point) end))))))) |
108 (goto-char startpt) | 98 (if (or (> begextra 0) (> endextra 0)) |
109 (while (< (point) endpt) | 99 (setq line (concat (spaces-string begextra) |
110 (apply function startcol endcol args) | 100 line |
111 (forward-line 1))) | 101 (spaces-string endextra)))) |
112 )) | 102 (setcdr lines (cons line (cdr lines))))) ; XEmacs |
113 | 103 |
114 | 104 (defconst spaces-strings |
115 (defun delete-rectangle-line (startcol endcol fill) | 105 (purecopy '["" " " " " " " " " " " " " " " " "])) |
116 (let ((pt (point-at-eol))) | 106 |
117 (when (= (move-to-column startcol (or fill 'coerce)) startcol) | |
118 (if (and (not fill) (<= pt endcol)) | |
119 (delete-region (point) pt) | |
120 ;; else | |
121 (setq pt (point)) | |
122 (move-to-column endcol t) | |
123 (delete-region pt (point)))) | |
124 )) | |
125 | |
126 ;;;###autoload | |
127 (defun delete-rectangle (start end &optional fill) | |
128 "Delete the text in the region-rectangle without saving it. | |
129 The same range of columns is deleted in each line starting with the line | |
130 where the region begins and ending with the line where the region ends. | |
131 | |
132 When called from a program, the rectangle's corners are START and END. | |
133 With a prefix (or FILL) argument, also fill lines where nothing has to be | |
134 deleted." | |
135 (interactive "*r\nP") | |
136 (apply-on-rectangle 'delete-rectangle-line start end fill)) | |
137 | |
138 | |
139 ;; I love ascii art ;-) | |
140 (defconst spaces-strings '["" | |
141 " " | |
142 " " | |
143 " " | |
144 " " | |
145 " " | |
146 " " | |
147 " " | |
148 " "]) | |
149 | |
150 ;; This function is untouched --dv | |
151 (defun spaces-string (n) | 107 (defun spaces-string (n) |
152 (if (<= n 8) (aref spaces-strings n) | 108 (if (<= n 8) (aref spaces-strings n) |
153 (let ((val "")) | 109 (let ((val "")) |
154 (while (> n 8) | 110 (while (> n 8) |
155 (setq val (concat " " val) | 111 (setq val (concat " " val) |
156 n (- n 8))) | 112 n (- n 8))) |
157 (concat val (aref spaces-strings n))))) | 113 (concat val (aref spaces-strings n))))) |
158 | 114 |
159 | 115 ;;;###autoload |
160 (defun delete-extract-rectangle-line (startcol endcol lines fill) | 116 (defun delete-rectangle (start end) |
161 (let ((pt (point-at-eol))) | 117 "Delete (don't save) text in rectangle with point and mark as corners. |
162 (if (< (move-to-column startcol (or fill 'coerce)) startcol) | 118 The same range of columns is deleted in each line starting with the line |
163 (setcdr lines (cons (spaces-string (- endcol startcol)) | 119 where the region begins and ending with the line where the region ends." |
164 (cdr lines))) | 120 (interactive "r") |
165 ;; else | 121 (operate-on-rectangle 'delete-rectangle-line start end t)) |
166 (setq pt (point)) | 122 |
167 (move-to-column endcol t) | 123 ;;;###autoload |
168 (setcdr lines (cons (buffer-substring pt (point)) (cdr lines))) | 124 (defun delete-extract-rectangle (start end) |
169 (delete-region pt (point))) | 125 "Delete contents of rectangle and return it as a list of strings. |
170 )) | 126 Arguments START and END are the corners of the rectangle. |
171 | 127 The value is list of strings, one for each line of the rectangle." |
172 ;;;###autoload | 128 (let ((lines (list nil))) ; XEmacs change |
173 (defun delete-extract-rectangle (start end &optional fill) | 129 (operate-on-rectangle 'delete-extract-rectangle-line |
174 "Delete the contents of the rectangle with corners at START and END, and | 130 start end t lines) |
175 return it as a list of strings, one for each line of the rectangle. | |
176 | |
177 With an optional FILL argument, also fill lines where nothing has to be | |
178 deleted." | |
179 (let ((lines (list nil))) | |
180 (apply-on-rectangle 'delete-extract-rectangle-line start end lines fill) | |
181 (nreverse (cdr lines)))) | 131 (nreverse (cdr lines)))) |
182 | 132 |
183 | |
184 ;; #### NOTE: this is actually the only function that needs to do complicated | |
185 ;; stuff like what's happening in `operate-on-rectangle', because the buffer | |
186 ;; might be read-only. --dv | |
187 (defun extract-rectangle-line (startcol endcol lines) | |
188 (let (start end begextra endextra line) | |
189 (move-to-column startcol) | |
190 (setq start (point) | |
191 begextra (- (current-column) startcol)) | |
192 (move-to-column endcol) | |
193 (setq end (point) | |
194 endextra (- endcol (current-column))) | |
195 (setq line (buffer-substring start (point))) | |
196 (if (< begextra 0) | |
197 (setq endextra (+ endextra begextra) | |
198 begextra 0)) | |
199 (if (< endextra 0) | |
200 (setq endextra 0)) | |
201 (goto-char start) | |
202 (while (search-forward "\t" end t) | |
203 (let ((width (- (current-column) | |
204 (save-excursion (forward-char -1) | |
205 (current-column))))) | |
206 (setq line (concat (substring line 0 (- (point) end 1)) | |
207 (spaces-string width) | |
208 (substring line (+ (length line) | |
209 (- (point) end))))))) | |
210 (if (or (> begextra 0) (> endextra 0)) | |
211 (setq line (concat (spaces-string begextra) | |
212 line | |
213 (spaces-string endextra)))) | |
214 (setcdr lines (cons line (cdr lines))))) | |
215 | |
216 ;;;###autoload | 133 ;;;###autoload |
217 (defun extract-rectangle (start end) | 134 (defun extract-rectangle (start end) |
218 "Return the contents of the rectangle with corners at START and END, | 135 "Return contents of rectangle with corners at START and END. |
219 as a list of strings, one for each line of the rectangle." | 136 Value is list of strings, one for each line of the rectangle." |
220 (let ((lines (list nil))) | 137 (let ((lines (list nil))) ; XEmacs change |
221 (apply-on-rectangle 'extract-rectangle-line start end lines) | 138 (operate-on-rectangle 'extract-rectangle-line start end nil lines) |
222 (nreverse (cdr lines)))) | 139 (nreverse (cdr lines)))) |
223 | 140 |
224 | |
225 ;;;###autoload | 141 ;;;###autoload |
226 (defvar killed-rectangle nil | 142 (defvar killed-rectangle nil |
227 "Rectangle for `yank-rectangle' to insert.") | 143 "Rectangle for yank-rectangle to insert.") |
228 | 144 |
229 ;;;###autoload | 145 ;;;###autoload |
230 (defun kill-rectangle (start end &optional fill) | 146 (defun kill-rectangle (start end) |
231 "Delete the region-rectangle and save it as the last killed one. | 147 "Delete rectangle with corners at point and mark; save as last killed one. |
232 You might prefer to use `delete-extract-rectangle' from a program. | 148 Calling from program, supply two args START and END, buffer positions. |
233 | 149 But in programs you might prefer to use `delete-extract-rectangle'." |
234 When called from a program, the rectangle's corners are START and END. | 150 (interactive "r") |
235 With a prefix (or FILL) argument, also fill lines where nothing has to be | 151 (if buffer-read-only |
236 deleted." | 152 (progn |
237 (interactive "*r\nP") | 153 (setq killed-rectangle (extract-rectangle start end)) |
238 (when buffer-read-only | 154 (barf-if-buffer-read-only))) |
239 (setq killed-rectangle (extract-rectangle start end)) | 155 (setq killed-rectangle (delete-extract-rectangle start end))) |
240 (barf-if-buffer-read-only)) | 156 |
241 (setq killed-rectangle (delete-extract-rectangle start end fill))) | |
242 | |
243 ;; This function is untouched --dv | |
244 ;;;###autoload | 157 ;;;###autoload |
245 (defun yank-rectangle () | 158 (defun yank-rectangle () |
246 "Yank the last killed rectangle with upper left corner at point." | 159 "Yank the last killed rectangle with upper left corner at point." |
247 (interactive "*") | 160 (interactive) |
248 (insert-rectangle killed-rectangle)) | 161 (insert-rectangle killed-rectangle)) |
249 | 162 |
250 | |
251 ;; This function is untouched --dv | |
252 ;;;###autoload | 163 ;;;###autoload |
253 (defun insert-rectangle (rectangle) | 164 (defun insert-rectangle (rectangle) |
254 "Insert text of RECTANGLE with upper left corner at point. | 165 "Insert text of RECTANGLE with upper left corner at point. |
255 RECTANGLE's first line is inserted at point, its second | 166 RECTANGLE's first line is inserted at point, its second |
256 line is inserted at a point vertically under point, etc. | 167 line is inserted at a point vertically under point, etc. |
262 (first t)) | 173 (first t)) |
263 (push-mark) | 174 (push-mark) |
264 (while lines | 175 (while lines |
265 (or first | 176 (or first |
266 (progn | 177 (progn |
267 (forward-line 1) | 178 (forward-line 1) |
268 (or (bolp) (insert ?\n)) | 179 (or (bolp) (insert ?\n)) |
269 (move-to-column insertcolumn t))) | 180 (move-to-column insertcolumn t))) |
270 (setq first nil) | 181 (setq first nil) |
271 (insert (car lines)) | 182 (insert (car lines)) |
272 (setq lines (cdr lines))))) | 183 (setq lines (cdr lines))))) |
273 | 184 |
274 | 185 ;;;###autoload |
275 (defun open-rectangle-line (startcol endcol fill) | 186 (defun open-rectangle (start end) |
276 (when (= (move-to-column startcol (or fill 'coerce)) startcol) | 187 "Blank out rectangle with corners at point and mark, shifting text right. |
277 (unless (and (not fill) | 188 The text previously in the region is not overwritten by the blanks, |
278 (= (point) (point-at-eol))) | 189 but instead winds up to the right of the rectangle." |
279 (indent-to endcol)))) | 190 (interactive "r") |
280 | 191 (operate-on-rectangle 'open-rectangle-line start end nil) |
281 ;;;###autoload | |
282 (defun open-rectangle (start end &optional fill) | |
283 "Blank out the region-rectangle, shifting text right. | |
284 | |
285 When called from a program, the rectangle's corners are START and END. | |
286 With a prefix (or FILL) argument, fill with blanks even if there is no text | |
287 on the right side of the rectangle." | |
288 (interactive "*r\nP") | |
289 (apply-on-rectangle 'open-rectangle-line start end fill) | |
290 (goto-char start)) | 192 (goto-char start)) |
291 | 193 |
292 | 194 (defun open-rectangle-line (startpos begextra endextra) |
293 (defun string-rectangle-line (startcol endcol string delete) | 195 ;; Column where rectangle ends. |
294 (move-to-column startcol t) | 196 (let ((endcol (+ (current-column) endextra)) |
295 (if delete | 197 whitewidth) |
296 (delete-rectangle-line startcol endcol nil)) | 198 (goto-char startpos) |
297 (insert string)) | 199 ;; Column where rectangle begins. |
200 (let ((begcol (- (current-column) begextra))) | |
201 (skip-chars-forward " \t") | |
202 ;; Width of whitespace to be deleted and recreated. | |
203 (setq whitewidth (- (current-column) begcol))) | |
204 ;; Delete the whitespace following the start column. | |
205 (delete-region startpos (point)) | |
206 ;; Open the desired width, plus same amount of whitespace we just deleted. | |
207 (indent-to (+ endcol whitewidth)))) | |
298 | 208 |
299 ;;;###autoload | 209 ;;;###autoload |
300 (defun string-rectangle (start end string) | 210 (defun string-rectangle (start end string) |
301 "Insert STRING on each line of the region-rectangle, shifting text right. | 211 "Insert STRING on each line of the region-rectangle, shifting text right. |
302 The left edge of the rectangle specifies the column for insertion. | 212 The left edge of the rectangle specifies the column for insertion. |
303 | 213 This command does not delete or overwrite any existing text. |
304 If `pending-delete-mode' is active the string replace the region. | 214 |
305 Otherwise this command does not delete or overwrite any existing text. | 215 Called from a program, takes three args; START, END and STRING." |
306 | 216 (interactive "r\nsString rectangle: ") |
307 When called from a program, the rectangle's corners are START and END." | 217 (operate-on-rectangle 'string-rectangle-line start end t string)) ; XEmacs |
308 (interactive "*r\nsString rectangle: ") | 218 |
309 (defvar pending-delete-mode) | 219 ;; XEmacs: add string arg |
310 (apply-on-rectangle 'string-rectangle-line start end string | 220 (defun string-rectangle-line (startpos begextra endextra string) |
311 (and (boundp 'pending-delete-mode) pending-delete-mode))) | 221 (let (whitespace) |
312 | 222 (goto-char startpos) |
313 (defun replace-rectangle (start end string) | 223 ;; Compute horizontal width of following whitespace. |
314 "Like `string-rectangle', but unconditionally replace the original region, | 224 (let ((ocol (current-column))) |
315 as if `pending-delete-mode' were active." | 225 (skip-chars-forward " \t") |
316 (interactive "*r\nsString rectangle: ") | 226 (setq whitespace (- (current-column) ocol))) |
317 (apply-on-rectangle 'string-rectangle-line start end string t)) | 227 ;; Delete the following whitespace. |
318 | 228 (delete-region startpos (point)) |
319 | 229 ;; Insert the desired string. |
320 (defun clear-rectangle-line (startcol endcol fill) | 230 (insert string) |
321 (let ((pt (point-at-eol)) | 231 ;; Insert the same width of whitespace that we had before. |
322 spaces) | 232 (indent-to (+ (current-column) whitespace)))) |
323 (when (= (move-to-column startcol (or fill 'coerce)) startcol) | 233 |
324 (if (and (not fill) | 234 ;;;###autoload |
325 (<= (save-excursion (goto-char pt) (current-column)) endcol)) | 235 (defun clear-rectangle (start end) |
326 (delete-region (point) pt) | 236 "Blank out rectangle with corners at point and mark. |
327 ;; else | 237 The text previously in the region is overwritten by the blanks. |
328 (setq pt (point)) | 238 When called from a program, requires two args which specify the corners." |
329 (move-to-column endcol t) | 239 (interactive "r") |
330 (setq spaces (- (point) pt)) | 240 (operate-on-rectangle 'clear-rectangle-line start end t)) |
331 (delete-region pt (point)) | 241 |
332 (indent-to (+ (current-column) spaces)))) | 242 (defun clear-rectangle-line (startpos begextra endextra) |
333 )) | 243 ;; Find end of whitespace after the rectangle. |
334 | 244 (skip-chars-forward " \t") |
335 ;;;###autoload | 245 (let ((column (+ (current-column) endextra))) |
336 (defun clear-rectangle (start end &optional fill) | 246 ;; Delete the text in the rectangle, and following whitespace. |
337 "Blank out the region-rectangle. | 247 (delete-region (point) |
338 The text previously in the region is overwritten with blanks. | 248 (progn (goto-char startpos) |
339 | 249 (skip-chars-backward " \t") |
340 When called from a program, the rectangle's corners are START and END. | 250 (point))) |
341 With a prefix (or FILL) argument, also fill with blanks the parts of the | 251 ;; Reindent out to same column that we were at. |
342 rectangle which were empty." | 252 (indent-to column))) |
343 (interactive "*r\nP") | |
344 (apply-on-rectangle 'clear-rectangle-line start end fill)) | |
345 | |
346 | 253 |
347 (provide 'rect) | 254 (provide 'rect) |
348 | 255 |
349 ;;; rect.el ends here | 256 ;;; rect.el ends here |