summaryrefslogtreecommitdiff
path: root/lisp/progmodes/cc-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/cc-mode.el')
-rw-r--r--lisp/progmodes/cc-mode.el198
1 files changed, 123 insertions, 75 deletions
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index cb138d5f8b6..4b8e41f1c54 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -471,6 +471,14 @@ preferably use the `c-mode-menu' language constant directly."
(defvar c-maybe-stale-found-type nil)
(make-variable-buffer-local 'c-maybe-stale-found-type)
+(defvar c-just-done-before-change nil)
+(make-variable-buffer-local 'c-just-done-before-change)
+;; This variable is set to t by `c-before-change' and to nil by
+;; `c-after-change'. It is used to detect a spurious invocation of
+;; `before-change-functions' directly following on from a correct one. This
+;; happens in some Emacsen, for example when `basic-save-buffer' does (insert
+;; ?\n) when `require-final-newline' is non-nil.
+
(defun c-basic-common-init (mode default-style)
"Do the necessary initialization for the syntax handling routines
and the line breaking/filling code. Intended to be used by other
@@ -541,10 +549,11 @@ that requires a literal mode spec at compile time."
;; Use this in Emacs 21+ to avoid meddling with the rear-nonsticky
;; property on each character.
(when (boundp 'text-property-default-nonsticky)
+ (make-local-variable 'text-property-default-nonsticky)
(mapc (lambda (tprop)
(unless (assq tprop text-property-default-nonsticky)
- (set (make-local-variable 'text-property-default-nonsticky)
- (cons `(,tprop . t) text-property-default-nonsticky))))
+ (setq text-property-default-nonsticky
+ (cons `(,tprop . t) text-property-default-nonsticky))))
'(syntax-table category c-type)))
;; In Emacs 21 and later it's possible to turn off the ad-hoc
@@ -604,10 +613,12 @@ that requires a literal mode spec at compile time."
(make-local-hook 'before-change-functions)
(make-local-hook 'after-change-functions))
(add-hook 'before-change-functions 'c-before-change nil t)
+ (setq c-just-done-before-change nil)
(add-hook 'after-change-functions 'c-after-change nil t)
- (set (make-local-variable 'font-lock-extend-after-change-region-function)
- 'c-extend-after-change-region)) ; Currently (2009-05) used by all
- ; languages with #define (C, C++,; ObjC), and by AWK.
+ (when (boundp 'font-lock-extend-after-change-region-function)
+ (set (make-local-variable 'font-lock-extend-after-change-region-function)
+ 'c-extend-after-change-region))) ; Currently (2009-05) used by all
+ ; languages with #define (C, C++,; ObjC), and by AWK.
(defun c-setup-doc-comment-style ()
"Initialize the variables that depend on the value of `c-doc-comment-style'."
@@ -668,9 +679,11 @@ compatible with old code; callers should always specify it."
(or (c-cpp-define-name) (c-defun-name))))
(let ((rfn (assq mode c-require-final-newline)))
(when rfn
- (and (cdr rfn)
- (set (make-local-variable 'require-final-newline)
- mode-require-final-newline)))))
+ (if (boundp 'mode-require-final-newline)
+ (and (cdr rfn)
+ (set (make-local-variable 'require-final-newline)
+ mode-require-final-newline))
+ (set (make-local-variable 'require-final-newline) (cdr rfn))))))
(defun c-count-cfss (lv-alist)
;; LV-ALIST is an alist like `file-local-variables-alist'. Count how many
@@ -947,7 +960,11 @@ Note that the style variables are always made local to the buffer."
c-new-END (min (cdr new-bounds) (c-determine-+ve-limit 500 endd)))
;; Clear all old relevant properties.
(c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1))
- (c-clear-char-property-with-value c-new-BEG c-new-END 'category 'c-cpp-delimiter)
+
+ ;; CPP "comment" markers:
+ (if (eval-when-compile (memq 'category-properties c-emacs-features));Emacs.
+ (c-clear-char-property-with-value
+ c-new-BEG c-new-END 'category 'c-cpp-delimiter))
;; FIXME!!! What about the "<" and ">" category properties? 2009-11-16
;; Add needed properties to each CPP construct in the region.
@@ -966,8 +983,10 @@ Note that the style variables are always made local to the buffer."
(setq mbeg (point))
(if (> (c-syntactic-end-of-macro) mbeg)
(progn
- (c-neutralize-CPP-line mbeg (point))
- (c-set-cpp-delimiters mbeg (point)))
+ (c-neutralize-CPP-line mbeg (point)) ; "punctuation" properties
+ (if (eval-when-compile
+ (memq 'category-properties c-emacs-features)) ;Emacs.
+ (c-set-cpp-delimiters mbeg (point)))) ; "comment" markers
(forward-line)) ; no infinite loop with, e.g., "#//"
)))))
@@ -987,64 +1006,71 @@ 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.
- (setq c-maybe-stale-found-type nil)
- (save-restriction
- (save-match-data
- (widen)
- (save-excursion
- ;; Are we inserting/deleting stuff in the middle of an identifier?
- (c-unfind-enclosing-token beg)
- (c-unfind-enclosing-token end)
- ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"?
- (when (< beg end)
- (c-unfind-coalesced-tokens beg end))
- ;; Are we (potentially) disrupting the syntactic context which
- ;; makes a type a type? E.g. by inserting stuff after "foo" in
- ;; "foo bar;", or before "foo" in "typedef foo *bar;"?
- ;;
- ;; We search for appropriate c-type properties "near" the change.
- ;; First, find an appropriate boundary for this property search.
- (let (lim
- type type-pos
- marked-id term-pos
- (end1
- (or (and (eq (get-text-property end 'face) 'font-lock-comment-face)
- (previous-single-property-change end 'face))
- end)))
- (when (>= end1 beg) ; Don't hassle about changes entirely in comments.
- ;; Find a limit for the search for a `c-type' property
- (while
- (and (/= (skip-chars-backward "^;{}") 0)
- (> (point) (point-min))
- (memq (c-get-char-property (1- (point)) 'face)
- '(font-lock-comment-face font-lock-string-face))))
- (setq lim (max (point-min) (1- (point))))
-
- ;; Look for the latest `c-type' property before end1
- (when (and (> end1 (point-min))
- (setq type-pos
- (if (get-text-property (1- end1) 'c-type)
- end1
- (previous-single-property-change end1 'c-type nil lim))))
- (setq type (get-text-property (max (1- type-pos) lim) 'c-type))
-
- (when (memq type '(c-decl-id-start c-decl-type-start))
- ;; Get the identifier, if any, that the property is on.
- (goto-char (1- type-pos))
- (setq marked-id
- (when (looking-at "\\(\\sw\\|\\s_\\)")
- (c-beginning-of-current-token)
- (buffer-substring-no-properties (point) type-pos)))
-
- (goto-char end1)
- (skip-chars-forward "^;{}") ; FIXME!!! loop for comment, maybe
- (setq lim (point))
- (setq term-pos
- (or (next-single-property-change end 'c-type nil lim) lim))
- (setq c-maybe-stale-found-type
- (list type marked-id
- type-pos term-pos
- (buffer-substring-no-properties type-pos term-pos)
+ (unless c-just-done-before-change ; Guard against a spurious second
+ ; invocation of before-change-functions.
+ (setq c-just-done-before-change t)
+ (setq c-maybe-stale-found-type nil)
+ (save-restriction
+ (save-match-data
+ (widen)
+ (save-excursion
+ ;; Are we inserting/deleting stuff in the middle of an identifier?
+ (c-unfind-enclosing-token beg)
+ (c-unfind-enclosing-token end)
+ ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"?
+ (when (< beg end)
+ (c-unfind-coalesced-tokens beg end))
+ ;; Are we (potentially) disrupting the syntactic context which
+ ;; makes a type a type? E.g. by inserting stuff after "foo" in
+ ;; "foo bar;", or before "foo" in "typedef foo *bar;"?
+ ;;
+ ;; We search for appropriate c-type properties "near" the change.
+ ;; First, find an appropriate boundary for this property search.
+ (let (lim
+ type type-pos
+ marked-id term-pos
+ (end1
+ (or (and (eq (get-text-property end 'face)
+ 'font-lock-comment-face)
+ (previous-single-property-change end 'face))
+ end)))
+ (when (>= end1 beg) ; Don't hassle about changes entirely in comments.
+ ;; Find a limit for the search for a `c-type' property
+ (while
+ (and (/= (skip-chars-backward "^;{}") 0)
+ (> (point) (point-min))
+ (memq (c-get-char-property (1- (point)) 'face)
+ '(font-lock-comment-face font-lock-string-face))))
+ (setq lim (max (point-min) (1- (point))))
+
+ ;; Look for the latest `c-type' property before end1
+ (when (and (> end1 (point-min))
+ (setq type-pos
+ (if (get-text-property (1- end1) 'c-type)
+ end1
+ (previous-single-property-change end1 'c-type
+ nil lim))))
+ (setq type (get-text-property (max (1- type-pos) lim) 'c-type))
+
+ (when (memq type '(c-decl-id-start c-decl-type-start))
+ ;; Get the identifier, if any, that the property is on.
+ (goto-char (1- type-pos))
+ (setq marked-id
+ (when (looking-at "\\(\\sw\\|\\s_\\)")
+ (c-beginning-of-current-token)
+ (buffer-substring-no-properties (point) type-pos)))
+
+ (goto-char end1)
+ (skip-chars-forward "^;{}") ;FIXME!!! loop for comment, maybe
+ (setq lim (point))
+ (setq term-pos
+ (or (c-next-single-property-change end 'c-type nil lim)
+ lim))
+ (setq c-maybe-stale-found-type
+ (list type marked-id
+ type-pos term-pos
+ (buffer-substring-no-properties type-pos
+ term-pos)
(buffer-substring-no-properties beg end)))))))
(if c-get-state-before-change-functions
@@ -1055,7 +1081,7 @@ Note that the style variables are always made local to the buffer."
)))
;; The following must be done here rather than in `c-after-change' because
;; newly inserted parens would foul up the invalidation algorithm.
- (c-invalidate-state-cache beg))
+ (c-invalidate-state-cache beg)))
(defvar c-in-after-change-fontification nil)
(make-variable-buffer-local 'c-in-after-change-fontification)
@@ -1076,6 +1102,7 @@ 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
@@ -1096,11 +1123,12 @@ Note that the style variables are always made local to the buffer."
;; 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.
- (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)
+ (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)
@@ -1238,6 +1266,7 @@ This function is called from `c-common-init', once per mode initialization."
(make-local-hook 'font-lock-mode-hook))
(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)
"Extend the region to be fontified, if necessary."
;; Note: the parameters are ignored here. This somewhat indirect
@@ -1251,6 +1280,21 @@ This function is called from `c-common-init', once per mode initialization."
;; function.
(cons c-new-BEG c-new-END))
+;; Emacs < 22 and XEmacs
+(defmacro c-advise-fl-for-region (function)
+ `(defadvice ,function (before get-awk-region activate)
+ ;; Make sure that any string/regexp is completely font-locked.
+ (when c-buffer-is-cc-mode
+ (save-excursion
+ (ad-set-arg 1 c-new-END) ; end
+ (ad-set-arg 0 c-new-BEG))))) ; beg
+
+(unless (boundp 'font-lock-extend-after-change-region-function)
+ (c-advise-fl-for-region font-lock-after-change-function)
+ (c-advise-fl-for-region jit-lock-after-change)
+ (c-advise-fl-for-region lazy-lock-defer-rest-after-change)
+ (c-advise-fl-for-region lazy-lock-defer-line-after-change))
+
;; Connect up to `electric-indent-mode' (Emacs 24.4 and later).
(defun c-electric-indent-mode-hook ()
;; Emacs has en/disabled `electric-indent-mode'. Propagate this through to
@@ -1779,4 +1823,8 @@ Key bindings:
(cc-provide 'cc-mode)
+;;; Local Variables:
+;;; indent-tabs-mode: t
+;;; tab-width: 8
+;;; End:
;;; cc-mode.el ends here