Mercurial > hg > xemacs-beta
comparison lisp/fill.el @ 209:41ff10fd062f r20-4b3
Import from CVS: tag r20-4b3
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:04:58 +0200 |
parents | |
children | 0e522484dd2a |
comparison
equal
deleted
inserted
replaced
208:f427b8ec4379 | 209:41ff10fd062f |
---|---|
1 ;;; fill.el --- fill commands for XEmacs. | |
2 | |
3 ;; Copyright (C) 1985, 86, 92, 94, 95, 1997 Free Software Foundation, Inc. | |
4 | |
5 ;; Maintainer: XEmacs Development Team | |
6 ;; Keywords: wp, dumped | |
7 | |
8 ;; This file is part of XEmacs. | |
9 | |
10 ;; XEmacs is free software; you can redistribute it and/or modify it | |
11 ;; under the terms of the GNU General Public License as published by | |
12 ;; the Free Software Foundation; either version 2, or (at your option) | |
13 ;; any later version. | |
14 | |
15 ;; XEmacs is distributed in the hope that it will be useful, but | |
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 ;; General Public License for more details. | |
19 | |
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 | |
22 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
23 ;; 02111-1307, USA. | |
24 | |
25 ;;; Synched up with: FSF 19.34. | |
26 | |
27 ;;; Commentary: | |
28 | |
29 ;; This file is dumped with XEmacs. | |
30 | |
31 ;; All the commands for filling text. These are documented in the XEmacs | |
32 ;; Reference Manual. | |
33 | |
34 ;; 97/3/14 Jareth Hein (jhod@po.iijnet.or.jp) added functions for kinsoku (asian text | |
35 ;; line break processing) | |
36 ;; 97/06/11 Steve Baur (steve@altair.xemacs.org) converted broken | |
37 ;; following-char/preceding-char calls to char-after/char-before. | |
38 | |
39 ;;; Code: | |
40 | |
41 (defconst fill-individual-varying-indent nil | |
42 "*Controls criterion for a new paragraph in `fill-individual-paragraphs'. | |
43 Non-nil means changing indent doesn't end a paragraph. | |
44 That mode can handle paragraphs with extra indentation on the first line, | |
45 but it requires separator lines between paragraphs. | |
46 A value of nil means that any change in indentation starts a new paragraph.") | |
47 | |
48 (defconst sentence-end-double-space t | |
49 "*Non-nil means a single space does not end a sentence. | |
50 This variable applies only to filling, not motion commands. To | |
51 change the behavior of motion commands, see `sentence-end'.") | |
52 | |
53 (defconst colon-double-space nil | |
54 "*Non-nil means put two spaces after a colon when filling.") | |
55 | |
56 (defvar fill-paragraph-function nil | |
57 "Mode-specific function to fill a paragraph, or nil if there is none. | |
58 If the function returns nil, then `fill-paragraph' does its normal work.") | |
59 | |
60 (defun set-fill-prefix () | |
61 "Set the fill prefix to the current line up to point. | |
62 Filling expects lines to start with the fill prefix and | |
63 reinserts the fill prefix in each resulting line." | |
64 (interactive) | |
65 (setq fill-prefix (buffer-substring | |
66 (save-excursion (move-to-left-margin) (point)) | |
67 (point))) | |
68 (if (equal fill-prefix "") | |
69 (setq fill-prefix nil)) | |
70 (if fill-prefix | |
71 (message "fill-prefix: \"%s\"" fill-prefix) | |
72 (message "fill-prefix cancelled"))) | |
73 | |
74 (defconst adaptive-fill-mode t | |
75 "*Non-nil means determine a paragraph's fill prefix from its text.") | |
76 | |
77 ;; #### - this is still weak. Yeah, there's filladapt, but this should | |
78 ;; still be better... --Stig | |
79 (defconst adaptive-fill-regexp (purecopy "[ \t]*\\([#;>*]+ +\\)?") | |
80 "*Regexp to match text at start of line that constitutes indentation. | |
81 If Adaptive Fill mode is enabled, whatever text matches this pattern | |
82 on the second line of a paragraph is used as the standard indentation | |
83 for the paragraph. If the paragraph has just one line, the indentation | |
84 is taken from that line.") | |
85 | |
86 (defvar adaptive-fill-function nil | |
87 "*Function to call to choose a fill prefix for a paragraph. | |
88 This function is used when `adaptive-fill-regexp' does not match.") | |
89 | |
90 ;; Added for kinsoku processing. Use this instead of | |
91 ;; (skip-chars-backward "^ \t\n") | |
92 ;; (skip-chars-backward "^ \n" linebeg) | |
93 (defun fill-move-backward-to-break-point (regexp &optional lim) | |
94 (let ((opoint (point))) | |
95 ;; 93.8.23 by kawamoto@ics.es.osaka-u.ac.jp | |
96 ;; case of first 'word' being longer than fill-column | |
97 (if (not (re-search-backward regexp lim 'move)) | |
98 nil | |
99 ;; we have skipped backward SPC or WAN (word-across-newline). So move point forward again. | |
100 (forward-char) | |
101 (if (< opoint (point)) | |
102 (forward-char -1))))) | |
103 | |
104 ;; Added for kinsoku processing. Use instead of | |
105 ;; (re-search-forward "[ \t]" opoint t) | |
106 ;; (skip-chars-forward "^ \n") | |
107 ;; (skip-chars-forward "^ \n") | |
108 (defun fill-move-forward-to-break-point (regexp &optional lim) | |
109 (let ((opoint (point))) | |
110 (if (not (re-search-forward regexp lim 'move)) | |
111 nil | |
112 (forward-char -1) | |
113 (if (< (point) opoint) | |
114 (forward-char)))) | |
115 (if (featurep 'mule) (kinsoku-process-extend))) | |
116 | |
117 (defun fill-end-of-sentence-p () | |
118 (save-excursion | |
119 (skip-chars-backward " ]})\"'") | |
120 (memq (char-before (point)) '(?. ?? ?!)))) | |
121 | |
122 (defun current-fill-column () | |
123 "Return the fill-column to use for this line. | |
124 The fill-column to use for a buffer is stored in the variable `fill-column', | |
125 but can be locally modified by the `right-margin' text property, which is | |
126 subtracted from `fill-column'. | |
127 | |
128 The fill column to use for a line is the first column at which the column | |
129 number equals or exceeds the local fill-column - right-margin difference." | |
130 (save-excursion | |
131 (if fill-column | |
132 (let* ((here (progn (beginning-of-line) (point))) | |
133 (here-col 0) | |
134 (eol (progn (end-of-line) (point))) | |
135 margin fill-col change col) | |
136 ;; Look separately at each region of line with a different right-margin. | |
137 (while (and (setq margin (get-text-property here 'right-margin) | |
138 fill-col (- fill-column (or margin 0)) | |
139 change (text-property-not-all | |
140 here eol 'right-margin margin)) | |
141 (progn (goto-char (1- change)) | |
142 (setq col (current-column)) | |
143 (< col fill-col))) | |
144 (setq here change | |
145 here-col col)) | |
146 (max here-col fill-col))))) | |
147 | |
148 (defun canonically-space-region (beg end) | |
149 "Remove extra spaces between words in region. | |
150 Leave one space between words, two at end of sentences or after colons | |
151 \(depending on values of `sentence-end-double-space' and `colon-double-space'). | |
152 Remove indentation from each line." | |
153 (interactive "r") | |
154 ;;;### 97/3/14 jhod: Do I have to add anything here for kinsoku? | |
155 (save-excursion | |
156 (goto-char beg) | |
157 ;; XEmacs - (ENE/stig from fa-extras.el): Skip the start of a comment. | |
158 (and comment-start-skip | |
159 (looking-at comment-start-skip) | |
160 (goto-char (match-end 0))) | |
161 ;; Nuke tabs; they get screwed up in a fill. | |
162 ;; This is quick, but loses when a tab follows the end of a sentence. | |
163 ;; Actually, it is difficult to tell that from "Mr.\tSmith". | |
164 ;; Blame the typist. | |
165 (subst-char-in-region beg end ?\t ?\ ) | |
166 (while (and (< (point) end) | |
167 (re-search-forward " *" end t)) | |
168 (delete-region | |
169 (+ (match-beginning 0) | |
170 ;; Determine number of spaces to leave: | |
171 (save-excursion | |
172 (skip-chars-backward " ]})\"'") | |
173 (cond ((and sentence-end-double-space | |
174 (memq (char-before (point)) '(?. ?? ?!))) 2) | |
175 ((and colon-double-space | |
176 (eq (char-before (point)) ?:)) 2) | |
177 ((char-equal (char-before (point)) ?\n) 0) | |
178 (t 1)))) | |
179 (match-end 0))) | |
180 ;; Make sure sentences ending at end of line get an extra space. | |
181 ;; loses on split abbrevs ("Mr.\nSmith") | |
182 (goto-char beg) | |
183 (while (and (< (point) end) | |
184 (re-search-forward "[.?!][])}\"']*$" end t)) | |
185 ;; We insert before markers in case a caller such as | |
186 ;; do-auto-fill has done a save-excursion with point at the end | |
187 ;; of the line and wants it to stay at the end of the line. | |
188 (insert ? )))) | |
189 ;; XEmacs: we don't have this function. | |
190 ;; (insert-before-markers-and-inherit ? )))) | |
191 | |
192 ;; XEmacs -- added DONT-SKIP-FIRST. Port of older code changes by Stig. | |
193 ;; #### probably this junk is broken -- do-auto-fill doesn't actually use | |
194 ;; it. If so, it should be removed. | |
195 | |
196 (defun fill-context-prefix (from to &optional first-line-regexp | |
197 dont-skip-first) | |
198 "Compute a fill prefix from the text between FROM and TO. | |
199 This uses the variables `adaptive-fill-prefix' and `adaptive-fill-function'. | |
200 If FIRST-LINE-REGEXP is non-nil, then when taking a prefix from the | |
201 first line, insist it must match FIRST-LINE-REGEXP." | |
202 (save-excursion | |
203 (goto-char from) | |
204 (if (eolp) (forward-line 1)) | |
205 ;; Move to the second line unless there is just one. | |
206 (let ((firstline (point)) | |
207 ;; Non-nil if we are on the second line. | |
208 at-second | |
209 result) | |
210 ;; XEmacs change | |
211 (if (not dont-skip-first) | |
212 (forward-line 1)) | |
213 (if (>= (point) to) | |
214 (goto-char firstline) | |
215 (setq at-second t)) | |
216 (move-to-left-margin) | |
217 ;; XEmacs change | |
218 (let ((start (point)) | |
219 ; jhod: no longer used? | |
220 ;(eol (save-excursion (end-of-line) (point))) | |
221 ) | |
222 (setq result | |
223 (if (not (looking-at paragraph-start)) | |
224 (cond ((and adaptive-fill-regexp (looking-at adaptive-fill-regexp)) | |
225 (buffer-substring-no-properties start (match-end 0))) | |
226 (adaptive-fill-function (funcall adaptive-fill-function))))) | |
227 (and result | |
228 (or at-second | |
229 (null first-line-regexp) | |
230 (string-match first-line-regexp result)) | |
231 result))))) | |
232 | |
233 ;; XEmacs (stig) - this is pulled out of fill-region-as-paragraph so that it | |
234 ;; can also be called from do-auto-fill | |
235 ;; #### But it's not used there. Chuck pulled it out because it broke things. | |
236 (defun maybe-adapt-fill-prefix (&optional from to dont-skip-first) | |
237 (if (and adaptive-fill-mode | |
238 (or (null fill-prefix) (string= fill-prefix ""))) | |
239 (setq fill-prefix (fill-context-prefix from to nil dont-skip-first)))) | |
240 | |
241 (defun fill-region-as-paragraph (from to &optional justify | |
242 nosqueeze squeeze-after) | |
243 "Fill the region as one paragraph. | |
244 It removes any paragraph breaks in the region and extra newlines at the end, | |
245 indents and fills lines between the margins given by the | |
246 `current-left-margin' and `current-fill-column' functions. | |
247 It leaves point at the beginning of the line following the paragraph. | |
248 | |
249 Normally performs justification according to the `current-justification' | |
250 function, but with a prefix arg, does full justification instead. | |
251 | |
252 From a program, optional third arg JUSTIFY can specify any type of | |
253 justification. Fourth arg NOSQUEEZE non-nil means not to make spaces | |
254 between words canonical before filling. Fifth arg SQUEEZE-AFTER, if non-nil, | |
255 means don't canonicalize spaces before that position. | |
256 | |
257 If `sentence-end-double-space' is non-nil, then period followed by one | |
258 space does not end a sentence, so don't break a line there." | |
259 (interactive | |
260 (progn | |
261 ;; XEmacs addition: | |
262 (barf-if-buffer-read-only nil (region-beginning) (region-end)) | |
263 (list (region-beginning) (region-end) | |
264 (if current-prefix-arg 'full)))) | |
265 ;; Arrange for undoing the fill to restore point. | |
266 (if (and buffer-undo-list (not (eq buffer-undo-list t))) | |
267 (setq buffer-undo-list (cons (point) buffer-undo-list))) | |
268 | |
269 ;; Make sure "to" is the endpoint. | |
270 (goto-char (min from to)) | |
271 (setq to (max from to)) | |
272 ;; Ignore blank lines at beginning of region. | |
273 (skip-chars-forward " \t\n") | |
274 | |
275 (let ((from-plus-indent (point)) | |
276 (oneleft nil)) | |
277 | |
278 (beginning-of-line) | |
279 (setq from (point)) | |
280 | |
281 ;; Delete all but one soft newline at end of region. | |
282 ;; And leave TO before that one. | |
283 (goto-char to) | |
284 (while (and (> (point) from) (eq ?\n (char-after (1- (point))))) | |
285 (if (and oneleft | |
286 (not (and use-hard-newlines | |
287 (get-text-property (1- (point)) 'hard)))) | |
288 (delete-backward-char 1) | |
289 (backward-char 1) | |
290 (setq oneleft t))) | |
291 (setq to (point)) | |
292 | |
293 ;; If there was no newline, and there is text in the paragraph, then | |
294 ;; create a newline. | |
295 (if (and (not oneleft) (> to from-plus-indent)) | |
296 (newline)) | |
297 (goto-char from-plus-indent)) | |
298 | |
299 (if (not (> to (point))) | |
300 nil ; There is no paragraph, only whitespace: exit now. | |
301 | |
302 (or justify (setq justify (current-justification))) | |
303 | |
304 ;; Don't let Adaptive Fill mode alter the fill prefix permanently. | |
305 (let ((fill-prefix fill-prefix)) | |
306 ;; Figure out how this paragraph is indented, if desired. | |
307 ;; XEmacs: move some code here to a separate function. | |
308 (maybe-adapt-fill-prefix from to t) | |
309 | |
310 (save-restriction | |
311 (goto-char from) | |
312 (beginning-of-line) | |
313 (narrow-to-region (point) to) | |
314 | |
315 (if (not justify) ; filling disabled: just check indentation | |
316 (progn | |
317 (goto-char from) | |
318 (while (not (eobp)) | |
319 (if (and (not (eolp)) | |
320 (< (current-indentation) (current-left-margin))) | |
321 (indent-to-left-margin)) | |
322 (forward-line 1))) | |
323 | |
324 (if use-hard-newlines | |
325 (remove-text-properties from (point-max) '(hard nil))) | |
326 ;; Make sure first line is indented (at least) to left margin... | |
327 (if (or (memq justify '(right center)) | |
328 (< (current-indentation) (current-left-margin))) | |
329 (indent-to-left-margin)) | |
330 ;; Delete the fill prefix from every line except the first. | |
331 ;; The first line may not even have a fill prefix. | |
332 (goto-char from) | |
333 (let ((fpre (and fill-prefix (not (equal fill-prefix "")) | |
334 (concat "[ \t]*" | |
335 (regexp-quote fill-prefix) | |
336 "[ \t]*")))) | |
337 (and fpre | |
338 (progn | |
339 (if (>= (+ (current-left-margin) (length fill-prefix)) | |
340 (current-fill-column)) | |
341 (error "fill-prefix too long for specified width")) | |
342 (goto-char from) | |
343 (forward-line 1) | |
344 (while (not (eobp)) | |
345 (if (looking-at fpre) | |
346 (delete-region (point) (match-end 0))) | |
347 (forward-line 1)) | |
348 (goto-char from) | |
349 (if (looking-at fpre) | |
350 (goto-char (match-end 0))) | |
351 (setq from (point))))) | |
352 ;; Remove indentation from lines other than the first. | |
353 (beginning-of-line 2) | |
354 (indent-region (point) (point-max) 0) | |
355 (goto-char from) | |
356 | |
357 ;; FROM, and point, are now before the text to fill, | |
358 ;; but after any fill prefix on the first line. | |
359 | |
360 ;; Make sure sentences ending at end of line get an extra space. | |
361 ;; loses on split abbrevs ("Mr.\nSmith") | |
362 (while (re-search-forward "[.?!][])}\"']*$" nil t) | |
363 ;; XEmacs change (no insert-and-inherit) | |
364 (or (eobp) (insert ?\ ?\ ))) | |
365 (goto-char from) | |
366 (skip-chars-forward " \t") | |
367 ;; Then change all newlines to spaces. | |
368 ;;; 97/3/14 jhod: Kinsoku change | |
369 ;; Spacing is not necessary for charcters of no word-separater. | |
370 ;; The regexp word-across-newline is used for this check. | |
371 (if (not (and (featurep 'mule) | |
372 (stringp word-across-newline))) | |
373 (subst-char-in-region from (point-max) ?\n ?\ ) | |
374 ;; | |
375 ;; WAN +NL+WAN --> WAN + WAN | |
376 ;; not(WAN)+NL+WAN --> not(WAN) + WAN | |
377 ;; WAN +NL+not(WAN) --> WAN + not(WAN) | |
378 ;; SPC +NL+not(WAN) --> SPC + not(WAN) | |
379 ;; not(WAN)+NL+not(WAN) --> not(WAN) + SPC + not(WAN) | |
380 ;; | |
381 (goto-char from) | |
382 (end-of-line) | |
383 (while (not (eobp)) | |
384 ;; Insert SPC only when point is between nonWAN. Insert | |
385 ;; before deleting to preserve marker if possible. | |
386 (if (or (prog2 ; check following char. | |
387 (forward-char) ; skip newline | |
388 (or (eobp) | |
389 (looking-at word-across-newline)) | |
390 (forward-char -1)) | |
391 (prog2 ; check previous char. | |
392 (forward-char -1) | |
393 (or (eq (char-after (point)) ?\ ) | |
394 (looking-at word-across-newline)) | |
395 (forward-char))) | |
396 nil | |
397 (insert ?\ )) | |
398 (delete-char 1) ; delete newline | |
399 (end-of-line))) | |
400 ;; end patch | |
401 (goto-char from) | |
402 (skip-chars-forward " \t") | |
403 (if (and nosqueeze (not (eq justify 'full))) | |
404 nil | |
405 (canonically-space-region (or squeeze-after (point)) (point-max)) | |
406 (goto-char (point-max)) | |
407 (delete-horizontal-space) | |
408 ;; XEmacs change (no insert-and-inherit) | |
409 (insert " ")) | |
410 (goto-char (point-min)) | |
411 | |
412 ;; This is the actual filling loop. | |
413 (let ((prefixcol 0) linebeg | |
414 (re-break-point (if (featurep 'mule) | |
415 (concat "[ \n\t]\\|" word-across-newline) | |
416 "[ \n\t]"))) | |
417 (while (not (eobp)) | |
418 (setq linebeg (point)) | |
419 (move-to-column (1+ (current-fill-column))) | |
420 (if (eobp) | |
421 (or nosqueeze (delete-horizontal-space)) | |
422 ;; Move back to start of word. | |
423 ;; 97/3/14 jhod: Kinsoku | |
424 ;(skip-chars-backward "^ \n" linebeg) | |
425 (fill-move-backward-to-break-point re-break-point linebeg) | |
426 ;; end patch | |
427 ;; Don't break after a period followed by just one space. | |
428 ;; Move back to the previous place to break. | |
429 ;; The reason is that if a period ends up at the end of a line, | |
430 ;; further fills will assume it ends a sentence. | |
431 ;; If we now know it does not end a sentence, | |
432 ;; avoid putting it at the end of the line. | |
433 (if sentence-end-double-space | |
434 (while (and (> (point) (+ linebeg 2)) | |
435 (eq (char-before (point)) ?\ ) | |
436 (not (eq (char-after (point)) ?\ )) | |
437 (eq (char-after (- (point) 2)) ?\.)) | |
438 (forward-char -2) | |
439 ;; 97/3/14 jhod: Kinsoku | |
440 ;(skip-chars-backward "^ \n" linebeg))) | |
441 (fill-move-backward-to-break-point re-break-point linebeg))) | |
442 (if (featurep 'mule) (kinsoku-process)) | |
443 ;end patch | |
444 | |
445 ;; If the left margin and fill prefix by themselves | |
446 ;; pass the fill-column. or if they are zero | |
447 ;; but we have no room for even one word, | |
448 ;; keep at least one word anyway. | |
449 ;; This handles ALL BUT the first line of the paragraph. | |
450 (if (if (zerop prefixcol) | |
451 (save-excursion | |
452 (skip-chars-backward " \t" linebeg) | |
453 (bolp)) | |
454 (>= prefixcol (current-column))) | |
455 ;; Ok, skip at least one word. | |
456 ;; Meanwhile, don't stop at a period followed by one space. | |
457 (let ((first t)) | |
458 (move-to-column prefixcol) | |
459 (while (and (not (eobp)) | |
460 (or first | |
461 (and (not (bobp)) | |
462 sentence-end-double-space | |
463 (save-excursion (forward-char -1) | |
464 (and (looking-at "\\. ") | |
465 (not (looking-at "\\. "))))))) | |
466 (skip-chars-forward " \t") | |
467 ;; 94/3/14 jhod: Kinsoku | |
468 ;(skip-chars-forward "^ \n\t") | |
469 (fill-move-forward-to-break-point re-break-point) | |
470 ;; end patch | |
471 (setq first nil))) | |
472 ;; Normally, move back over the single space between the words. | |
473 (if (eq (char-before (point)) ?\ ) | |
474 (forward-char -1))) | |
475 ;; If the left margin and fill prefix by themselves | |
476 ;; pass the fill-column, keep at least one word. | |
477 ;; This handles the first line of the paragraph. | |
478 (if (and (zerop prefixcol) | |
479 (let ((fill-point (point)) nchars) | |
480 (save-excursion | |
481 (move-to-left-margin) | |
482 (setq nchars (- fill-point (point))) | |
483 (or (< nchars 0) | |
484 (and fill-prefix | |
485 (< nchars (length fill-prefix)) | |
486 (string= (buffer-substring (point) fill-point) | |
487 (substring fill-prefix 0 nchars))))))) | |
488 ;; Ok, skip at least one word. But | |
489 ;; don't stop at a period followed by just one space. | |
490 (let ((first t)) | |
491 (while (and (not (eobp)) | |
492 (or first | |
493 (and (not (bobp)) | |
494 sentence-end-double-space | |
495 (save-excursion (forward-char -1) | |
496 (and (looking-at "\\. ") | |
497 (not (looking-at "\\. "))))))) | |
498 (skip-chars-forward " \t") | |
499 ;; 97/3/14 jhod: Kinsoku | |
500 ;(skip-chars-forward "^ \t\n") | |
501 (fill-move-forward-to-break-point re-break-point) | |
502 ;; end patch | |
503 (setq first nil)))) | |
504 ;; Check again to see if we got to the end of the paragraph. | |
505 (if (save-excursion (skip-chars-forward " \t") (eobp)) | |
506 (or nosqueeze (delete-horizontal-space)) | |
507 ;; Replace whitespace here with one newline, then indent to left | |
508 ;; margin. | |
509 (skip-chars-backward " \t") | |
510 ;; 97/3/14 jhod: More kinsoku stuff | |
511 (if (featurep 'mule) | |
512 ;; WAN means chars which match word-across-newline. | |
513 ;; (0) | SPC + SPC* <EOB> --> NL | |
514 ;; (1) WAN | SPC + SPC* --> WAN + SPC + NL | |
515 ;; (2) | SPC + SPC* + WAN --> SPC + NL + WAN | |
516 ;; (3) '.' | SPC + nonSPC --> '.' + SPC + NL + nonSPC | |
517 ;; (4) '.' | SPC + SPC --> '.' + NL | |
518 ;; (5) | SPC* --> NL | |
519 (let ((start (point)) ; 92.6.30 by K.Handa | |
520 (ch (char-after (point)))) | |
521 (if (and (= ch ? ) | |
522 (progn ; not case (0) -- 92.6.30 by K.Handa | |
523 (skip-chars-forward " \t") | |
524 (not (eobp))) | |
525 (or | |
526 (progn ; case (1) | |
527 (goto-char start) | |
528 (forward-char -1) | |
529 (looking-at word-across-newline)) | |
530 (progn ; case (2) | |
531 (goto-char start) | |
532 (skip-chars-forward " \t") | |
533 (and (not (eobp)) | |
534 (looking-at word-across-newline) | |
535 ;; never leave space after the end of sentence | |
536 (not (fill-end-of-sentence-p)))) | |
537 (progn ; case (3) | |
538 (goto-char (1+ start)) | |
539 (and (not (eobp)) | |
540 (not (eq (char-after (point)) ? )) | |
541 (fill-end-of-sentence-p))))) | |
542 ;; We should keep one SPACE before NEWLINE. (1),(2),(3) | |
543 (goto-char (1+ start)) | |
544 ;; We should delete all SPACES around break point. (4),(5) | |
545 (goto-char start)))) | |
546 ;; end of patch | |
547 (insert ?\n) | |
548 ;; Give newline the properties of the space(s) it replaces | |
549 (set-text-properties (1- (point)) (point) | |
550 (text-properties-at (point))) | |
551 (indent-to-left-margin) | |
552 ;; Insert the fill prefix after indentation. | |
553 ;; Set prefixcol so whitespace in the prefix won't get lost. | |
554 (and fill-prefix (not (equal fill-prefix "")) | |
555 (progn | |
556 (insert fill-prefix) | |
557 (setq prefixcol (current-column)))))) | |
558 ;; Justify the line just ended, if desired. | |
559 (if justify | |
560 (if (save-excursion (skip-chars-forward " \t") (eobp)) | |
561 (progn | |
562 (delete-horizontal-space) | |
563 (justify-current-line justify t t)) | |
564 (forward-line -1) | |
565 (justify-current-line justify nil t) | |
566 (forward-line 1)))))) | |
567 ;; Leave point after final newline. | |
568 (goto-char (point-max))) | |
569 (forward-char 1)))) | |
570 | |
571 (defun fill-paragraph (arg) | |
572 "Fill paragraph at or after point. Prefix arg means justify as well. | |
573 If `sentence-end-double-space' is non-nil, then period followed by one | |
574 space does not end a sentence, so don't break a line there. | |
575 | |
576 If `fill-paragraph-function' is non-nil, we call it (passing our | |
577 argument to it), and if it returns non-nil, we simply return its value." | |
578 (interactive (list (if current-prefix-arg 'full))) | |
579 (or (and fill-paragraph-function | |
580 (let ((function fill-paragraph-function) | |
581 fill-paragraph-function) | |
582 (funcall function arg))) | |
583 (let ((before (point))) | |
584 (save-excursion | |
585 (forward-paragraph) | |
586 (or (bolp) (newline 1)) | |
587 (let ((end (point)) | |
588 (beg (progn (backward-paragraph) (point)))) | |
589 (goto-char before) | |
590 (if use-hard-newlines | |
591 ;; Can't use fill-region-as-paragraph, since this paragraph may | |
592 ;; still contain hard newlines. See fill-region. | |
593 (fill-region beg end arg) | |
594 (fill-region-as-paragraph beg end arg))))))) | |
595 | |
596 (defun fill-region (from to &optional justify nosqueeze to-eop) | |
597 "Fill each of the paragraphs in the region. | |
598 Prefix arg (non-nil third arg, if called from program) means justify as well. | |
599 | |
600 Noninteractively, fourth arg NOSQUEEZE non-nil means to leave | |
601 whitespace other than line breaks untouched, and fifth arg TO-EOP | |
602 non-nil means to keep filling to the end of the paragraph (or next | |
603 hard newline, if `use-hard-newlines' is on). | |
604 | |
605 If `sentence-end-double-space' is non-nil, then period followed by one | |
606 space does not end a sentence, so don't break a line there." | |
607 (interactive | |
608 (progn | |
609 ;; XEmacs addition: | |
610 (barf-if-buffer-read-only nil (region-beginning) (region-end)) | |
611 (list (region-beginning) (region-end) | |
612 (if current-prefix-arg 'full)))) | |
613 (let (end beg) | |
614 (save-restriction | |
615 (goto-char (max from to)) | |
616 (if to-eop | |
617 (progn (skip-chars-backward "\n") | |
618 (forward-paragraph))) | |
619 (setq end (point)) | |
620 (goto-char (setq beg (min from to))) | |
621 (beginning-of-line) | |
622 (narrow-to-region (point) end) | |
623 (while (not (eobp)) | |
624 (let ((initial (point)) | |
625 end) | |
626 ;; If using hard newlines, break at every one for filling | |
627 ;; purposes rather than using paragraph breaks. | |
628 (if use-hard-newlines | |
629 (progn | |
630 (while (and (setq end (text-property-any (point) (point-max) | |
631 'hard t)) | |
632 (not (eq ?\n (char-after end))) | |
633 (not (= end (point-max)))) | |
634 (goto-char (1+ end))) | |
635 (setq end (if end (min (point-max) (1+ end)) (point-max))) | |
636 (goto-char initial)) | |
637 (forward-paragraph 1) | |
638 (setq end (point)) | |
639 (forward-paragraph -1)) | |
640 (if (< (point) beg) | |
641 (goto-char beg)) | |
642 (if (>= (point) initial) | |
643 (fill-region-as-paragraph (point) end justify nosqueeze) | |
644 (goto-char end))))))) | |
645 | |
646 ;; XEmacs addition: from Tim Bradshaw <tfb@edinburgh.ac.uk> | |
647 (defun fill-paragraph-or-region (arg) | |
648 "Fill the current region, if it's active; otherwise, fill the paragraph. | |
649 See `fill-paragraph' and `fill-region' for more information." | |
650 (interactive "*P") | |
651 (if (region-active-p) | |
652 (fill-region (point) (mark) arg) | |
653 (fill-paragraph arg))) | |
654 | |
655 | |
656 (defconst default-justification 'left | |
657 "*Method of justifying text not otherwise specified. | |
658 Possible values are `left', `right', `full', `center', or `none'. | |
659 The requested kind of justification is done whenever lines are filled. | |
660 The `justification' text-property can locally override this variable. | |
661 This variable automatically becomes buffer-local when set in any fashion.") | |
662 (make-variable-buffer-local 'default-justification) | |
663 | |
664 (defun current-justification () | |
665 "How should we justify this line? | |
666 This returns the value of the text-property `justification', | |
667 or the variable `default-justification' if there is no text-property. | |
668 However, it returns nil rather than `none' to mean \"don't justify\"." | |
669 (let ((j (or (get-text-property | |
670 ;; Make sure we're looking at paragraph body. | |
671 (save-excursion (skip-chars-forward " \t") | |
672 (if (and (eobp) (not (bobp))) | |
673 (1- (point)) (point))) | |
674 'justification) | |
675 default-justification))) | |
676 (if (eq 'none j) | |
677 nil | |
678 j))) | |
679 | |
680 (defun set-justification (begin end value &optional whole-par) | |
681 "Set the region's justification style. | |
682 The kind of justification to use is prompted for. | |
683 If the mark is not active, this command operates on the current paragraph. | |
684 If the mark is active, the region is used. However, if the beginning and end | |
685 of the region are not at paragraph breaks, they are moved to the beginning and | |
686 end of the paragraphs they are in. | |
687 If `use-hard-newlines' is true, all hard newlines are taken to be paragraph | |
688 breaks. | |
689 | |
690 When calling from a program, operates just on region between BEGIN and END, | |
691 unless optional fourth arg WHOLE-PAR is non-nil. In that case bounds are | |
692 extended to include entire paragraphs as in the interactive command." | |
693 ;; XEmacs change (was mark-active) | |
694 (interactive (list (if (region-active-p) (region-beginning) (point)) | |
695 (if (region-active-p) (region-end) (point)) | |
696 (let ((s (completing-read | |
697 "Set justification to: " | |
698 '(("left") ("right") ("full") | |
699 ("center") ("none")) | |
700 nil t))) | |
701 (if (equal s "") (error "")) | |
702 (intern s)) | |
703 t)) | |
704 (save-excursion | |
705 (save-restriction | |
706 (if whole-par | |
707 (let ((paragraph-start (if use-hard-newlines "." paragraph-start)) | |
708 (paragraph-ignore-fill-prefix (if use-hard-newlines t | |
709 paragraph-ignore-fill-prefix))) | |
710 (goto-char begin) | |
711 (while (and (bolp) (not (eobp))) (forward-char 1)) | |
712 (backward-paragraph) | |
713 (setq begin (point)) | |
714 (goto-char end) | |
715 (skip-chars-backward " \t\n" begin) | |
716 (forward-paragraph) | |
717 (setq end (point)))) | |
718 | |
719 (narrow-to-region (point-min) end) | |
720 (unjustify-region begin (point-max)) | |
721 (put-text-property begin (point-max) 'justification value) | |
722 (fill-region begin (point-max) nil t)))) | |
723 | |
724 (defun set-justification-none (b e) | |
725 "Disable automatic filling for paragraphs in the region. | |
726 If the mark is not active, this applies to the current paragraph." | |
727 ;; XEmacs change (was mark-active) | |
728 (interactive (list (if (region-active-p) (region-beginning) (point)) | |
729 (if (region-active-p) (region-end) (point)))) | |
730 (set-justification b e 'none t)) | |
731 | |
732 (defun set-justification-left (b e) | |
733 "Make paragraphs in the region left-justified. | |
734 This is usually the default, but see the variable `default-justification'. | |
735 If the mark is not active, this applies to the current paragraph." | |
736 ;; XEmacs change (was mark-active) | |
737 (interactive (list (if (region-active-p) (region-beginning) (point)) | |
738 (if (region-active-p) (region-end) (point)))) | |
739 (set-justification b e 'left t)) | |
740 | |
741 (defun set-justification-right (b e) | |
742 "Make paragraphs in the region right-justified: | |
743 Flush at the right margin and ragged on the left. | |
744 If the mark is not active, this applies to the current paragraph." | |
745 ;; XEmacs change (was mark-active) | |
746 (interactive (list (if (region-active-p) (region-beginning) (point)) | |
747 (if (region-active-p) (region-end) (point)))) | |
748 (set-justification b e 'right t)) | |
749 | |
750 (defun set-justification-full (b e) | |
751 "Make paragraphs in the region fully justified: | |
752 This makes lines flush on both margins by inserting spaces between words. | |
753 If the mark is not active, this applies to the current paragraph." | |
754 ;; XEmacs change (was mark-active) | |
755 (interactive (list (if (region-active-p) (region-beginning) (point)) | |
756 (if (region-active-p) (region-end) (point)))) | |
757 (set-justification b e 'full t)) | |
758 | |
759 (defun set-justification-center (b e) | |
760 "Make paragraphs in the region centered. | |
761 If the mark is not active, this applies to the current paragraph." | |
762 ;; XEmacs change (was mark-active) | |
763 (interactive (list (if (region-active-p) (region-beginning) (point)) | |
764 (if (region-active-p) (region-end) (point)))) | |
765 (set-justification b e 'center t)) | |
766 | |
767 ;; 97/3/14 jhod: This functions are added for Kinsoku support | |
768 (defun find-space-insertable-point () | |
769 "Search backward for a permissable point for inserting justification spaces" | |
770 (if (boundp 'space-insertable) | |
771 (if (re-search-backward space-insertable nil t) | |
772 (progn (forward-char 1) | |
773 t) | |
774 nil) | |
775 (search-backward " " nil t))) | |
776 | |
777 ;; A line has up to six parts: | |
778 ;; | |
779 ;; >>> hello. | |
780 ;; [Indent-1][FP][ Indent-2 ][text][trailing whitespace][newline] | |
781 ;; | |
782 ;; "Indent-1" is the left-margin indentation; normally it ends at column | |
783 ;; given by the `current-left-margin' function. | |
784 ;; "FP" is the fill-prefix. It can be any string, including whitespace. | |
785 ;; "Indent-2" is added to justify a line if the `current-justification' is | |
786 ;; `center' or `right'. In `left' and `full' justification regions, any | |
787 ;; whitespace there is part of the line's text, and should not be changed. | |
788 ;; Trailing whitespace is not counted as part of the line length when | |
789 ;; center- or right-justifying. | |
790 ;; | |
791 ;; All parts of the line are optional, although the final newline can | |
792 ;; only be missing on the last line of the buffer. | |
793 | |
794 (defun justify-current-line (&optional how eop nosqueeze) | |
795 "Do some kind of justification on this line. | |
796 Normally does full justification: adds spaces to the line to make it end at | |
797 the column given by `current-fill-column'. | |
798 Optional first argument HOW specifies alternate type of justification: | |
799 it can be `left', `right', `full', `center', or `none'. | |
800 If HOW is t, will justify however the `current-justification' function says to. | |
801 If HOW is nil or missing, full justification is done by default. | |
802 Second arg EOP non-nil means that this is the last line of the paragraph, so | |
803 it will not be stretched by full justification. | |
804 Third arg NOSQUEEZE non-nil means to leave interior whitespace unchanged, | |
805 otherwise it is made canonical." | |
806 (interactive) | |
807 (if (eq t how) (setq how (or (current-justification) 'none)) | |
808 (if (null how) (setq how 'full) | |
809 (or (memq how '(none left right center)) | |
810 (setq how 'full)))) | |
811 (or (memq how '(none left)) ; No action required for these. | |
812 (let ((fc (current-fill-column)) | |
813 (pos (point-marker)) | |
814 fp-end ; point at end of fill prefix | |
815 beg ; point at beginning of line's text | |
816 end ; point at end of line's text | |
817 indent ; column of `beg' | |
818 endcol ; column of `end' | |
819 ncols) ; new indent point or offset | |
820 (end-of-line) | |
821 ;; Check if this is the last line of the paragraph. | |
822 (if (and use-hard-newlines (null eop) | |
823 (get-text-property (point) 'hard)) | |
824 (setq eop t)) | |
825 (skip-chars-backward " \t") | |
826 ;; Quick exit if it appears to be properly justified already | |
827 ;; or there is no text. | |
828 (if (or (bolp) | |
829 (and (memq how '(full right)) | |
830 (= (current-column) fc))) | |
831 nil | |
832 (setq end (point)) | |
833 (beginning-of-line) | |
834 (skip-chars-forward " \t") | |
835 ;; Skip over fill-prefix. | |
836 (if (and fill-prefix | |
837 (not (string-equal fill-prefix "")) | |
838 (equal fill-prefix | |
839 (buffer-substring | |
840 (point) (min (point-max) (+ (length fill-prefix) | |
841 (point)))))) | |
842 (forward-char (length fill-prefix)) | |
843 (if (and adaptive-fill-mode | |
844 (looking-at adaptive-fill-regexp)) | |
845 (goto-char (match-end 0)))) | |
846 (setq fp-end (point)) | |
847 (skip-chars-forward " \t") | |
848 ;; This is beginning of the line's text. | |
849 (setq indent (current-column)) | |
850 (setq beg (point)) | |
851 (goto-char end) | |
852 (setq endcol (current-column)) | |
853 | |
854 ;; HOW can't be null or left--we would have exited already | |
855 (cond ((eq 'right how) | |
856 (setq ncols (- fc endcol)) | |
857 (if (< ncols 0) | |
858 ;; Need to remove some indentation | |
859 (delete-region | |
860 (progn (goto-char fp-end) | |
861 (if (< (current-column) (+ indent ncols)) | |
862 (move-to-column (+ indent ncols) t)) | |
863 (point)) | |
864 (progn (move-to-column indent) (point))) | |
865 ;; Need to add some | |
866 (goto-char beg) | |
867 (indent-to (+ indent ncols)) | |
868 ;; If point was at beginning of text, keep it there. | |
869 (if (= beg pos) | |
870 (move-marker pos (point))))) | |
871 | |
872 ((eq 'center how) | |
873 ;; Figure out how much indentation is needed | |
874 (setq ncols (+ (current-left-margin) | |
875 (/ (- fc (current-left-margin) ;avail. space | |
876 (- endcol indent)) ;text width | |
877 2))) | |
878 (if (< ncols indent) | |
879 ;; Have too much indentation - remove some | |
880 (delete-region | |
881 (progn (goto-char fp-end) | |
882 (if (< (current-column) ncols) | |
883 (move-to-column ncols t)) | |
884 (point)) | |
885 (progn (move-to-column indent) (point))) | |
886 ;; Have too little - add some | |
887 (goto-char beg) | |
888 (indent-to ncols) | |
889 ;; If point was at beginning of text, keep it there. | |
890 (if (= beg pos) | |
891 (move-marker pos (point))))) | |
892 | |
893 ((eq 'full how) | |
894 ;; Insert extra spaces between words to justify line | |
895 (save-restriction | |
896 (narrow-to-region beg end) | |
897 (or nosqueeze | |
898 (canonically-space-region beg end)) | |
899 (goto-char (point-max)) | |
900 (setq ncols (- fc endcol)) | |
901 ;; Ncols is number of additional spaces needed | |
902 (if (> ncols 0) | |
903 (if (and (not eop) | |
904 ;; 97/3/14 jhod: Kinsoku | |
905 (find-space-insertable-point)) ;(search-backward " " nil t)) | |
906 (while (> ncols 0) | |
907 (let ((nmove (+ 3 (random 3)))) | |
908 (while (> nmove 0) | |
909 (or (find-space-insertable-point) ;(search-backward " " nil t) | |
910 (progn | |
911 (goto-char (point-max)) | |
912 (find-space-insertable-point))) ;(search-backward " "))) | |
913 (skip-chars-backward " ") | |
914 (setq nmove (1- nmove)))) | |
915 ;; XEmacs change | |
916 (insert " ") | |
917 (skip-chars-backward " ") | |
918 (setq ncols (1- ncols))))))) | |
919 (t (error "Unknown justification value")))) | |
920 (goto-char pos) | |
921 (move-marker pos nil))) | |
922 nil) | |
923 | |
924 (defun unjustify-current-line () | |
925 "Remove justification whitespace from current line. | |
926 If the line is centered or right-justified, this function removes any | |
927 indentation past the left margin. If the line is full-justified, it removes | |
928 extra spaces between words. It does nothing in other justification modes." | |
929 (let ((justify (current-justification))) | |
930 (cond ((eq 'left justify) nil) | |
931 ((eq nil justify) nil) | |
932 ((eq 'full justify) ; full justify: remove extra spaces | |
933 (beginning-of-line-text) | |
934 (canonically-space-region | |
935 (point) (save-excursion (end-of-line) (point)))) | |
936 ((memq justify '(center right)) | |
937 (save-excursion | |
938 (move-to-left-margin nil t) | |
939 ;; Position ourselves after any fill-prefix. | |
940 (if (and fill-prefix | |
941 (not (string-equal fill-prefix "")) | |
942 (equal fill-prefix | |
943 (buffer-substring | |
944 (point) (min (point-max) (+ (length fill-prefix) | |
945 (point)))))) | |
946 (forward-char (length fill-prefix))) | |
947 (delete-region (point) (progn (skip-chars-forward " \t") | |
948 (point)))))))) | |
949 | |
950 (defun unjustify-region (&optional begin end) | |
951 "Remove justification whitespace from region. | |
952 For centered or right-justified regions, this function removes any indentation | |
953 past the left margin from each line. For full-justified lines, it removes | |
954 extra spaces between words. It does nothing in other justification modes. | |
955 Arguments BEGIN and END are optional; default is the whole buffer." | |
956 (save-excursion | |
957 (save-restriction | |
958 (if end (narrow-to-region (point-min) end)) | |
959 (goto-char (or begin (point-min))) | |
960 (while (not (eobp)) | |
961 (unjustify-current-line) | |
962 (forward-line 1))))) | |
963 | |
964 | |
965 (defun fill-nonuniform-paragraphs (min max &optional justifyp mailp) | |
966 "Fill paragraphs within the region, allowing varying indentation within each. | |
967 This command divides the region into \"paragraphs\", | |
968 only at paragraph-separator lines, then fills each paragraph | |
969 using as the fill prefix the smallest indentation of any line | |
970 in the paragraph. | |
971 | |
972 When calling from a program, pass range to fill as first two arguments. | |
973 | |
974 Optional third and fourth arguments JUSTIFY and MAIL-FLAG: | |
975 JUSTIFY to justify paragraphs (prefix arg), | |
976 MAIL-FLAG for a mail message, i. e. don't fill header lines." | |
977 (interactive (list (region-beginning) (region-end) | |
978 (if current-prefix-arg 'full))) | |
979 (let ((fill-individual-varying-indent t)) | |
980 (fill-individual-paragraphs min max justifyp mailp))) | |
981 | |
982 (defun fill-individual-paragraphs (min max &optional justify mailp) | |
983 "Fill paragraphs of uniform indentation within the region. | |
984 This command divides the region into \"paragraphs\", | |
985 treating every change in indentation level as a paragraph boundary, | |
986 then fills each paragraph using its indentation level as the fill prefix. | |
987 | |
988 When calling from a program, pass range to fill as first two arguments. | |
989 | |
990 Optional third and fourth arguments JUSTIFY and MAIL-FLAG: | |
991 JUSTIFY to justify paragraphs (prefix arg), | |
992 MAIL-FLAG for a mail message, i. e. don't fill header lines." | |
993 (interactive (list (region-beginning) (region-end) | |
994 (if current-prefix-arg 'full))) | |
995 (save-restriction | |
996 (save-excursion | |
997 (goto-char min) | |
998 (beginning-of-line) | |
999 (narrow-to-region (point) max) | |
1000 (if mailp | |
1001 (while (and (not (eobp)) | |
1002 (or (looking-at "[ \t]*[^ \t\n]+:") | |
1003 (looking-at "[ \t]*$"))) | |
1004 (if (looking-at "[ \t]*[^ \t\n]+:") | |
1005 (search-forward "\n\n" nil 'move) | |
1006 (forward-line 1)))) | |
1007 (narrow-to-region (point) max) | |
1008 ;; Loop over paragraphs. | |
1009 (while (progn (skip-chars-forward " \t\n") (not (eobp))) | |
1010 (move-to-left-margin) | |
1011 (let ((start (point)) | |
1012 fill-prefix fill-prefix-regexp) | |
1013 ;; Find end of paragraph, and compute the smallest fill-prefix | |
1014 ;; that fits all the lines in this paragraph. | |
1015 (while (progn | |
1016 ;; Update the fill-prefix on the first line | |
1017 ;; and whenever the prefix good so far is too long. | |
1018 (if (not (and fill-prefix | |
1019 (looking-at fill-prefix-regexp))) | |
1020 (setq fill-prefix | |
1021 (if (and adaptive-fill-mode adaptive-fill-regexp | |
1022 (looking-at adaptive-fill-regexp)) | |
1023 (match-string 0) | |
1024 (buffer-substring | |
1025 (point) | |
1026 (save-excursion (skip-chars-forward " \t") | |
1027 (point)))) | |
1028 fill-prefix-regexp (regexp-quote fill-prefix))) | |
1029 (forward-line 1) | |
1030 (if (bolp) | |
1031 ;; If forward-line went past a newline | |
1032 ;; move further to the left margin. | |
1033 (move-to-left-margin)) | |
1034 ;; Now stop the loop if end of paragraph. | |
1035 (and (not (eobp)) | |
1036 (if fill-individual-varying-indent | |
1037 ;; If this line is a separator line, with or | |
1038 ;; without prefix, end the paragraph. | |
1039 (and | |
1040 (not (looking-at paragraph-separate)) | |
1041 (save-excursion | |
1042 (not (and (looking-at fill-prefix-regexp) | |
1043 ;; XEmacs change | |
1044 (progn | |
1045 (forward-char (length fill-prefix)) | |
1046 (looking-at paragraph-separate)))))) | |
1047 ;; If this line has more or less indent | |
1048 ;; than the fill prefix wants, end the paragraph. | |
1049 (and (looking-at fill-prefix-regexp) | |
1050 (save-excursion | |
1051 (not | |
1052 (progn | |
1053 (forward-char (length fill-prefix)) | |
1054 (or (looking-at paragraph-separate) | |
1055 (looking-at paragraph-start)))))))))) | |
1056 ;; Fill this paragraph, but don't add a newline at the end. | |
1057 (let ((had-newline (bolp))) | |
1058 (fill-region-as-paragraph start (point) justify) | |
1059 (or had-newline (delete-char -1)))))))) | |
1060 | |
1061 ;;; fill.el ends here |