Mercurial > hg > xemacs-beta
comparison lisp/format.el @ 272:c5d627a313b1 r21-0b34
Import from CVS: tag r21-0b34
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:28:48 +0200 |
parents | 557eaa0339bf |
children | 74fd4e045ea6 |
comparison
equal
deleted
inserted
replaced
271:c7b7086b0a39 | 272:c5d627a313b1 |
---|---|
48 ;; risk losing any text-properties in the buffer). | 48 ;; risk losing any text-properties in the buffer). |
49 ;; | 49 ;; |
50 ;; You can manually translate a buffer into or out of a particular format | 50 ;; You can manually translate a buffer into or out of a particular format |
51 ;; with the functions `format-encode-buffer' and `format-decode-buffer'. | 51 ;; with the functions `format-encode-buffer' and `format-decode-buffer'. |
52 ;; To translate just the region use the functions `format-encode-region' | 52 ;; To translate just the region use the functions `format-encode-region' |
53 ;; and `format-decode-region'. | 53 ;; and `format-decode-region'. |
54 ;; | 54 ;; |
55 ;; You can define a new format by writing the encoding and decoding | 55 ;; You can define a new format by writing the encoding and decoding |
56 ;; functions, and adding an entry to `format-alist'. See enriched.el for | 56 ;; functions, and adding an entry to `format-alist'. See enriched.el for |
57 ;; an example of how to implement a file format. There are various | 57 ;; an example of how to implement a file format. There are various |
58 ;; functions defined in this file that may be useful for writing the | 58 ;; functions defined in this file that may be useful for writing the |
92 richtext-decode richtext-encode t enriched-mode) | 92 richtext-decode richtext-encode t enriched-mode) |
93 (plain "ISO 8859-1 standard format, no text properties." | 93 (plain "ISO 8859-1 standard format, no text properties." |
94 ;; Plain only exists so that there is an obvious neutral choice in | 94 ;; Plain only exists so that there is an obvious neutral choice in |
95 ;; the completion list. | 95 ;; the completion list. |
96 nil nil nil nil nil) | 96 nil nil nil nil nil) |
97 ;; (ibm "IBM Code Page 850 (DOS)" | 97 ;; (ibm "IBM Code Page 850 (DOS)" |
98 ;; "1\\(^\\)" | 98 ;; "1\\(^\\)" |
99 ;; "recode ibm-pc:latin1" "recode latin1:ibm-pc" t nil) | 99 ;; "recode ibm-pc:latin1" "recode latin1:ibm-pc" t nil) |
100 ;; (mac "Apple Macintosh" | 100 ;; (mac "Apple Macintosh" |
101 ;; "1\\(^\\)" | 101 ;; "1\\(^\\)" |
102 ;; "recode mac:latin1" "recode latin1:mac" t nil) | 102 ;; "recode mac:latin1" "recode latin1:mac" t nil) |
103 ;; (hp "HP Roman8" | 103 ;; (hp "HP Roman8" |
104 ;; "1\\(^\\)" | 104 ;; "1\\(^\\)" |
105 ;; "recode roman8:latin1" "recode latin1:roman8" t nil) | 105 ;; "recode roman8:latin1" "recode latin1:roman8" t nil) |
106 ;; (TeX "TeX (encoding)" | 106 ;; (TeX "TeX (encoding)" |
107 ;; "1\\(^\\)" | 107 ;; "1\\(^\\)" |
108 ;; iso-tex2iso iso-iso2tex t nil) | 108 ;; iso-tex2iso iso-iso2tex t nil) |
109 ;; (gtex "German TeX (encoding)" | 109 ;; (gtex "German TeX (encoding)" |
110 ;; "1\\(^\\)" | 110 ;; "1\\(^\\)" |
111 ;; iso-gtex2iso iso-iso2gtex t nil) | 111 ;; iso-gtex2iso iso-iso2gtex t nil) |
112 ;; (html "HTML (encoding)" | 112 ;; (html "HTML (encoding)" |
113 ;; "1\\(^\\)" | 113 ;; "1\\(^\\)" |
114 ;; "recode html:latin1" "recode latin1:html" t nil) | 114 ;; "recode html:latin1" "recode latin1:html" t nil) |
115 ;; (rot13 "rot13" | 115 ;; (rot13 "rot13" |
116 ;; "1\\(^\\)" | 116 ;; "1\\(^\\)" |
117 ;; "tr a-mn-z n-za-m" "tr a-mn-z n-za-m" t nil) | 117 ;; "tr a-mn-z n-za-m" "tr a-mn-z n-za-m" t nil) |
118 ;; (duden "Duden Ersatzdarstellung" | 118 ;; (duden "Duden Ersatzdarstellung" |
119 ;; "1\\(^\\)" | 119 ;; "1\\(^\\)" |
120 ;; "diac" iso-iso2duden t nil) | 120 ;; "diac" iso-iso2duden t nil) |
121 ;; (de646 "German ASCII (ISO 646)" | 121 ;; (de646 "German ASCII (ISO 646)" |
122 ;; "1\\(^\\)" | 122 ;; "1\\(^\\)" |
123 ;; "recode iso646-ge:latin1" "recode latin1:iso646-ge" t nil) | 123 ;; "recode iso646-ge:latin1" "recode latin1:iso646-ge" t nil) |
124 ;; (denet "net German" | 124 ;; (denet "net German" |
125 ;; "1\\(^\\)" | 125 ;; "1\\(^\\)" |
126 ;; iso-german iso-cvt-read-only t nil) | 126 ;; iso-german iso-cvt-read-only t nil) |
127 ;; (esnet "net Spanish" | 127 ;; (esnet "net Spanish" |
128 ;; "1\\(^\\)" | 128 ;; "1\\(^\\)" |
129 ;; iso-spanish iso-cvt-read-only t nil) | 129 ;; iso-spanish iso-cvt-read-only t nil) |
130 ) | 130 ) |
131 "List of information about understood file formats. | 131 "List of information about understood file formats. |
132 Elements are of the form \(NAME DOC-STR REGEXP FROM-FN TO-FN MODIFY MODE-FN). | 132 Elements are of the form \(NAME DOC-STR REGEXP FROM-FN TO-FN MODIFY MODE-FN). |
138 the user if they ask for more information. | 138 the user if they ask for more information. |
139 | 139 |
140 REGEXP is a regular expression to match against the beginning of the file; | 140 REGEXP is a regular expression to match against the beginning of the file; |
141 it should match only files in that format. | 141 it should match only files in that format. |
142 | 142 |
143 FROM-FN is called to decode files in that format; it gets two args, BEGIN | 143 FROM-FN is called to decode files in that format; it gets two args, BEGIN |
144 and END, and can make any modifications it likes, returning the new | 144 and END, and can make any modifications it likes, returning the new |
145 end. It must make sure that the beginning of the file no longer | 145 end. It must make sure that the beginning of the file no longer |
146 matches REGEXP, or else it will get called again. | 146 matches REGEXP, or else it will get called again. |
147 Alternatively, FROM-FN can be a string, which specifies a shell command | 147 Alternatively, FROM-FN can be a string, which specifies a shell command |
148 (including options) to be used as a filter to perform the conversion. | 148 (including options) to be used as a filter to perform the conversion. |
156 Alternatively, TO-FN can be a string, which specifies a shell command | 156 Alternatively, TO-FN can be a string, which specifies a shell command |
157 (including options) to be used as a filter to perform the conversion. | 157 (including options) to be used as a filter to perform the conversion. |
158 | 158 |
159 MODIFY, if non-nil, means the TO-FN wants to modify the region. If nil, | 159 MODIFY, if non-nil, means the TO-FN wants to modify the region. If nil, |
160 TO-FN will not make any changes but will instead return a list of | 160 TO-FN will not make any changes but will instead return a list of |
161 annotations. | 161 annotations. |
162 | 162 |
163 MODE-FN, if specified, is called when visiting a file with that format.") | 163 MODE-FN, if specified, is called when visiting a file with that format.") |
164 | 164 |
165 ;;; Basic Functions (called from Lisp) | 165 ;;; Basic Functions (called from Lisp) |
166 | 166 |
187 (shell-command-on-region from to method t nil)) | 187 (shell-command-on-region from to method t nil)) |
188 (point)) | 188 (point)) |
189 (funcall method from to))) | 189 (funcall method from to))) |
190 | 190 |
191 (defun format-annotate-function (format from to orig-buf) | 191 (defun format-annotate-function (format from to orig-buf) |
192 "Returns annotations for writing region as FORMAT. | 192 "Return annotations for writing region as FORMAT. |
193 FORMAT is a symbol naming one of the formats defined in `format-alist', | 193 FORMAT is a symbol naming one of the formats defined in `format-alist', |
194 it must be a single symbol, not a list like `buffer-file-format'. | 194 it must be a single symbol, not a list like `buffer-file-format'. |
195 FROM and TO delimit the region to be operated on in the current buffer. | 195 FROM and TO delimit the region to be operated on in the current buffer. |
196 ORIG-BUF is the original buffer that the data came from. | 196 ORIG-BUF is the original buffer that the data came from. |
197 This function works like a function on `write-region-annotate-functions': | 197 This function works like a function on `write-region-annotate-functions': |
198 it either returns a list of annotations, or returns with a different buffer | 198 it either returns a list of annotations, or returns with a different buffer |
199 current, which contains the modified text to write. | 199 current, which contains the modified text to write. |
200 | 200 |
201 For most purposes, consider using `format-encode-region' instead." | 201 For most purposes, consider using `format-encode-region' instead." |
202 ;; This function is called by write-region (actually build-annotations) | 202 ;; This function is called by write-region (actually build-annotations) |
203 ;; for each element of buffer-file-format. | 203 ;; for each element of buffer-file-format. |
204 (let* ((info (assq format format-alist)) | 204 (let* ((info (assq format format-alist)) |
205 (to-fn (nth 4 info)) | 205 (to-fn (nth 4 info)) |
206 (modify (nth 5 info))) | 206 (modify (nth 5 info))) |
207 (if to-fn | 207 (if to-fn |
216 ;; Otherwise just call function, it will return annotations. | 216 ;; Otherwise just call function, it will return annotations. |
217 (funcall to-fn from to orig-buf))))) | 217 (funcall to-fn from to orig-buf))))) |
218 | 218 |
219 (defun format-decode (format length &optional visit-flag) | 219 (defun format-decode (format length &optional visit-flag) |
220 "Decode text from any known FORMAT. | 220 "Decode text from any known FORMAT. |
221 FORMAT is a symbol appearing in `format-alist' or a list of such symbols, | 221 FORMAT is a symbol appearing in `format-alist' or a list of such symbols, |
222 or nil, in which case this function tries to guess the format of the data by | 222 or nil, in which case this function tries to guess the format of the data by |
223 matching against the regular expressions in `format-alist'. After a match is | 223 matching against the regular expressions in `format-alist'. After a match is |
224 found and the region decoded, the alist is searched again from the beginning | 224 found and the region decoded, the alist is searched again from the beginning |
225 for another match. | 225 for another match. |
226 | 226 |
281 ;;; | 281 ;;; |
282 | 282 |
283 (defun format-decode-buffer (&optional format) | 283 (defun format-decode-buffer (&optional format) |
284 "Translate the buffer from some FORMAT. | 284 "Translate the buffer from some FORMAT. |
285 If the format is not specified, this function attempts to guess. | 285 If the format is not specified, this function attempts to guess. |
286 `buffer-file-format' is set to the format used, and any mode-functions | 286 `buffer-file-format' is set to the format used, and any mode-functions |
287 for the format are called." | 287 for the format are called." |
288 (interactive | 288 (interactive |
289 (list (format-read "Translate buffer from format (default: guess): "))) | 289 (list (format-read "Translate buffer from format (default: guess): "))) |
290 (save-excursion | 290 (save-excursion |
291 (goto-char (point-min)) | 291 (goto-char (point-min)) |
294 (defun format-decode-region (from to &optional format) | 294 (defun format-decode-region (from to &optional format) |
295 "Decode the region from some format. | 295 "Decode the region from some format. |
296 Arg FORMAT is optional; if omitted the format will be determined by looking | 296 Arg FORMAT is optional; if omitted the format will be determined by looking |
297 for identifying regular expressions at the beginning of the region." | 297 for identifying regular expressions at the beginning of the region." |
298 (interactive | 298 (interactive |
299 (list (region-beginning) (region-end) | 299 (list (region-beginning) (region-end) |
300 (format-read "Translate region from format (default: guess): "))) | 300 (format-read "Translate region from format (default: guess): "))) |
301 (save-excursion | 301 (save-excursion |
302 (goto-char from) | 302 (goto-char from) |
303 (format-decode format (- to from) nil))) | 303 (format-decode format (- to from) nil))) |
304 | 304 |
323 (if (symbolp format) (setq format (list format))) | 323 (if (symbolp format) (setq format (list format))) |
324 (save-excursion | 324 (save-excursion |
325 (goto-char end) | 325 (goto-char end) |
326 (let ( ; (cur-buf (current-buffer)) | 326 (let ( ; (cur-buf (current-buffer)) |
327 (end (point-marker))) | 327 (end (point-marker))) |
328 (while format | 328 (while format |
329 (let* ((info (assq (car format) format-alist)) | 329 (let* ((info (assq (car format) format-alist)) |
330 (to-fn (nth 4 info)) | 330 (to-fn (nth 4 info)) |
331 (modify (nth 5 info)) | 331 (modify (nth 5 info)) |
332 ;; result | 332 ;; result |
333 ) | 333 ) |
351 nil nil nil nil) | 351 nil nil nil nil) |
352 (read-file-name "Write file: " | 352 (read-file-name "Write file: " |
353 (cdr (assq 'default-directory | 353 (cdr (assq 'default-directory |
354 (buffer-local-variables))) | 354 (buffer-local-variables))) |
355 nil nil (buffer-name)))) | 355 nil nil (buffer-name)))) |
356 (fmt (format-read (format "Write file `%s' in format: " | 356 (fmt (format-read (format "Write file `%s' in format: " |
357 (file-name-nondirectory file))))) | 357 (file-name-nondirectory file))))) |
358 (list file fmt))) | 358 (list file fmt))) |
359 (setq buffer-file-format format) | 359 (setq buffer-file-format format) |
360 (write-file filename)) | 360 (write-file filename)) |
361 | 361 |
363 "Find the file FILE using data format FORMAT. | 363 "Find the file FILE using data format FORMAT. |
364 If FORMAT is nil then do not do any format conversion." | 364 If FORMAT is nil then do not do any format conversion." |
365 (interactive | 365 (interactive |
366 ;; Same interactive spec as write-file, plus format question. | 366 ;; Same interactive spec as write-file, plus format question. |
367 (let* ((file (read-file-name "Find file: ")) | 367 (let* ((file (read-file-name "Find file: ")) |
368 (fmt (format-read (format "Read file `%s' in format: " | 368 (fmt (format-read (format "Read file `%s' in format: " |
369 (file-name-nondirectory file))))) | 369 (file-name-nondirectory file))))) |
370 (list file fmt))) | 370 (list file fmt))) |
371 (let ((format-alist nil)) | 371 (let ((format-alist nil)) |
372 (find-file filename)) | 372 (find-file filename)) |
373 (if format | 373 (if format |
382 The return value is like the value of `insert-file-contents': | 382 The return value is like the value of `insert-file-contents': |
383 a list (ABSOLUTE-FILE-NAME . SIZE)." | 383 a list (ABSOLUTE-FILE-NAME . SIZE)." |
384 (interactive | 384 (interactive |
385 ;; Same interactive spec as write-file, plus format question. | 385 ;; Same interactive spec as write-file, plus format question. |
386 (let* ((file (read-file-name "Find file: ")) | 386 (let* ((file (read-file-name "Find file: ")) |
387 (fmt (format-read (format "Read file `%s' in format: " | 387 (fmt (format-read (format "Read file `%s' in format: " |
388 (file-name-nondirectory file))))) | 388 (file-name-nondirectory file))))) |
389 (list file fmt))) | 389 (list file fmt))) |
390 (let (value size) | 390 (let (value size) |
391 (let ((format-alist nil)) | 391 (let ((format-alist nil)) |
392 (setq value (insert-file-contents filename nil beg end)) | 392 (setq value (insert-file-contents filename nil beg end)) |
415 "Do multiple replacements on the buffer. | 415 "Do multiple replacements on the buffer. |
416 ALIST is a list of (from . to) pairs, which should be proper arguments to | 416 ALIST is a list of (from . to) pairs, which should be proper arguments to |
417 `search-forward' and `replace-match' respectively. | 417 `search-forward' and `replace-match' respectively. |
418 Optional 2nd arg REVERSE, if non-nil, means the pairs are (to . from), so that | 418 Optional 2nd arg REVERSE, if non-nil, means the pairs are (to . from), so that |
419 you can use the same list in both directions if it contains only literal | 419 you can use the same list in both directions if it contains only literal |
420 strings. | 420 strings. |
421 Optional args BEGIN and END specify a region of the buffer to operate on." | 421 Optional args BEGIN and END specify a region of the buffer to operate on." |
422 (save-excursion | 422 (save-excursion |
423 (save-restriction | 423 (save-restriction |
424 (or beg (setq beg (point-min))) | 424 (or beg (setq beg (point-min))) |
425 (if end (narrow-to-region (point-min) end)) | 425 (if end (narrow-to-region (point-min) end)) |
438 | 438 |
439 ;;; Some list-manipulation functions that we need. | 439 ;;; Some list-manipulation functions that we need. |
440 | 440 |
441 (defun format-delq-cons (cons list) | 441 (defun format-delq-cons (cons list) |
442 "Remove the given CONS from LIST by side effect, | 442 "Remove the given CONS from LIST by side effect, |
443 and return the new LIST. Since CONS could be the first element | 443 and return the new LIST. Since CONS could be the first element |
444 of LIST, write `\(setq foo \(format-delq-cons element foo))' to be sure of | 444 of LIST, write `\(setq foo \(format-delq-cons element foo))' to be sure of |
445 changing the value of `foo'." | 445 changing the value of `foo'." |
446 (if (eq cons list) | 446 (if (eq cons list) |
447 (cdr list) | 447 (cdr list) |
448 (let ((p list)) | 448 (let ((p list)) |
449 (while (not (eq (cdr p) cons)) | 449 (while (not (eq (cdr p) cons)) |
450 (if (null p) (error "format-delq-cons: not an element.")) | 450 (if (null p) (error "format-delq-cons: not an element.")) |
451 (setq p (cdr p))) | 451 (setq p (cdr p))) |
452 ;; Now (cdr p) is the cons to delete | 452 ;; Now (cdr p) is the cons to delete |
453 (setcdr p (cdr cons)) | 453 (setcdr p (cdr cons)) |
454 list))) | 454 list))) |
455 | 455 |
456 (defun format-make-relatively-unique (a b) | 456 (defun format-make-relatively-unique (a b) |
457 "Delete common elements of lists A and B, return as pair. | 457 "Delete common elements of lists A and B, return as pair. |
458 Compares using `equal'." | 458 Compares using `equal'." |
459 (let* ((acopy (copy-sequence a)) | 459 (let* ((acopy (copy-sequence a)) |
460 (bcopy (copy-sequence b)) | 460 (bcopy (copy-sequence b)) |
473 equivalent part of B. If even the last items of the two are not equal, | 473 equivalent part of B. If even the last items of the two are not equal, |
474 returns nil." | 474 returns nil." |
475 (let ((la (length a)) | 475 (let ((la (length a)) |
476 (lb (length b))) | 476 (lb (length b))) |
477 ;; Make sure they are the same length | 477 ;; Make sure they are the same length |
478 (if (> la lb) | 478 (if (> la lb) |
479 (setq a (nthcdr (- la lb) a)) | 479 (setq a (nthcdr (- la lb) a)) |
480 (setq b (nthcdr (- lb la) b)))) | 480 (setq b (nthcdr (- lb la) b)))) |
481 (while (not (equal a b)) | 481 (while (not (equal a b)) |
482 (setq a (cdr a) | 482 (setq a (cdr a) |
483 b (cdr b))) | 483 b (cdr b))) |
488 Elements of ITEMS equal to elements of ORDER will be rearranged to follow the | 488 Elements of ITEMS equal to elements of ORDER will be rearranged to follow the |
489 ORDER. Unmatched items will go last." | 489 ORDER. Unmatched items will go last." |
490 (if order | 490 (if order |
491 (let ((item (member (car order) items))) | 491 (let ((item (member (car order) items))) |
492 (if item | 492 (if item |
493 (cons (car item) | 493 (cons (car item) |
494 (format-reorder (format-delq-cons item items) | 494 (format-reorder (format-delq-cons item items) |
495 (cdr order))) | 495 (cdr order))) |
496 (format-reorder items (cdr order)))) | 496 (format-reorder items (cdr order)))) |
497 items)) | 497 items)) |
498 | 498 |
506 ;;; Decoding | 506 ;;; Decoding |
507 ;;; | 507 ;;; |
508 | 508 |
509 (defun format-deannotate-region (from to translations next-fn) | 509 (defun format-deannotate-region (from to translations next-fn) |
510 "Translate annotations in the region into text properties. | 510 "Translate annotations in the region into text properties. |
511 This sets text properties between FROM to TO as directed by the | 511 This sets text properties between FROM to TO as directed by the |
512 TRANSLATIONS and NEXT-FN arguments. | 512 TRANSLATIONS and NEXT-FN arguments. |
513 | 513 |
514 NEXT-FN is a function that searches forward from point for an annotation. | 514 NEXT-FN is a function that searches forward from point for an annotation. |
515 It should return a list of 4 elements: \(BEGIN END NAME POSITIVE). BEGIN and | 515 It should return a list of 4 elements: \(BEGIN END NAME POSITIVE). BEGIN and |
516 END are buffer positions bounding the annotation, NAME is the name searched | 516 END are buffer positions bounding the annotation, NAME is the name searched |
708 (subtrahend (copy-alist subtra)) | 708 (subtrahend (copy-alist subtra)) |
709 (m (car minuend)) | 709 (m (car minuend)) |
710 (s (car subtrahend)) | 710 (s (car subtrahend)) |
711 results) | 711 results) |
712 (while (and minuend subtrahend) | 712 (while (and minuend subtrahend) |
713 (cond | 713 (cond |
714 ;; The minuend starts after the subtrahend ends; keep it. | 714 ;; The minuend starts after the subtrahend ends; keep it. |
715 ((> (car m) (cdr s)) | 715 ((> (car m) (cdr s)) |
716 (setq results (cons m results) | 716 (setq results (cons m results) |
717 minuend (cdr minuend) | 717 minuend (cdr minuend) |
718 m (car minuend))) | 718 m (car minuend))) |
756 Inserts each element of the given LIST of buffer annotations at its | 756 Inserts each element of the given LIST of buffer annotations at its |
757 appropriate place. Use second arg OFFSET if the annotations' locations are | 757 appropriate place. Use second arg OFFSET if the annotations' locations are |
758 not relative to the beginning of the buffer: annotations will be inserted | 758 not relative to the beginning of the buffer: annotations will be inserted |
759 at their location-OFFSET+1 \(ie, the offset is treated as the character number | 759 at their location-OFFSET+1 \(ie, the offset is treated as the character number |
760 of the first character in the buffer)." | 760 of the first character in the buffer)." |
761 (if (not offset) | 761 (if (not offset) |
762 (setq offset 0) | 762 (setq offset 0) |
763 (setq offset (1- offset))) | 763 (setq offset (1- offset))) |
764 (let ((l (reverse list))) | 764 (let ((l (reverse list))) |
765 (while l | 765 (while l |
766 (goto-char (- (car (car l)) offset)) | 766 (goto-char (- (car (car l)) offset)) |
790 elements are VALUES of that property followed by the names of zero or more | 790 elements are VALUES of that property followed by the names of zero or more |
791 ANNOTATIONS. Whenever the property takes on that value, the annotations | 791 ANNOTATIONS. Whenever the property takes on that value, the annotations |
792 \(as formatted by FORMAT-FN) are inserted into the file. | 792 \(as formatted by FORMAT-FN) are inserted into the file. |
793 When the property stops having that value, the matching negated annotation | 793 When the property stops having that value, the matching negated annotation |
794 will be inserted \(it may actually be closed earlier and reopened, if | 794 will be inserted \(it may actually be closed earlier and reopened, if |
795 necessary, to keep proper nesting). | 795 necessary, to keep proper nesting). |
796 | 796 |
797 If the property's value is a list, then each element of the list is dealt with | 797 If the property's value is a list, then each element of the list is dealt with |
798 separately. | 798 separately. |
799 | 799 |
800 If a VALUE is numeric, then it is assumed that there is a single annotation | 800 If a VALUE is numeric, then it is assumed that there is a single annotation |
832 (message "Can't close %s: not open." (car neg-ans)) | 832 (message "Can't close %s: not open." (car neg-ans)) |
833 (while (not (equal (car neg-ans) (car open-ans))) | 833 (while (not (equal (car neg-ans) (car open-ans))) |
834 ;; To close anno. N, need to first close ans 1 to N-1, | 834 ;; To close anno. N, need to first close ans 1 to N-1, |
835 ;; remembering to re-open them later. | 835 ;; remembering to re-open them later. |
836 (setq pos-ans (cons (car open-ans) pos-ans)) | 836 (setq pos-ans (cons (car open-ans) pos-ans)) |
837 (setq all-ans | 837 (setq all-ans |
838 (cons (cons loc (funcall format-fn (car open-ans) nil)) | 838 (cons (cons loc (funcall format-fn (car open-ans) nil)) |
839 all-ans)) | 839 all-ans)) |
840 (setq open-ans (cdr open-ans))) | 840 (setq open-ans (cdr open-ans))) |
841 ;; Now remove the one we're really interested in from open list. | 841 ;; Now remove the one we're really interested in from open list. |
842 (setq open-ans (cdr open-ans)) | 842 (setq open-ans (cdr open-ans)) |
843 ;; And put the closing annotation here. | 843 ;; And put the closing annotation here. |
844 (setq all-ans | 844 (setq all-ans |
845 (cons (cons loc (funcall format-fn (car neg-ans) nil)) | 845 (cons (cons loc (funcall format-fn (car neg-ans) nil)) |
846 all-ans))) | 846 all-ans))) |
847 (setq neg-ans (cdr neg-ans))) | 847 (setq neg-ans (cdr neg-ans))) |
848 ;; Now deal with positive (opening) annotations | 848 ;; Now deal with positive (opening) annotations |
849 (let ( ; (p pos-ans) | 849 (let ( ; (p pos-ans) |
850 ) | 850 ) |
851 (while pos-ans | 851 (while pos-ans |
852 (setq open-ans (cons (car pos-ans) open-ans)) | 852 (setq open-ans (cons (car pos-ans) open-ans)) |
853 (setq all-ans | 853 (setq all-ans |
854 (cons (cons loc (funcall format-fn (car pos-ans) t)) | 854 (cons (cons loc (funcall format-fn (car pos-ans) t)) |
855 all-ans)) | 855 all-ans)) |
856 (setq pos-ans (cdr pos-ans)))))) | 856 (setq pos-ans (cdr pos-ans)))))) |
857 | 857 |
858 ;; Close any annotations still open | 858 ;; Close any annotations still open |
859 (while open-ans | 859 (while open-ans |
860 (setq all-ans | 860 (setq all-ans |
861 (cons (cons to (funcall format-fn (car open-ans) nil)) | 861 (cons (cons to (funcall format-fn (car open-ans) nil)) |
862 all-ans)) | 862 all-ans)) |
863 (setq open-ans (cdr open-ans))) | 863 (setq open-ans (cdr open-ans))) |
864 (if not-found | 864 (if not-found |
865 (message "These text properties could not be saved:\n %s" | 865 (message "These text properties could not be saved:\n %s" |
928 (let* ((old (if (listp old) old (list old))) | 928 (let* ((old (if (listp old) old (list old))) |
929 (new (if (listp new) new (list new))) | 929 (new (if (listp new) new (list new))) |
930 ;; (tail (format-common-tail old new)) | 930 ;; (tail (format-common-tail old new)) |
931 close open) | 931 close open) |
932 (while old | 932 (while old |
933 (setq close | 933 (setq close |
934 (append (car (format-annotate-atomic-property-change | 934 (append (car (format-annotate-atomic-property-change |
935 prop-alist (car old) nil)) | 935 prop-alist (car old) nil)) |
936 close) | 936 close) |
937 old (cdr old))) | 937 old (cdr old))) |
938 (while new | 938 (while new |
939 (setq open | 939 (setq open |
940 (append (cdr (format-annotate-atomic-property-change | 940 (append (cdr (format-annotate-atomic-property-change |
941 prop-alist nil (car new))) | 941 prop-alist nil (car new))) |
942 open) | 942 open) |
943 new (cdr new))) | 943 new (cdr new))) |
944 (format-make-relatively-unique close open)) | 944 (format-make-relatively-unique close open)) |