;;; richtext.el -- read and save files in text/richtext format ;; Copyright (C) 1995,1996,1997 Free Software Foundation, Inc. ;; Author: MORIOKA Tomohiko ;; 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., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, 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 '(("<" . ""))) (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 "\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]*[ \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 ;;; (provide 'richtext) ;;; richtext.el ends here