; This file implements "mhe", the display-oriented front end to the MH mail
; system. Documentation is in file mh-doc.ml.
; To install this at your site you must edit the variables flagged with
; an asterisk below.
; 
;  Brian K. Reid, Stanford, April 1982
;
; This is version 4 (September 1982); it uses fast-filter-region.
; 
; UCI modification: we don't need fast-filter-region since we have
;		    use-users-shell
    (setq stack-trace-on-error 1)
    (declare-global		;*marks installation constants
	 mh-keymap-defined	; T iff keymap exists.
	 mh-folder		; string name, e.g. "inbox"
	 mh-path		; "/mnt/reid/Mail", or whatever
	 mh-progs		;*"/usr/local/lib/mh", or whatever
	 bboard-path		;*"/usr/spool/netnews", or whatever
	 mh-buffer-filename	; "/mnt/reid/Mail/inbox", or whatever
	 t-buffer-filename	; scratch for side effect from mh-folder
	 mh-flist		; "inbox,carbons,news", or whatever
	 mh-direction		; 1 is up, -1 is down.
	 mh-annotate		; are we annotating processed msgs?
	 mh-writeable		; is this folder write-enabled?
	 mh-last-destination	; destination of last "move" command
	 mhe-debug		; are we debugging macro package?
    )

    (argc)			; is this early enough, James?
    (setq mh-keymap-defined 0)
    (setq mhe-debug 0)
    (setq-default mh-annotate 1)
    (setq-default mh-writeable 1)
    (setq bboard-path "/dev/null"); UCI
    (setq mh-path "")
    (setq mh-progs "/usr/uci")	; UCI
    (setq mh-flist "")
    (setq-default right-margin 77)
    (setq-default mh-direction 1)
    (setq pop-up-windows 1)	; mhe requires popup windows!

    (declare-buffer-specific
	mh-direction
	mh-buffer-filename
	mh-folder-title
	mh-annotate
	mh-writeable
	backup-before-writing
	wrap-long-lines
    )

(defun				; (mh "folder" "range")
    (mh folder range
	(temp-use-buffer "cmd-buffer") (erase-buffer)
	(setq backup-before-writing 0)
	(find-path)
	(setq folder (arg 1 (concat ": mh on folder? [" mh-folder "] ")))
	(if (= folder "")
	    (setq folder mh-folder))
	(if (= '+' (string-to-char (substr folder 1 1)))
	    (setq folder (substr folder 2 -1)))
	(setq range (arg 2))
	(setq mh-folder (get-folder-name "??" folder 1))
	(&mh-read-folder mh-folder range t-buffer-filename mh-folder)
	(progn stop-loop
	       (setq stop-loop 0)
	       (while (! stop-loop)
		      (pop-to-buffer (concat "+" mh-folder))
		      (use-local-map "&mh-keymap")
		      (error-occured (recursive-edit))
		      (setq stop-loop (&mh-exit))
	       )
	)
    )
)
; This function marks a message as being deleted. This mark has two parts.
; The letter "D" is placed in column 4 of the header line, and the message
; number is added to the text of an "rmm" command that is being assembled
; in the command buffer.
(defun 
    (&mh-Mark-file-deleted
	(pop-to-buffer (concat "+" mh-folder))
	(if (! mh-writeable)
	    (error-message "Sorry; this folder is read-only."))
	(beginning-of-line)
	(goto-character (+ (dot) 3))
	(if (| (= (following-char) ' ') (= (following-char) '+'))
	    (progn 
		   (delete-next-character)
		   (insert-string "D")
		   (setq buffer-is-modified 0)
		   (temp-use-buffer "cmd-buffer")
		   (beginning-of-file)
		   (if (error-occured
			   (re-search-forward
			       (concat "^rmm +" mh-folder)))
		       (progn 
			      (end-of-file)
			      (insert-string (concat "rmm +" mh-folder "\n"))
			      (backward-character)
		       )
		   )
		   (end-of-line)
		   (insert-string (concat " " (&mh-get-msgnum)))
		   (setq buffer-is-modified 0)
		   (pop-to-buffer (concat "+" mh-folder))
	    )
	)
	(another-line)
    )
)
; These functions create (and make current) a header buffer on a new message
; or bboard directory.
(defun 
    (&mh-new-folder which
	(setq which (get-folder-name "New" "" 1))
	(&mh-read-folder which "" t-buffer-filename which)
    )
    
    (&mh-bboard which
	(error-message "B: command not implemented at UCI."); UCI
;UCI	(setq which (get-bboard-name))
;UCI	(&mh-read-folder which "" t-buffer-filename t-buffer-filename)
;UCI	(setq mh-annotate 0)
;UCI	(setq mh-writeable 0)
    )
)

(defun    
    (&mh-remove
	(if (= "+" (substr (current-buffer-name) 1 1))
	    (progn 
		   (beginning-of-line)
		   (&mh-unmark)
		   (kill-to-end-of-line) (kill-to-end-of-line)
		   (setq buffer-is-modified 0)
	    )
	    (error-message "The " (char-to-string (last-key-struck)) " command works only in header windows.")
	)
    )

; This function gets redefined when &mh-move is autoloaded. Shame on me for
; giving it a name so similar to the function above.
    (&mh-re-move
	(error-message "I can't repeat the last ^ command because you haven't typed one yet")
    )

    (&mh-summary
	(message
		"nxt prev del ^put !rpt unmrk typ edit mail forw inc repl get bboard ^X^C ?")
    )

;  This function is redefined when file mh-extras.ml is autoloaded
    (&mh-beep (send-string-to-terminal ""))
)
; These functions are used to preserve the contents of the kill buffer
; across things that we want to be invisible, so that the keyboard-level
; user does not have to worry about system functions clobbering the kill
; buffer.
(defun     
    (&mh-save-killbuffer
	(save-excursion 
	    (temp-use-buffer "Kill buffer")
	    (temp-use-buffer "Kill save")
	    (setq backup-before-writing 0)
	    (erase-buffer)
	    (yank-buffer "Kill buffer")
	    (setq buffer-is-modified 0)
	)
    )
    
    (&mh-restore-killbuffer
	(save-excursion 
	    (temp-use-buffer "Kill buffer")
	    (erase-buffer)
	    (yank-buffer "Kill save")
	)
    )
)
; These functions move the cursor around in a header buffer, and possibly
; also display the message that the cursor now points to.
(defun     
    (&mh-next-line
	(pop-to-buffer (concat "+" mh-folder))
	(setq mh-direction 1)
	(next-line) (beginning-of-line)
	(if (eobp)
	    (progn (previous-line)
		   (setq mh-direction -1)))
    )
    (&mh-previous-line
	(pop-to-buffer (concat "+" mh-folder))
	(setq mh-direction -1)
	(previous-line) (beginning-of-line)
	(if (bobp)
	    (setq mh-direction 1))
    )
    
    (another-line old-direction
	(setq old-direction mh-direction)
	(if (> mh-direction 0)
	    (&mh-next-line)
	    (&mh-previous-line)
	)
	(if (!= old-direction mh-direction)
	    (if (> mh-direction 0)
		(beginning-of-line)
		(&mh-previous-line)
	    )
	)
    )
    
)
; These functions query the user for various things, and error-check the
; responses. "get-response" reads a 1-letter response code in the minibuffer.
; "get-folder-name" extracts the string name of an MH folder or file.
; "get-bboard-name" gets the string name of a bboard file.
(defun     
    (get-response chr ok s c pr
	(setq ok 0) (setq pr (arg 1))
	(while (! ok)
	       (setq chr
		     (string-to-char 
			 (setq c
			       (get-tty-string pr)
			 )
		     )
	       )
	       
	       (setq s (arg 2))
	       (while (> (length s) 0)
		      (if (= chr (string-to-char (substr s 1 1)))
			  (progn (setq ok 1) (setq s ""))
			  (setq s (substr s 2 -1))
		      )
	       )
	       (if (= ok 0)
		   (progn (if (!= chr '?')
			      (setq pr (concat "Illegal response '"
					       (char-to-string chr)
					       "'. " (arg 1)))
			      (setq pr (arg 3))
			  )
		   )
	       )
	)
	(if (& (>= chr 'A') (<= chr 'Z'))
	    (+ chr (- 'a' 'A'))
	    chr
	)
    )
    
    (get-folder-name		; (g-f-n "prompt" "default" can-create)
	exists msgg name defarg
	(setq exists 0)
	(if (> (nargs) 1) (setq defarg (arg 2)) (setq defarg ""))
	(setq msgg (concat (arg 1) " folder name? "))
	(while (! exists)
	       (if (= 0 (length defarg))
		   (setq name (get-tty-string msgg))
		   (setq name defarg)
	       )
	       (setq defarg "")
	       (if (= 0 (length name))
		   (error-message "Aborted."))
	       (if (!= (string-to-char (substr name 1 1)) '/')
		   (setq t-buffer-filename (concat mh-path "/" name))
		   (setq t-buffer-filename name)
	       )
	       (setq exists (file-exists t-buffer-filename))
	       (if (& (!= exists 1) (!= (arg 3) 0))
		   (progn ans
			  (setq ans (get-response
					(concat "Folder +" name " does not exist. May I create it for you? ")
					"yYnN\"
					"Please answer y or n"))
			  (if (= ans 'y')
			      (progn 
				     (message "OK, I will create one for you.")
				     (send-to-shell 
					 (concat "mkdir " t-buffer-filename))
				     (setq exists 1)
			      )
			  )
		   )
	       )
	       (if (!= exists 1)
		   (setq msgg  (concat "Sorry, no such folder as `" name
				       "'.  Folder name? "))
	       )
	)
	name
    )
    
    (get-bboard-name  exists msgg name
	(setq exists 0)
	(setq msgg "BBoard name? ")
	(while (! exists)
	       (setq name (get-tty-string msgg))
	       (if (= 0 (length name))
		   (error-message "Aborted."))
	       (if (!= (string-to-char (substr name 1 1)) '/')
		   (setq t-buffer-filename (concat bboard-path "/" name))
		   (setq t-buffer-filename name)
	       )
	       (setq exists (file-exists t-buffer-filename))
	       (if (!= exists 1)
		   (setq msgg  (concat "Sorry, no such BBoard as `" name
				       "'.  BBoard name? "))
	       )
	)
	name
    )
)
; UCI hack for fast-filter-region
(defun (fast-filter-region UseUsersShell
		(setq UseUsersShell use-users-shell)
		(setq use-users-shell 0)
		(filter-region
		    (arg 1 ": fast-filter-region (through command) "))
		(setq use-users-shell UseUsersShell)
       )
)
; These functions are the initial entry points to mhe. "startup" is 
; expecting an argv like "emacs -lmh-e.ml -estartup +inbox 100-last
(defun
    (startup
	    (setq stack-trace-on-error 0)
	    (mh (if (> (argc) 3)
		    (argv 3)
		    "")
		(if (> (argc) 4)
		    (argv 4)
		    "")
	    )
	    (error-occured (kill-process "newtime"))
	    (exit-emacs)
    )
    
    (debug-startup
	(setq mh-progs "/usr/local/src/cmd/mh/progs")
	(setq stack-trace-on-error 0)
	(startup)
    )
)
    (load "mh-util.ml")
    (load "mh-shell.ml")
    (load "mh-cache.ml")
    (autoload "&mh-send" "mh-send.ml")
    (autoload "&mh-show" "mh-show.ml")
    (autoload "&mh-edit" "mh-edit.ml")
    (autoload "&mh-repl" "mh-repl.ml")
    (autoload "&mh-inc" "mh-inc.ml")
    (autoload "&mh-help" "mh-help.ml")
    (autoload "&mh-move" "mh-move.ml")
    (autoload "&mh-unmark" "mh-unmark.ml")
    (autoload "&mh-forw" "mh-forw.ml")
    (autoload "&mh-exit" "mh-exit.ml")
    (autoload "annotate" "mh-annot.ml")
    (autoload "mail-mode" "mh-mode.ml")
    (autoload "&mh-extras" "mh-extras.ml")
    (autoload "&mh-xpack" "mh-extras.ml")
    (if (! (is-bound time))
	(load "time.ml")
	(time)
    )
    (load "mh-keymap.ml")
