;;!emacs
;; $Id:
;;
;; FILE:         hlvar.el
;; SUMMARY:      Permits use of Hyperbole variables in local variable lists.
;; USAGE:        GNU Emacs Lisp Library
;;
;; AUTHOR:       Bob Weiner
;; ORG:          Brown U.
;;
;; ORIG-DATE:     4-Nov-91 at 00:26:06
;; LAST-MOD:     24-Mar-93 at 20:21:19 by Bob Weiner
;;
;; This file is for use with Hyperbole.
;;
;; Copyright (C) 1985, 1986, 1987, 1990, 1991 Free Software Foundation, Inc.
;; Available for use and distribution under the same terms as GNU Emacs.
;;
;; This file is not part of GNU Emacs but the code here is a slight
;; variant of that found in "files.el" from GNU Emacs.
;;
;; DESCRIPTION:  
;;
;;   Hyperbole uses the colon character extensively in its variable names.
;;   The standard GNU Emacs syntax for local variable setting does not allow
;;   the use of this character, even though it is a valid symbol name
;;   character.  The code here is slightly modified to support local setting of
;;   variables with colons in their names.
;;
;;   Where the standard code allows: var:val
;    This code requires one use:     var: val  (where var may include colons)
;;
;;   So functionality is gained and none is lost, but a slight incompatibility
;;   in protocol is introduced.
;;
;; DESCRIP-END.

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

(defun hack-local-variables (&optional force)
  "Parse, and bind or evaluate as appropriate, any local variables
for current buffer."
  ;; Look for "Local variables" line in last page.
  (save-excursion
    (goto-char (point-max))
    (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
    (if (let ((case-fold-search t)
	      (ignore nil))
	  (and (search-forward "Local Variables\:" nil t)
	       (or (and (not (string-match "^19\\." emacs-version))
			(not inhibit-local-variables))
		   force
		   (if (string-match "^19\\." emacs-version)
		       (cond ((eq enable-local-variables t) t)
			     ((eq enable-local-variables nil)
			      (setq ignore t))))
		   (if ignore
		       nil
		     (save-window-excursion
		       (switch-to-buffer (current-buffer))
		       (save-excursion
			 (beginning-of-line)
			 (set-window-start (selected-window) (point)))
		       (y-or-n-p
			(format "Set local variables as specified at end of %s? "
				(file-name-nondirectory
				 buffer-file-name))))))))
	(let ((continue t)
	      prefix prefixlen suffix beg)
	  ;; The prefix is what comes before "local variables" in its line.
	  ;; The suffix is what comes after "local variables" in its line.
	  (skip-chars-forward " \t")
	  (or (eolp)
	      (setq suffix (buffer-substring (point)
					     (progn (end-of-line) (point)))))
	  (goto-char (match-beginning 0))
	  (or (bolp)
	      (setq prefix
		    (buffer-substring (point)
				      (progn (beginning-of-line) (point)))))
	  (if prefix (setq prefixlen (length prefix)
			   prefix (regexp-quote prefix)))
	  (if suffix (setq suffix (concat (regexp-quote suffix) "$")))
	  (while continue
	    ;; Look at next local variable spec.
	    (if selective-display (re-search-forward "[\n\C-m]")
	      (forward-line 1))
	    ;; Skip the prefix, if any.
	    (if prefix
		(if (looking-at prefix)
		    (forward-char prefixlen)
		  (error "Local variables entry is missing the prefix")))
	    ;; Find the variable name; strip whitespace.
	    (skip-chars-forward " \t")
	    (setq beg (point))
	    ;;
	    ;; RSW - changed following lines to allow colons in var names.
	    ;;
	    (skip-chars-forward "^ \t\n")
	    (skip-chars-backward ":")
	    (or (looking-at "[ \t]*:")
		(error "Missing colon in local variables entry"))
	    ;;
	    ;; RSW - end changes.
	    ;;
	    (let* ((str (buffer-substring beg (point)))
		   (var (read str))
		   val)
	      ;; Setting variable named "end" means end of list.
	      (if (string-equal (downcase str) "end")
		  (setq continue nil)
		;; Otherwise read the variable value.
		(skip-chars-forward "^:")
		(forward-char 1)
		(setq val (read (current-buffer)))
		(skip-chars-backward "\n")
		(skip-chars-forward " \t")
		(or (if suffix (looking-at suffix) (eolp))
		    (error "Local variables entry is terminated incorrectly"))
		;; Set the variable.  "Variables" mode and eval are funny.
		(cond ((eq var 'mode)
		       (funcall (intern (concat (downcase (symbol-name val))
						"-mode"))))
		      ((eq var 'eval)
		       (if (string= (user-login-name) "root")
			   (message
			    "Ignoring `eval:' in file's local variables")
			 (eval val)))
		      (t (make-local-variable var)
			 (set var val))))))))))

(provide 'hlvar)
