; 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 6 (August 1984) for 4.2 unix
;
;  Made mh-e.ml call (mh-user-configure) at the end, for user
;  customizations, such as setting print options.
;	Glenn Trewitt, WRL/NSL 27-Jan-92
; 
    (setq stack-trace-on-error 0)
    (declare-global		;*marks installation constants
	 mh-keymap-defined	; T iff keymap exists.
	 mh-folder		; string name, e.g. "inbox"
	 mh-profile		; "/mnt/reid/.mh_profile", or whatever
	 mh-path		; "/mnt/reid/Mail", or whatever
	 mh-remote		; "rsh <host> ", if spool dir is remote
	 mh-progs		;*"/usr/stanford/bin", or whatever
	 mh-lib			;*"/usr/stanford/lib/mh", or whatever
	 bboard-path		;*"/usr/spool/netnews", or whatever
	 mh-print-filter	;*"/pr", or whatever
	 mh-pspool-filter	;*"lpr", 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?
	 mh-screen-size		; how many lines are effectively on the
				; screen?
	 mh-width		; header file width
	 mh-has-mouse		; nonzero if we have a mouse
	 mh-version-6-or-later	; true if later version
	 ; the rest are set by &mh-determine-version
	 mh-msgnum-cols		; column where the message number starts,
	 mh-file-command	; command for filing messages
    )

    (argc)			; is this early enough, James?
    (setq mh-keymap-defined 0)
    (setq mhe-debug 0)
    (setq mh-profile (concat (getenv "HOME") "/.mh_profile"))
    (setq mh-version-6-or-later 1)	;  set by &mh-determine-version
    (setq mh-msgnum-cols (if mh-version-6-or-later 4 3)) ;  likewise
    (setq mh-file-command (if mh-version-6-or-later "refile" "filem"))
    (setq-default mh-annotate 1)
    (setq-default mh-writeable 1)
    (setq bboard-path "/usr/spool/mail")
    (setq mh-print-filter "enscript -2r")
    (setq mh-pspool-filter "")
    (setq mh-path "")
    (setq mh-remote "")
    (setq mh-progs
	  (if
	     (file-exists "/usr/bin/mh/inc") "/usr/bin/mh"
	     (file-exists "/usr/new/mh/inc") "/usr/new/mh"
	     (file-exists "local/bin/inc") "local/bin"
	     (error-message "Couldn't find mh programs!")
	  )
    )
    (setq mh-lib
	  (if
	     (file-exists "/usr/lib/mh/components") "/usr/lib/mh"
	     (file-exists "/usr/new/lib/mh/components") "/usr/new/lib/mh"
;	     (file-exists "/usr/stanford/lib/mh/components") "/usr/stanford/lib/mh"
	     (error-message "Couldn't find mh library!")
	  )
    )
    (setq mh-flist "")
    (setq-default right-margin 77)
    (setq-default mh-direction 1)
    (setq pop-up-windows 1)	; mhe requires popup windows!

    (delete-other-windows)
    (setq mh-screen-size (window-height))
    (setq mh-has-mouse 0)
    (if (is-bound mouse-exists)
	(if (!= mouse-exists 0)
	    (setq mh-has-mouse 1)
	)
    )

    (declare-buffer-specific
	mh-direction
	mh-buffer-filename
	mh-folder-title
	mh-annotate
	mh-writeable
    )
    
    ;  Create "window-priority" variable for emacs' that don't have it.
    (if (! (is-bound window-priority))
	(declare-global window-priority))

(defun
    (&mh-determine-version
	(temp-use-buffer "mh-temp")
	(setq needs-checkpointing 0)
	(erase-buffer)
	(set-mark)
	(fast-filter-region (concat mh-progs "/scan -help"))
	(beginning-of-file)
	(if (error-occured (re-search-forward "version: MH 6"))
	    (progn 		; old version
		(setq mh-version-6-or-later 0)
		(setq mh-msgnum-cols 3)
		(setq mh-file-command "filem")
		(setq mh-width ""))
	    (progn 		; new version
		(setq mh-version-6-or-later 1)
		(setq mh-msgnum-cols 4)
		(setq mh-file-command "refile")
		(setq mh-width
		      (concat " -width "
			      (if
				 (! (error-occured (terminal-width)))
					(terminal-width)
				 (! (error-occured (window-width)))
					(- (window-width) 1)
			 	 79
			      )
		      )
		))
	)
	(erase-buffer)
    )

    ; (mh "folder" "range")
    (mh folder range
	(temp-use-buffer "cmd-buffer") (erase-buffer)
	(setq needs-checkpointing 0)
	(find-path)		;  sets mh-path, mh-folder
	(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 (if (< (nargs) 2)
			""
			(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)
		      (&mh-pop-to-buffer (concat "+" mh-folder))
		      (setq window-priority 40)
		      (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 after the number in 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
	(&mh-pop-to-buffer (concat "+" mh-folder))
	(if (! mh-writeable)
	    (error-message "Sorry; this folder is read-only."))
	(beginning-of-line)
	(goto-character (+ (dot) mh-msgnum-cols))
	(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)
		   (&mh-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
	(setq which (get-bboard-name))
	(&mh-read-folder which "" t-buffer-filename t-buffer-filename)
	(setq mh-annotate 0)
	(setq mh-writeable 0)
    )
)

(defun    
    (&mh-remove dot
	(if (= "+" (substr (current-buffer-name) 1 1))
	    (progn 
		   (beginning-of-line)
		   (save-excursion (&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 repl inc que 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 needs-checkpointing 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
	(&mh-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
	(&mh-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 0) (!= (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) 
					 'f')
				     (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
    )
)
; 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 "/user/reid/mh/cmds")
	(setq mh-lib "/user/reid/mh/support")
	(setq stack-trace-on-error 0)
	(startup)
    )

    ; Function to let mhe "make a buffer visible".
    ; This may later be redefined to customize this function.
    (&mh-pop-to-buffer
	(pop-to-buffer (arg 1))
    )
)

; Here is an alternate version for emacs with multiple windows.
;  This attempts to make mhe live in one window.
(if (is-bound default-window-selector)
    (progn 
	   (message "Restricting mhe to one window.") (sit-for 5)
	   (defun 
		  (&mh-pop-to-buffer old-dws
		      (setq old-dws default-window-selector)
		      (setq default-window-selector "")
		      (pop-to-buffer (arg 1))
		      (error-occured (setq window-lock 1))
		      (setq default-window-selector old-dws)
		  )
	   )
    )
)

    ;  MH Version 6 has a terrible bug if .mh_profile has no newline at end.
    (save-excursion
	(temp-use-buffer "mh-temp")
	(read-file mh-profile)
	(end-of-file)
	(if (!= (preceding-char) '\n')
	    (progn (insert-character '\n') (write-current-file)))
    )
    (delete-buffer "mh-temp")

    (&mh-determine-version)	; Needed before mh-cache is loaded.
    (load "mh-util.ml")
    (load "mh-shell.ml")
    (load "mh-cache.ml")
    (autoload "&mh-compose" "mh-comp.ml")
    (autoload "&mh-send" "mh-send.ml")
    (autoload "&mh-show" "mh-show.ml")
    (autoload "&mh-clean-header" "mh-show.ml")
    (autoload "&mh-list" "mh-list.ml")
    (autoload "&mh-edit" "mh-edit.ml")
    (autoload "&mh-repl" "mh-repl.ml")
    (autoload "&mh-resend" "mh-resend.ml")
    (autoload "&mh-inc" "mh-inc.ml")
    (autoload "&mh-check-queue" "mh-checkq.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 (error-occured (time))
	(progn (load "time")
	       (time)))

    (load "mh-mline.ml")
    (load "mh-keymap.ml")

    (error-occured (mh-user-configure))
    (novalue)

; 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 6 (August 1984) for 4.2 unix
;
;  Made mh-e.ml call (mh-user-configure) at the end, for user
;  customizations, such as setting print options.
;	Glenn Trewitt, WRL/NSL 27-Jan-92
; 
    (setq stack-trace-on-error 0)
    (declare-global		;*marks installation constants
	 mh-keymap-defined	; T iff keymap exists.
	 mh-folder		; string name, e.g. "inbox"
	 mh-profile		; "/mnt/reid/.mh_profile", or whatever
	 mh-path		; "/mnt/reid/Mail", or whatever
	 mh-remote		; "rsh <host> ", if spool dir is remote
	 mh-progs		;*"/usr/stanford/bin", or whatever
	 mh-lib			;*"/usr/stanford/lib/mh", or whatever
	 bboard-path		;*"/usr/spool/netnews", or whatever
	 mh-print-filter	;*"/pr", or whatever
	 mh-pspool-filter	;*"lpr", 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?
	 mh-screen-size		; how many lines are effectively on the
				; screen?
	 mh-width		; header file width
	 mh-has-mouse		; nonzero if we have a mouse
	 mh-version-6-or-later	; true if later version
	 ; the rest are set by &mh-determine-version
	 mh-msgnum-cols		; column where the message number starts,
	 mh-file-command	; command for filing messages
    )

    (argc)			; is this early enough, James?
    (setq mh-keymap-defined 0)
    (setq mhe-debug 0)
    (setq mh-profile (concat (getenv "HOME") "/.mh_profile"))
    (setq mh-version-6-or-later 1)	;  set by &mh-determine-version
    (setq mh-msgnum-cols (if mh-version-6-or-later 4 3)) ;  likewise
    (setq mh-file-command (if mh-version-6-or-later "refile" "filem"))
    (setq-default mh-annotate 1)
    (setq-default mh-writeable 1)
    (setq bboard-path "/usr/spool/mail")
    (setq mh-print-filter "enscript -2r")
    (setq mh-pspool-filter "")
    (setq mh-path "")
    (setq mh-remote "")
    (setq mh-progs
	  (if
	     (file-exists "/usr/bin/mh/inc") "/usr/bin/mh"
	     (file-exists "/usr/new/mh/inc") "/usr/new/mh"
	     (file-exists "local/bin/inc") "local/bin"
	     (error-message "Couldn't find mh programs!")
	  )
    )
    (setq mh-lib
	  (if
	     (file-exists "/usr/lib/mh/components") "/usr/lib/mh"
	     (file-exists "/usr/new/lib/mh/components") "/usr/new/lib/mh"
;	     (file-exists "/usr/stanford/lib/mh/components") "/usr/stanford/lib/mh"
	     (error-message "Couldn't find mh library!")
	  )
    )
    (setq mh-flist "")
    (setq-default right-margin 77)
    (setq-default mh-direction 1)
    (setq pop-up-windows 1)	; mhe requires popup windows!

    (delete-other-windows)
    (setq mh-screen-size (window-height))
    (setq mh-has-mouse 0)
    (if (is-bound mouse-exists)
	(if (!= mouse-exists 0)
	    (setq mh-has-mouse 1)
	)
    )

    (declare-buffer-specific
	mh-direction
	mh-buffer-filename
	mh-folder-title
	mh-annotate
	mh-writeable
    )
    
    ;  Create "window-priority" variable for emacs' that don't have it.
    (if (! (is-bound window-priority))
	(declare-global window-priority))

(defun
    (&mh-determine-version
	(temp-use-buffer "mh-temp")
	(setq needs-checkpointing 0)
	(erase-buffer)
	(set-mark)
	(fast-filter-region (concat mh-progs "/scan -help"))
	(beginning-of-file)
	(if (error-occured (re-search-forward "version: MH 6"))
	    (progn 		; old version
		(setq mh-version-6-or-later 0)
		(setq mh-msgnum-cols 3)
		(setq mh-file-command "filem")
		(setq mh-width ""))
	    (progn 		; new version
		(setq mh-version-6-or-later 1)
		(setq mh-msgnum-cols 4)
		(setq mh-file-command "refile")
		(setq mh-width
		      (concat " -width "
			      (if
				 (! (error-occured (terminal-width)))
					(terminal-width)
				 (! (error-occured (window-width)))
					(- (window-width) 1)
			 	 79
			      )
		      )
		))
	)
	(erase-buffer)
    )

    ; (mh "folder" "range")
    (mh folder range
	(temp-use-buffer "cmd-buffer") (erase-buffer)
	(setq needs-checkpointing 0)
	(find-path)		;  sets mh-path, mh-folder
	(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 (if (< (nargs) 2)
			""
			(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)
		      (&mh-pop-to-buffer (concat "+" mh-folder))
		      (setq window-priority 40)
		      (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 after the number in 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
	(&mh-pop-to-buffer (concat "+" mh-folder))
	(if (! mh-writeable)
	    (error-message "Sorry; this folder is read-only."))
	(beginning-of-line)
	(goto-character (+ (dot) mh-msgnum-cols))
	(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)
		   (&mh-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
	(setq which (get-bboard-name))
	(&mh-read-folder which "" t-buffer-filename t-buffer-filename)
	(setq mh-annotate 0)
	(setq mh-writeable 0)
    )
)

(defun    
    (&mh-remove dot
	(if (= "+" (substr (current-buffer-name) 1 1))
	    (progn 
		   (beginning-of-line)
		   (save-excursion (&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 repl inc que 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 needs-checkpointing 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
	(&mh-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
	(&mh-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 0) (!= (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) 
					 'f')
				     (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
    )
)
; 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 "/user/reid/mh/cmds")
	(setq mh-lib "/user/reid/mh/support")
	(setq stack-trace-on-error 0)
	(startup)
    )

    ; Function to let mhe "make a buffer visible".
    ; This may later be redefined to customize this function.
    (&mh-pop-to-buffer
	(pop-to-buffer (arg 1))
    )
)

; Here is an alternate version for emacs with multiple windows.
;  This attempts to make mhe live in one window.
(if (is-bound default-window-selector)
    (progn 
	   (message "Restricting mhe to one window.") (sit-for 5)
	   (defun 
		  (&mh-pop-to-buffer old-dws
		      (setq old-dws default-window-selector)
		      (setq default-window-selector "")
		      (pop-to-buffer (arg 1))
		      (error-occured (setq window-lock 1))
		      (setq default-window-selector old-dws)
		  )
	   )
    )
)

    ;  MH Version 6 has a terrible bug if .mh_profile has no newline at end.
    (save-excursion
	(temp-use-buffer "mh-temp")
	(read-file mh-profile)
	(end-of-file)
	(if (!= (preceding-char) '\n')
	    (progn (insert-character '\n') (write-current-file)))
    )
    (delete-buffer "mh-temp")

    (&mh-determine-version)	; Needed before mh-cache is loaded.
    (load "mh-util.ml")
    (load "mh-shell.ml")
    (load "mh-cache.ml")
    (autoload "&mh-compose" "mh-comp.ml")
    (autoload "&mh-send" "mh-send.ml")
    (autoload "&mh-show" "mh-show.ml")
    (autoload "&mh-clean-header" "mh-show.ml")
    (autoload "&mh-list" "mh-list.ml")
    (autoload "&mh-edit" "mh-edit.ml")
    (autoload "&mh-repl" "mh-repl.ml")
    (autoload "&mh-resend" "mh-resend.ml")
    (autoload "&mh-inc" "mh-inc.ml")
    (autoload "&mh-check-queue" "mh-checkq.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 (error-occured (time))
	(progn (load "time")
	       (time)))

    (load "mh-mline.ml")
    (load "mh-keymap.ml")

    (error-occured (mh-user-configure))
    (novalue)
