;;
;; $Id: crnl-mode.el,v 1.2 1996/08/13 18:21:56 ejb Exp $
;; $Source: /home/ejb/elisp/q/RCS/crnl-mode.el,v $
;; $Author: ejb $
;;
;; Minor mode for removing CR on read and re-inserting on write.
;;

(provide 'crnl-mode)

(defvar crnl-mode nil)
(make-variable-buffer-local 'crnl-mode)

(defun crnl-remove-cr ()
  (if crnl-mode
      (save-restriction
	(widen)
	(save-excursion
	  (goto-char (point-min))
	  (let ((modified (buffer-modified-p))
		(buffer-undo-list t)
		(inhibit-read-only t)
		)
	    (while (search-forward "\r" nil t)
	      (replace-match ""))
	    (set-buffer-modified-p modified)
	    )
	  )
	)
    )
  nil
  )

(defun crnl-add-cr ()
  (if crnl-mode
      (progn
	(crnl-remove-cr)
	(save-restriction
	  (widen)
	  (save-excursion
	    (goto-char (point-min))
	    (let ((modified (buffer-modified-p))
		  (buffer-undo-list t)
		  (inhibit-read-only t)
		  )
	      (while (search-forward "\n" nil t)
		(replace-match "\r\n")
		)
	      (set-buffer-modified-p modified)
	      )
	    )
	  )
	)
      )
  nil
  )

(defun crnl-mode-setup (arg)
  "Perform setup for crnl mode with t or cleanup with nil arg."
  (if arg
      (progn
	;; setup
	(make-local-hook 'write-contents-hooks)
	(add-hook 'write-contents-hooks 'crnl-add-cr t t)
	(make-local-hook 'after-save-hook)
	(add-hook 'after-save-hook 'crnl-remove-cr t t)
	(crnl-remove-cr)
	)
    ;; cleanup
    ;; no cleanup required
    )
  )

(defun crnl-mode (arg)
  "Toggle on crnl mode."
  (interactive "P")
  (if (null arg)
      (setq crnl-mode (not crnl-mode))
    (setq crnl-mode t))
  (if crnl-mode
      (progn
	;; Turn on minor mode
	(or (assq 'crnl-mode minor-mode-alist)
	    (setq minor-mode-alist
		  (append '((crnl-mode " CR/NL"))
			  minor-mode-alist)
		  )
	    )
	;;
	;; Do any other minor mode initialization here
	;;
	(crnl-mode-setup t)
	)
    ;; else
    ;; Do any minor mode exiting stuff here
    (crnl-mode-setup nil)
    )
  (force-mode-line-update)
  )

(defun crnl-buffer-has-crs ()
  "Determine whether buffer looks like text with CRNL"
  (save-excursion
    (and (progn
	   (goto-char (point-min))
	   (not (re-search-forward "[^\r]\n" nil t))
	   )
	 (progn
	   (goto-char (point-min))
	   (re-search-forward "\n" nil t))
	 )
    )
  )

(defun crnl-mode-maybe ()
  "Enter crnl-mode if buffer looks like it is text with CRNL instead of NL"
  (if (crnl-buffer-has-crs)
      (crnl-mode t)
    )
  )
