* hl-line.el (hl-line): New face.
[bpt/emacs.git] / lisp / progmodes / cc-mode.el
index 3994fe5..eb5ae4b 100644 (file)
@@ -1,7 +1,7 @@
 ;;; cc-mode.el --- major mode for editing C and similar languages
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005, 2006
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005, 2006 Free Software
+;; Foundation, Inc.
 
 ;; Authors:    2003- Alan Mackenzie
 ;;             1998- Martin Stjernholm
 
 ;; Load cc-fonts first after font-lock is loaded, since it isn't
 ;; necessary until font locking is requested.
-(eval-after-load "font-lock"
-  '(require 'cc-fonts))
+; (eval-after-load "font-lock" ; 2006-07-09: font-lock is now preloaded.
+;   '
+(require 'cc-fonts) ;)
 
 ;; cc-langs isn't loaded when we're byte compiled, so add autoload
 ;; directives for the interface functions.
 (defun c-leave-cc-mode-mode ()
   (setq c-buffer-is-cc-mode nil))
 
+;; Make the `c-lang-setvar' variables buffer local in the current buffer.
+;; These are typically standard emacs variables such as `comment-start'.
+(defmacro c-make-emacs-variables-local ()
+  `(progn
+     ,@(mapcan (lambda (init)
+                `((make-local-variable ',(car init))))
+              (cdr c-emacs-variable-inits))))
+
 (defun c-init-language-vars-for (mode)
   "Initialize the language variables for one of the language modes
 directly supported by CC Mode.  This can be used instead of the
 `c-init-language-vars' macro if the language you want to use is one of
 those, rather than a derived language defined through the language
 variable system (see \"cc-langs.el\")."
+  (c-make-emacs-variables-local)
   (cond ((eq mode 'c-mode)    (c-init-language-vars c-mode))
        ((eq mode 'c++-mode)  (c-init-language-vars c++-mode))
        ((eq mode 'objc-mode) (c-init-language-vars objc-mode))
@@ -242,9 +252,9 @@ control).  See \"cc-mode.el\" for more info."
        (define-key c-mode-base-map (kbd "C-c C-<delete>")
          'c-hungry-delete-forward)
        (define-key c-mode-base-map (kbd "C-c C-<backspace>")
-         'c-hungry-backspace))
+         'c-hungry-delete-backwards))
     (define-key c-mode-base-map (kbd "C-c C-<delete>")
-      'c-hungry-backspace)
+      'c-hungry-delete-backwards)
     (define-key c-mode-base-map (kbd "C-c C-<backspace>")
       'c-hungry-delete-forward)))
 
@@ -304,10 +314,11 @@ control).  See \"cc-mode.el\" for more info."
   ;; `c-electric-backspace'.  The hungry variants are bound to the
   ;; same keys but prefixed with C-c.  This implies that C-c C-d is
   ;; `c-hungry-delete-forward'.  For consistency, we bind not only C-c
-  ;; <backspace> to `c-hungry-backspace' but also C-c C-<backspace>,
-  ;; so that the Ctrl key can be held down during the whole sequence
-  ;; regardless of the direction.  This in turn implies that we bind
-  ;; C-c C-<delete> to `c-hungry-delete-forward', for the same reason.
+  ;; <backspace> to `c-hungry-delete-backwards' but also
+  ;; C-c C-<backspace>, so that the Ctrl key can be held down during
+  ;; the whole sequence regardless of the direction.  This in turn
+  ;; implies that we bind C-c C-<delete> to `c-hungry-delete-forward',
+  ;; for the same reason.
 
   ;; Bind the electric deletion functions to C-d and DEL.  Emacs 21
   ;; automatically maps the [delete] and [backspace] keys to these two
@@ -316,8 +327,8 @@ control).  See \"cc-mode.el\" for more info."
   (define-key c-mode-base-map "\C-d" 'c-electric-delete-forward)
   (define-key c-mode-base-map "\177" 'c-electric-backspace)
   (define-key c-mode-base-map "\C-c\C-d"     'c-hungry-delete-forward)
-  (define-key c-mode-base-map [?\C-c ?\d]    'c-hungry-backspace)
-  (define-key c-mode-base-map [?\C-c ?\C-\d] 'c-hungry-backspace)
+  (define-key c-mode-base-map [?\C-c ?\d]    'c-hungry-delete-backwards)
+  (define-key c-mode-base-map [?\C-c ?\C-\d] 'c-hungry-delete-backwards)
   (define-key c-mode-base-map [?\C-c deletechar] 'c-hungry-delete-forward) ; C-c <delete> on a tty.
   (define-key c-mode-base-map [?\C-c (control deletechar)] ; C-c C-<delete> on a tty.
     'c-hungry-delete-forward)
@@ -339,8 +350,10 @@ control).  See \"cc-mode.el\" for more info."
     (define-key c-mode-base-map [backspace] 'c-electric-backspace)
     (define-key c-mode-base-map (kbd "C-c <delete>") 'c-hungry-delete)
     (define-key c-mode-base-map (kbd "C-c C-<delete>") 'c-hungry-delete)
-    (define-key c-mode-base-map (kbd "C-c <backspace>") 'c-hungry-backspace)
-    (define-key c-mode-base-map (kbd "C-c C-<backspace>") 'c-hungry-backspace))
+    (define-key c-mode-base-map (kbd "C-c <backspace>")
+      'c-hungry-delete-backwards)
+    (define-key c-mode-base-map (kbd "C-c C-<backspace>")
+      'c-hungry-delete-backwards))
 
   (define-key c-mode-base-map "#"         'c-electric-pound)
   (define-key c-mode-base-map "{"         'c-electric-brace)
@@ -414,23 +427,24 @@ preferably use the `c-mode-menu' language constant directly."
     ;; with regions outside the current narrowing.  This has been
     ;; observed in Emacs 20.7.
     (save-restriction
-      (widen)
+      (save-match-data           ; c-recognize-<>-arglists changes match-data
+       (widen)
 
-      (when (> end (point-max))
-       ;; Some emacsen might return positions past the end. This has been
-       ;; observed in Emacs 20.7 when rereading a buffer changed on disk
-       ;; (haven't been able to minimize it, but Emacs 21.3 appears to
-       ;; work).
-       (setq end (point-max))
-       (when (> beg end)
-         (setq beg end)))
+       (when (> end (point-max))
+         ;; Some emacsen might return positions past the end. This has been
+         ;; observed in Emacs 20.7 when rereading a buffer changed on disk
+         ;; (haven't been able to minimize it, but Emacs 21.3 appears to
+         ;; work).
+         (setq end (point-max))
+         (when (> beg end)
+           (setq beg end)))
 
-      (c-invalidate-sws-region-after beg end)
-      (c-invalidate-state-cache beg)
-      (c-invalidate-find-decl-cache beg)
+       (c-invalidate-sws-region-after beg end)
+       (c-invalidate-state-cache beg)
+       (c-invalidate-find-decl-cache beg)
 
-      (when c-recognize-<>-arglists
-       (c-after-change-check-<>-operators beg end)))))
+       (when c-recognize-<>-arglists
+         (c-after-change-check-<>-operators beg end))))))
 
 (defun c-basic-common-init (mode default-style)
   "Do the necessary initialization for the syntax handling routines
@@ -550,11 +564,12 @@ that requires a literal mode spec at compile time."
   (make-local-variable 'comment-indent-function)
   (setq comment-indent-function 'c-comment-indent)
 
-  ;; Put submode indicators onto minor-mode-alist, but only once.
-  (or (assq 'c-submode-indicators minor-mode-alist)
-      (setq minor-mode-alist
-           (cons '(c-submode-indicators c-submode-indicators)
-                 minor-mode-alist)))
+;;   ;; Put submode indicators onto minor-mode-alist, but only once.
+;;   (or (assq 'c-submode-indicators minor-mode-alist)
+;;       (setq minor-mode-alist
+;;         (cons '(c-submode-indicators c-submode-indicators)
+;;               minor-mode-alist)))
+  (c-update-modeline)
 
   ;; Install the functions that ensure that various internal caches
   ;; don't become invalid due to buffer changes.
@@ -629,6 +644,51 @@ compatible with old code; callers should always specify it."
       (and (cdr rfn)
           (setq require-final-newline mode-require-final-newline)))))
 
+(defun c-remove-any-local-eval-or-mode-variables ()
+  ;; If the buffer specifies `mode' or `eval' in its File Local Variable list
+  ;; or on the first line, remove all occurrences.  See
+  ;; `c-postprocess-file-styles' for justification.  There is no need to save
+  ;; point here, or even bother too much about the buffer contents.
+  ;;
+  ;; Most of the code here is derived from Emacs 21.3's `hack-local-variables'
+  ;; in files.el.
+  (goto-char (point-max))
+  (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
+  (let (lv-point (prefix "") (suffix ""))
+    (when (let ((case-fold-search t))
+           (search-forward "Local Variables:" nil t))
+      (setq lv-point (point))
+      ;; 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)))))
+
+      (while (search-forward-regexp
+             (concat "^[ \t]*"
+                     (regexp-quote prefix)
+                     "\\(mode\\|eval\\):.*"
+                     (regexp-quote suffix)
+                     "$")
+             nil t)
+       (beginning-of-line)
+       (kill-line 1)))
+
+    ;; Delete the first line, if we've got one, in case it contains a mode spec.
+    (unless (and lv-point
+                (progn (goto-char lv-point)
+                       (forward-line 0)
+                       (bobp)))
+      (goto-char (point-min))
+      (unless (eobp)
+       (kill-line 1)))))
+
 (defun c-postprocess-file-styles ()
   "Function that post processes relevant file local variables in CC Mode.
 Currently, this function simply applies any style and offset settings
@@ -656,12 +716,20 @@ Note that the style variables are always made local to the buffer."
     ;; overwritten this.  So we run `hack-local-variables' again to remedy
     ;; this.  There are no guarantees this will work properly, particularly as
     ;; we have no control over what the other hook functions on
-    ;; `hack-local-variables-hook' would have done, or what any "eval"
-    ;; expression will do when evaluated again.  C'est la vie!  ACM,
-    ;; 2005/11/2.
+    ;; `hack-local-variables-hook' would have done.  We now (2006/2/1) remove
+    ;; any `eval' or `mode' expressions before we evaluate again (see below).
+    ;; ACM, 2005/11/2.
+    ;;
+    ;; Problem (bug reported by Gustav Broberg): if one of the variables is
+    ;; `mode', this will invoke c-mode (etc.) again, setting up the style etc.
+    ;; We prevent this by temporarily removing `mode' from the Local Variables
+    ;; section.
     (if (or c-file-style c-file-offsets)
-       (let ((hack-local-variables-hook nil))
-         (hack-local-variables)))))
+       (c-tentative-buffer-changes
+         (let ((hack-local-variables-hook nil))
+           (c-remove-any-local-eval-or-mode-variables)
+           (hack-local-variables))
+         nil))))
 
 (add-hook 'hack-local-variables-hook 'c-postprocess-file-styles)