Function: combine-change-calls-1

combine-change-calls-1 is a byte-compiled function defined in subr.el.gz.

Signature

(combine-change-calls-1 BEG END BODY)

Documentation

Evaluate BODY, running the change hooks just once, for region (BEG END).

Firstly, before-change-functions is invoked for the region
(BEG END), then BODY (a function) is evaluated with
before-change-functions and after-change-functions bound to nil, then finally after-change-functions is invoked on the updated region (BEG NEW-END) with a calculated OLD-LEN argument. If inhibit-modification-hooks is initially non-nil, the change hooks are not run.

The result of combine-change-calls-1 is the value returned by BODY. BODY must not make a different buffer current, except temporarily. It must not make any changes to the buffer outside the specified region. It must not change before-change-functions or after-change-functions.

Additionally, the buffer modifications of BODY are recorded on the buffer's undo list as a single (apply ...) entry containing the function undo--wrap-and-run-primitive-undo.

Source Code

;; Defined in /usr/src/emacs/lisp/subr.el.gz
(defun combine-change-calls-1 (beg end body)
  "Evaluate BODY, running the change hooks just once, for region \(BEG END).

Firstly, `before-change-functions' is invoked for the region
\(BEG END), then BODY (a function) is evaluated with
`before-change-functions' and `after-change-functions' bound to
nil, then finally `after-change-functions' is invoked on the
updated region (BEG NEW-END) with a calculated OLD-LEN argument.
If `inhibit-modification-hooks' is initially non-nil, the change
hooks are not run.

The result of `combine-change-calls-1' is the value returned by
BODY.  BODY must not make a different buffer current, except
temporarily.  It must not make any changes to the buffer outside
the specified region.  It must not change
`before-change-functions' or `after-change-functions'.

Additionally, the buffer modifications of BODY are recorded on
the buffer's undo list as a single (apply ...) entry containing
the function `undo--wrap-and-run-primitive-undo'."
  (if (markerp beg) (setq beg (marker-position beg)))
  (if (markerp end) (setq end (marker-position end)))
  (let ((old-bul buffer-undo-list)
	(end-marker (copy-marker end t))
	result)
    (if undo--combining-change-calls
	(setq result (funcall body))
      (let ((undo--combining-change-calls t))
	(if (not inhibit-modification-hooks)
	    (run-hook-with-args 'before-change-functions beg end))
	(let ((bcf before-change-functions)
	      (acf after-change-functions)
	      (local-bcf (local-variable-p 'before-change-functions))
	      (local-acf (local-variable-p 'after-change-functions)))
	  (unwind-protect
              ;; FIXME: WIBNI we could just use `inhibit-modification-hooks'?
              (progn
                ;; Ugly Hack: if the body uses syntax-ppss/syntax-propertize
                ;; (e.g. via a regexp-search or sexp-movement triggering
                ;; on-the-fly syntax-propertize), make sure that this gets
                ;; properly refreshed after subsequent changes.
                (setq-local before-change-functions
                            (if (memq #'syntax-ppss-flush-cache bcf)
                                '(syntax-ppss-flush-cache)))
                (setq-local after-change-functions nil)
                (setq result (funcall body)))
	    (if local-bcf (setq before-change-functions bcf)
	      (kill-local-variable 'before-change-functions))
	    (if local-acf (setq after-change-functions acf)
	      (kill-local-variable 'after-change-functions))))
        (when (not (eq buffer-undo-list t))
          (let ((ap-elt
		 (list 'apply
		       (- end end-marker)
		       beg
		       (marker-position end-marker)
		       #'undo--wrap-and-run-primitive-undo
		       beg (marker-position end-marker) buffer-undo-list))
		(ptr buffer-undo-list))
	    (if (not (eq buffer-undo-list old-bul))
		(progn
		  (while (and (not (eq (cdr ptr) old-bul))
			      ;; In case garbage collection has removed OLD-BUL.
			      (cdr ptr))
		    (if (and (consp (cdr ptr))
			     (consp (cadr ptr))
			     (eq (caadr ptr) t))
			;; Don't include a timestamp entry.
			(setcdr ptr (cddr ptr))
		      (setq ptr (cdr ptr))))
		  (unless (or (cdr ptr) (null old-bul))
		    (message "combine-change-calls: buffer-undo-list presumably truncated by GC"))
		  (setcdr ptr nil)
		  (push ap-elt buffer-undo-list)
		  (setcdr buffer-undo-list old-bul)))))
	(if (not inhibit-modification-hooks)
	    (run-hook-with-args 'after-change-functions
				beg (marker-position end-marker)
				(- end beg)))))
    (set-marker end-marker nil)
    result))