Function: c-before-change
c-before-change is a byte-compiled function defined in cc-mode.el.gz.
Signature
(c-before-change BEG END)
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/cc-mode.el.gz
(defun c-before-change (beg end)
;; Function to be put on `before-change-functions'. Primarily, this calls
;; the language dependent `c-get-state-before-change-functions'. It is
;; otherwise used only to remove stale entries from the `c-found-types'
;; cache, and to record entries which a `c-after-change' function might
;; confirm as stale.
;;
;; Note that this function must be FAST rather than accurate. Note
;; also that it only has any effect when font locking is enabled.
;; We exploit this by checking for font-lock-*-face instead of doing
;; rigorous syntactic analysis.
;; If either change boundary is wholly inside an identifier, delete
;; 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-called-from-text-property-change-p)
(c-with-string-fences
(save-restriction
(widen)
;; Clear the list of found types if we make a change at the start of the
;; buffer, to make it easier to get rid of misspelled types and
;; variables that have gotten recognized as types in malformed code.
(when (eq beg (point-min))
(c-clear-found-types))
(if c-just-done-before-change
;; We have two consecutive calls to `before-change-functions'
;; without an intervening `after-change-functions'. An example of
;; this is bug #38691. To protect CC Mode, assume that the entire
;; buffer has changed.
(setq beg (point-min)
end (point-max)
c-just-done-before-change 'whole-buffer)
(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)
(setq c-open-string-opener nil)
;; A workaround for syntax-ppss's failure to notice syntax-table text
;; property changes.
(when (fboundp 'syntax-ppss)
(setq c-syntax-table-hwm most-positive-fixnum))
(save-match-data
(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))
(c-invalidate-sws-region-before 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 lim-2
type type-pos
marked-id term-pos
(end1
(or (and (eq (get-text-property end 'face)
'font-lock-comment-face)
(c-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
;; Point is currently undefined. A `goto-char' somewhere is needed. (2020-12-06).
(setq lim-2 (c-determine-limit 1000 (point) ; that is wrong. FIXME!!! (2020-12-06)
))
(while
(and (/= (skip-chars-backward "^;{}" lim-2) 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
(c-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)
(setq lim-2 (c-determine-+ve-limit 1000))
(skip-chars-forward "^;{}" lim-2) ; 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 we're about to delete "typedef"s, clear the identifiers from
;; `c-found-types'.
(c-before-change-de-typedef beg end)
(if c-get-state-before-change-functions
(mapc (lambda (fn)
(funcall fn beg end))
c-get-state-before-change-functions))
(c-laomib-invalidate-cache beg end))))
(c-truncate-lit-pos/state-cache beg)
;; 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)
;; The following must happen after the previous, which likely alters
;; the macro cache.
(when c-opt-cpp-symbol
(c-invalidate-macro-cache beg end))
(setq c-no-bracelist-cache
(c-whack-state-after beg c-no-bracelist-cache)))))