;;; coldc-mode.el --- major mode for editing ColdC code

;; Copyright (C) 1997 Neale Pickett <zephyr@nmt.edu>

;; Modified: 24 February 1998 by Sleeper@LambdaMOO
;; Further hacking to bring it up to date with the latest cc-mode.el.
;;
;; Created: March 15, 1997
;; Version: 1.0
;; Time-stamp: <16 Mar 97 14:05:12 zephyr>
;; Keywords: coldc

;;    This program is free software; you can redistribute it and/or
;;    modify it under the terms of the GNU General Public License as
;;    published by the Free Software Foundation; either version 2 of the
;;    License, or (at your option) any later version.
;;
;;    This program is distributed in the hope that it will be useful,
;;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;    General Public License for more details.
;;
;;    You should have received a copy of the GNU General Public License
;;    along with this program; see the file COPYING.  If not, write to
;;    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;;    Boston, MA 02111-1307, USA.

;;; Commentary:

;; I pretty much ripped most of this out of the cc-mode.el that came
;; with my XEmacs distribution.  It works great for me, your mileage may
;; vary.
;;
;; Feel free to mail me (zephyr@nmt.edu) with comments/suggestions.  In
;; particular, I'd like to know if there's a way to fix my grody hack of
;; c-in-literal or a better way to set c-style-alist.
;;
;; To get this mode to work, put this file somewhere in your load-path,
;; and insert the following line in your .emacs:
;;
;; (autoload 'coldc-mode "coldc-mode" "ColdC-mode" t)
;;
;; you might also want to add ("\\.cdc$" . coldc-mode) to your
;; auto-mode-alist, or whatever extension you prefer.


(require 'cc-mode)
(c-initialize-cc-mode)

(defconst c-ColdC-conditional-key
  "\\b\\(for\\|if\\|do\\|else\\|while\\|switch\\|catch\\|with\\)\\b[^_]"
  "Regexp describing a conditional control for ColdC.")

(defconst coldc-font-lock-keywords
  '(("\\(for\\|in\\|if\\|to\\|else\\|while\\|switch\\|catch\\|with\\|var\\|arg\\|break\\|continue\\|return\\|any\\)[ \t\n]"
     . 1)

    ("^@program[ \t]+\\(\\(\\sw\\|[-_.]\\)+\\)"
     1 'font-lock-function-name-face)
    ("^\\(@\\(\\sw\\|[-_]\\)+\\)"
     1 'font-lock-preprocessor-face)
   
    ("case[ \t]+\\(\\(\\sw\\|\\s_\\)+\\):" . 1)
    ("\\<\\(default\\):" . 1)))


(defconst c-ColdC-method-key
  "^ @program"
  "Regexp describing a ColdC method intro.")

(setq coldc-mode-syntax-table nil)
;  "Syntax table used in coldc-mode buffers.")
(if coldc-mode-syntax-table
    ()
  (setq coldc-mode-syntax-table (make-syntax-table))
  (c-populate-syntax-table coldc-mode-syntax-table)
  ;; add extra comment syntax
  ;;; Default now ;(c-setup-dual-comments coldc-mode-syntax-table)
  ;; symbols
  (modify-syntax-entry ?\' "." coldc-mode-syntax-table)
  ;; comments
  (modify-syntax-entry ?/ ". 12" coldc-mode-syntax-table)
  (modify-syntax-entry ?\n "> a" coldc-mode-syntax-table)
  (modify-syntax-entry ?\^m "> a" coldc-mode-syntax-table)
  (modify-syntax-entry ?\* "." coldc-mode-syntax-table)
  )

(setq c-style-alist
      (append c-style-alist
	      '(("coldc"
		 (c-basic-offset . 4)
		 (c-offsets-alist . ((topmost-intro-cont . +)))
		 ))
	      ))

(defvar coldc-mode-abbrev-table nil
  "Abbrev table used in ColdC-mode buffers.")
(define-abbrev-table 'coldc-mode-abbrev-table ())

(defvar coldc-mode-map ()
  "Keymap used in ColdC-mode buffers.")
(if coldc-mode-map
    nil
  (setq coldc-mode-map (c-make-inherited-keymap))
  ;; add bindings which are only useful for ColdC
  )

(easy-menu-define c-coldc-menu coldc-mode-map "ColdC Mode Commands"
		  (c-mode-menu "ColdC"))

;; This is a nasty, evil, yukky kludge, but I can't find a better way to
;; do it.  Perhaps a more experienced elisp programmer can clean up how
;; I do this.  I've added an extra condition that checks for lines
;; beginning with "@" or lines containing only ".", which returns 'pound
;; iff we're in coldc-mode.
;;
;; Barf Gag Retch
;;
;; This is for all v19 Emacsen supporting either 1-bit or 8-bit syntax
(defun c-in-literal (&optional lim)
  ;; Determine if point is in a C++ literal. we cache the last point
  ;; calculated if the cache is enabled
  (if (and (boundp 'c-in-literal-cache)
	   c-in-literal-cache
	   (= (point) (aref c-in-literal-cache 0)))
      (aref c-in-literal-cache 1)
    (let ((rtn (save-excursion
		 (let* ((lim (or lim (c-point 'bod)))
			(here (point))
			(state (parse-partial-sexp lim (point))))
		   (cond
		    ((nth 3 state) 'string)
		    ((nth 4 state) (if (nth 7 state) 'c++ 'c))
		    ((progn
		       (goto-char here)
		       (beginning-of-line)
		       (looking-at "[ \t]*#"))
		     'pound)
		    ;; \begin{kludge}
		    ((and (eq major-mode 'coldc-mode)
			  (progn
			    (goto-char here)
			    (beginning-of-line)
			    (looking-at "@\\|\\.\n")))
		     'pound)
		    ;; \end{kludge}
		    (t nil))))))
      ;; cache this result if the cache is enabled
      (and (boundp 'c-in-literal-cache)
	   (setq c-in-literal-cache (vector (point) rtn)))
      rtn)))

(defun coldc-mode ()
  "Major mode for editing ColdC code.
Nasty hack of cc-mode.

To see what version of cc-mode you are running, enter `\\[c-version]'.

The hook variable `coldc-mode-hook' is run with no args, if that value
is bound and has a non-nil value.  Also the common hook
`c-mode-common-hook' is run first.

Key bindings:
\\{coldc-mode-map}"
  (interactive)
  (c-initialize-cc-mode)
  (kill-all-local-variables)
  (set-syntax-table coldc-mode-syntax-table)
  (setq major-mode 'coldc-mode
	mode-name "ColdC"
	local-abbrev-table coldc-mode-abbrev-table)
  (use-local-map coldc-mode-map)
  (c-common-init)
  (setq comment-start "// "
	comment-end ""
	c-conditional-key c-ColdC-conditional-key
	c-comment-start-regexp "//"
	parse-sexp-ignore-comments nil)
;;  (setq comment-start "// "
;; 	comment-end   ""
;; 	comment-multi-line nil
;; 	c-conditional-key c-ColdC-conditional-key
;; 	c-comment-start-regexp c-C++-comment-start-regexp
;;  	c-class-key c-ColdC-class-key
;;	c-method-key c-ColdC-method-key
;;	c-double-slash-is-comments-p t
;; 	c-baseclass-key nil
;; 	c-access-key c-ColdC-access-key)
  (c-set-style "ColdC")
  (run-hooks 'c-mode-common-hook)
  (run-hooks 'coldc-mode-hook)
  (c-update-modeline)
  (make-local-variable 'font-lock-defaults)
  (setq font-lock-defaults '(coldc-font-lock-keywords nil nil))
  (turn-on-font-lock))


(provide 'coldc-mode)
;;; coldc-mode.el ends here