Matt Armstrong [Mon, 10 Oct 2022 15:48:41 +0000 (08:48 -0700)]
Improve check_subtree
* src/itree.c (struct check_subtree_result): new struct returned by
check_subtree.
(check_subtree): new function, renamed from recurse_check_tree. Add
new black height assertions.
(check_tree): assert that the tree has non-negative size, assert that
limiting to interval_tree_max_height(tree) levels is enough to
traverses the complete tree.
Stefan Monnier [Sun, 9 Oct 2022 23:45:26 +0000 (19:45 -0400)]
Tighten up handling of `otick`
Move args between `build_overlay` and `add_buffer_overlay`,
to try and keep buffer positions together with their buffer.
Be more strict in the `otick` values passed to `interval_tree_insert`.
Move a few things around to try and reduce dependencies through `.h` files.
Fix a thinko bug in `check_tree`.
* src/alloc.c (build_overlay): Remove `begin` and `end` args.
* src/buffer.c (add_buffer_overlay): Move from `buffer.h`.
Add `begin` and `end` args.
(copy_overlays): Adjust accordingly.
(Fmake_overlay): Use BUF_BEG and BUF_Z; adjust call to `build_overlay`
and `add_buffer_overlay`.
(Fmove_overlay): Use BUF_BEG and BUF_Z; Use the new `begin` and `end`
args of `add_buffer_overlay` so we don't need to use
`interval_node_set_region` when moving to a new buffer.
(remove_buffer_overlay, set_overlay_region): Move from `buffer.h`.
* src/buffer.h (set_overlay_region, add_buffer_overlay)
(remove_buffer_overlay): Move to `buffer.c`.
(build_overlay): Move from `lisp.h`.
(maybe_alloc_buffer_overlays): Delete function (inline into its only
caller).
* src/itree.c (interval_tree_insert): Move declaration `from buffer.h`.
(check_tree): Fix initial offset in call to `recurse_check_tree`.
Remove redundant check of the `limit` value.
(interval_node_init): Remove `begin` and `end` args.
(interval_tree_insert): Mark it as static.
Assert that the new node's `otick` should already be uptodate and its
new parent as well.
(itree_insert_node): New function.
(interval_tree_insert_gap): Assert the otick of the removed+added nodes
were uptodate and mark them as uptodate again after adjusting
their positions.
(interval_tree_inherit_offset): Check that the parent is at least as
uptodate as the child.
Stefan Monnier [Sun, 9 Oct 2022 04:56:24 +0000 (00:56 -0400)]
itree.c: Use `interval_tree_inherit_offset`
The insertion code tried to manipulate the offset in its own way,
and apparently there was a bug in it. Replace that with a call to
`interval_tree_inherit_offset`, making the whole logic a bit simpler,
and fixing a bug along the way (not sure where the bug was, to be honest).
* src/itree.c (interval_tree_insert): Use `interval_tree_inherit_offset`.
Check the tree before insert_fix.
(recurse_check_tree): Don't check RB invariants.
(itree_limits_are_stable): Delete function (subsumed by `check_tree`).
Stefan Monnier [Thu, 6 Oct 2022 03:52:01 +0000 (23:52 -0400)]
itree.c: Get rid of the trick using null->parent
* src/itree.c (interval_tree_remove_fix): Add a `parent` argument.
Change the loop so it always keeps both `node` and `parent` in sync,
thus avoiding the use of `node->parent` on the initial node (since
that one can be null).
(interval_tree_remove): Manually keep track of the `broken` node's
parent to pass it to `interval_tree_remove_fix`.
Stefan Monnier [Thu, 6 Oct 2022 02:55:54 +0000 (22:55 -0400)]
itree.c: Fix corner case errors in offsets
In some cases, `interval_tree_remove` could cause some nodes to
inherit fewer (or additional) offsets than the should because nodes
were transplanted between two parts of the tree where offsets had not
been propagated "equally". So we remove/apply all offsets along the
path between the two points of a transplant before doing the transplant.
* src/itree.c (interval_tree_subtree_min): Move before first use; delete
the declaration; add an `otick` argument, and use it to update offsets
along the way.
(interval_tree_remove): Update all offsets on the way from `node` to `min`.
Reorder some of the operations so that when we transplant `min` to `node`
those nodes are in the proper state where `interval_tree_transplant`
can do its sanity checks.
(itree_total_offset): New function.
(interval_tree_transplant): Use it to sanity check that improper
offsets aren't accidentally inherited/lost because of the transplant.
(itree_newlimit): New function.
(itree_limit_is_stable, interval_tree_update_limit)
(interval_tree_propagate_limit): Use it.
(null_is_sane): Remove `inline` annotation; it's not needed.
(interval_tree_inherit_offset): Sanity check that `offset` is 0 when
`otick` is uptodate. Skip the unneeded increments when the offset is 0.
(interval_tree_insert_fix): Add sanity check that we indeed have 2 reds.
Stefan Monnier [Wed, 5 Oct 2022 20:35:31 +0000 (16:35 -0400)]
itree.c: Fix incomplete update of `limit`s in corner cases
`interval_tree_remove` called `interval_tree_propagate_limit (subst)`
and `interval_tree_propagate_limit (min_right)` but both of those nodes
are moved without touching their subtrees, so their `limit`s are
"stable" causing `interval_tree_propagate_limit` to do nothing.
Indeed we don't need to update those nodes's `limit`s but we *do*
need to update their parents since those nodes have been moved.
Incidentally, this removes some uses of `null->parent` :-)
There are more uses of `null->parent`, tho, so I added more comments
explaining them (with the help of the matching section of the book
from which the algorithm was taken).
* src/itree.c (interval_tree_update_limit): Remove unused arg `tree`.
(interval_tree_rotate_left, interval_tree_rotate_right): Adjust callers.
(interval_tree_contains): Mark as static.
(itree_limit_is_stable, itree_limits_are_stable): New functions.
(interval_tree_remove): Fix incomplete update of `limit`s in corner
cases.
(interval_generator_next): Add sanity check to make sure the `limit`s
were properly updated.
Stefan Monnier [Wed, 5 Oct 2022 16:12:01 +0000 (12:12 -0400)]
itree.c: Clarify how the sentinel is used
* src/itree.c (null_is_sane): New function.
(interval_tree_iter_start): Use it to make sure we haven't garbled null.
(itree_init): Fully initialize `itree_null` here...
(interval_tree_clear): ...instead of here.
(interval_tree_propagate_limit): Remove special code that read NULL->parent.
(interval_tree_remove): Do it explicitly before the call in those two
places where it can happen.
Stefan Monnier [Sun, 2 Oct 2022 16:27:37 +0000 (12:27 -0400)]
itree: Use a single iterator object
Instead of having one iterator object per buffer, use just a single
global one. There is virtually no benefit to having per-buffer
iterators anyway: if two iterations can be active at the same time,
then there can be cases where those two iterations happen
to operate on the same buffer :-(
* src/itree.h (struct interval_tree): Remove `iter` field.
* src/itree.c (interval_generator_destroy)
(interval_tree_iter_ensure_space): Delete functions.
(iter): New global variable.
(init_itree_null): Rename to `itree_init` and adjust all callers.
Initialize `iter` as well.
(interval_tree_create, interval_tree_init):
Don't initialize `iter` field any more.
(interval_tree_destroy): Don't destroy `iter` field any more.
(interval_tree_insert): Don't bother growing the iterator (it's grown
in `interval_stack_push_flagged` if needed anyway, and in any case
there's no `iter` here to grow any more).
(interval_tree_remove): Tweak assertion to be more precise and
self-evident.
(interval_tree_iter_start): Use the global `iter`.
(interval_generator_create): Make it work with a NULL argument.
Stefan Monnier [Sun, 2 Oct 2022 16:21:13 +0000 (12:21 -0400)]
mark_overlays: Use the normal ITREE_FOREACH
This commit basically reverts commit 5b954f8f9. The problem of nested
iterations hasn't been fixed in the mean time, but since the GC can
run arbitrary ELisp code (via `post-gc-hook`), running the GC from
within an itree iteration is already unsafe anyway :-(
* src/alloc.c (mark_overlays): Delete function.
(mark_buffer): Use ITREE_FOREACH.
Stefan Monnier [Sun, 2 Oct 2022 15:11:57 +0000 (11:11 -0400)]
itree.c: Remove `tree` field from iterator
* src/itree.c (interval_generator_ensure_space, interval_generator_reset):
Inline and then delete functions.
(interval_tree_inherit_offset): Only take the tree's `otick` as arg.
Update all callers.
(struct interval_generator): Remove `tree` field, replace with a copy
of the tree's `otick`.
(interval_stack_push_flagged): The arg should be a real node.
(interval_tree_insert_gap): Prefer checking root==NULL rather than size==0.
Skip loop when tree is empty to avoid pushing&processing the NULL node.
(interval_tree_inherit_offset): Prefer parent==NULL rather than
node==root to avoid accessing the tree object.
* src/itree.c (interval_tree_contains, interval_tree_insert_gap):
Use the new ITREE_FOREACH macro.
(interval_tree_nodes): Delete function.
(interval_tree_iter_start): Return the iterator.
(interval_generator_next, interval_tree_destroy):
Don't accept a NULL arg any more.
* src/xdisp.c (load_overlay_strings, strings_with_newlines):
* src/textprop.c (get_char_property_and_overlay):
* src/buffer.c (copy_overlays, delete_all_overlays)
(set_overlays_multibyte, swap_buffer_overlays, overlays_in)
(next_overlay_change, previous_overlay_change, overlay_touches_p)
(overlay_strings, Foverlay_lists, report_overlay_modification)
(evaporate_overlays): Use the new ITREE_FOREACH macro.
* src/itree.c (struct interval_generator): New fields `running`,
`file`, and `line` moved from `interval_tree`.
(interval_stack_push_flagged): Adjust comment to resolve a FIXME.
(interval_tree_clear): Replace assignment with an a
(interval_tree_iter_next): Delete function.
(interval_tree_clear): Don't set `iter_running` here any more.
(interval_generator_create): Set it here instead.
(interval_tree_iter_start): Fetch `iter` once and for all.
(interval_generator_narrow): Mark it as non-static.
(interval_tree_iter_next, interval_tree_iter_narrow):
Delete functions. Inline their old bodies in the callers.
(interval_tree_iter_finish): Take the iter rather than
the whole tree. Adjust all callers.
(interval_generator_next): Move `running `assertion here from
`interval_tree_iter_next`.
* src/buffer.h: Adjust accordingly.
* src/itree.h (struct interval_tree): Remove fields `iter_running`,
`file`, and `line`, moved to `interval_generator`.
(interval_generator_narrow): Replace `interval_tree_iter_narrow`.
Stefan Monnier [Thu, 29 Sep 2022 21:12:21 +0000 (17:12 -0400)]
itree: Remove the `visited` flag from the tree nodes
These bits really belong in the "workstack" used within
`interval_generator_next`, so move them there.
* src/itree.c (nodeptr_and_flag): New type;
(struct interval_stack): Use it.
(make_nav, nav_nodeptr, nav_flag): New functions.
(interval_tree_insert_gap, interval_tree_delete_gap): Adjust accordingly.
(interval_generator_next): Stash the `visited` bit in the work stack
rather than inside the tree nodes.
(interval_stack_create, interval_stack_destroy, interval_stack_clear)
(interval_stack_ensure_space, interval_stack_push_flagged)
(interval_stack_push, interval_stack_pop): Move before first use.
Stefan Monnier [Wed, 28 Sep 2022 23:05:16 +0000 (19:05 -0400)]
itree.[ch]: Add sanity checks, comments, and minor tweaks
* src/alloc.c (mark_overlay): Add sanity check.
* src/buffer.c (next_overlay_change, previous_overlay_change):
Tweak code to keep the same vars for the bounds.
* src/itree.c (interval_tree_clear, interval_tree_insert)
(interval_tree_remove, interval_tree_insert_fix, interval_tree_remove_fix):
Adjust to the `color` -> `red` change.
(interval_tree_clear): Prefer `true/false` for booleans.
(interval_generator_create): Use an actual `interval_tree_order` value
rather than 0.
(interval_generator_next): Simplify a tiny bit. Add comment.
(interval_generator_narrow): Add sanity check.
* src/itree.h (struct interval_node): Replace `color` field with
boolean `red` field.
(enum interval_tree_order): Remove unused `ITREE_DEFLT_ORDER` value.
* src/pdumper.c (dump_interval_node): Adjust to the
`color` -> `red` change.
Add debugging help for nested iterators (nug#58144)
When starting an iteration, store __FILE__ and __LINE__ where this
happens in the interval_tree structure.
* src/buffer.h (buffer_overlay_iter_start): New macro adding __FILE
and __LINE__.
(buffer_overlay_iter_start1): Renamed from ..._start.
* src/itree.h (struct interval_tree): Add file and line info.
* src/itree.c: (interval_tree_contains, interval_tree_nodes,
interval_tree_insert_gap): Pass __FILE__ and __LINE__ to iter_start.
(interval_tree_iter_start): Record file and line info in tree.
* lisp/progmodes/hideshow.el
(hs-find-block-beginning-match): New function to be used in
`hs-already-hidden-p'.
(hs-already-hidden-p): Add check if beginning of line is inside a
block.
(hs-toggle-hiding): Don't change to selected-window's buffer when
event arg is absent.
* test/lisp/progmodes/hideshow-tests.el
(hideshow-tests-with-temp-buffer-selected): New helper macro.
(hideshow-tests-make-event-at): New helper function.
(hideshow-already-hidden-p-1): New test.
(hideshow-toggle-hiding-1): New test.
(hideshow-mouse-toggle-hiding-1): New test (bug#52092).
* lisp/emacs-lisp/nadvice.el:
* lisp/emacs-lisp/cl-generic.el: Don't push to
package--builtin-versions "manually", because loaddefs-gen does
this correctly now.
* lisp/vc/vc-svn.el (vc-exec-after):
* lisp/vc/vc-hg.el (vc-exec-after):
* lisp/vc/vc-git.el (vc-exec-after):
* lisp/vc/vc-cvs.el (vc-exec-after):
* lisp/vc/vc-bzr.el (vc-exec-after):
* lisp/org/org-macro.el (vc-exec-after):
* lisp/obsolete/vc-mtn.el (vc-exec-after):
* lisp/obsolete/vc-arch.el (vc-exec-after): Update declaration.
* lisp/vc/vc-dispatcher.el (vc--process-sentinel): Allow running
code only on success.
(vc-exec-after): Ditto.
(vc--inhibit-change-window-start): New variable.
(vc-do-async-command): Use it to allow chaining commands without
moving window point. Return the process instead of the buffer,
since the process may have exited already, and then we can't get
at the process.
* lisp/vc/vc-git.el (vc-git--pushpull): Return the process object.
(vc-git-pull-and-push): New function.
* lisp/vc/vc.el (vc-pull-and-push): New command (bug#51964).
Alan Mackenzie [Sat, 24 Sep 2022 12:23:32 +0000 (12:23 +0000)]
CC Mode. Make AWK Mode work with electric-pair-mode
Also fix some minor anomalies with other CC Mode modes in electric-pair-mode.
This fixes bug #53446.
* lisp/progmodes/cc-mode.el (c-open-string-opener): New buffer local
variable.
(c-after-change-mark-abnormal-strings): Set c-open-string-opener when an
unbalanced string is detected.
(c-before-change): Initilize c-open-string-opener to nil, each buffer change.
(c-electric-pair-inhibit-predicate): Use the value of c-open-string-opener to
flag an unbalaced string rather than trying to calculate it again.
* lisp/progmodes/cc-awk.el (c-awk-syntax-tablify-string): Set
c-open-string-opener when an unbalanced string is detected.
docview: Use svg images when using mupdf for conversion
* lisp/doc-view.el (doc-view-mupdf-use-svg, doc-view-svg-background)
(doc-view-svg-foreground): New user options.
(doc-view-insert-image): Add :background and :foreground image
attributes when display svg images.
(doc-view-set-up-single-converter): Produce svg images when using
mupdf (bug#58041).
Stefan Kangas [Sat, 24 Sep 2022 11:36:39 +0000 (13:36 +0200)]
image-dired: Fix C-a/C-e in thumbnail buffer
* lisp/image/image-dired.el
(image-dired--movement-ensure-point-pos): New function, and...
(image-dired--movement-command): ...new macros broken out from...
(image-dired-next-line, image-dired-previous-line)
(image-dired-beginning-of-buffer, image-dired-end-of-buffer):
...here.
(image-dired-move-beginning-of-line)
(image-dired-move-end-of-line): New commands.
(image-dired-thumbnail-mode-map): Remap 'move-beginning-of-line'
and 'move-beginning-of-line' to above new commands.
Stefan Kangas [Sat, 24 Sep 2022 11:08:11 +0000 (13:08 +0200)]
image-dired: Regenerate old thumbnails when needed
* lisp/image/image-dired.el
(image-dired--get-create-thumbnail-file): Rename from
'image-dired-get-thumbnail-image'. Update callers and make old
name into an obsolete alias.
(image-dired-display-thumbs): Use above function to simplify and
regenerate the thumbnail if it's outdated.
Stefan Kangas [Sat, 24 Sep 2022 10:44:11 +0000 (12:44 +0200)]
image-dired: Improve performance of marking commands
* lisp/image/image-dired.el (image-dired-thumbnail-storage): Mark
(image-dired--thumb-update-mark-at-point): New function.
(image-dired--thumb-update-marks):
(image-dired--do-mark-command): Use it.
(image-dired--thumb-update-marks): Rename from
'image-dired-thumb-update-marks'. Update all callers and make the
old name into an obsolete alias.
Stefan Kangas [Sat, 24 Sep 2022 09:49:46 +0000 (11:49 +0200)]
Add new macro image-dired--with-dired-buffer
* lisp/image/image-dired-util.el
(image-dired--with-dired-buffer): New macro.
* lisp/image/image-dired.el (image-dired-track-original-file)
(image-dired--on-file-in-dired-buffer)
(image-dired--do-mark-command)
(image-dired--on-file-in-dired-buffer)
(image-dired-jump-original-dired-buffer)
(image-dired-thumb-file-marked-p, image-dired-delete-marked):
Use above new macro to simplify and improve error handling.
(image-dired-show-all-from-dir): Simplify removing Dired marks.
(image-dired-thumb-update-marks): Avoid triggering above new error
handling.
Stefan Kangas [Sat, 24 Sep 2022 09:06:51 +0000 (11:06 +0200)]
Improve image-dired-thumbnail-display-external
* lisp/image/image-dired.el: (image-dired-external-viewer): Add more
image viewers and slightly re-arrange.
(image-dired-thumbnail-display-external): Correctly handle
external viewers with spaces or flags.
Po Lu [Sat, 24 Sep 2022 08:27:42 +0000 (16:27 +0800)]
Reduce complexity of scroll bar window protection code
It turns out my previous theories of why ClientMessages were
generated were wrong, and they are just generated so we can set
finish to X_EVENT_GOTO_OUT to have them delivered immediately.
This allows for the code to be simplified greatly, by not
unpacking pointers to the raw window into the client messages.
* src/xterm.c (x_unprotect_window_for_callback): Return the
window removed from the queue, or nil if none.
(x_scroll_bar_to_input_event)
(x_horizontal_scroll_bar_to_input_event): Use window provided by
x_unprotect_window_for_callback.
(handle_one_xevent): Pass dpyinfo to functions that need it.
(x_free_frame_resources): Remove "first scroll bar request"
code.
Augusto Stoffel [Sat, 17 Sep 2022 16:30:04 +0000 (18:30 +0200)]
New Flymake backend using the shellcheck program
See bug#57884.
* lisp/progmodes/sh-script.el: Require let-alist and subr-x when
compiling.
(sh--json-read): Helper function to deal with possible absence of
json-parse-buffer.
(sh-shellcheck-program, sh--shellcheck-process,
sh-shellcheck-flymake): Variables and function defining a Flymake
backend.
(sh-mode): Add it to 'flymake-diagnostic-functions'.
Sean Whitton [Fri, 23 Sep 2022 17:43:31 +0000 (10:43 -0700)]
vc-git--pushpull: Restore handling of vc-git-program
* lisp/vc/vc-git.el (vc-git--pushpull): Restore handling of
vc-git-program before recent change: respect a buffer-local value of
vc-git-program, and don't ignore user edits to the git program name
when PROMPT.
Stefan Kangas [Fri, 23 Sep 2022 21:12:10 +0000 (23:12 +0200)]
image-dired: Rewrite and extend slideshow feature
* lisp/image/image-dired.el
(image-dired--slideshow-start-timer)
(image-dired--slideshow-stop-timer)
(image-dired--slideshow-show-message): New functions.
(image-dired--slideshow-current-delay): New variable.
(image-dired--slideshow-initial): Delete variable.
(image-dired-slideshow-start): Simplify and ensure we display the
image at start.
* lisp/image/image-dired.el (image-dired--slideshow-stop): Add support
for pausing, and going backwards and forwards during slideshow.
Stefan Kangas [Fri, 23 Sep 2022 18:18:17 +0000 (20:18 +0200)]
image-dired: Mark two slideshow defuns as internal
* lisp/image/image-dired.el (image-dired--slideshow-step)
(image-dired--slideshow-stop): Rename from
'image-dired--slideshow-step' and 'image-dired--slideshow-stop'.
Update callers and make old names into obsolete aliases.
Stefan Monnier [Fri, 23 Sep 2022 20:36:16 +0000 (16:36 -0400)]
cconv.el: Fix interactive closure bug#51695
Make cconv.el detect when a closure's interactive form needs to
capture variables from the context and tweak the code accordingly
if so.
* lisp/emacs-lisp/cconv.el (cconv--interactive-form-funs): New var.
(cconv-convert): Handle the case where the interactive form captures
vars from the surrounding context. Remove left over handling of
`declare` which was already removed from the cconv-analyze` phase.
(cconv-analyze-form): Adjust analysis of interactive forms accordingly.
* lisp/emacs-lisp/oclosure.el (cconv--interactive-helper): New type and
function.
* lisp/simple.el (function-documentation, oclosure-interactive-form):
Add methods for it.
* test/lisp/emacs-lisp/cconv-tests.el
(cconv-tests-interactive-closure-bug51695): New test.
* lisp/image/image-crop.el (image-crop--crop-image-1): Darken the
selected region to make the bounding-box more noticable in images
which are mostly white (bug#58004).
Fix syntax check in python-info-looking-at-beginning-of-defun
* lisp/progmodes/python.el
(python-info-looking-at-beginning-of-defun): Check syntax after moving
to the beginning of line.
* test/lisp/progmodes/python-tests.el (python-nav-beginning-of-defun-6)
(python-end-of-defun-1, python-info-looking-at-beginning-of-defun-3):
New tests (bug#58023).
* test/src/eval-tests.el (eval-tests--exceed-specbind-limit)
(eval-exceed-specbind-with-signal-hook): Remove test that is
no longer useful, since there is no longer any specpdl limit
to overrun. (The test still passed but vacuously so, by
hitting the max-lisp-eval-depth limit instead.)
This silences an obsoletion warning.
Stefan Kangas [Fri, 23 Sep 2022 13:01:36 +0000 (15:01 +0200)]
Rename 'image-dired-db-file' to 'image-dired-tags-db-file'
* lisp/image/image-dired.el (image-dired-tags-db-file): Rename
from 'image-dired-db-file'. Update all uses and make old name
into an obsolete variable alias.
Po Lu [Fri, 23 Sep 2022 12:41:24 +0000 (20:41 +0800)]
Fix more toolkit scroll bar window protection issues
* src/xterm.c (handle_one_xevent): Ignore outdated scroll bar
events.
(x_free_frame_resources): Clear protected windows and invalidate
previous scroll bar events.
* src/xterm.h (struct x_display_info): New field
`first_valid_scroll_bar_req'.
Eli Zaretskii [Fri, 23 Sep 2022 06:36:24 +0000 (09:36 +0300)]
Support Noto Emoji font as fallback
The black-and-white emoji font is back under active development,
see https://github.com/googlefonts/noto-emoji. So this adds
that font as fallback for systems that don't have the capability
of using color fonts.
* lisp/international/fontset.el (setup-default-fontset): Support
black-and-white Noto Emoji font as fallback for Emoji display.