annotate lisp/format.el @ 826:6728e641994e

[xemacs-hg @ 2002-05-05 11:30:15 by ben] syntax cache, 8-bit-format, lots of code cleanup README.packages: Update info about --package-path. i.c: Create an inheritable event and pass it on to XEmacs, so that ^C can be handled properly. Intercept ^C and signal the event. "Stop Build" in VC++ now works. bytecomp-runtime.el: Doc string changes. compat.el: Some attempts to redo this to make it truly useful and fix the "multiple versions interacting with each other" problem. Not yet done. Currently doesn't work. files.el: Use with-obsolete-variable to avoid warnings in new revert-buffer code. xemacs.mak: Split up CFLAGS into a version without flags specifying the C library. The problem seems to be that minitar depends on zlib, which depends specifically on libc.lib, not on any of the other C libraries. Unless you compile with libc.lib, you get errors -- specifically, no _errno in the other libraries, which must make it something other than an int. (#### But this doesn't seem to obtain in XEmacs, which also uses zlib, and can be linked with any of the C libraries. Maybe zlib is used differently and doesn't need errno, or maybe XEmacs provides an int errno; ... I don't understand. Makefile.in.in: Fix so that packages are around when testing. abbrev.c, alloc.c, buffer.c, buffer.h, bytecode.c, callint.c, casefiddle.c, casetab.c, casetab.h, charset.h, chartab.c, chartab.h, cmds.c, console-msw.h, console-stream.c, console-x.c, console.c, console.h, data.c, device-msw.c, device.c, device.h, dialog-msw.c, dialog-x.c, dired-msw.c, dired.c, doc.c, doprnt.c, dumper.c, editfns.c, elhash.c, emacs.c, eval.c, event-Xt.c, event-gtk.c, event-msw.c, event-stream.c, events.c, events.h, extents.c, extents.h, faces.c, file-coding.c, file-coding.h, fileio.c, fns.c, font-lock.c, frame-gtk.c, frame-msw.c, frame-x.c, frame.c, frame.h, glade.c, glyphs-gtk.c, glyphs-msw.c, glyphs-msw.h, glyphs-x.c, glyphs.c, glyphs.h, gui-msw.c, gui-x.c, gui.h, gutter.h, hash.h, indent.c, insdel.c, intl-win32.c, intl.c, keymap.c, lisp-disunion.h, lisp-union.h, lisp.h, lread.c, lrecord.h, lstream.c, lstream.h, marker.c, menubar-gtk.c, menubar-msw.c, menubar-x.c, menubar.c, minibuf.c, mule-ccl.c, mule-charset.c, mule-coding.c, mule-wnnfns.c, nas.c, objects-msw.c, objects-x.c, opaque.c, postgresql.c, print.c, process-nt.c, process-unix.c, process.c, process.h, profile.c, rangetab.c, redisplay-gtk.c, redisplay-msw.c, redisplay-output.c, redisplay-x.c, redisplay.c, redisplay.h, regex.c, regex.h, scrollbar-msw.c, search.c, select-x.c, specifier.c, specifier.h, symbols.c, symsinit.h, syntax.c, syntax.h, syswindows.h, tests.c, text.c, text.h, tooltalk.c, ui-byhand.c, ui-gtk.c, unicode.c, win32.c, window.c: Another big Ben patch. -- FUNCTIONALITY CHANGES: add partial support for 8-bit-fixed, 16-bit-fixed, and 32-bit-fixed formats. not quite done yet. (in particular, needs functions to actually convert the buffer.) NOTE: lots of changes to regex.c here. also, many new *_fmt() inline funs that take an Internal_Format argument. redo syntax cache code. make the cache per-buffer; keep the cache valid across calls to functions that use it. also keep it valid across insertions/deletions and extent changes, as much as is possible. eliminate the junky regex-reentrancy code by passing in the relevant lisp info to the regex routines as local vars. add general mechanism in extents code for signalling extent changes. fix numerous problems with the case-table implementation; yoshiki never properly transferred many algorithms from old-style to new-style case tables. redo char tables to support a default argument, so that mapping only occurs over changed args. change many chartab functions to accept Lisp_Object instead of Lisp_Char_Table *. comment out the code in font-lock.c by default, because font-lock.el no longer uses it. we should consider eliminating it entirely. Don't output bell as ^G in console-stream when not a TTY. add -mswindows-termination-handle to interface with i.c, so we can properly kill a build. add more error-checking to buffer/string macros. add some additional buffer_or_string_() funs. -- INTERFACE CHANGES AFFECTING MORE CODE: switch the arguments of write_c_string and friends to be consistent with write_fmt_string, which must have printcharfun first. change BI_* macros to BYTE_* for increased clarity; similarly for bi_* local vars. change VOID_TO_LISP to be a one-argument function. eliminate no-longer-needed CVOID_TO_LISP. -- char/string macro changes: rename MAKE_CHAR() to make_emchar() for slightly less confusion with make_char(). (The former generates an Emchar, the latter a Lisp object. Conceivably we should rename make_char() -> wrap_char() and similarly for make_int(), make_float().) Similar changes for other *CHAR* macros -- we now consistently use names with `emchar' whenever we are working with Emchars. Any remaining name with just `char' always refers to a Lisp object. rename macros with XSTRING_* to string_* except for those that reference actual fields in the Lisp_String object, following conventions used elsewhere. rename set_string_{data,length} macros (the only ones to work with a Lisp_String_* instead of a Lisp_Object) to set_lispstringp_* to make the difference clear. try to be consistent about caps vs. lowercase in macro/inline-fun names for chars and such, which wasn't the case before. we now reserve caps either for XFOO_ macros that reference object fields (e.g. XSTRING_DATA) or for things that have non-function semantics, e.g. directly modifying an arg (BREAKUP_EMCHAR) or evaluating an arg (any arg) more than once. otherwise, use lowercase. here is a summary of most of the macros/inline funs changed by all of the above changes: BYTE_*_P -> byte_*_p XSTRING_BYTE -> string_byte set_string_data/length -> set_lispstringp_data/length XSTRING_CHAR_LENGTH -> string_char_length XSTRING_CHAR -> string_emchar INTBYTE_FIRST_BYTE_P -> intbyte_first_byte_p INTBYTE_LEADING_BYTE_P -> intbyte_leading_byte_p charptr_copy_char -> charptr_copy_emchar LEADING_BYTE_* -> leading_byte_* CHAR_* -> EMCHAR_* *_CHAR_* -> *_EMCHAR_* *_CHAR -> *_EMCHAR CHARSET_BY_ -> charset_by_* BYTE_SHIFT_JIS* -> byte_shift_jis* BYTE_BIG5* -> byte_big5* REP_BYTES_BY_FIRST_BYTE -> rep_bytes_by_first_byte char_to_unicode -> emchar_to_unicode valid_char_p -> valid_emchar_p Change intbyte_strcmp -> qxestrcmp_c (duplicated functionality). -- INTERFACE CHANGES AFFECTING LESS CODE: use DECLARE_INLINE_HEADER in various places. remove '#ifdef emacs' from XEmacs-only files. eliminate CHAR_TABLE_VALUE(), which duplicated the functionality of get_char_table(). add BUFFER_TEXT_LOOP to simplify iterations over buffer text. define typedefs for signed and unsigned types of fixed sizes (INT_32_BIT, UINT_32_BIT, etc.). create ALIGN_FOR_TYPE as a higher-level interface onto ALIGN_SIZE; fix code to use it. add charptr_emchar_len to return the text length of the character pointed to by a ptr; use it in place of charcount_to_bytecount(..., 1). add emchar_len to return the text length of a given character. add types Bytexpos and Charxpos to generalize Bytebpos/Bytecount and Charbpos/Charcount, in code (particularly, the extents code and redisplay code) that works with either kind of index. rename redisplay struct params with names such as `charbpos' to e.g. `charpos' when they are e.g. a Charxpos, not a Charbpos. eliminate xxDEFUN in place of DEFUN; no longer necessary with changes awhile back to doc.c. split up big ugly combined list of EXFUNs in lisp.h on a file-by-file basis, since other prototypes are similarly split. rewrite some "*_UNSAFE" macros as inline funs and eliminate the _UNSAFE suffix. move most string code from lisp.h to text.h; the string code and text.h code is now intertwined in such a fashion that they need to be in the same place and partially interleaved. (you can't create forward references for inline funs) automated/lisp-tests.el, automated/symbol-tests.el, automated/test-harness.el: Fix test harness to output FAIL messages to stderr when in batch mode. Fix up some problems in lisp-tests/symbol-tests that were causing spurious failures.
author ben
date Sun, 05 May 2002 11:33:57 +0000
parents 576fb035e263
children 517f6887fbc0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1 ;;; format.el --- read and save files in multiple formats
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
2
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
3 ;; Copyright (c) 1994, 1995, 1997 Free Software Foundation
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
4
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
5 ;; Author: Boris Goldowsky <boris@gnu.ai.mit.edu>
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
6 ;; Keywords: extensions, dumped
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
7
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
8 ;; This file is part of XEmacs.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
9
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
10 ;; XEmacs is free software; you can redistribute it and/or modify it
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
11 ;; under the terms of the GNU General Public License as published by
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
12 ;; the Free Software Foundation; either version 2, or (at your option)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
13 ;; any later version.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
14
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
15 ;; XEmacs is distributed in the hope that it will be useful, but
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
18 ;; General Public License for more details.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
19
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
20 ;; You should have received a copy of the GNU General Public License
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
21 ;; along with XEmacs; see the file COPYING. If not, write to the Free
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
22 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
23 ;; 02111-1307, USA.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
24
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
25 ;;; Synched up with: Emacs 20.2.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
26
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
27 ;;; Commentary:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
28
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
29 ;; This file is dumped with XEmacs.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
30
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
31 ;; This file defines a unified mechanism for saving & loading files stored
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
32 ;; in different formats. `format-alist' contains information that directs
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
33 ;; Emacs to call an encoding or decoding function when reading or writing
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
34 ;; files that match certain conditions.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
35 ;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
36 ;; When a file is visited, its format is determined by matching the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
37 ;; beginning of the file against regular expressions stored in
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
38 ;; `format-alist'. If this fails, you can manually translate the buffer
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
39 ;; using `format-decode-buffer'. In either case, the formats used are
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
40 ;; listed in the variable `buffer-file-format', and become the default
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
41 ;; format for saving the buffer. To save a buffer in a different format,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
42 ;; change this variable, or use `format-write-file'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
43 ;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
44 ;; Auto-save files are normally created in the same format as the visited
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
45 ;; file, but the variable `auto-save-file-format' can be set to a
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
46 ;; particularly fast or otherwise preferred format to be used for
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
47 ;; auto-saving (or nil to do no encoding on auto-save files, but then you
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
48 ;; risk losing any text-properties in the buffer).
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
49 ;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
50 ;; You can manually translate a buffer into or out of a particular format
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
51 ;; with the functions `format-encode-buffer' and `format-decode-buffer'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
52 ;; To translate just the region use the functions `format-encode-region'
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
53 ;; and `format-decode-region'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
54 ;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
55 ;; You can define a new format by writing the encoding and decoding
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
56 ;; functions, and adding an entry to `format-alist'. See enriched.el for
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
57 ;; an example of how to implement a file format. There are various
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
58 ;; functions defined in this file that may be useful for writing the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
59 ;; encoding and decoding functions:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
60 ;; * `format-annotate-region' and `format-deannotate-region' allow a
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
61 ;; single alist of information to be used for encoding and decoding.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
62 ;; The alist defines a correspondence between strings in the file
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
63 ;; ("annotations") and text-properties in the buffer.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
64 ;; * `format-replace-strings' is similarly useful for doing simple
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
65 ;; string->string translations in a reversible manner.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
66
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
67 ;;; Code:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
68
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
69 (put 'buffer-file-format 'permanent-local t)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
70
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
71 (defvar format-alist
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
72 '(
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
73 ; (image/jpeg "JPEG image" "\377\330\377\340\000\020JFIF"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
74 ; image-decode-jpeg nil t image-mode)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
75 ; (image/gif "GIF image" "GIF8[79]"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
76 ; image-decode-gif nil t image-mode)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
77 ; (image/png "Portable Network Graphics" "\211PNG"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
78 ; image-decode-png nil t image-mode)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
79 ; (image/x-xpm "XPM image" "/\\* XPM \\*/"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
80 ; image-decode-xpm nil t image-mode)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
81
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
82 ; ;; TIFF files have lousy magic
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
83 ; (image/tiff "TIFF image" "II\\*\000"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
84 ; image-decode-tiff nil t image-mode) ;; TIFF 6.0 big-endian
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
85 ; (image/tiff "TIFF image" "MM\000\\*"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
86 ; image-decode-tiff nil t image-mode) ;; TIFF 6.0 little-endian
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
87
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
88 (text/enriched "Extended MIME text/enriched format."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
89 "Content-[Tt]ype:[ \t]*text/enriched"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
90 enriched-decode enriched-encode t enriched-mode)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
91 (text/richtext "Extended MIME obsolete text/richtext format."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
92 "Content-[Tt]ype:[ \t]*text/richtext"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
93 richtext-decode richtext-encode t enriched-mode)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
94 (plain "ISO 8859-1 standard format, no text properties."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
95 ;; Plain only exists so that there is an obvious neutral choice in
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
96 ;; the completion list.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
97 nil nil nil nil nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
98 ;; (ibm "IBM Code Page 850 (DOS)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
99 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
100 ;; "recode ibm-pc:latin1" "recode latin1:ibm-pc" t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
101 ;; (mac "Apple Macintosh"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
102 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
103 ;; "recode mac:latin1" "recode latin1:mac" t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
104 ;; (hp "HP Roman8"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
105 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
106 ;; "recode roman8:latin1" "recode latin1:roman8" t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
107 ;; (TeX "TeX (encoding)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
108 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
109 ;; iso-tex2iso iso-iso2tex t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
110 ;; (gtex "German TeX (encoding)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
111 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
112 ;; iso-gtex2iso iso-iso2gtex t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
113 ;; (html "HTML (encoding)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
114 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
115 ;; "recode html:latin1" "recode latin1:html" t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
116 ;; (rot13 "rot13"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
117 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
118 ;; "tr a-mn-z n-za-m" "tr a-mn-z n-za-m" t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
119 ;; (duden "Duden Ersatzdarstellung"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
120 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
121 ;; "diac" iso-iso2duden t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
122 ;; (de646 "German ASCII (ISO 646)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
123 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
124 ;; "recode iso646-ge:latin1" "recode latin1:iso646-ge" t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
125 ;; (denet "net German"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
126 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
127 ;; iso-german iso-cvt-read-only t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
128 ;; (esnet "net Spanish"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
129 ;; "1\\(^\\)"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
130 ;; iso-spanish iso-cvt-read-only t nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
131 )
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
132 "List of information about understood file formats.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
133 Elements are of the form \(NAME DOC-STR REGEXP FROM-FN TO-FN MODIFY MODE-FN).
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
134
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
135 NAME is a symbol, which is stored in `buffer-file-format'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
136
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
137 DOC-STR should be a single line providing more information about the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
138 format. It is currently unused, but in the future will be shown to
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
139 the user if they ask for more information.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
140
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
141 REGEXP is a regular expression to match against the beginning of the file;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
142 it should match only files in that format.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
143
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
144 FROM-FN is called to decode files in that format; it gets two args, BEGIN
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
145 and END, and can make any modifications it likes, returning the new
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
146 end. It must make sure that the beginning of the file no longer
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
147 matches REGEXP, or else it will get called again.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
148 Alternatively, FROM-FN can be a string, which specifies a shell command
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
149 (including options) to be used as a filter to perform the conversion.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
150
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
151 TO-FN is called to encode a region into that format; it is passed three
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
152 arguments: BEGIN, END, and BUFFER. BUFFER is the original buffer that
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
153 the data being written came from, which the function could use, for
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
154 example, to find the values of local variables. TO-FN should either
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
155 return a list of annotations like `write-region-annotate-functions',
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
156 or modify the region and return the new end.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
157 Alternatively, TO-FN can be a string, which specifies a shell command
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
158 (including options) to be used as a filter to perform the conversion.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
159
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
160 MODIFY, if non-nil, means the TO-FN wants to modify the region. If nil,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
161 TO-FN will not make any changes but will instead return a list of
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
162 annotations.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
163
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
164 MODE-FN, if specified, is called when visiting a file with that format.")
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
165
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
166 ;;; Basic Functions (called from Lisp)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
167
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
168 (defun format-encode-run-method (method from to &optional buffer)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
169 "Translate using function or shell script METHOD the text from FROM to TO.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
170 If METHOD is a string, it is a shell command;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
171 otherwise, it should be a Lisp function.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
172 BUFFER should be the buffer that the output originally came from."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
173 (if (stringp method)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
174 (save-current-buffer
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
175 (set-buffer buffer)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
176 (with-output-to-temp-buffer "*Format Errors*"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
177 (shell-command-on-region from to method t nil))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
178 (point))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
179 (funcall method from to buffer)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
180
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
181 (defun format-decode-run-method (method from to &optional buffer)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
182 "Decode using function or shell script METHOD the text from FROM to TO.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
183 If METHOD is a string, it is a shell command;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
184 otherwise, it should be a Lisp function."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
185 (if (stringp method)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
186 (progn
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
187 (with-output-to-temp-buffer "*Format Errors*"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
188 (shell-command-on-region from to method t nil))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
189 (point))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
190 (funcall method from to)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
191
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
192 (defun format-annotate-function (format from to orig-buf)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
193 "Return annotations for writing region as FORMAT.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
194 FORMAT is a symbol naming one of the formats defined in `format-alist',
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
195 it must be a single symbol, not a list like `buffer-file-format'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
196 FROM and TO delimit the region to be operated on in the current buffer.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
197 ORIG-BUF is the original buffer that the data came from.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
198 This function works like a function on `write-region-annotate-functions':
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
199 it either returns a list of annotations, or returns with a different buffer
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
200 current, which contains the modified text to write.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
201
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
202 For most purposes, consider using `format-encode-region' instead."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
203 ;; This function is called by write-region (actually build-annotations)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
204 ;; for each element of buffer-file-format.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
205 (let* ((info (assq format format-alist))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
206 (to-fn (nth 4 info))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
207 (modify (nth 5 info)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
208 (if to-fn
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
209 (if modify
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
210 ;; To-function wants to modify region. Copy to safe place.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
211 (let ((copy-buf (get-buffer-create " *Format Temp*")))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
212 (copy-to-buffer copy-buf from to)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
213 (set-buffer copy-buf)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
214 (format-insert-annotations write-region-annotations-so-far from)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
215 (format-encode-run-method to-fn (point-min) (point-max) orig-buf)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
216 nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
217 ;; Otherwise just call function, it will return annotations.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
218 (funcall to-fn from to orig-buf)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
219
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
220 (defun format-decode (format length &optional visit-flag)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
221 "Decode text from any known FORMAT.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
222 FORMAT is a symbol appearing in `format-alist' or a list of such symbols,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
223 or nil, in which case this function tries to guess the format of the data by
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
224 matching against the regular expressions in `format-alist'. After a match is
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
225 found and the region decoded, the alist is searched again from the beginning
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
226 for another match.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
227
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
228 Second arg LENGTH is the number of characters following point to operate on.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
229 If optional third arg VISIT-FLAG is true, set `buffer-file-format'
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
230 to the list of formats used, and call any mode functions defined for those
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
231 formats.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
232
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
233 Returns the new length of the decoded region.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
234
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
235 For most purposes, consider using `format-decode-region' instead.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
236
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
237 This function is called by insert-file-contents whenever a file is read."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
238 (let ((mod (buffer-modified-p))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
239 (begin (point))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
240 (end (+ (point) length)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
241 (if (null format)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
242 ;; Figure out which format it is in, remember list in `format'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
243 (let ((try format-alist))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
244 (while try
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
245 (let* ((f (car try))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
246 (regexp (nth 2 f))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
247 (p (point)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
248 (if (and regexp (looking-at regexp)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
249 (< (match-end 0) (+ begin length)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
250 (progn
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
251 (setq format (cons (car f) format))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
252 ;; Decode it
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
253 (if (nth 3 f)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
254 (setq end (format-decode-run-method (nth 3 f) begin end)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
255 ;; Call visit function if required
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
256 (if (and visit-flag (nth 6 f)) (funcall (nth 6 f) 1))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
257 ;; Safeguard against either of the functions changing pt.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
258 (goto-char p)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
259 ;; Rewind list to look for another format
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
260 (setq try format-alist))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
261 (setq try (cdr try))))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
262 ;; Deal with given format(s)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
263 (or (listp format) (setq format (list format)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
264 (let ((do format) f)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
265 (while do
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
266 (or (setq f (assq (car do) format-alist))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
267 (error "Unknown format" (car do)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
268 ;; Decode:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
269 (if (nth 3 f)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
270 (setq end (format-decode-run-method (nth 3 f) begin end)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
271 ;; Call visit function if required
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
272 (if (and visit-flag (nth 6 f)) (funcall (nth 6 f) 1))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
273 (setq do (cdr do)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
274 (if visit-flag
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
275 (setq buffer-file-format format))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
276 (set-buffer-modified-p mod)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
277 ;; Return new length of region
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
278 (- end begin)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
279
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
280 ;;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
281 ;;; Interactive functions & entry points
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
282 ;;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
283
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
284 (defun format-decode-buffer (&optional format)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
285 "Translate the buffer from some FORMAT.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
286 If the format is not specified, this function attempts to guess.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
287 `buffer-file-format' is set to the format used, and any mode-functions
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
288 for the format are called."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
289 (interactive
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
290 (list (format-read "Translate buffer from format (default: guess): ")))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
291 (save-excursion
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
292 (goto-char (point-min))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
293 (format-decode format (buffer-size) t)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
294
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
295 (defun format-decode-region (from to &optional format)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
296 "Decode the region from some format.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
297 Arg FORMAT is optional; if omitted the format will be determined by looking
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
298 for identifying regular expressions at the beginning of the region."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
299 (interactive
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
300 (list (region-beginning) (region-end)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
301 (format-read "Translate region from format (default: guess): ")))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
302 (save-excursion
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
303 (goto-char from)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
304 (format-decode format (- to from) nil)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
305
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
306 (defun format-encode-buffer (&optional format)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
307 "Translate the buffer into FORMAT.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
308 FORMAT defaults to `buffer-file-format'. It is a symbol naming one of the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
309 formats defined in `format-alist', or a list of such symbols."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
310 (interactive
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
311 (list (format-read (format "Translate buffer to format (default %s): "
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
312 buffer-file-format))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
313 (format-encode-region (point-min) (point-max) format))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
314
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 428
diff changeset
315 (defun format-encode-region (start end &optional format)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
316 "Translate the region into some FORMAT.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
317 FORMAT defaults to `buffer-file-format', it is a symbol naming
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
318 one of the formats defined in `format-alist', or a list of such symbols."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
319 (interactive
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
320 (list (region-beginning) (region-end)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
321 (format-read (format "Translate region to format (default %s): "
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
322 buffer-file-format))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
323 (if (null format) (setq format buffer-file-format))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
324 (if (symbolp format) (setq format (list format)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
325 (save-excursion
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
326 (goto-char end)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
327 (let ( ; (cur-buf (current-buffer))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
328 (end (point-marker)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
329 (while format
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
330 (let* ((info (assq (car format) format-alist))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
331 (to-fn (nth 4 info))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
332 (modify (nth 5 info))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
333 ;; result
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
334 )
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
335 (if to-fn
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
336 (if modify
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 428
diff changeset
337 (setq end (format-encode-run-method to-fn start end
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
338 (current-buffer)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
339 (format-insert-annotations
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 428
diff changeset
340 (funcall to-fn start end (current-buffer)))))
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
341 (setq format (cdr format)))))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
342
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
343 (defun format-write-file (filename format)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
344 "Write current buffer into a FILE using some FORMAT.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
345 Makes buffer visit that file and sets the format as the default for future
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
346 saves. If the buffer is already visiting a file, you can specify a directory
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
347 name as FILE, to write a file of the same old name in that directory."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
348 (interactive
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
349 ;; Same interactive spec as write-file, plus format question.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
350 (let* ((file (if buffer-file-name
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
351 (read-file-name "Write file: "
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
352 nil nil nil nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
353 (read-file-name "Write file: "
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
354 (cdr (assq 'default-directory
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
355 (buffer-local-variables)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
356 nil nil (buffer-name))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
357 (fmt (format-read (format "Write file `%s' in format: "
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
358 (file-name-nondirectory file)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
359 (list file fmt)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
360 (setq buffer-file-format format)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
361 (write-file filename))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
362
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
363 (defun format-find-file (filename format)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
364 "Find the file FILE using data format FORMAT.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
365 If FORMAT is nil then do not do any format conversion."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
366 (interactive
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
367 ;; Same interactive spec as write-file, plus format question.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
368 (let* ((file (read-file-name "Find file: "))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
369 (fmt (format-read (format "Read file `%s' in format: "
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
370 (file-name-nondirectory file)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
371 (list file fmt)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
372 (let ((format-alist nil))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
373 (find-file filename))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
374 (if format
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
375 (format-decode-buffer format)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
376
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 428
diff changeset
377 (defun format-insert-file (filename format &optional start end)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
378 "Insert the contents of file FILE using data format FORMAT.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
379 If FORMAT is nil then do not do any format conversion.
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 428
diff changeset
380 The optional third and fourth arguments START and END specify
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
381 the part of the file to read.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
382
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
383 The return value is like the value of `insert-file-contents':
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
384 a list (ABSOLUTE-FILE-NAME . SIZE)."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
385 (interactive
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
386 ;; Same interactive spec as write-file, plus format question.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
387 (let* ((file (read-file-name "Find file: "))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
388 (fmt (format-read (format "Read file `%s' in format: "
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
389 (file-name-nondirectory file)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
390 (list file fmt)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
391 (let (value size)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
392 (let ((format-alist nil))
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 428
diff changeset
393 (setq value (insert-file-contents filename nil start end))
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
394 (setq size (nth 1 value)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
395 (if format
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
396 (setq size (format-decode format size)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
397 value (cons (car value) size)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
398 value))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
399
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
400 (defun format-read (&optional prompt)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
401 "Read and return the name of a format.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
402 Return value is a list, like `buffer-file-format'; it may be nil.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
403 Formats are defined in `format-alist'. Optional arg is the PROMPT to use."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
404 (let* ((table (mapcar (lambda (x) (list (symbol-name (car x))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
405 format-alist))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
406 (ans (completing-read (or prompt "Format: ") table nil t)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
407 (if (not (equal "" ans)) (list (intern ans)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
408
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
409
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
410 ;;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
411 ;;; Below are some functions that may be useful in writing encoding and
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
412 ;;; decoding functions for use in format-alist.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
413 ;;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
414
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 428
diff changeset
415 (defun format-replace-strings (alist &optional reverse start end)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
416 "Do multiple replacements on the buffer.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
417 ALIST is a list of (from . to) pairs, which should be proper arguments to
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
418 `search-forward' and `replace-match' respectively.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
419 Optional 2nd arg REVERSE, if non-nil, means the pairs are (to . from), so that
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
420 you can use the same list in both directions if it contains only literal
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
421 strings.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
422 Optional args BEGIN and END specify a region of the buffer to operate on."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
423 (save-excursion
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
424 (save-restriction
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 428
diff changeset
425 (or start (setq start (point-min)))
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
426 (if end (narrow-to-region (point-min) end))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
427 (while alist
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
428 (let ((from (if reverse (cdr (car alist)) (car (car alist))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
429 (to (if reverse (car (cdr alist)) (cdr (car alist)))))
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 428
diff changeset
430 (goto-char start)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
431 (while (search-forward from nil t)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
432 (goto-char (match-beginning 0))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
433 (insert to)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
434 (set-text-properties (- (point) (length to)) (point)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
435 (text-properties-at (point)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
436 (delete-region (point) (+ (point) (- (match-end 0)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
437 (match-beginning 0)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
438 (setq alist (cdr alist)))))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
439
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
440 ;;; Some list-manipulation functions that we need.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
441
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
442 (defun format-delq-cons (cons list)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
443 "Remove the given CONS from LIST by side effect,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
444 and return the new LIST. Since CONS could be the first element
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
445 of LIST, write `\(setq foo \(format-delq-cons element foo))' to be sure of
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
446 changing the value of `foo'."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
447 (if (eq cons list)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
448 (cdr list)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
449 (let ((p list))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
450 (while (not (eq (cdr p) cons))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
451 (if (null p) (error "format-delq-cons: not an element."))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
452 (setq p (cdr p)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
453 ;; Now (cdr p) is the cons to delete
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
454 (setcdr p (cdr cons))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
455 list)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
456
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
457 (defun format-make-relatively-unique (a b)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
458 "Delete common elements of lists A and B, return as pair.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
459 Compares using `equal'."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
460 (let* ((acopy (copy-sequence a))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
461 (bcopy (copy-sequence b))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
462 (tail acopy))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
463 (while tail
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
464 (let ((dup (member (car tail) bcopy))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
465 (next (cdr tail)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
466 (if dup (setq acopy (format-delq-cons tail acopy)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
467 bcopy (format-delq-cons dup bcopy)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
468 (setq tail next)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
469 (cons acopy bcopy)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
470
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
471 (defun format-common-tail (a b)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
472 "Given two lists that have a common tail, return it.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
473 Compares with `equal', and returns the part of A that is equal to the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
474 equivalent part of B. If even the last items of the two are not equal,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
475 returns nil."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
476 (let ((la (length a))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
477 (lb (length b)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
478 ;; Make sure they are the same length
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
479 (if (> la lb)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
480 (setq a (nthcdr (- la lb) a))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
481 (setq b (nthcdr (- lb la) b))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
482 (while (not (equal a b))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
483 (setq a (cdr a)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
484 b (cdr b)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
485 a)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
486
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
487 (defun format-reorder (items order)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
488 "Arrange ITEMS to following partial ORDER.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
489 Elements of ITEMS equal to elements of ORDER will be rearranged to follow the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
490 ORDER. Unmatched items will go last."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
491 (if order
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
492 (let ((item (member (car order) items)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
493 (if item
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
494 (cons (car item)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
495 (format-reorder (format-delq-cons item items)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
496 (cdr order)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
497 (format-reorder items (cdr order))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
498 items))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
499
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
500 (put 'face 'format-list-valued t) ; These text-properties take values
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
501 (put 'unknown 'format-list-valued t) ; that are lists, the elements of which
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
502 ; should be considered separately.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
503 ; See format-deannotate-region and
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
504 ; format-annotate-region.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
505
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
506 ;;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
507 ;;; Decoding
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
508 ;;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
509
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
510 (defun format-deannotate-region (from to translations next-fn)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
511 "Translate annotations in the region into text properties.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
512 This sets text properties between FROM to TO as directed by the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
513 TRANSLATIONS and NEXT-FN arguments.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
514
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
515 NEXT-FN is a function that searches forward from point for an annotation.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
516 It should return a list of 4 elements: \(BEGIN END NAME POSITIVE). BEGIN and
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
517 END are buffer positions bounding the annotation, NAME is the name searched
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
518 for in TRANSLATIONS, and POSITIVE should be non-nil if this annotation marks
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
519 the beginning of a region with some property, or nil if it ends the region.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
520 NEXT-FN should return nil if there are no annotations after point.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
521
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
522 The basic format of the TRANSLATIONS argument is described in the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
523 documentation for the `format-annotate-region' function. There are some
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
524 additional things to keep in mind for decoding, though:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
525
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
526 When an annotation is found, the TRANSLATIONS list is searched for a
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
527 text-property name and value that corresponds to that annotation. If the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
528 text-property has several annotations associated with it, it will be used only
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
529 if the other annotations are also in effect at that point. The first match
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
530 found whose annotations are all present is used.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
531
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
532 The text property thus determined is set to the value over the region between
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
533 the opening and closing annotations. However, if the text-property name has a
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
534 non-nil `format-list-valued' property, then the value will be consed onto the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
535 surrounding value of the property, rather than replacing that value.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
536
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
537 There are some special symbols that can be used in the \"property\" slot of
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
538 the TRANSLATIONS list: PARAMETER and FUNCTION \(spelled in uppercase).
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
539 Annotations listed under the pseudo-property PARAMETER are considered to be
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
540 arguments of the immediately surrounding annotation; the text between the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
541 opening and closing parameter annotations is deleted from the buffer but saved
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
542 as a string. The surrounding annotation should be listed under the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
543 pseudo-property FUNCTION. Instead of inserting a text-property for this
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
544 annotation, the function listed in the VALUE slot is called to make whatever
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
545 changes are appropriate. The function's first two arguments are the START and
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
546 END locations, and the rest of the arguments are any PARAMETERs found in that
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
547 region.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
548
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
549 Any annotations that are found by NEXT-FN but not defined by TRANSLATIONS
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
550 are saved as values of the `unknown' text-property \(which is list-valued).
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
551 The TRANSLATIONS list should usually contain an entry of the form
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
552 \(unknown \(nil format-annotate-value))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
553 to write these unknown annotations back into the file."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
554 (save-excursion
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
555 (save-restriction
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
556 (narrow-to-region (point-min) to)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
557 (goto-char from)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
558 (let (next open-ans todo
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
559 ;; loc
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
560 unknown-ans)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
561 (while (setq next (funcall next-fn))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
562 (let* ((loc (nth 0 next))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
563 (end (nth 1 next))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
564 (name (nth 2 next))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
565 (positive (nth 3 next))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
566 (found nil))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
567
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
568 ;; Delete the annotation
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
569 (delete-region loc end)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
570 (cond
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
571 ;; Positive annotations are stacked, remembering location
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
572 (positive (setq open-ans (cons `(,name ((,loc . nil))) open-ans)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
573 ;; It is a negative annotation:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
574 ;; Close the top annotation & add its text property.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
575 ;; If the file's nesting is messed up, the close might not match
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
576 ;; the top thing on the open-annotations stack.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
577 ;; If no matching annotation is open, just ignore the close.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
578 ((not (assoc name open-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
579 (message "Extra closing annotation (%s) in file" name))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
580 ;; If one is open, but not on the top of the stack, close
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
581 ;; the things in between as well. Set `found' when the real
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
582 ;; one is closed.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
583 (t
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
584 (while (not found)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
585 (let* ((top (car open-ans)) ; first on stack: should match.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
586 (top-name (car top)) ; text property name
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
587 (top-extents (nth 1 top)) ; property regions
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
588 (params (cdr (cdr top))) ; parameters
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
589 (aalist translations)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
590 (matched nil))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
591 (if (equal name top-name)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
592 (setq found t)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
593 (message "Improper nesting in file."))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
594 ;; Look through property names in TRANSLATIONS
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
595 (while aalist
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
596 (let ((prop (car (car aalist)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
597 (alist (cdr (car aalist))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
598 ;; And look through values for each property
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
599 (while alist
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
600 (let ((value (car (car alist)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
601 (ans (cdr (car alist))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
602 (if (member top-name ans)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
603 ;; This annotation is listed, but still have to
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
604 ;; check if multiple annotations are satisfied
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
605 (if (member nil (mapcar (lambda (r)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
606 (assoc r open-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
607 ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
608 nil ; multiple ans not satisfied
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
609 ;; If there are multiple annotations going
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
610 ;; into one text property, split up the other
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
611 ;; annotations so they apply individually to
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
612 ;; the other regions.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
613 (setcdr (car top-extents) loc)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
614 (let ((to-split ans) this-one extents)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
615 (while to-split
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
616 (setq this-one
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
617 (assoc (car to-split) open-ans)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
618 extents (nth 1 this-one))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
619 (if (not (eq this-one top))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
620 (setcar (cdr this-one)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
621 (format-subtract-regions
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
622 extents top-extents)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
623 (setq to-split (cdr to-split))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
624 ;; Set loop variables to nil so loop
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
625 ;; will exit.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
626 (setq alist nil aalist nil matched t
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
627 ;; pop annotation off stack.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
628 open-ans (cdr open-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
629 (let ((extents top-extents)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
630 (start (car (car top-extents)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
631 (loc (cdr (car top-extents))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
632 (while extents
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
633 (cond
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
634 ;; Check for pseudo-properties
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
635 ((eq prop 'PARAMETER)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
636 ;; A parameter of the top open ann:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
637 ;; delete text and use as arg.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
638 (if open-ans
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
639 ;; (If nothing open, discard).
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
640 (setq open-ans
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
641 (cons
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
642 (append (car open-ans)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
643 (list
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
644 (buffer-substring
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
645 start loc)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
646 (cdr open-ans))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
647 (delete-region start loc))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
648 ((eq prop 'FUNCTION)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
649 ;; Not a property, but a function.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
650 (let ((rtn
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
651 (apply value start loc params)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
652 (if rtn (setq todo (cons rtn todo)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
653 (t
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
654 ;; Normal property/value pair
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
655 (setq todo
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
656 (cons (list start loc prop value)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
657 todo))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
658 (setq extents (cdr extents)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
659 start (car (car extents))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
660 loc (cdr (car extents))))))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
661 (setq alist (cdr alist))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
662 (setq aalist (cdr aalist)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
663 (unless matched
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
664 ;; Didn't find any match for the annotation:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
665 ;; Store as value of text-property `unknown'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
666 (setcdr (car top-extents) loc)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
667 (let ((extents top-extents)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
668 (start (car (car top-extents)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
669 (loc (cdr (car top-extents))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
670 (while extents
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
671 (setq open-ans (cdr open-ans)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
672 todo (cons (list start loc 'unknown top-name)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
673 todo)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
674 unknown-ans (cons name unknown-ans)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
675 extents (cdr extents)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
676 start (car (car extents))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
677 loc (cdr (car extents))))))))))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
678
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
679 ;; Once entire file has been scanned, add the properties.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
680 (while todo
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
681 (let* ((item (car todo))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
682 (from (nth 0 item))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
683 (to (nth 1 item))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
684 (prop (nth 2 item))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
685 (val (nth 3 item)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
686
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
687 (if (numberp val) ; add to ambient value if numeric
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
688 (format-property-increment-region from to prop val 0)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
689 (put-text-property
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
690 from to prop
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
691 (cond ((get prop 'format-list-valued) ; value gets consed onto
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
692 ; list-valued properties
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
693 (let ((prev (get-text-property from prop)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
694 (cons val (if (listp prev) prev (list prev)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
695 (t val))))) ; normally, just set to val.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
696 (setq todo (cdr todo)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
697
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
698 (if unknown-ans
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
699 (message "Unknown annotations: %s" unknown-ans))))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
700
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
701 (defun format-subtract-regions (minu subtra)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
702 "Remove the regions in SUBTRAHEND from the regions in MINUEND. A region
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
703 is a dotted pair (from . to). Both parameters are lists of regions. Each
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
704 list must contain nonoverlapping, noncontiguous regions, in descending
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
705 order. The result is also nonoverlapping, noncontiguous, and in descending
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
706 order. The first element of MINUEND can have a cdr of nil, indicating that
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
707 the end of that region is not yet known."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
708 (let* ((minuend (copy-alist minu))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
709 (subtrahend (copy-alist subtra))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
710 (m (car minuend))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
711 (s (car subtrahend))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
712 results)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
713 (while (and minuend subtrahend)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
714 (cond
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
715 ;; The minuend starts after the subtrahend ends; keep it.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
716 ((> (car m) (cdr s))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
717 (setq results (cons m results)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
718 minuend (cdr minuend)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
719 m (car minuend)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
720 ;; The minuend extends beyond the end of the subtrahend. Chop it off.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
721 ((or (null (cdr m)) (> (cdr m) (cdr s)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
722 (setq results (cons (cons (1+ (cdr s)) (cdr m)) results))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
723 (setcdr m (cdr s)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
724 ;; The subtrahend starts after the minuend ends; throw it away.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
725 ((< (cdr m) (car s))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
726 (setq subtrahend (cdr subtrahend) s (car subtrahend)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
727 ;; The subtrahend extends beyond the end of the minuend. Chop it off.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
728 (t ;(<= (cdr m) (cdr s)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
729 (if (>= (car m) (car s))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
730 (setq minuend (cdr minuend) m (car minuend))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
731 (setcdr m (1- (car s)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
732 (setq subtrahend (cdr subtrahend) s (car subtrahend))))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
733 (nconc (nreverse results) minuend)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
734
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
735 ;; This should probably go somewhere other than format.el. Then again,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
736 ;; indent.el has alter-text-property. NOTE: We can also use
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
737 ;; next-single-property-change instead of text-property-not-all, but then
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
738 ;; we have to see if we passed TO.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
739 (defun format-property-increment-region (from to prop delta default)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
740 "Increment property PROP over the region between FROM and TO by the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
741 amount DELTA (which may be negative). If property PROP is nil anywhere
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
742 in the region, it is treated as though it were DEFAULT."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
743 (let ((cur from) val newval next)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
744 (while cur
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
745 (setq val (get-text-property cur prop)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
746 newval (+ (or val default) delta)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
747 next (text-property-not-all cur to prop val))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
748 (put-text-property cur (or next to) prop newval)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
749 (setq cur next))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
750
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
751 ;;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
752 ;;; Encoding
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
753 ;;;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
754
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
755 (defun format-insert-annotations (list &optional offset)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
756 "Apply list of annotations to buffer as `write-region' would.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
757 Inserts each element of the given LIST of buffer annotations at its
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
758 appropriate place. Use second arg OFFSET if the annotations' locations are
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
759 not relative to the beginning of the buffer: annotations will be inserted
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
760 at their location-OFFSET+1 \(ie, the offset is treated as the character number
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
761 of the first character in the buffer)."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
762 (if (not offset)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
763 (setq offset 0)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
764 (setq offset (1- offset)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
765 (let ((l (reverse list)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
766 (while l
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
767 (goto-char (- (car (car l)) offset))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
768 (insert (cdr (car l)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
769 (setq l (cdr l)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
770
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
771 (defun format-annotate-value (old new)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
772 "Return OLD and NEW as a \(close . open) annotation pair.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
773 Useful as a default function for TRANSLATIONS alist when the value of the text
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
774 property is the name of the annotation that you want to use, as it is for the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
775 `unknown' text property."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
776 (cons (if old (list old))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
777 (if new (list new))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
778
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
779 (defun format-annotate-region (from to trans format-fn ignore)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
780 "Generate annotations for text properties in the region.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
781 Searches for changes between FROM and TO, and describes them with a list of
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
782 annotations as defined by alist TRANSLATIONS and FORMAT-FN. IGNORE lists text
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
783 properties not to consider; any text properties that are neither ignored nor
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
784 listed in TRANSLATIONS are warned about.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
785 If you actually want to modify the region, give the return value of this
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
786 function to `format-insert-annotations'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
787
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
788 Format of the TRANSLATIONS argument:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
789
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
790 Each element is a list whose car is a PROPERTY, and the following
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
791 elements are VALUES of that property followed by the names of zero or more
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
792 ANNOTATIONS. Whenever the property takes on that value, the annotations
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
793 \(as formatted by FORMAT-FN) are inserted into the file.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
794 When the property stops having that value, the matching negated annotation
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
795 will be inserted \(it may actually be closed earlier and reopened, if
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
796 necessary, to keep proper nesting).
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
797
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
798 If the property's value is a list, then each element of the list is dealt with
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
799 separately.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
800
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
801 If a VALUE is numeric, then it is assumed that there is a single annotation
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
802 and each occurrence of it increments the value of the property by that number.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
803 Thus, given the entry \(left-margin \(4 \"indent\")), if the left margin
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
804 changes from 4 to 12, two <indent> annotations will be generated.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
805
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
806 If the VALUE is nil, then instead of annotations, a function should be
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
807 specified. This function is used as a default: it is called for all
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
808 transitions not explicitly listed in the table. The function is called with
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
809 two arguments, the OLD and NEW values of the property. It should return
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
810 lists of annotations like `format-annotate-location' does.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
811
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
812 The same structure can be used in reverse for reading files."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
813 (let ((all-ans nil) ; All annotations - becomes return value
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
814 (open-ans nil) ; Annotations not yet closed
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
815 (loc nil) ; Current location
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
816 (not-found nil)) ; Properties that couldn't be saved
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
817 (while (or (null loc)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
818 (and (setq loc (next-property-change loc nil to))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
819 (< loc to)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
820 (or loc (setq loc from))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
821 (let* ((ans (format-annotate-location loc (= loc from) ignore trans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
822 (neg-ans (format-reorder (aref ans 0) open-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
823 (pos-ans (aref ans 1))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
824 (ignored (aref ans 2)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
825 (setq not-found (append ignored not-found)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
826 ignore (append ignored ignore))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
827 ;; First do the negative (closing) annotations
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
828 (while neg-ans
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
829 ;; Check if it's missing. This can happen (eg, a numeric property
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
830 ;; going negative can generate closing annotations before there are
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
831 ;; any open). Warn user & ignore.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
832 (if (not (member (car neg-ans) open-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
833 (message "Can't close %s: not open." (car neg-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
834 (while (not (equal (car neg-ans) (car open-ans)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
835 ;; To close anno. N, need to first close ans 1 to N-1,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
836 ;; remembering to re-open them later.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
837 (setq pos-ans (cons (car open-ans) pos-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
838 (setq all-ans
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
839 (cons (cons loc (funcall format-fn (car open-ans) nil))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
840 all-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
841 (setq open-ans (cdr open-ans)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
842 ;; Now remove the one we're really interested in from open list.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
843 (setq open-ans (cdr open-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
844 ;; And put the closing annotation here.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
845 (setq all-ans
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
846 (cons (cons loc (funcall format-fn (car neg-ans) nil))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
847 all-ans)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
848 (setq neg-ans (cdr neg-ans)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
849 ;; Now deal with positive (opening) annotations
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
850 (let ( ; (p pos-ans)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
851 )
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
852 (while pos-ans
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
853 (setq open-ans (cons (car pos-ans) open-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
854 (setq all-ans
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
855 (cons (cons loc (funcall format-fn (car pos-ans) t))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
856 all-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
857 (setq pos-ans (cdr pos-ans))))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
858
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
859 ;; Close any annotations still open
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
860 (while open-ans
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
861 (setq all-ans
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
862 (cons (cons to (funcall format-fn (car open-ans) nil))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
863 all-ans))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
864 (setq open-ans (cdr open-ans)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
865 (if not-found
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
866 (message "These text properties could not be saved:\n %s"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
867 not-found))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
868 (nreverse all-ans)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
869
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
870 ;;; Internal functions for format-annotate-region.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
871
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
872 (defun format-annotate-location (loc all ignore trans)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
873 "Return annotation(s) needed at LOCATION.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
874 This includes any properties that change between LOC-1 and LOC.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
875 If ALL is true, don't look at previous location, but generate annotations for
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
876 all non-nil properties.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
877 Third argument IGNORE is a list of text-properties not to consider.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
878
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
879 Return value is a vector of 3 elements:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
880 1. List of names of the annotations to close
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
881 2. List of the names of annotations to open.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
882 3. List of properties that were ignored or couldn't be annotated."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
883 (let* ((prev-loc (1- loc))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
884 (before-plist (if all nil (text-properties-at prev-loc)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
885 (after-plist (text-properties-at loc))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
886 p negatives positives prop props not-found)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
887 ;; make list of all property names involved
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
888 (setq p before-plist)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
889 (while p
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
890 (if (not (memq (car p) props))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
891 (setq props (cons (car p) props)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
892 (setq p (cdr (cdr p))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
893 (setq p after-plist)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
894 (while p
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
895 (if (not (memq (car p) props))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
896 (setq props (cons (car p) props)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
897 (setq p (cdr (cdr p))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
898
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
899 (while props
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
900 (setq prop (car props)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
901 props (cdr props))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
902 (if (memq prop ignore)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
903 nil ; If it's been ignored before, ignore it now.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
904 (let ((before (if all nil (car (cdr (memq prop before-plist)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
905 (after (car (cdr (memq prop after-plist)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
906 (if (equal before after)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
907 nil ; no change; ignore
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
908 (let ((result (format-annotate-single-property-change
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
909 prop before after trans)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
910 (if (not result)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
911 (setq not-found (cons prop not-found))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
912 (setq negatives (nconc negatives (car result))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
913 positives (nconc positives (cdr result)))))))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
914 (vector negatives positives not-found)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
915
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
916 (defun format-annotate-single-property-change (prop old new trans)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
917 "Return annotations for PROPERTY changing from OLD to NEW.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
918 These are searched for in the TRANSLATIONS alist.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
919 If NEW does not appear in the list, but there is a default function, then that
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
920 function is called.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
921 Annotations to open and to close are returned as a dotted pair."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
922 (let ((prop-alist (cdr (assoc prop trans)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
923 ;; default
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
924 )
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
925 (if (not prop-alist)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
926 nil
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
927 ;; If either old or new is a list, have to treat both that way.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
928 (if (or (consp old) (consp new))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
929 (let* ((old (if (listp old) old (list old)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
930 (new (if (listp new) new (list new)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
931 ;; (tail (format-common-tail old new))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
932 close open)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
933 (while old
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
934 (setq close
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
935 (append (car (format-annotate-atomic-property-change
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
936 prop-alist (car old) nil))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
937 close)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
938 old (cdr old)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
939 (while new
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
940 (setq open
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
941 (append (cdr (format-annotate-atomic-property-change
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
942 prop-alist nil (car new)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
943 open)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
944 new (cdr new)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
945 (format-make-relatively-unique close open))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
946 (format-annotate-atomic-property-change prop-alist old new)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
947
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
948 (defun format-annotate-atomic-property-change (prop-alist old new)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
949 "Internal function annotate a single property change.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
950 PROP-ALIST is the relevant segment of a TRANSLATIONS list.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
951 OLD and NEW are the values."
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
952 (let (num-ann)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
953 ;; If old and new values are numbers,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
954 ;; look for a number in PROP-ALIST.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
955 (if (and (or (null old) (numberp old))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
956 (or (null new) (numberp new)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
957 (progn
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
958 (setq num-ann prop-alist)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
959 (while (and num-ann (not (numberp (car (car num-ann)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
960 (setq num-ann (cdr num-ann)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
961 (if num-ann
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
962 ;; Numerical annotation - use difference
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
963 (progn
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
964 ;; If property is numeric, nil means 0
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
965 (cond ((and (numberp old) (null new))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
966 (setq new 0))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
967 ((and (numberp new) (null old))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
968 (setq old 0)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
969
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
970 (let* ((entry (car num-ann))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
971 (increment (car entry))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
972 (n (ceiling (/ (float (- new old)) (float increment))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
973 (anno (car (cdr entry))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
974 (if (> n 0)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
975 (cons nil (make-list n anno))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
976 (cons (make-list (- n) anno) nil))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
977
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
978 ;; Standard annotation
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
979 (let ((close (and old (cdr (assoc old prop-alist))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
980 (open (and new (cdr (assoc new prop-alist)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
981 (if (or close open)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
982 (format-make-relatively-unique close open)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
983 ;; Call "Default" function, if any
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
984 (let ((default (assq nil prop-alist)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
985 (if default
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
986 (funcall (car (cdr default)) old new))))))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
987
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
988 ;;; format.el ends here