;;!emacs
;; $Id:
;;
;; FILE:         hinit.el
;; SUMMARY:      Standard initializations for Hyperbole hypertext system.
;; USAGE:        GNU Emacs Lisp Library
;;
;; AUTHOR:       Bob Weiner
;; ORG:          Brown U.
;;
;; ORIG-DATE:     1-Oct-91 at 02:32:51
;; LAST-MOD:     16-Oct-92 at 15:57:16 by Bob Weiner
;;
;; This file is part of Hyperbole.
;; 
;; Copyright (C) 1991, Brown University, Providence, RI
;; Developed with support from Motorola Inc.
;; 
;; Permission to use, modify and redistribute this software and its
;; documentation for any purpose other than its incorporation into a
;; commercial product is hereby granted without fee.  A distribution fee
;; may be charged with any redistribution.  Any distribution requires
;; that the above copyright notice appear in all copies, that both that
;; copyright notice and this permission notice appear in supporting
;; documentation, and that neither the name of Brown University nor the
;; author's name be used in advertising or publicity pertaining to
;; distribution of the software without specific, written prior permission.
;; 
;; Brown University makes no representations about the suitability of this
;; software for any purpose.  It is provided "as is" without express or
;; implied warranty.
;;
;;
;; DESCRIPTION:  
;; DESCRIP-END.

;;; ************************************************************************
;;; Public variables
;;; ************************************************************************

(defvar   hyperb:host-domain nil
  "<@domain-name> for current host.  Set automatically by 'hyperb:init'.")

;;; ************************************************************************
;;; Required Init functions
;;; ************************************************************************

(require 'set)

(defun var:append (var-symbol-name list-to-add)
  "Appends to value held by VAR-SYMBOL-NAME, LIST-TO-ADD.  Returns new value.
If VAR-SYMBOL-NAME is unbound, it is set to LIST-TO-ADD.
Often used to append to 'hook' variables."
  (let ((val))
    (if (and (boundp var-symbol-name)
	     (setq val (symbol-value var-symbol-name))
	     (or (if (symbolp val) (setq val (cons val nil)))
		 (listp val)))
	;; Don't add if list elts are already there.
	(if (memq nil (mapcar '(lambda (elt) (set:member elt val))
			      list-to-add))
	    (set-variable var-symbol-name
			  (if (eq (car val) 'lambda)
			      (apply 'list val list-to-add)
			    (append val list-to-add)))
	  val)
      (set-variable var-symbol-name list-to-add))))

(defun first-line-p ()
  "Returns true if point is on the first line of the buffer."
  (save-excursion (beginning-of-line) (bobp)))

(defun last-line-p ()
  "Returns true if point is on the last line of the buffer."
  (save-excursion (end-of-line) (eobp)))

;;; ************************************************************************
;;; Other required Elisp libraries
;;; ************************************************************************

(load "hversion")

(if (fboundp 'smart-menu)
    (mapcar 'makunbound '(smart-key-alist smart-key-mouse-alist)))
(mapcar 'require '(hui-mouse hypb hui-menus hbmap hibtypes))

;;; Hyperbole msg reader autoloads.
(autoload 'Rmail-init "hrmail" "Initializes Hyperbole Rmail support.")
(autoload 'Mh-init    "hmh"    "Initializes Hyperbole Mh support.")
(autoload 'Vm-init    "hvm"    "Initializes Hyperbole Vm support.")
(autoload 'Pm-init    "hpm"    "Initializes Hyperbole PIEmail support.")
(autoload 'Gnus-init  "hgnus"  "Initializes Hyperbole Gnus support.")

;;; Window configuration save and restore ring autoloads.
(setq features (set:remove 'wconfig features))
(autoload 'wconfig-ring-save  "wconfig"   "Save window-config to ring."  t)
(autoload 'wconfig-yank-pop   "wconfig"   "Pop window-config from ring." t)
(autoload 'wconfig-delete-pop "wconfig"   "Delete window-config from ring." t)

;;; ************************************************************************
;;; Public functions
;;; ************************************************************************

(defun hyperb:init ()
  "Standard configuration routine for Hyperbole."
  (interactive)
  (run-hooks 'hyperb:init-hook)
  (hyperb:check-dir-user)
  (or hyperb:host-domain (setq hyperb:host-domain (hypb:domain-name)))
  (hyperb:act-set)
  ;;
  ;; Highlight explicit buttons whenever a file is read in.
  ;;
  (if (or hyperb:epoch-p hyperb:lemacs-p)
      (var:append 'find-file-hooks '(ep:but-create)))
  ;;
  ;; Save button attribute file whenever same dir file is saved and
  ;; 'ebut:hattr-save' is non-nil.
  ;;
  (var:append 'write-file-hooks '(hattr:save))
)

(defun hyperb:act-set ()
  "COORDINATION IS NOT YET OPERATIONAL.  hui-coord.el IS NOT INCLUDED.
Sets Hyperbole action command to uncoordinated or coordinated operation.
Coordinated is used when 'hcoord:hosts' is a non-nil list.
See \"hui-coord.el\"."
  (interactive)
  (fset 'hyperb:act (if (and (boundp 'hcoord:hosts) hcoord:hosts)
		     'hcoord:act 'hbut:act)))

(defun hyperb:action-v1 ()
  "Signals error if Version 1 Hyperbole link button is selected."
  (error "(hyperb:action-v1): Hyperbole version 1 buttons are not supported."))

;;; ************************************************************************
;;; Private functions
;;; ************************************************************************

(defun hyperb:check-dir-user ()
  "Ensures 'hbmap:dir-user' exists and is writable or signals an error."
  (if (or (null hbmap:dir-user) (not (stringp hbmap:dir-user))
	  (and (setq hbmap:dir-user (file-name-as-directory
				     (expand-file-name hbmap:dir-user)))
	       (file-directory-p hbmap:dir-user)
	       (not (file-writable-p hbmap:dir-user))))
      (error
       "(hyperb:init): 'hbmap:dir-user' must be a writable directory name."))
  (let ((hbmap:dir-user (directory-file-name hbmap:dir-user)))
    (or (file-directory-p hbmap:dir-user)   ;; Exists and is writable.
	(let* ((parent-dir (file-name-directory
			    (directory-file-name hbmap:dir-user))))
	  (cond
	   ((not (file-directory-p parent-dir))
	    (error
	     "(hyperb:init): 'hbmap:dir-user' parent dir does not exist."))
	   ((not (file-writable-p parent-dir))
	    (error
	     "(hyperb:init): 'hbmap:dir-user' parent directory not writable."))
	   ((hypb:call-process-p "mkdir" nil nil hbmap:dir-user)
	    (or (file-writable-p hbmap:dir-user)
		(or (progn (hypb:chmod '+ 700 hbmap:dir-user)
			   (file-writable-p hbmap:dir-user))
		    (error "(hyperb:init): Can't write to 'hbmap:dir-user'.")
		    )))
	   (t (error "(hyperb:init): 'hbmap:dir-user' create failed."))))))
  t)

(provide 'hinit)

