;;
;; pdb.el --- emacs lisp file for PDB major mode
;;
;; Copyright (c) 2000 Martyn Winn
;;
;; Author: Martyn Winn <m.d.winn@dl.ac.uk>
;;
;; For licensing purposes this program should be regarded as 
;; `Part i)' software of the CCP4 suite and its use is
;; governed by the licences to be found on the CCP4 site
;; (http://www.dl.ac.uk/CCP/CCP4/main.html).
;;
;; Version 0.1 May 2000
;;
;; Can be loaded in several ways:
;;    1) M-x load-file RET ~/cif.el
;;    2) Put the line (load "~/cif.el" t) in the .emacs file
;;
;; N.B. you may need following lines in .emacs to get colours:
;;
;; (global-font-lock-mode t) ;turn on Font Lock mode automatically in all modes
;; (setq font-lock-maximum-size nil) ;no buffer too large!
;;
;; Functionality:
;;   Components of PDB file coloured according to function
;;   

(defconst pdb-mode-version "version 0.1")

(defvar running-emacs20 (string-match "^2" emacs-version))

(cond (running-emacs20
  (progn
    (defgroup pdb nil
       "pdb-mode for Emacs"
       :group 'languages)

    (defgroup pdb-comment nil
       "Comment-handling variables in pdb-mode"
       :prefix "pdb-"
       :group 'pdb)
  )
))

; Activate pdb-mode for file endings .pdb

(setq auto-mode-alist (cons '("\\.pdb\\'" . pdb-mode) auto-mode-alist))

; Identify different records of PDB file

(defvar pdb-remark "^REMARK.*"
  "Regexp to match REMARK record in pdb file.")
(defvar pdb-scalex "^SCALE[123].*"
  "Regexp to match SCALEX record in pdb file.")
(defvar pdb-cryst "^CRYST1.*"
  "Regexp to match CRYST1 record in pdb file.")
(defvar pdb-atom "^ATOM  .*"
  "Regexp to match ATOM record in pdb file.")
(defvar pdb-hetatm "^HETATM.*"
  "Regexp to match HETATM record in pdb file.")
(defvar pdb-ter "^TER   .*"
  "Regexp to match TER record in pdb file.")
(defvar pdb-end "^END   .*"
  "Regexp to match END record in pdb file.")

; Tie components to particular faces
; Can't seem to be able to change standard faces via
;   font-lock or hilit, so set up explicit faces

(cond (running-emacs20
  (progn
    (defvar pdb-font-lock-remark-face  'pdb-font-lock-remark-face
      "Face name to use for remarks.")
    (defvar pdb-font-lock-cryscal-face  'pdb-font-lock-cryscal-face
      "Face name to use for CRYST1 and SCALEx cards.")
    (defvar pdb-font-lock-atomhet-face  'pdb-font-lock-atomhet-face
      "Face name to use for ATOM and HETATM cards.")
    (defvar pdb-font-lock-terend-face  'pdb-font-lock-terend-face
      "Face name to use for TER and END cards.")

    (defface pdb-font-lock-remark-face
      '((t (:foreground "Cyan")))
      "Font Lock mode face used to highlight remarks."
      :group 'font-lock-highlighting-faces)
    (defface pdb-font-lock-cryscal-face
      '((t (:foreground "Yellow")))
      "Font Lock mode face used to highlight CRYST1 and SCALEx cards."
      :group 'font-lock-highlighting-faces)
    (defface pdb-font-lock-atomhet-face
      '((t (:foreground "Green")))
      "Font Lock mode face used to highlight ATOM and HETATM cards."
      :group 'font-lock-highlighting-faces)
    (defface pdb-font-lock-terend-face
      '((t (:foreground "Red")))
      "Font Lock mode face used to highlight TER and END cards."
      :group 'font-lock-highlighting-faces)
  ))
  (t
  (progn
    (defvar pdb-font-lock-remark-face    'font-lock-remark-face
      "Face name to use for remarks.")
    (defvar pdb-font-lock-cryscal-face    'font-lock-keyword-face
      "Face name to use for CRYST1 and SCALEx cards.")
    (defvar pdb-font-lock-atomhet-face    'font-lock-variable-name-face
      "Face name to use for ATOM and HETATM cards.")
    (defvar pdb-font-lock-terend-face    'font-lock-keyword-face
      "Face name to use for TER and END cards.")
  ))
)

(defvar pdb-font-lock-defaults
  (list (cons pdb-remark 'pdb-font-lock-remark-face)
        (cons pdb-scalex 'pdb-font-lock-cryscal-face)
        (cons pdb-cryst 'pdb-font-lock-cryscal-face)
        (cons pdb-atom 'pdb-font-lock-atomhet-face)
        (cons pdb-hetatm 'pdb-font-lock-atomhet-face)
        (cons pdb-ter 'pdb-font-lock-terend-face)
        (cons pdb-end 'pdb-font-lock-terend-face))
  "doc")

(defvar pdb-columns
  "1        10        20        30        40        50        60        70        80\n\
\     |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |\n"
  "*String displayed above current line by \\[pdb-column-ruler].")

; Define keymap for pdb-mode
; map contains keybindings, menu-map contains pull-down menu

(defvar pdb-mode-map
  (let ((map (make-sparse-keymap))
	(menu-map (make-sparse-keymap "PDB")))
    (define-key map "\C-c\C-r" 'pdb-column-ruler)
    (define-key map [menu-bar insert] (cons "PDB" menu-map))
    (define-key menu-map [pdb-column-ruler]  
                  '("Temporary column ruler" . pdb-column-ruler))
    map)
  "Keymap used in pdb-mode.")


; Specify pdb-mode itself

(defun pdb-mode ()
  "Put some documentation here!"
  (interactive)
  (kill-all-local-variables)
  (use-local-map pdb-mode-map)

  (setq mode-name "PDB")
  (setq major-mode 'pdb-mode)

  (make-local-variable 'font-lock-defaults)
  (setq font-lock-defaults '(pdb-font-lock-defaults t))
  (make-local-variable 'pdb-columns))


(defun pdb-column-ruler ()
  "Inserts a column ruler momentarily above current line, till next keystroke.
The ruler is defined by the value of `pdb-columns'.
The key typed is executed unless it is SPC."
  (interactive)
  (momentary-string-display 
   pdb-columns 
   (save-excursion
     (beginning-of-line) 
     (if (eq (window-start (selected-window))
	     (window-point (selected-window)))
	 (progn (forward-line) (point))
       (point)))
   nil "Type SPC or any command to erase ruler."))
