diff options
| author | Andreas Politz | 2017-02-07 17:56:50 +0100 |
|---|---|---|
| committer | Andreas Politz | 2017-10-04 22:32:26 +0200 |
| commit | 8d7bdfa3fca076b34aaf86548d3243bee11872ad (patch) | |
| tree | 419c7897f336ad206bb9e99824f35819ba9796c1 /src/buffer.h | |
| parent | f204e6e1a418073bd1e24a83947f1f3c53581c7f (diff) | |
| download | emacs-8d7bdfa3fca076b34aaf86548d3243bee11872ad.tar.gz emacs-8d7bdfa3fca076b34aaf86548d3243bee11872ad.zip | |
Provide a new tree data-structure for overlays.
* src/itree.c
(interval_generator_narrow, interval_generator_next)
(interval_node_init, interval_node_begin)
(interval_node_end, interval_node_set_region)
(interval_tree_create, interval_tree_clear)
(interval_tree_init, interval_tree_destroy)
(interval_tree_size, interval_tree_insert)
(interval_tree_contains, interval_tree_remove)
(interval_tree_validate, interval_tree_iter_start)
(interval_tree_iter_finish, interval_tree_iter_next)
(interval_tree_iter_ensure_space, interval_tree_max_height)
(interval_tree_insert_gap, interval_tree_delete_gap)
(interval_generator_create, interval_generator_reset)
(interval_generator_ensure_space, interval_node_intersects)
(interval_generator_next, interval_generator_narrow)
(interval_generator_destroy, interval_stack_create)
(interval_stack_destroy, interval_stack_clear)
(interval_stack_ensure_space, interval_stack_push)
(interval_stack_push_flagged, interval_stack_pop)
(interval_tree_update_limit, interval_tree_inherit_offset)
(interval_tree_propagate_limit, interval_tree_rotate_left)
(interval_tree_rotate_right, interval_tree_insert_fix)
(interval_tree_remove_fix, interval_tree_transplant)
(interval_tree_subtree_min): New file and new functions.
* src/itree.h: New file.
* configure.ac: Create Makefile for manual overlay tests.
* src/Makefile.in: Add itree.o target.
* src/alloc.c (build_overlay, mark_overlay, mark_buffer)
(sweep_misc, sweep_buffers): Adapt to new tree data-structure.
* src/buffer.c (overlays_in, overlays_at): Remove unused arguments
prev_ptr and change_req, adapt to new data-structure and reuse
code.
(copy_overlays, drop_overlays, delete_all_overlays)
(reset_buffer, kill-buffer, buffer-swap-text, next_overlay_change)
(previous_overlay_change, mouse_face_overlay_overlaps)
(disable_line_numbers_overlay_at_eob, overlay_touches_p)
(overlay_strings, adjust_overlays_for_insert)
(adjust_overlays_for_delete, overlayp, make-overlay, move-overlay)
(delete-overlay, overlay-start, overlay-end, overlay-buffer)
(overlay-properties, overlays-at, overlays-in)
(next-overlay-change, previous-overlay-change, overlay-put)
(overlay-get, report_overlay_modification, evaporate_overlays)
(init_buffer_once): Adapt to changes and tree data-structure.
(overlay-lists, overlay-recenter): Funtions are now obsolete, but
kept anyway.
(set_buffer_overlays_before, set_buffer_overlays_after)
(recenter_overlay_lists,fix_start_end_in_overlays,fix_overlays_before)
(unchain_overlay,): Removed functions of the old list
data-structure.
(swap_buffer_overlays, make_sortvec_item): New functions.
(sort_overlays): Adapt to changes and tree data-structure.
(sortvec): Moved to buffer.h .
(make_lispy_interval_node, overlay_tree, overlay-tree)
[ITREE_DEBUG]: New debugging functions.
* src/buffer.h (overlays_before, overlays_after): Removed struct
member of the list data-structure.
(overlays): Added tree struct member.
(sortvec): Moved here from buffer.c .
(GET_OVERLAYS_AT): Adapt to changes.
(set_buffer_intervals, OVERLAY_START, OVERLAY_END, OVERLAY_PLIST):
Adapt to tree data-structure.
(OVERLAY_POSITION): Removed macro of the list data-structure.
(OVERLAY_REAR_ADVANCE_P, OVERLAY_FRONT_ADVANCE_P): New macros.
(overlay_start, overlay_end)
(set_overlay_region, maybe_alloc_buffer_overlays)
(free_buffer_overlays, add_buffer_overlay)
(remove_buffer_overlay, buffer_overlay_iter_start)
(buffer_overlay_iter_next, buffer_overlay_iter_finish)
(buffer_overlay_iter_narrow): New functions.
(compare_overlays, make_sortvec_item): Export functions.
* src/editfns.c (overlays_around): Reuse overlays_in.
(get-pos-property): Adapt to tree data-structure.
(transpose-regions): Remove call to deleted function.
* src/fileio.c: (insert-file-contents): Remove
references to deleted struct member.
* src/fns.c (internal_equal): Adapt to tree data-structure.
* src/indent.c (check_display_width): Adapt to tree
data-structure.
(skip_invisible): Remove call to deleted function.
* src/insdel.c (adjust_markers_for_insert): Remove calls to
deleted functions.
* src/intervals.c (adjust_for_invis_intang): Adapt to tree
data-structure.
* src/keyboard.c (adjust_point_for_property): Adapt to tree
data-structure.
* src/lisp.h (Lisp_Overlay): Modified struct layout.
* src/print.c (temp_output_buffer_setup, print_object): Adapt to
tree data-structure.
* src/textprop.c (get_char_property_and_overlay): Adapt to tree
data-structure. Take advantage of the new data-structure.
* src/window.h (overlay_matches_window): New function.
* src/xdisp.h (next_overlay_change): Removed function. Use
next-overlay-change, which does not use xmalloc anymore.
(handle_single_display_spec, load_overlay_strings)
(back_to_previous_visible_line_start, note_mouse_highlight): Adapt
to tree data-structure.
(move_it_to, display_line): Remove calls to deleted functions.
* src/xfaces.c (face_at_buffer_position): Adapt to changes and
tree data-structure.
* test/src/buffer-tests.el: Many tests regarding overlays added.
* test/manual/noverlay/itree-tests.c: New file with tests of the
tree data-structure on the C level.
* test/manual/noverlay/Makefile.in: New file.
* test/manual/noverlay/check-sanitize.sh: New file.
* test/manual/noverlay/emacs-compat.h: New file.
* test/manual/noverlay/.gitignore: New file.
* test/manual/noverlay/overlay-perf.el: New file providing
performance tests.
* test/manual/noverlay/many-errors.h: New file.
Diffstat (limited to 'src/buffer.h')
| -rw-r--r-- | src/buffer.h | 161 |
1 files changed, 134 insertions, 27 deletions
diff --git a/src/buffer.h b/src/buffer.h index ac7c5a54679..ef31ad1ed9d 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -26,6 +26,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 26 | 26 | ||
| 27 | #include "character.h" | 27 | #include "character.h" |
| 28 | #include "lisp.h" | 28 | #include "lisp.h" |
| 29 | #include "itree.h" | ||
| 29 | 30 | ||
| 30 | INLINE_HEADER_BEGIN | 31 | INLINE_HEADER_BEGIN |
| 31 | 32 | ||
| @@ -877,16 +878,8 @@ struct buffer | |||
| 877 | /* Non-zero whenever the narrowing is changed in this buffer. */ | 878 | /* Non-zero whenever the narrowing is changed in this buffer. */ |
| 878 | bool_bf clip_changed : 1; | 879 | bool_bf clip_changed : 1; |
| 879 | 880 | ||
| 880 | /* List of overlays that end at or before the current center, | 881 | /* The inveral tree containing this buffer's overlays. */ |
| 881 | in order of end-position. */ | 882 | struct interval_tree *overlays; |
| 882 | struct Lisp_Overlay *overlays_before; | ||
| 883 | |||
| 884 | /* List of overlays that end after the current center, | ||
| 885 | in order of start-position. */ | ||
| 886 | struct Lisp_Overlay *overlays_after; | ||
| 887 | |||
| 888 | /* Position where the overlay lists are centered. */ | ||
| 889 | ptrdiff_t overlay_center; | ||
| 890 | 883 | ||
| 891 | /* Changes in the buffer are recorded here for undo, and t means | 884 | /* Changes in the buffer are recorded here for undo, and t means |
| 892 | don't record anything. This information belongs to the base | 885 | don't record anything. This information belongs to the base |
| @@ -896,6 +889,14 @@ struct buffer | |||
| 896 | Lisp_Object undo_list_; | 889 | Lisp_Object undo_list_; |
| 897 | }; | 890 | }; |
| 898 | 891 | ||
| 892 | struct sortvec | ||
| 893 | { | ||
| 894 | Lisp_Object overlay; | ||
| 895 | ptrdiff_t beg, end; | ||
| 896 | EMACS_INT priority; | ||
| 897 | EMACS_INT spriority; /* Secondary priority. */ | ||
| 898 | }; | ||
| 899 | |||
| 899 | INLINE bool | 900 | INLINE bool |
| 900 | BUFFERP (Lisp_Object a) | 901 | BUFFERP (Lisp_Object a) |
| 901 | { | 902 | { |
| @@ -1109,8 +1110,11 @@ extern void delete_all_overlays (struct buffer *); | |||
| 1109 | extern void reset_buffer (struct buffer *); | 1110 | extern void reset_buffer (struct buffer *); |
| 1110 | extern void compact_buffer (struct buffer *); | 1111 | extern void compact_buffer (struct buffer *); |
| 1111 | extern void evaporate_overlays (ptrdiff_t); | 1112 | extern void evaporate_overlays (ptrdiff_t); |
| 1112 | extern ptrdiff_t overlays_at (EMACS_INT, bool, Lisp_Object **, | 1113 | extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *); |
| 1113 | ptrdiff_t *, ptrdiff_t *, ptrdiff_t *, bool); | 1114 | extern ptrdiff_t overlays_in (ptrdiff_t, ptrdiff_t, bool, Lisp_Object **, |
| 1115 | ptrdiff_t *, bool, ptrdiff_t *); | ||
| 1116 | extern ptrdiff_t previous_overlay_change (ptrdiff_t); | ||
| 1117 | extern ptrdiff_t next_overlay_change (ptrdiff_t); | ||
| 1114 | extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *); | 1118 | extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *); |
| 1115 | extern void recenter_overlay_lists (struct buffer *, ptrdiff_t); | 1119 | extern void recenter_overlay_lists (struct buffer *, ptrdiff_t); |
| 1116 | extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **); | 1120 | extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **); |
| @@ -1162,18 +1166,16 @@ record_unwind_current_buffer (void) | |||
| 1162 | If NEXTP is non-NULL, return next overlay there. | 1166 | If NEXTP is non-NULL, return next overlay there. |
| 1163 | See overlay_at arg CHANGE_REQ for meaning of CHRQ arg. */ | 1167 | See overlay_at arg CHANGE_REQ for meaning of CHRQ arg. */ |
| 1164 | 1168 | ||
| 1165 | #define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq) \ | 1169 | #define GET_OVERLAYS_AT(posn, overlays, noverlays, next) \ |
| 1166 | do { \ | 1170 | do { \ |
| 1167 | ptrdiff_t maxlen = 40; \ | 1171 | ptrdiff_t maxlen = 40; \ |
| 1168 | SAFE_NALLOCA (overlays, 1, maxlen); \ | 1172 | SAFE_NALLOCA (overlays, 1, maxlen); \ |
| 1169 | (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, \ | 1173 | (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, next); \ |
| 1170 | nextp, NULL, chrq); \ | ||
| 1171 | if ((noverlays) > maxlen) \ | 1174 | if ((noverlays) > maxlen) \ |
| 1172 | { \ | 1175 | { \ |
| 1173 | maxlen = noverlays; \ | 1176 | maxlen = noverlays; \ |
| 1174 | SAFE_NALLOCA (overlays, 1, maxlen); \ | 1177 | SAFE_NALLOCA (overlays, 1, maxlen); \ |
| 1175 | (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, \ | 1178 | (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, next); \ |
| 1176 | nextp, NULL, chrq); \ | ||
| 1177 | } \ | 1179 | } \ |
| 1178 | } while (false) | 1180 | } while (false) |
| 1179 | 1181 | ||
| @@ -1208,7 +1210,8 @@ set_buffer_intervals (struct buffer *b, INTERVAL i) | |||
| 1208 | INLINE bool | 1210 | INLINE bool |
| 1209 | buffer_has_overlays (void) | 1211 | buffer_has_overlays (void) |
| 1210 | { | 1212 | { |
| 1211 | return current_buffer->overlays_before || current_buffer->overlays_after; | 1213 | return current_buffer->overlays |
| 1214 | && (interval_tree_size (current_buffer->overlays) > 0); | ||
| 1212 | } | 1215 | } |
| 1213 | 1216 | ||
| 1214 | /* Return character code of multi-byte form at byte position POS. If POS | 1217 | /* Return character code of multi-byte form at byte position POS. If POS |
| @@ -1248,23 +1251,124 @@ buffer_window_count (struct buffer *b) | |||
| 1248 | 1251 | ||
| 1249 | /* Overlays */ | 1252 | /* Overlays */ |
| 1250 | 1253 | ||
| 1251 | /* Return the marker that stands for where OV starts in the buffer. */ | 1254 | INLINE ptrdiff_t |
| 1255 | overlay_start (struct Lisp_Overlay *ov) | ||
| 1256 | { | ||
| 1257 | if (! ov->buffer) | ||
| 1258 | return -1; | ||
| 1259 | return interval_node_begin (ov->buffer->overlays, ov->interval); | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | INLINE ptrdiff_t | ||
| 1263 | overlay_end (struct Lisp_Overlay *ov) | ||
| 1264 | { | ||
| 1265 | if (! ov->buffer) | ||
| 1266 | return -1; | ||
| 1267 | return interval_node_end (ov->buffer->overlays, ov->interval); | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | INLINE void | ||
| 1271 | set_overlay_region (struct Lisp_Overlay *ov, ptrdiff_t begin, ptrdiff_t end) | ||
| 1272 | { | ||
| 1273 | eassert (ov->buffer); | ||
| 1274 | begin = clip_to_bounds (BEG, begin, ov->buffer->text->z); | ||
| 1275 | end = clip_to_bounds (begin, end, ov->buffer->text->z); | ||
| 1276 | interval_node_set_region (ov->buffer->overlays, ov->interval, begin, end); | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | INLINE void | ||
| 1280 | maybe_alloc_buffer_overlays (struct buffer *b) | ||
| 1281 | { | ||
| 1282 | if (! b->overlays) | ||
| 1283 | b->overlays = interval_tree_create (); | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | /* FIXME: Actually this does not free any overlay, but the tree | ||
| 1287 | only. --ap */ | ||
| 1288 | |||
| 1289 | INLINE void | ||
| 1290 | free_buffer_overlays (struct buffer *b) | ||
| 1291 | { | ||
| 1292 | eassert (! b->overlays || 0 == interval_tree_size (b->overlays)); | ||
| 1293 | if (b->overlays) | ||
| 1294 | { | ||
| 1295 | interval_tree_destroy (b->overlays); | ||
| 1296 | b->overlays = NULL; | ||
| 1297 | } | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | INLINE void | ||
| 1301 | add_buffer_overlay (struct buffer *b, struct Lisp_Overlay *ov) | ||
| 1302 | { | ||
| 1303 | eassert (! ov->buffer); | ||
| 1304 | maybe_alloc_buffer_overlays (b); | ||
| 1305 | ov->buffer = b; | ||
| 1306 | interval_tree_insert (b->overlays, ov->interval); | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | INLINE void | ||
| 1310 | remove_buffer_overlay (struct buffer *b, struct Lisp_Overlay *ov) | ||
| 1311 | { | ||
| 1312 | eassert (b->overlays); | ||
| 1313 | eassert (ov->buffer == b); | ||
| 1314 | interval_tree_remove (ov->buffer->overlays, ov->interval); | ||
| 1315 | ov->buffer = NULL; | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | INLINE void | ||
| 1319 | buffer_overlay_iter_start (struct buffer *b, ptrdiff_t begin, ptrdiff_t end, | ||
| 1320 | enum interval_tree_order order) | ||
| 1321 | { | ||
| 1322 | if (b->overlays) | ||
| 1323 | interval_tree_iter_start (b->overlays, begin, end, order); | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | INLINE struct interval_node* | ||
| 1327 | buffer_overlay_iter_next (struct buffer *b) | ||
| 1328 | { | ||
| 1329 | if (! b->overlays) | ||
| 1330 | return NULL; | ||
| 1331 | return interval_tree_iter_next (b->overlays); | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | INLINE void | ||
| 1335 | buffer_overlay_iter_finish (struct buffer *b) | ||
| 1336 | { | ||
| 1337 | if (b->overlays) | ||
| 1338 | interval_tree_iter_finish (b->overlays); | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | INLINE void | ||
| 1342 | buffer_overlay_iter_narrow (struct buffer *b, ptrdiff_t begin, ptrdiff_t end) | ||
| 1343 | { | ||
| 1344 | if (b->overlays) | ||
| 1345 | interval_tree_iter_narrow (b->overlays, begin, end); | ||
| 1346 | } | ||
| 1252 | 1347 | ||
| 1253 | #define OVERLAY_START(OV) XOVERLAY (OV)->start | 1348 | /* Return the start of OV in its buffer, or -1 if OV is not associated |
| 1349 | with any buffer. */ | ||
| 1254 | 1350 | ||
| 1255 | /* Return the marker that stands for where OV ends in the buffer. */ | 1351 | #define OVERLAY_START(OV) (overlay_start (XOVERLAY (OV))) |
| 1256 | 1352 | ||
| 1257 | #define OVERLAY_END(OV) XOVERLAY (OV)->end | 1353 | /* Return the end of OV in its buffer, or -1. */ |
| 1354 | |||
| 1355 | #define OVERLAY_END(OV) (overlay_end (XOVERLAY (OV))) | ||
| 1258 | 1356 | ||
| 1259 | /* Return the plist of overlay OV. */ | 1357 | /* Return the plist of overlay OV. */ |
| 1260 | 1358 | ||
| 1261 | #define OVERLAY_PLIST(OV) XOVERLAY (OV)->plist | 1359 | #define OVERLAY_PLIST(OV) (XOVERLAY (OV)->plist) |
| 1360 | |||
| 1361 | /* Return the buffer of overlay OV. */ | ||
| 1362 | |||
| 1363 | #define OVERLAY_BUFFER(OV) (XOVERLAY (OV)->buffer) | ||
| 1262 | 1364 | ||
| 1263 | /* Return the actual buffer position for the marker P. | 1365 | /* Return true, if OV's rear-advance is set. */ |
| 1264 | We assume you know which buffer it's pointing into. */ | ||
| 1265 | 1366 | ||
| 1266 | #define OVERLAY_POSITION(P) \ | 1367 | #define OVERLAY_REAR_ADVANCE_P(OV) (XOVERLAY (OV)->interval->rear_advance) |
| 1267 | (MARKERP (P) ? marker_position (P) : (emacs_abort (), 0)) | 1368 | |
| 1369 | /* Return true, if OV's front-advance is set. */ | ||
| 1370 | |||
| 1371 | #define OVERLAY_FRONT_ADVANCE_P(OV) (XOVERLAY (OV)->interval->front_advance) | ||
| 1268 | 1372 | ||
| 1269 | 1373 | ||
| 1270 | /*********************************************************************** | 1374 | /*********************************************************************** |
| @@ -1405,4 +1509,7 @@ lowercasep (int c) | |||
| 1405 | 1509 | ||
| 1406 | INLINE_HEADER_END | 1510 | INLINE_HEADER_END |
| 1407 | 1511 | ||
| 1512 | int compare_overlays (const void *v1, const void *v2); | ||
| 1513 | void make_sortvec_item (struct sortvec *item, Lisp_Object overlay); | ||
| 1514 | |||
| 1408 | #endif /* EMACS_BUFFER_H */ | 1515 | #endif /* EMACS_BUFFER_H */ |