186 lines
5.6 KiB
EmacsLisp
186 lines
5.6 KiB
EmacsLisp
;;; richtext.el -- read and save files in text/richtext format
|
|
|
|
;; Copyright (C) 1995,1996,1997 Free Software Foundation, Inc.
|
|
|
|
;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
|
|
;; Created: 1995/7/15
|
|
;; Version: $Id: richtext.el,v 3.6 1997/06/28 17:58:34 morioka Exp $
|
|
;; Keywords: wp, faces, MIME, multimedia
|
|
|
|
;; This file is not part of GNU Emacs yet.
|
|
|
|
;; This program is free software; you can redistribute it and/or
|
|
;; modify it under the terms of the GNU General Public License as
|
|
;; published by the Free Software Foundation; either version 2, or (at
|
|
;; your option) any later version.
|
|
|
|
;; This program is distributed in the hope that it will be useful, but
|
|
;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
;; General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs; see the file COPYING. If not, write to the
|
|
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
;; Boston, MA 02110-1301, USA.
|
|
|
|
;;; Code:
|
|
|
|
(require 'enriched)
|
|
|
|
|
|
;;; @ variables
|
|
;;;
|
|
|
|
(defconst richtext-initial-annotation
|
|
(lambda ()
|
|
(format "Content-Type: text/richtext\nText-Width: %d\n\n"
|
|
(enriched-text-width)))
|
|
"What to insert at the start of a text/richtext file.
|
|
If this is a string, it is inserted. If it is a list, it should be a lambda
|
|
expression, which is evaluated to get the string to insert.")
|
|
|
|
(defconst richtext-annotation-regexp
|
|
"[ \t\n]*\\(<\\(/\\)?\\([-A-za-z0-9]+\\)>\\)[ \t\n]*"
|
|
"Regular expression matching richtext annotations.")
|
|
|
|
(defconst richtext-translations
|
|
'((face (bold-italic "bold" "italic")
|
|
(bold "bold")
|
|
(italic "italic")
|
|
(underline "underline")
|
|
(fixed "fixed")
|
|
(excerpt "excerpt")
|
|
(default )
|
|
(nil enriched-encode-other-face))
|
|
(invisible (t "comment"))
|
|
(left-margin (4 "indent"))
|
|
(right-margin (4 "indentright"))
|
|
(justification (right "flushright")
|
|
(left "flushleft")
|
|
(full "flushboth")
|
|
(center "center"))
|
|
;; The following are not part of the standard:
|
|
(FUNCTION (enriched-decode-foreground "x-color")
|
|
(enriched-decode-background "x-bg-color"))
|
|
(read-only (t "x-read-only"))
|
|
(unknown (nil format-annotate-value))
|
|
; (font-size (2 "bigger") ; unimplemented
|
|
; (-2 "smaller"))
|
|
)
|
|
"List of definitions of text/richtext annotations.
|
|
See `format-annotate-region' and `format-deannotate-region' for the definition
|
|
of this structure.")
|
|
|
|
|
|
;;; @ encoder
|
|
;;;
|
|
|
|
;;;###autoload
|
|
(defun richtext-encode (from to)
|
|
(if enriched-verbose (message "Richtext: encoding document..."))
|
|
(save-restriction
|
|
(narrow-to-region from to)
|
|
(delete-to-left-margin)
|
|
(unjustify-region)
|
|
(goto-char from)
|
|
(format-replace-strings '(("<" . "<lt>")))
|
|
(format-insert-annotations
|
|
(format-annotate-region from (point-max) richtext-translations
|
|
'enriched-make-annotation enriched-ignore))
|
|
(goto-char from)
|
|
(insert (if (stringp enriched-initial-annotation)
|
|
richtext-initial-annotation
|
|
(funcall richtext-initial-annotation)))
|
|
(enriched-map-property-regions 'hard
|
|
(lambda (v b e)
|
|
(goto-char b)
|
|
(if (eolp)
|
|
(while (search-forward "\n" nil t)
|
|
(replace-match "<nl>\n")
|
|
)))
|
|
(point) nil)
|
|
(if enriched-verbose (message nil))
|
|
;; Return new end.
|
|
(point-max)))
|
|
|
|
|
|
;;; @ decoder
|
|
;;;
|
|
|
|
(defun richtext-next-annotation ()
|
|
"Find and return next text/richtext annotation.
|
|
Return value is \(begin end name positive-p), or nil if none was found."
|
|
(catch 'tag
|
|
(while (re-search-forward richtext-annotation-regexp nil t)
|
|
(let* ((beg0 (match-beginning 0))
|
|
(end0 (match-end 0))
|
|
(beg (match-beginning 1))
|
|
(end (match-end 1))
|
|
(name (downcase (buffer-substring
|
|
(match-beginning 3) (match-end 3))))
|
|
(pos (not (match-beginning 2)))
|
|
)
|
|
(cond ((equal name "lt")
|
|
(delete-region beg end)
|
|
(goto-char beg)
|
|
(insert "<")
|
|
)
|
|
((equal name "comment")
|
|
(if pos
|
|
(throw 'tag (list beg0 end name pos))
|
|
(throw 'tag (list beg end0 name pos))
|
|
)
|
|
)
|
|
(t
|
|
(throw 'tag (list beg end name pos))
|
|
))
|
|
))))
|
|
|
|
;;;###autoload
|
|
(defun richtext-decode (from to)
|
|
(if enriched-verbose (message "Richtext: decoding document..."))
|
|
(save-excursion
|
|
(save-restriction
|
|
(narrow-to-region from to)
|
|
(goto-char from)
|
|
(let ((file-width (enriched-get-file-width))
|
|
(use-hard-newlines t))
|
|
(enriched-remove-header)
|
|
|
|
(goto-char from)
|
|
(while (re-search-forward "\n\n+" nil t)
|
|
(replace-match "\n")
|
|
)
|
|
|
|
;; Deal with newlines
|
|
(goto-char from)
|
|
(while (re-search-forward "[ \t\n]*<nl>[ \t\n]*" nil t)
|
|
(replace-match "\n")
|
|
(put-text-property (match-beginning 0) (point) 'hard t)
|
|
(put-text-property (match-beginning 0) (point) 'front-sticky nil)
|
|
)
|
|
|
|
;; Translate annotations
|
|
(format-deannotate-region from (point-max) richtext-translations
|
|
'richtext-next-annotation)
|
|
|
|
;; Fill paragraphs
|
|
(if (and file-width ; possible reasons not to fill:
|
|
(= file-width (enriched-text-width))) ; correct wd.
|
|
;; Minimally, we have to insert indentation and justification.
|
|
(enriched-insert-indentation)
|
|
(if enriched-verbose (message "Filling paragraphs..."))
|
|
(fill-region (point-min) (point-max))))
|
|
(if enriched-verbose (message nil))
|
|
(point-max))))
|
|
|
|
|
|
;;; @ end
|
|
;;;
|
|
|
|
(require 'product)
|
|
(product-provide (provide 'richtext) (require 'apel-ver))
|
|
|
|
;;; richtext.el ends here
|