]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-mode.el
Update docs for `customize-mode'
[gnu-emacs] / lisp / progmodes / cc-mode.el
index f84f4ae2c20079c8c415833861eaaa4f3307a9a6..738870b727ae802dbebd1069f5041a2c1bfb193a 100644 (file)
@@ -1,6 +1,6 @@
 ;;; cc-mode.el --- major mode for editing C and similar languages
 
-;; Copyright (C) 1985, 1987, 1992-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2016 Free Software Foundation, Inc.
 
 ;; Authors:    2003- Alan Mackenzie
 ;;             1998- Martin Stjernholm
 (cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs
 (cc-bytecomp-defun run-mode-hooks)     ; Emacs 21.1
 
-;; We set these variables during mode init, yet we don't require
+;; We set this variable during mode init, yet we don't require
 ;; font-lock.
 (cc-bytecomp-defvar font-lock-defaults)
-(cc-bytecomp-defvar font-lock-syntactic-keywords)
 
 ;; Menu support for both XEmacs and Emacs.  If you don't have easymenu
 ;; with your version of Emacs, you are incompatible!
@@ -479,7 +478,7 @@ preferably use the `c-mode-menu' language constant directly."
 and the line breaking/filling code.  Intended to be used by other
 packages that embed CC Mode.
 
-MODE is the CC Mode flavor to set up, e.g. 'c-mode or 'java-mode.
+MODE is the CC Mode flavor to set up, e.g. `c-mode' or `java-mode'.
 DEFAULT-STYLE tells which indentation style to install.  It has the
 same format as `c-default-style'.
 
@@ -511,6 +510,14 @@ that requires a literal mode spec at compile time."
   (set (make-local-variable 'comment-line-break-function)
        'c-indent-new-comment-line)
 
+  ;; Prevent time-wasting activity on C-y.
+  (when (boundp 'yank-handled-properties)
+    (make-local-variable 'yank-handled-properties)
+    (let ((yank-cat-handler (assq 'category yank-handled-properties)))
+      (when yank-cat-handler
+       (setq yank-handled-properties (remq yank-cat-handler
+                                           yank-handled-properties)))))
+
   ;; For the benefit of adaptive file, which otherwise mis-fills.
   (setq fill-paragraph-handle-comment nil)
 
@@ -624,8 +631,11 @@ that requires a literal mode spec at compile time."
     (font-lock-mode 1)))
 
 ;; Buffer local variables defining the region to be fontified by a font lock
-;; after-change function.  They are set in c-after-change to
-;; after-change-functions' BEG and END, and may be modified by functions in
+;; after-change function.  They are initialized in c-before-change to
+;; before-change-functions' BEG and END.  `c-new-END' is amended in
+;; c-after-change with after-change-functions' BEG, END, and OLD-LEN.  These
+;; variables may be modified by any before/after-change function, in
+;; particular by functions in `c-get-state-before-change-functions' and
 ;; `c-before-font-lock-functions'.
 (defvar c-new-BEG 0)
 (make-variable-buffer-local 'c-new-BEG)
@@ -639,7 +649,7 @@ In addition to the work done by `c-basic-common-init' and
 customary in CC Mode modes but which aren't strictly necessary for CC
 Mode to operate correctly.
 
-MODE is the symbol for the mode to initialize, like 'c-mode.  See
+MODE is the symbol for the mode to initialize, like `c-mode'.  See
 `c-basic-common-init' for details.  It's only optional to be
 compatible with old code; callers should always specify it."
 
@@ -659,13 +669,15 @@ compatible with old code; callers should always specify it."
     (setq c-new-BEG (point-min))
     (setq c-new-END (point-max))
     (save-excursion
-      (mapc (lambda (fn)
-             (funcall fn (point-min) (point-max)))
-           c-get-state-before-change-functions)
-      (mapc (lambda (fn)
-             (funcall fn (point-min) (point-max)
-                      (- (point-max) (point-min))))
-           c-before-font-lock-functions)))
+      (let (before-change-functions after-change-functions)
+       (mapc (lambda (fn)
+               (funcall fn (point-min) (point-max)))
+             c-get-state-before-change-functions)
+       (mapc (lambda (fn)
+               (if (not (eq fn 'c-restore-<>-properties))
+                   (funcall fn (point-min) (point-max)
+                            (- (point-max) (point-min)))))
+             c-before-font-lock-functions))))
 
   (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
   (set (make-local-variable 'outline-level) 'c-outline-level)
@@ -838,6 +850,18 @@ Note that the style variables are always made local to the buffer."
 (defvar c-old-EOM 0)
 (make-variable-buffer-local 'c-old-EOM)
 
+(defun c-called-from-text-property-change-p ()
+  ;; Is the primitive which invoked `before-change-functions' or
+  ;; `after-change-functions' one which merely changes text properties?  This
+  ;; function must be called directly from a member of one of the above hooks.
+  ;;
+  ;; In the following call, frame 0 is `backtrace-frame', frame 1 is
+  ;; `c-called-from-text-property-change-p', frame 2 is
+  ;; `c-before/after-change', frame 3 is the primitive invoking the change
+  ;; hook.
+  (memq (cadr (backtrace-frame 3))
+       '(put-text-property remove-list-of-text-properties)))
+
 (defun c-extend-region-for-CPP (beg end)
   ;; Set c-old-BOM or c-old-EOM respectively to BEG, END, each extended to the
   ;; beginning/end of any preprocessor construct they may be in.
@@ -972,7 +996,9 @@ Note that the style variables are always made local to the buffer."
        (unless
            (or (save-excursion
                  (goto-char (match-beginning 0))
-                 (c-beginning-of-macro))
+                 (let ((here (point)))
+                   (and (save-match-data (c-beginning-of-macro))
+                        (< (point) here))))
                (progn
                  (setq pps-state
                        (parse-partial-sexp pps-position (point) nil nil pps-state)
@@ -1006,9 +1032,12 @@ Note that the style variables are always made local to the buffer."
   ;; it/them from the cache.  Don't worry about being inside a string
   ;; or a comment - "wrongly" removing a symbol from `c-found-types'
   ;; isn't critical.
-  (unless c-just-done-before-change  ; Guard against a spurious second
-                             ; invocation of before-change-functions.
+  (unless (or (c-called-from-text-property-change-p)
+             c-just-done-before-change) ; guard against a spurious second
+                                       ; invocation of before-change-functions.
     (setq c-just-done-before-change t)
+    ;; (c-new-BEG c-new-END) will be the region to fontify.
+    (setq c-new-BEG beg  c-new-END end)
     (setq c-maybe-stale-found-type nil)
     (save-restriction
       (save-match-data
@@ -1074,10 +1103,9 @@ Note that the style variables are always made local to the buffer."
                              (buffer-substring-no-properties beg end)))))))
 
          (if c-get-state-before-change-functions
-             (let (open-paren-in-column-0-is-defun-start)
-               (mapc (lambda (fn)
-                       (funcall fn beg end))
-                     c-get-state-before-change-functions)))
+             (mapc (lambda (fn)
+                     (funcall fn beg end))
+                   c-get-state-before-change-functions))
          )))
     ;; The following must be done here rather than in `c-after-change' because
     ;; newly inserted parens would foul up the invalidation algorithm.
@@ -1102,57 +1130,60 @@ Note that the style variables are always made local to the buffer."
   ;; This calls the language variable c-before-font-lock-functions, if non nil.
   ;; This typically sets `syntax-table' properties.
 
-  (setq c-just-done-before-change nil)
-  (c-save-buffer-state (case-fold-search open-paren-in-column-0-is-defun-start)
-    ;; When `combine-after-change-calls' is used we might get calls
-    ;; with regions outside the current narrowing.  This has been
-    ;; observed in Emacs 20.7.
-    (save-restriction
-      (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)))
-
-       ;; C-y is capable of spuriously converting category properties
-       ;; c-</>-as-paren-syntax and c-cpp-delimiter into hard syntax-table
-       ;; properties.  Remove these when it happens.
-       (when (eval-when-compile (memq 'category-properties c-emacs-features))
-         (c-clear-char-property-with-value beg end 'syntax-table
-                                           c-<-as-paren-syntax)
-         (c-clear-char-property-with-value beg end 'syntax-table
-                                           c->-as-paren-syntax)
-         (c-clear-char-property-with-value beg end 'syntax-table nil))
-
-       (c-trim-found-types beg end old-len) ; maybe we don't need all of these.
-       (c-invalidate-sws-region-after beg end)
-       ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'.
-       (c-invalidate-find-decl-cache beg)
-
-       (when c-recognize-<>-arglists
-         (c-after-change-check-<>-operators beg end))
-
-       ;; (c-new-BEG c-new-END) will be the region to fontify.  It may become
-       ;; larger than (beg end).
-       (setq c-new-BEG beg
-             c-new-END end)
-       (setq c-in-after-change-fontification t)
-       (save-excursion
-         (mapc (lambda (fn)
-                 (funcall fn beg end old-len))
-               c-before-font-lock-functions))))))
-
-(defun c-set-fl-decl-start (pos)
+  ;; (c-new-BEG c-new-END) will be the region to fontify.  It may become
+  ;; larger than (beg end).
+  ;; (setq c-new-BEG beg  c-new-END end)
+  (setq c-new-END (- (+ c-new-END (- end beg)) old-len))
+
+  (unless (c-called-from-text-property-change-p)
+    (setq c-just-done-before-change nil)
+    (c-save-buffer-state (case-fold-search)
+      ;; When `combine-after-change-calls' is used we might get calls
+      ;; with regions outside the current narrowing.  This has been
+      ;; observed in Emacs 20.7.
+      (save-restriction
+       (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)))
+
+         ;; C-y is capable of spuriously converting category properties
+         ;; c-</>-as-paren-syntax and c-cpp-delimiter into hard syntax-table
+         ;; properties.  Remove these when it happens.
+         (when (eval-when-compile (memq 'category-properties c-emacs-features))
+           (c-save-buffer-state ()
+             (c-clear-char-property-with-value beg end 'syntax-table
+                                               c-<-as-paren-syntax)
+             (c-clear-char-property-with-value beg end 'syntax-table
+                                               c->-as-paren-syntax)
+             (c-clear-char-property-with-value beg end 'syntax-table nil)))
+
+         (c-trim-found-types beg end old-len) ; maybe we don't need all of these.
+         (c-invalidate-sws-region-after beg end)
+         ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'.
+         (c-invalidate-find-decl-cache beg)
+
+         (when c-recognize-<>-arglists
+           (c-after-change-check-<>-operators beg end))
+
+         (setq c-in-after-change-fontification t)
+         (save-excursion
+           (mapc (lambda (fn)
+                   (funcall fn beg end old-len))
+                 c-before-font-lock-functions)))))))
+
+(defun c-fl-decl-start (pos)
   ;; If the beginning of the line containing POS is in the middle of a "local"
   ;; declaration (i.e. one which does not start outside of braces enclosing
   ;; POS, such as a struct), return the beginning of that declaration.
-  ;; Otherwise return POS.  Note that declarations, in this sense, can be
+  ;; Otherwise return nil.  Note that declarations, in this sense, can be
   ;; nested.
   ;;
   ;; This function is called indirectly from font locking stuff - either from
@@ -1170,6 +1201,7 @@ Note that the style variables are always made local to the buffer."
        ;; Go to a less nested declaration each time round this loop.
        (and
         (eq (car (c-beginning-of-decl-1 bod-lim)) 'same)
+        (> (point) bod-lim)
         (progn (setq bo-decl (point))
                ;; Are we looking at a keyword such as "template" or
                ;; "typedef" which can decorate a type, or the type itself?
@@ -1189,56 +1221,100 @@ Note that the style variables are always made local to the buffer."
                              (1- (point)) 'syntax-table)
                             c-<-as-paren-syntax)))))
         (not (bobp)))
-      (backward-char))
-    new-pos))                          ; back over (, [, <.
-
-(defun c-change-set-fl-decl-start (_beg _end _old-len)
-  ;; Set c-new-BEG to the beginning of a "local" declaration if it('s BOL) is
-  ;; inside one.  This is called from an after-change-function, but the
-  ;; parameters BEG END and OLD-LEN are ignored.  See `c-set-fl-decl-start'
-  ;; for the detailed functionality.
-  (if font-lock-mode
-      (setq c-new-BEG (c-set-fl-decl-start c-new-BEG))))
-
-(defun c-context-set-fl-decl-start (beg end)
-  ;; Return a cons (NEW-BEG . END), where NEW-BEG is the beginning of a
-  ;; "local" declaration (BOL at) NEW is inside or BEG.  See
-  ;; `c-set-fl-decl-start' for the detailed functionality.
-  (cons (c-set-fl-decl-start beg) end))
+      (backward-char))                 ; back over (, [, <.
+    (and (/= new-pos pos) new-pos)))
+
+(defun c-change-expand-fl-region (beg end old-len)
+  ;; Expand the region (c-new-BEG c-new-END) to an after-change font-lock
+  ;; region.  This will usually be the smallest sequence of whole lines
+  ;; containing `c-new-BEG' and `c-new-END', but if `c-new-BEG' is in a
+  ;; "local" declaration (see `c-fl-decl-start') the beginning of this is used
+  ;; as the lower bound.
+  ;;
+  ;; This is called from an after-change-function, but the parameters BEG END
+  ;; and OLD-LEN are not used.
+   (if font-lock-mode
+       (setq c-new-BEG
+            (or (c-fl-decl-start c-new-BEG) (c-point 'bol c-new-BEG))
+            c-new-END (c-point 'bonl c-new-END))))
+
+(defun c-context-expand-fl-region (beg end)
+  ;; Return a cons (NEW-BEG . NEW-END), where NEW-BEG is the beginning of a
+  ;; "local" declaration containing BEG (see `c-fl-decl-start') or BOL BEG is
+  ;; in.  NEW-END is beginning of the line after the one END is in.
+  (cons (or (c-fl-decl-start beg) (c-point 'bol beg))
+       (c-point 'bonl end)))
+
+(defun c-before-context-fl-expand-region (beg end)
+  ;; Expand the region (BEG END) as specified by
+  ;; `c-before-context-fontification-functions'.  Return a cons of the bounds
+  ;; of the new region.
+  (save-restriction
+    (widen)
+    (save-excursion
+      (let ((new-beg beg) (new-end end)
+           (new-region (cons beg end)))
+       (mapc (lambda (fn)
+               (setq new-region (funcall fn new-beg new-end))
+               (setq new-beg (car new-region) new-end (cdr new-region)))
+             c-before-context-fontification-functions)
+       new-region))))
 
 (defun c-font-lock-fontify-region (beg end &optional verbose)
   ;; Effectively advice around `font-lock-fontify-region' which extends the
   ;; region (BEG END), for example, to avoid context fontification chopping
-  ;; off the start of the context.  Do not do anything if it's already been
-  ;; done (i.e. from an after-change fontification.  An example (C++) where
-  ;; this used to happen is this:
+  ;; off the start of the context.  Do not extend the region if it's already
+  ;; been done (i.e. from an after-change fontification.  An example (C++)
+  ;; where the chopping off used to happen is this:
   ;;
   ;;     template <typename T>
   ;;
   ;;
   ;;     void myfunc(T* p) {}
-  ;; 
+  ;;
   ;; Type a space in the first blank line, and the fontification of the next
   ;; line was fouled up by context fontification.
-  (let ((new-beg beg) (new-end end) new-region case-fold-search
-       open-paren-in-column-0-is-defun-start)
-    (if c-in-after-change-fontification
-       (setq c-in-after-change-fontification nil)
-      (save-restriction
-       (widen)
-       (save-excursion
-         (mapc (lambda (fn)
-                 (setq new-region (funcall fn new-beg new-end))
-                 (setq new-beg (car new-region)  new-end (cdr new-region)))
-               c-before-context-fontification-functions))))
+  (let (new-beg new-end new-region case-fold-search)
+    (if (and c-in-after-change-fontification
+            (< beg c-new-END) (> end c-new-BEG))
+       ;; Region and the latest after-change fontification region overlap.
+       ;; Determine the upper and lower bounds of our adjusted region
+       ;; separately.
+       (progn
+         (if (<= beg c-new-BEG)
+             (setq c-in-after-change-fontification nil))
+         (setq new-beg
+               (if (and (>= beg (c-point 'bol c-new-BEG))
+                        (<= beg c-new-BEG))
+                   ;; Either jit-lock has accepted `c-new-BEG', or has
+                   ;; (probably) extended the change region spuriously to
+                   ;; BOL, which position likely has a syntactically
+                   ;; different position.  To ensure correct fontification,
+                   ;; we start at `c-new-BEG', assuming any characters to the
+                   ;; left of `c-new-BEG' on the line do not require
+                   ;; fontification.
+                   c-new-BEG
+                 (setq new-region (c-before-context-fl-expand-region beg end)
+                       new-end (cdr new-region))
+                 (car new-region)))
+         (setq new-end
+               (if (and (>= end (c-point 'bol c-new-END))
+                        (<= end c-new-END))
+                   c-new-END
+                 (or new-end
+                     (cdr (c-before-context-fl-expand-region beg end))))))
+      ;; Context (etc.) fontification.
+      (setq new-region (c-before-context-fl-expand-region beg end)
+           new-beg (car new-region)  new-end (cdr new-region)))
     (funcall (default-value 'font-lock-fontify-region-function)
             new-beg new-end verbose)))
 
 (defun c-after-font-lock-init ()
   ;; Put on `font-lock-mode-hook'.  This function ensures our after-change
   ;; function will get executed before the font-lock one.
-  (remove-hook 'after-change-functions 'c-after-change t)
-  (add-hook 'after-change-functions 'c-after-change nil t))
+  (when (memq #'c-after-change after-change-functions)
+    (remove-hook 'after-change-functions #'c-after-change t)
+    (add-hook 'after-change-functions #'c-after-change nil t)))
 
 (defun c-font-lock-init ()
   "Set up the font-lock variables for using the font-lock support in CC Mode.
@@ -1260,12 +1336,13 @@ This function is called from `c-common-init', once per mode initialization."
           . c-mark-function)))
 
   ;; Prevent `font-lock-default-fontify-region' extending the region it will
-  ;; fontify to whole lines by removing `font-lock-extend-region-whole-lines'
-  ;; (and, coincidentally, `font-lock-extend-region-multiline' (which we do
-  ;; not need)) from `font-lock-extend-region-functions'.  (Emacs only).  This
-  ;; fixes Emacs bug #19669.
+  ;; fontify to whole lines by removing `font-lock-extend-region-wholelines'
+  ;; from `font-lock-extend-region-functions'.  (Emacs only).  This fixes
+  ;; Emacs bug #19669.
   (when (boundp 'font-lock-extend-region-functions)
-    (setq font-lock-extend-region-functions nil))
+    (setq font-lock-extend-region-functions
+         (delq 'font-lock-extend-region-wholelines
+               font-lock-extend-region-functions)))
 
   (make-local-variable 'font-lock-fontify-region-function)
   (setq font-lock-fontify-region-function 'c-font-lock-fontify-region)
@@ -1275,9 +1352,9 @@ This function is called from `c-common-init', once per mode initialization."
   (add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t))
 
 ;; Emacs 22 and later.
-(defun c-extend-after-change-region (_beg _end _old-len)
+(defun c-extend-after-change-region (beg end _old-len)
   "Extend the region to be fontified, if necessary."
-  ;; Note: the parameters are ignored here.  This somewhat indirect
+  ;; Note: the parameter OLD-LEN is ignored here.  This somewhat indirect
   ;; implementation exists because it is minimally different from the
   ;; stand-alone CC Mode which, lacking
   ;; font-lock-extend-after-change-region-function, is forced to use advice
@@ -1286,6 +1363,14 @@ This function is called from `c-common-init', once per mode initialization."
   ;; Of the seven CC Mode languages, currently (2009-05) only C, C++, Objc
   ;; (the languages with #define) and AWK Mode make non-null use of this
   ;; function.
+  (when (eq font-lock-support-mode 'jit-lock-mode)
+    (save-restriction
+      (widen)
+      (c-save-buffer-state () ; Protect the undo-list from put-text-property.
+       (if (< c-new-BEG beg)
+           (put-text-property c-new-BEG beg 'fontified nil))
+       (if (> c-new-END end)
+           (put-text-property end c-new-END 'fontified nil)))))
   (cons c-new-BEG c-new-END))
 
 ;; Emacs < 22 and XEmacs
@@ -1377,7 +1462,8 @@ This function is called from `c-common-init', once per mode initialization."
 
 ;;;###autoload
 (define-derived-mode c-mode prog-mode "C"
-  "Major mode for editing K&R and ANSI C code.
+  "Major mode for editing C code.
+
 To submit a problem report, enter `\\[c-submit-bug-report]' from a
 c-mode buffer.  This automatically sets up a mail buffer with version
 information already added.  You just need to add a description of the
@@ -1745,7 +1831,7 @@ Key bindings:
 ;; bug reporting
 
 (defconst c-mode-help-address
-  "bug-cc-mode@gnu.org"
+  "submit@debbugs.gnu.org"
   "Address(es) for CC Mode bug reports.")
 
 (defun c-version ()
@@ -1762,6 +1848,13 @@ Key bindings:
 (defvar reporter-prompt-for-summary-p)
 (defvar reporter-dont-compact-list)
 
+;; This could be "emacs,cc-mode" in the version included in Emacs.
+(defconst c-mode-bug-package "cc-mode"
+  "The package to use in the bug submission.")
+
+;; reporter-submit-bug-report requires sendmail.
+(declare-function mail-position-on-field "sendmail" (field &optional soft))
+
 (defun c-submit-bug-report ()
   "Submit via mail a bug report on CC Mode."
   (interactive)
@@ -1825,14 +1918,17 @@ Key bindings:
        vars)
       (lambda ()
        (run-hooks 'c-prepare-bug-report-hook)
+       (save-excursion
+         (or (mail-position-on-field "X-Debbugs-Package")
+             (insert c-mode-bug-package)))
        (insert (format "Buffer Style: %s\nc-emacs-features: %s\n"
                        style c-features)))))))
 
 \f
 (cc-provide 'cc-mode)
 
-;;; Local Variables:
-;;; indent-tabs-mode: t
-;;; tab-width: 8
-;;; End:
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
 ;;; cc-mode.el ends here