2 ;;; richtext.el -- read and save files in text/richtext format
4 ;;; $Id: richtext.el,v 2.1 1995/07/17 22:59:10 morioka Exp $
13 (defconst richtext-initial-annotation
15 (format "Content-Type: text/richtext\nText-Width: %d\n\n"
16 (enriched-text-width)))
17 "What to insert at the start of a text/richtext file.
18 If this is a string, it is inserted. If it is a list, it should be a lambda
19 expression, which is evaluated to get the string to insert.")
21 (defconst richtext-annotation-regexp
22 "[ \t\n]*\\(<\\(/\\)?\\([-A-za-z0-9]+\\)>\\)[ \t\n]*"
23 "Regular expression matching richtext annotations.")
25 (defconst richtext-translations
26 '((face (bold-italic "bold" "italic")
29 (underline "underline")
33 (nil enriched-encode-other-face))
34 (invisible (t "comment"))
35 (left-margin (4 "indent"))
36 (right-margin (4 "indentright"))
37 (justification (right "flushright")
41 ;; The following are not part of the standard:
42 (FUNCTION (enriched-decode-foreground "x-color")
43 (enriched-decode-background "x-bg-color"))
44 (read-only (t "x-read-only"))
45 (unknown (nil format-annotate-value))
46 ; (font-size (2 "bigger") ; unimplemented
49 "List of definitions of text/richtext annotations.
50 See `format-annotate-region' and `format-deannotate-region' for the definition
57 (defun richtext-encode (from to)
58 (if enriched-verbose (message "Richtext: encoding document..."))
60 (narrow-to-region from to)
61 (delete-to-left-margin)
64 (format-replace-strings '(("<" . "<lt>")))
65 (format-insert-annotations
66 (format-annotate-region from (point-max) richtext-translations
67 'enriched-make-annotation enriched-ignore))
69 (insert (if (stringp enriched-initial-annotation)
70 richtext-initial-annotation
71 (funcall richtext-initial-annotation)))
72 (enriched-map-property-regions 'hard
76 (while (search-forward "\n" nil t)
77 (replace-match "<nl>\n")
80 (if enriched-verbose (message nil))
88 (defun richtext-next-annotation ()
89 "Find and return next text/richtext annotation.
90 Return value is \(begin end name positive-p), or nil if none was found."
92 (while (re-search-forward richtext-annotation-regexp nil t)
93 (let* ((beg0 (match-beginning 0))
95 (beg (match-beginning 1))
97 (name (downcase (buffer-substring
98 (match-beginning 3) (match-end 3))))
99 (pos (not (match-beginning 2)))
101 (cond ((equal name "lt")
102 (delete-region beg end)
106 ((equal name "comment")
108 (throw 'tag (list beg0 end name pos))
109 (throw 'tag (list beg end0 name pos))
113 (throw 'tag (list beg end name pos))
117 (defun richtext-decode (from to)
118 (if enriched-verbose (message "Richtext: decoding document..."))
121 (narrow-to-region from to)
123 (let ((file-width (enriched-get-file-width))
124 (use-hard-newlines t) pc nc)
125 (enriched-remove-header)
128 (while (re-search-forward "\n\n+" nil t)
132 ;; Deal with newlines
134 (while (re-search-forward "[ \t\n]*<nl>[ \t\n]*" nil t)
136 (put-text-property (match-beginning 0) (point) 'hard t)
137 (put-text-property (match-beginning 0) (point) 'front-sticky nil)
140 ;; Translate annotations
141 (format-deannotate-region from (point-max) richtext-translations
142 'richtext-next-annotation)
145 (if (or (and file-width ; possible reasons not to fill:
146 (= file-width (enriched-text-width))) ; correct wd.
147 (null enriched-fill-after-visiting) ; never fill
148 (and (eq 'ask enriched-fill-after-visiting) ; asked & declined
149 (not (y-or-n-p "Re-fill for current display width? "))))
150 ;; Minimally, we have to insert indentation and justification.
151 (enriched-insert-indentation)
152 (if enriched-verbose (message "Filling paragraphs..."))
153 (fill-region (point-min) (point-max))))
154 (if enriched-verbose (message nil))