Function: org-fold-core--fix-folded-region

org-fold-core--fix-folded-region is a byte-compiled function defined in org-fold-core.el.gz.

Signature

(org-fold-core--fix-folded-region FROM TO _)

Documentation

Process modifications in folded elements within FROM . TO region.

This function intended to be used as one of after-change-functions.

This function does nothing if text the only modification was changing text properties (for the sake of reducing overheads).

If a text was inserted into invisible region, hide the inserted text. If a text was inserted in front/back of the region, hide it according to :front-sticky/:rear-sticky folding spec property.

If the folded region is folded with a spec with non-nil :fragile property, unfold the region if the :fragile function returns non-nil.

Source Code

;; Defined in /usr/src/emacs/lisp/org/org-fold-core.el.gz
(defun org-fold-core--fix-folded-region (from to _)
  "Process modifications in folded elements within FROM . TO region.
This function intended to be used as one of `after-change-functions'.

This function does nothing if text the only modification was changing
text properties (for the sake of reducing overheads).

If a text was inserted into invisible region, hide the inserted text.
If a text was inserted in front/back of the region, hide it according
to :front-sticky/:rear-sticky folding spec property.

If the folded region is folded with a spec with non-nil :fragile
property, unfold the region if the :fragile function returns non-nil."
  ;; If no insertions or deletions in buffer, skip all the checks.
  (unless (or org-fold-core--ignore-modifications
              (eq org-fold-core--last-buffer-chars-modified-tick (buffer-chars-modified-tick))
              (memql 'ignore-modification-checks org-fold-core--optimise-for-huge-buffers))
    ;; Store the new buffer modification state.
    (setq org-fold-core--last-buffer-chars-modified-tick (buffer-chars-modified-tick))
    (save-match-data
      ;; Handle changes in all the indirect buffers and in the base
      ;; buffer.  Work around Emacs bug#46982.
      ;; Re-hide text inserted in the middle/front/back of a folded
      ;; region.
      (unless (or org-fold-core--suppress-folding-fix (equal from to)) ; Ignore deletions.
        (when (eq org-fold-core-style 'text-properties)
          (org-fold-core-cycle-over-indirect-buffers
	    (dolist (spec (org-fold-core-folding-spec-list))
              ;; Reveal fully invisible text inserted in the middle
              ;; of visible portion of the buffer.  This is needed,
              ;; for example, when there was a deletion in a folded
              ;; heading, the heading was unfolded, end `undo' was
              ;; called.  The `undo' would insert the folded text.
              (when (and (or (eq from (point-min))
                             (not (org-fold-core-folded-p (1- from) spec)))
                         (or (eq to (point-max))
                             (not (org-fold-core-folded-p to spec)))
                         (org-fold-core-region-folded-p from to spec))
                (org-fold-core-region from to nil spec))
              ;; Look around and fold the new text if the nearby folds are
              ;; sticky.
              (unless (org-fold-core-region-folded-p from to spec)
                (let ((spec-to (org-fold-core-get-folding-spec spec (min to (1- (point-max)))))
		      (spec-from (org-fold-core-get-folding-spec spec (max (point-min) (1- from)))))
                  ;; Reveal folds around undone deletion.
                  (when undo-in-progress
                    (let ((lregion (org-fold-core-get-region-at-point spec (max (point-min) (1- from))))
                          (rregion (org-fold-core-get-region-at-point spec (min to (1- (point-max))))))
                      (if (and lregion rregion)
                          (org-fold-core-region (car lregion) (cdr rregion) nil spec)
                        (when lregion
                          (org-fold-core-region (car lregion) (cdr lregion) nil spec))
                        (when rregion
                          (org-fold-core-region (car rregion) (cdr rregion) nil spec)))))
                  ;; Hide text inserted in the middle of a fold.
                  (when (and (or spec-from (eq from (point-min)))
                             (or spec-to (eq to (point-max)))
                             (or spec-from spec-to)
                             (eq spec-to spec-from)
                             (or (org-fold-core-get-folding-spec-property spec :front-sticky)
                                 (org-fold-core-get-folding-spec-property spec :rear-sticky)))
                    (unless (and (eq from (point-min)) (eq to (point-max))) ; Buffer content replaced.
                      (org-fold-core-region from to t (or spec-from spec-to))))
                  ;; Hide text inserted at the end of a fold.
                  (when (and spec-from (org-fold-core-get-folding-spec-property spec-from :rear-sticky))
                    (org-fold-core-region from to t spec-from))
                  ;; Hide text inserted in front of a fold.
                  (when (and spec-to
                             (not (eq to (point-max))) ; Text inserted at the end of buffer is not prepended anywhere.
                             (org-fold-core-get-folding-spec-property spec-to :front-sticky))
                    (org-fold-core-region from to t spec-to))))))))
      ;; Process all the folded text between `from' and `to'.  Do it
      ;; only in current buffer to avoid verifying semantic structure
      ;; multiple times in indirect buffers that have exactly same
      ;; text anyway.
      (unless (or org-fold-core--ignore-fragility-checks
                  (memql 'ignore-fragility-checks org-fold-core--optimise-for-huge-buffers))
        (dolist (func org-fold-core-extend-changed-region-functions)
          (let ((new-region (funcall func from to)))
            (setq from (car new-region))
            (setq to (cdr new-region))))
        (org-fold-core-cycle-over-indirect-buffers
          (dolist (spec (org-fold-core-folding-spec-list))
            ;; No action is needed when :fragile is nil for the spec.
            (when (org-fold-core-get-folding-spec-property spec :fragile)
              (org-with-wide-buffer
               ;; Expand the considered region to include partially present fold.
               ;; Note: It is important to do this inside loop over all
               ;; specs.  Otherwise, the region may be expanded to huge
               ;; outline fold, potentially involving majority of the
               ;; buffer.  That would cause the below code to loop over
               ;; almost all the folds in buffer, which would be too slow.
               (let ((local-from from)
                     (local-to to)
                     (region-from (org-fold-core-get-region-at-point spec (max (point-min) (1- from))))
                     (region-to (org-fold-core-get-region-at-point spec (min to (1- (point-max))))))
                 (when region-from (setq local-from (car region-from)))
                 (when region-to (setq local-to (cdr region-to)))
                 (let ((pos local-from))
                   ;; Move to the first hidden region.
                   (unless (org-fold-core-get-folding-spec spec pos)
                     (setq pos (org-fold-core-next-folding-state-change spec pos local-to)))
                   ;; Cycle over all the folds.
                   (while (< pos local-to)
                     (save-match-data ; we should not clobber match-data in after-change-functions
                       (let ((fold-begin (and (org-fold-core-get-folding-spec spec pos)
                                              pos))
                             (fold-end (org-fold-core-next-folding-state-change spec pos local-to)))
                         (when (and fold-begin fold-end)
                           (when (save-excursion
                                   (funcall (org-fold-core-get-folding-spec-property spec :fragile)
                                            (cons fold-begin fold-end)
                                            spec))
                             ;; Reveal completely, not just from the SPEC.
                             ;; Do it only after command is finished -
                             ;; some Emacs commands assume that
                             ;; visibility is not altered by `after-change-functions'.
                             (org-fold-core--region-delayed fold-begin fold-end nil)))))
                     ;; Move to next fold.
                     (setq pos (org-fold-core-next-folding-state-change spec pos local-to)))))))))))))