Prefer ITREE_FOREACH over overlays_in

Use `ITREE_FOREACH` instead of `overlays_in` if that can save us from
allocating an array.

* src/buffer.c (overlays_in): Mark as static.
(mouse_face_overlay_overlaps): Use `ITREE_FOREACH` instead of `overlays_in`.
(disable_line_numbers_overlay_at_eob): Same, and also change return
value to a boolean.
* src/buffer.h (overlays_in): Don't declare.
* src/editfns.c (overlays_around): Delete function.
(Fget_pos_property): Use `ITREE_FOREACH` and keep the "best so far"
instead of using `overlays_in` and sorting the elements.

* src/lisp.h (disable_line_numbers_overlay_at_eob): Change return
type to a boolean.
* src/xdisp.c (should_produce_line_number): Adjust accordingly.
This commit is contained in:
Stefan Monnier 2024-02-05 17:58:47 -05:00
parent aedfb4f048
commit 10faaa3c91
5 changed files with 51 additions and 101 deletions

View file

@ -3002,7 +3002,7 @@ the normal hook `change-major-mode-hook'. */)
But still return the total number of overlays.
*/
ptrdiff_t
static ptrdiff_t
overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend,
Lisp_Object **vec_ptr, ptrdiff_t *len_ptr,
bool empty, bool trailing,
@ -3125,56 +3125,38 @@ mouse_face_overlay_overlaps (Lisp_Object overlay)
{
ptrdiff_t start = OVERLAY_START (overlay);
ptrdiff_t end = OVERLAY_END (overlay);
ptrdiff_t n, i, size;
Lisp_Object *v, tem;
Lisp_Object vbuf[10];
USE_SAFE_ALLOCA;
Lisp_Object tem;
struct itree_node *node;
size = ARRAYELTS (vbuf);
v = vbuf;
n = overlays_in (start, end, 0, &v, &size, true, false, NULL);
if (n > size)
ITREE_FOREACH (node, current_buffer->overlays,
start, min (end, ZV) + 1,
ASCENDING)
{
SAFE_NALLOCA (v, 1, n);
overlays_in (start, end, 0, &v, &n, true, false, NULL);
if (node->begin < end && node->end > start
&& node->begin < node->end
&& !EQ (node->data, overlay)
&& (tem = Foverlay_get (overlay, Qmouse_face),
!NILP (tem)))
return true;
}
for (i = 0; i < n; ++i)
if (!EQ (v[i], overlay)
&& (tem = Foverlay_get (overlay, Qmouse_face),
!NILP (tem)))
break;
SAFE_FREE ();
return i < n;
return false;
}
/* Return the value of the 'display-line-numbers-disable' property at
EOB, if there's an overlay at ZV with a non-nil value of that property. */
Lisp_Object
bool
disable_line_numbers_overlay_at_eob (void)
{
ptrdiff_t n, i, size;
Lisp_Object *v, tem = Qnil;
Lisp_Object vbuf[10];
USE_SAFE_ALLOCA;
Lisp_Object tem = Qnil;
struct itree_node *node;
size = ARRAYELTS (vbuf);
v = vbuf;
n = overlays_in (ZV, ZV, 0, &v, &size, false, false, NULL);
if (n > size)
ITREE_FOREACH (node, current_buffer->overlays, ZV, ZV, ASCENDING)
{
SAFE_NALLOCA (v, 1, n);
overlays_in (ZV, ZV, 0, &v, &n, false, false, NULL);
if ((tem = Foverlay_get (node->data, Qdisplay_line_numbers_disable),
!NILP (tem)))
return true;
}
for (i = 0; i < n; ++i)
if ((tem = Foverlay_get (v[i], Qdisplay_line_numbers_disable),
!NILP (tem)))
break;
SAFE_FREE ();
return tem;
return false;
}

View file

@ -1174,8 +1174,6 @@ extern void delete_all_overlays (struct buffer *);
extern void reset_buffer (struct buffer *);
extern void compact_buffer (struct buffer *);
extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *);
extern ptrdiff_t overlays_in (ptrdiff_t, ptrdiff_t, bool, Lisp_Object **,
ptrdiff_t *, bool, bool, ptrdiff_t *);
extern ptrdiff_t previous_overlay_change (ptrdiff_t);
extern ptrdiff_t next_overlay_change (ptrdiff_t);
extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *);

View file

@ -272,24 +272,6 @@ If you set the marker not to point anywhere, the buffer will have no mark. */)
}
/* Find all the overlays in the current buffer that touch position POS.
Return the number found, and store them in a vector in VEC
of length LEN.
Note: this can return overlays that do not touch POS. The caller
should filter these out. */
static ptrdiff_t
overlays_around (ptrdiff_t pos, Lisp_Object *vec, ptrdiff_t len)
{
/* Find all potentially rear-advance overlays at (POS - 1). Find
all overlays at POS, so end at (POS + 1). Find even empty
overlays, which due to the way 'overlays-in' works implies that
we might also fetch empty overlays starting at (POS + 1). */
return overlays_in (pos - 1, pos + 1, false, &vec, &len,
true, false, NULL);
}
DEFUN ("get-pos-property", Fget_pos_property, Sget_pos_property, 2, 3, 0,
doc: /* Return the value of POSITION's property PROP, in OBJECT.
Almost identical to `get-char-property' except for the following difference:
@ -315,53 +297,41 @@ at POSITION. */)
else
{
EMACS_INT posn = XFIXNUM (position);
ptrdiff_t noverlays;
Lisp_Object *overlay_vec, tem;
Lisp_Object tem;
struct buffer *obuf = current_buffer;
USE_SAFE_ALLOCA;
struct itree_node *node;
struct sortvec items[2];
struct sortvec *result = NULL;
struct buffer *b = XBUFFER (object);
Lisp_Object res = Qnil;
set_buffer_temp (XBUFFER (object));
set_buffer_temp (b);
/* First try with room for 40 overlays. */
Lisp_Object overlay_vecbuf[40];
noverlays = ARRAYELTS (overlay_vecbuf);
overlay_vec = overlay_vecbuf;
noverlays = overlays_around (posn, overlay_vec, noverlays);
/* If there are more than 40,
make enough space for all, and try again. */
if (ARRAYELTS (overlay_vecbuf) < noverlays)
ITREE_FOREACH (node, b->overlays, posn - 1, posn + 1, ASCENDING)
{
SAFE_ALLOCA_LISP (overlay_vec, noverlays);
noverlays = overlays_around (posn, overlay_vec, noverlays);
}
noverlays = sort_overlays (overlay_vec, noverlays, NULL);
Lisp_Object ol = node->data;
tem = Foverlay_get (ol, prop);
if (NILP (tem)
/* Check the overlay is indeed active at point. */
|| ((node->begin == posn
&& OVERLAY_FRONT_ADVANCE_P (ol))
|| (node->end == posn
&& ! OVERLAY_REAR_ADVANCE_P (ol))
|| node->begin > posn
|| node->end < posn))
/* The overlay will not cover a char inserted at point. */
continue;
struct sortvec *this = (result == items ? items + 1 : items);
if (NILP (res)
|| (make_sortvec_item (this, node->data),
compare_overlays (result, this) < 0))
res = tem;
}
set_buffer_temp (obuf);
/* Now check the overlays in order of decreasing priority. */
while (--noverlays >= 0)
{
Lisp_Object ol = overlay_vec[noverlays];
tem = Foverlay_get (ol, prop);
if (!NILP (tem))
{
/* Check the overlay is indeed active at point. */
if ((OVERLAY_START (ol) == posn
&& OVERLAY_FRONT_ADVANCE_P (ol))
|| (OVERLAY_END (ol) == posn
&& ! OVERLAY_REAR_ADVANCE_P (ol))
|| OVERLAY_START (ol) > posn
|| OVERLAY_END (ol) < posn)
; /* The overlay will not cover a char inserted at point. */
else
{
SAFE_FREE ();
return tem;
}
}
}
SAFE_FREE ();
if (!NILP (res))
return res;
{ /* Now check the text properties. */
int stickiness = text_property_stickiness (prop, position, object);

View file

@ -4802,7 +4802,7 @@ extern void syms_of_editfns (void);
/* Defined in buffer.c. */
extern bool mouse_face_overlay_overlaps (Lisp_Object);
extern Lisp_Object disable_line_numbers_overlay_at_eob (void);
extern bool disable_line_numbers_overlay_at_eob (void);
extern AVOID nsberror (Lisp_Object);
extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t, bool);
extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t);

View file

@ -25060,7 +25060,7 @@ should_produce_line_number (struct it *it)
because get-char-property always returns nil for ZV, except if
the property is in 'default-text-properties'. */
if (NILP (val) && IT_CHARPOS (*it) >= ZV)
val = disable_line_numbers_overlay_at_eob ();
return !disable_line_numbers_overlay_at_eob ();
return NILP (val) ? true : false;
}