X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/36429c89cbd7282a7614a358e5edb4d37f4a3f47..21238f117336d2a3f1e7970832ba05da14d44a03:/src/buffer.c diff --git a/src/buffer.c b/src/buffer.c index 08118baa3d..6085746ee6 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -19,6 +19,8 @@ along with GNU Emacs. If not, see . */ #include +#define BUFFER_INLINE EXTERN_INLINE + #include #include #include @@ -56,7 +58,7 @@ struct buffer *all_buffers; Setting the default value also goes through the alist of buffers and stores into each buffer that does not say it has a local value. */ -DECL_ALIGN (struct buffer, buffer_defaults); +struct buffer alignas (GCALIGNMENT) buffer_defaults; /* A Lisp_Object pointer to the above, used for staticpro */ @@ -83,7 +85,7 @@ struct buffer buffer_local_flags; /* This structure holds the names of symbols whose values may be buffer-local. It is indexed and accessed in the same way as the above. */ -DECL_ALIGN (struct buffer, buffer_local_symbols); +struct buffer alignas (GCALIGNMENT) buffer_local_symbols; /* A Lisp_Object pointer to the above, used for staticpro */ static Lisp_Object Vbuffer_local_symbols; @@ -97,7 +99,7 @@ static Lisp_Object Vbuffer_local_symbols; /* Maximum length of an overlay vector. */ #define OVERLAY_COUNT_MAX \ ((ptrdiff_t) min (MOST_POSITIVE_FIXNUM, \ - min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Lisp_Object))) + min (PTRDIFF_MAX, SIZE_MAX) / word_size)) /* Flags indicating which built-in buffer-local variables are permanent locals. */ @@ -107,8 +109,6 @@ static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS]; int last_per_buffer_idx; -static Lisp_Object Fset_buffer_major_mode (Lisp_Object); -static Lisp_Object Fdelete_overlay (Lisp_Object); static void call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, int after, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3); @@ -155,7 +155,7 @@ static void alloc_buffer_text (struct buffer *, ptrdiff_t); static void free_buffer_text (struct buffer *b); static struct Lisp_Overlay * copy_overlays (struct buffer *, struct Lisp_Overlay *); static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t); -static Lisp_Object buffer_lisp_local_variables (struct buffer *); +static Lisp_Object buffer_lisp_local_variables (struct buffer *, int); /* For debugging; temporary. See set_buffer_internal. */ /* Lisp_Object Qlisp_mode, Vcheck_symbol; */ @@ -193,9 +193,9 @@ followed by the rest of the buffers. */) Lisp_Object args[3]; CHECK_FRAME (frame); - framelist = Fcopy_sequence (XFRAME (frame)->buffer_list); + framelist = Fcopy_sequence (FGET (XFRAME (frame), buffer_list)); prevlist = Fnreverse (Fcopy_sequence - (XFRAME (frame)->buried_buffer_list)); + (FGET (XFRAME (frame), buried_buffer_list))); /* Remove from GENERAL any buffer that duplicates one in FRAMELIST or PREVLIST. */ @@ -331,7 +331,9 @@ even if it is dead. The return value is never nil. */) /* An ordinary buffer uses its own struct buffer_text. */ b->text = &b->own_text; - b->base_buffer = 0; + b->base_buffer = NULL; + /* No one shares the text with us now. */ + b->indirections = 0; BUF_GAP_SIZE (b) = 20; BLOCK_INPUT; @@ -410,36 +412,24 @@ even if it is dead. The return value is never nil. */) static struct Lisp_Overlay * copy_overlays (struct buffer *b, struct Lisp_Overlay *list) { - Lisp_Object buffer; struct Lisp_Overlay *result = NULL, *tail = NULL; - XSETBUFFER (buffer, b); - for (; list; list = list->next) { - Lisp_Object overlay, start, end, old_overlay; - ptrdiff_t charpos; - - XSETMISC (old_overlay, list); - charpos = marker_position (OVERLAY_START (old_overlay)); - start = Fmake_marker (); - Fset_marker (start, make_number (charpos), buffer); - XMARKER (start)->insertion_type - = XMARKER (OVERLAY_START (old_overlay))->insertion_type; - - charpos = marker_position (OVERLAY_END (old_overlay)); - end = Fmake_marker (); - Fset_marker (end, make_number (charpos), buffer); - XMARKER (end)->insertion_type - = XMARKER (OVERLAY_END (old_overlay))->insertion_type; - - overlay = allocate_misc (); - XMISCTYPE (overlay) = Lisp_Misc_Overlay; - OVERLAY_START (overlay) = start; - OVERLAY_END (overlay) = end; - OVERLAY_PLIST (overlay) = Fcopy_sequence (OVERLAY_PLIST (old_overlay)); - XOVERLAY (overlay)->next = NULL; + Lisp_Object overlay, start, end; + struct Lisp_Marker *m; + + eassert (MARKERP (MVAR (list, start))); + m = XMARKER (MVAR (list, start)); + start = build_marker (b, m->charpos, m->bytepos); + XMARKER (start)->insertion_type = m->insertion_type; + eassert (MARKERP (MVAR (list, end))); + m = XMARKER (MVAR (list, end)); + end = build_marker (b, m->charpos, m->bytepos); + XMARKER (end)->insertion_type = m->insertion_type; + + overlay = build_overlay (start, end, Fcopy_sequence (MVAR (list, plist))); if (tail) tail = tail->next = XOVERLAY (overlay); else @@ -460,12 +450,9 @@ copy_overlays (struct buffer *b, struct Lisp_Overlay *list) static void clone_per_buffer_values (struct buffer *from, struct buffer *to) { - Lisp_Object to_buffer; int offset; - XSETBUFFER (to_buffer, to); - - for_each_per_buffer_object_at (offset) + FOR_EACH_PER_BUFFER_OBJECT_AT (offset) { Lisp_Object obj; @@ -477,9 +464,9 @@ clone_per_buffer_values (struct buffer *from, struct buffer *to) if (MARKERP (obj) && XMARKER (obj)->buffer == from) { struct Lisp_Marker *m = XMARKER (obj); - obj = Fmake_marker (); + + obj = build_marker (to, m->charpos, m->bytepos); XMARKER (obj)->insertion_type = m->insertion_type; - set_marker_both (obj, to_buffer, m->charpos, m->bytepos); } PER_BUFFER_VALUE (to, offset) = obj; @@ -492,7 +479,7 @@ clone_per_buffer_values (struct buffer *from, struct buffer *to) /* Get (a copy of) the alist of Lisp-level local variables of FROM and install that in TO. */ - BVAR (to, local_var_alist) = buffer_lisp_local_variables (from); + BVAR (to, local_var_alist) = buffer_lisp_local_variables (from, 1); } @@ -573,12 +560,18 @@ CLONE nil means the indirect buffer's state is reset to default values. */) b = allocate_buffer (); + /* No double indirection - if base buffer is indirect, + new buffer becomes an indirect to base's base. */ b->base_buffer = (XBUFFER (base_buffer)->base_buffer ? XBUFFER (base_buffer)->base_buffer : XBUFFER (base_buffer)); /* Use the base buffer's text object. */ b->text = b->base_buffer->text; + /* We have no own text. */ + b->indirections = -1; + /* Notify base buffer that we share the text now. */ + b->base_buffer->indirections++; b->pt = b->base_buffer->pt; b->begv = b->base_buffer->begv; @@ -617,32 +610,24 @@ CLONE nil means the indirect buffer's state is reset to default values. */) eassert (NILP (BVAR (b->base_buffer, begv_marker))); eassert (NILP (BVAR (b->base_buffer, zv_marker))); - BVAR (b->base_buffer, pt_marker) = Fmake_marker (); - set_marker_both (BVAR (b->base_buffer, pt_marker), base_buffer, - b->base_buffer->pt, - b->base_buffer->pt_byte); + BVAR (b->base_buffer, pt_marker) + = build_marker (b->base_buffer, b->base_buffer->pt, b->base_buffer->pt_byte); - BVAR (b->base_buffer, begv_marker) = Fmake_marker (); - set_marker_both (BVAR (b->base_buffer, begv_marker), base_buffer, - b->base_buffer->begv, - b->base_buffer->begv_byte); + BVAR (b->base_buffer, begv_marker) + = build_marker (b->base_buffer, b->base_buffer->begv, b->base_buffer->begv_byte); + + BVAR (b->base_buffer, zv_marker) + = build_marker (b->base_buffer, b->base_buffer->zv, b->base_buffer->zv_byte); - BVAR (b->base_buffer, zv_marker) = Fmake_marker (); - set_marker_both (BVAR (b->base_buffer, zv_marker), base_buffer, - b->base_buffer->zv, - b->base_buffer->zv_byte); XMARKER (BVAR (b->base_buffer, zv_marker))->insertion_type = 1; } if (NILP (clone)) { /* Give the indirect buffer markers for its narrowing. */ - BVAR (b, pt_marker) = Fmake_marker (); - set_marker_both (BVAR (b, pt_marker), buf, b->pt, b->pt_byte); - BVAR (b, begv_marker) = Fmake_marker (); - set_marker_both (BVAR (b, begv_marker), buf, b->begv, b->begv_byte); - BVAR (b, zv_marker) = Fmake_marker (); - set_marker_both (BVAR (b, zv_marker), buf, b->zv, b->zv_byte); + BVAR (b, pt_marker) = build_marker (b, b->pt, b->pt_byte); + BVAR (b, begv_marker) = build_marker (b, b->begv, b->begv_byte); + BVAR (b, zv_marker) = build_marker (b, b->zv, b->zv_byte); XMARKER (BVAR (b, zv_marker))->insertion_type = 1; } else @@ -669,27 +654,41 @@ CLONE nil means the indirect buffer's state is reset to default values. */) return buf; } +/* Mark OV as no longer associated with B. */ + +static void +drop_overlay (struct buffer *b, struct Lisp_Overlay *ov) +{ + eassert (b == XBUFFER (Fmarker_buffer (MVAR (ov, start)))); + modify_overlay (b, marker_position (MVAR (ov, start)), + marker_position (MVAR (ov, end))); + Fset_marker (MVAR (ov, start), Qnil, Qnil); + Fset_marker (MVAR (ov, end), Qnil, Qnil); + +} + +/* Delete all overlays of B and reset it's overlay lists. */ + void delete_all_overlays (struct buffer *b) { - Lisp_Object overlay; + struct Lisp_Overlay *ov, *next; - /* `reset_buffer' blindly sets the list of overlays to NULL, so we - have to empty the list, otherwise we end up with overlays that - think they belong to this buffer while the buffer doesn't know about - them any more. */ - while (b->overlays_before) + for (ov = b->overlays_before; ov; ov = next) { - XSETMISC (overlay, b->overlays_before); - Fdelete_overlay (overlay); + drop_overlay (b, ov); + next = ov->next; + ov->next = NULL; } - while (b->overlays_after) + + for (ov = b->overlays_after; ov; ov = next) { - XSETMISC (overlay, b->overlays_after); - Fdelete_overlay (overlay); + drop_overlay (b, ov); + next = ov->next; + ov->next = NULL; } - eassert (b->overlays_before == NULL); - eassert (b->overlays_after == NULL); + + b->overlays_before = b->overlays_after = NULL; } /* Reinitialize everything about a buffer except its name and contents @@ -705,7 +704,7 @@ reset_buffer (register struct buffer *b) BVAR (b, filename) = Qnil; BVAR (b, file_truename) = Qnil; BVAR (b, directory) = (current_buffer) ? BVAR (current_buffer, directory) : Qnil; - EMACS_SET_SECS_NSECS (b->modtime, 0, UNKNOWN_MODTIME_NSECS); + b->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS); b->modtime_size = -1; XSETFASTINT (BVAR (b, save_length), 0); b->last_window_start = 1; @@ -817,7 +816,7 @@ reset_buffer_local_variables (register struct buffer *b, int permanent_too) SET_PER_BUFFER_VALUE_P (b, i, 0); /* For each slot that has a default value, copy that into the slot. */ - for_each_per_buffer_object_at (offset) + FOR_EACH_PER_BUFFER_OBJECT_AT (offset) { int idx = PER_BUFFER_IDX (offset); if ((idx > 0 @@ -838,10 +837,14 @@ If there is no live buffer named NAME, then return NAME. Otherwise modify name by appending `', incrementing NUMBER \(starting at 2) until an unused name is found, and then return that name. Optional second argument IGNORE specifies a name that is okay to use (if -it is in the sequence to be tried) even if a buffer with that name exists. */) +it is in the sequence to be tried) even if a buffer with that name exists. + +If NAME begins with a space (i.e., a buffer that is not normally +visible to users), then if buffer NAME already exists a random number +is first appended to NAME, to speed up finding a non-existent buffer. */) (register Lisp_Object name, Lisp_Object ignore) { - register Lisp_Object gentemp, tem; + register Lisp_Object gentemp, tem, tem2; ptrdiff_t count; char number[INT_BUFSIZE_BOUND (ptrdiff_t) + sizeof "<>"]; @@ -854,11 +857,24 @@ it is in the sequence to be tried) even if a buffer with that name exists. */) if (NILP (tem)) return name; + if (!strncmp (SSDATA (name), " ", 1)) /* see bug#1229 */ + { + /* Note fileio.c:make_temp_name does random differently. */ + tem2 = concat2 (name, make_formatted_string + (number, "-%"pI"d", + XFASTINT (Frandom (make_number (999999))))); + tem = Fget_buffer (tem2); + if (NILP (tem)) + return tem2; + } + else + tem2 = name; + count = 1; while (1) { - sprintf (number, "<%"pD"d>", ++count); - gentemp = concat2 (name, build_string (number)); + gentemp = concat2 (tem2, make_formatted_string + (number, "<%"pD"d>", ++count)); tem = Fstring_equal (gentemp, ignore); if (!NILP (tem)) return gentemp; @@ -995,10 +1011,12 @@ buffer_local_value_1 (Lisp_Object variable, Lisp_Object buffer) /* Return an alist of the Lisp-level buffer-local bindings of buffer BUF. That is, don't include the variables maintained - in special slots in the buffer object. */ + in special slots in the buffer object. + If CLONE is zero elements of the form (VAR . unbound) are replaced + by VAR. */ static Lisp_Object -buffer_lisp_local_variables (struct buffer *buf) +buffer_lisp_local_variables (struct buffer *buf, int clone) { Lisp_Object result = Qnil; register Lisp_Object tail; @@ -1018,7 +1036,7 @@ buffer_lisp_local_variables (struct buffer *buf) if (buf != current_buffer) val = XCDR (elt); - result = Fcons (EQ (val, Qunbound) + result = Fcons (!clone && EQ (val, Qunbound) ? XCAR (elt) : Fcons (XCAR (elt), val), result); @@ -1047,13 +1065,13 @@ No argument or nil as argument means use current buffer as BUFFER. */) buf = XBUFFER (buffer); } - result = buffer_lisp_local_variables (buf); + result = buffer_lisp_local_variables (buf, 0); /* Add on all the variables stored in special slots. */ { int offset, idx; - for_each_per_buffer_object_at (offset) + FOR_EACH_PER_BUFFER_OBJECT_AT (offset) { idx = PER_BUFFER_IDX (offset); if ((idx == -1 || PER_BUFFER_VALUE_P (buf, idx)) @@ -1309,7 +1327,7 @@ exists, return the buffer `*scratch*' (creating it if necessary). */) pred = frame_buffer_predicate (frame); /* Consider buffers that have been seen in the frame first. */ - tail = XFRAME (frame)->buffer_list; + tail = FGET (XFRAME (frame), buffer_list); for (; CONSP (tail); tail = XCDR (tail)) { buf = XCAR (tail); @@ -1415,14 +1433,55 @@ No argument or nil as argument means do this for the current buffer. */) return Qnil; } -/* - DEFVAR_LISP ("kill-buffer-hook", ..., "\ -Hook to be run (by `run-hooks', which see) when a buffer is killed.\n\ -The buffer being killed will be current while the hook is running.\n\ +/* Truncate undo list and shrink the gap of BUFFER. */ + +int +compact_buffer (struct buffer *buffer) +{ + /* Verify indirection counters. */ + if (buffer->base_buffer) + { + eassert (buffer->indirections == -1); + eassert (buffer->base_buffer->indirections > 0); + } + else + eassert (buffer->indirections >= 0); + + /* Skip dead buffers, indirect buffers and buffers + which aren't changed since last compaction. */ + if (!NILP (buffer->INTERNAL_FIELD (name)) + && (buffer->base_buffer == NULL) + && (buffer->text->compact != buffer->text->modiff)) + { + /* If a buffer's undo list is Qt, that means that undo is + turned off in that buffer. Calling truncate_undo_list on + Qt tends to return NULL, which effectively turns undo back on. + So don't call truncate_undo_list if undo_list is Qt. */ + if (!EQ (buffer->INTERNAL_FIELD (undo_list), Qt)) + truncate_undo_list (buffer); + + /* Shrink buffer gaps. */ + if (!buffer->text->inhibit_shrinking) + { + /* If a buffer's gap size is more than 10% of the buffer + size, or larger than 2000 bytes, then shrink it + accordingly. Keep a minimum size of 20 bytes. */ + int size = min (2000, max (20, (buffer->text->z_byte / 10))); + + if (buffer->text->gap_size > size) + { + struct buffer *save_current = current_buffer; + current_buffer = buffer; + make_gap (-(buffer->text->gap_size - size)); + current_buffer = save_current; + } + } + buffer->text->compact = buffer->text->modiff; + return 1; + } + return 0; +} -Functions run by this hook are supposed to not change the current -buffer. See `kill-buffer'." -*/ DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 0, 1, "bKill buffer: ", doc: /* Kill the buffer specified by BUFFER-OR-NAME. The argument may be a buffer or the name of an existing buffer. @@ -1501,22 +1560,21 @@ cleaning up all windows currently displaying the buffer to be killed. */) since anything can happen within do_yes_or_no_p. */ /* Don't kill the minibuffer now current. */ - if (EQ (buffer, XWINDOW (minibuf_window)->buffer)) + if (EQ (buffer, WGET (XWINDOW (minibuf_window), buffer))) return Qnil; - /* When we kill a base buffer, kill all its indirect buffers. + /* When we kill an ordinary buffer which shares it's buffer text + with indirect buffer(s), we must kill indirect buffer(s) too. We do it at this stage so nothing terrible happens if they ask questions or their hooks get errors. */ - if (! b->base_buffer) + if (!b->base_buffer && b->indirections > 0) { struct buffer *other; GCPRO1 (buffer); - for (other = all_buffers; other; other = other->header.next.buffer) - /* all_buffers contains dead buffers too; - don't re-kill them. */ - if (other->base_buffer == b && !NILP (BVAR (other, name))) + FOR_EACH_BUFFER (other) + if (other->base_buffer == b) { Lisp_Object buf; XSETBUFFER (buf, other); @@ -1553,7 +1611,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) /* If the buffer now current is shown in the minibuffer and our buffer is the sole other buffer give up. */ XSETBUFFER (tem, current_buffer); - if (EQ (tem, XWINDOW (minibuf_window)->buffer) + if (EQ (tem, WGET (XWINDOW (minibuf_window), buffer)) && EQ (buffer, Fother_buffer (buffer, Qnil, Qnil))) return Qnil; @@ -1645,7 +1703,15 @@ cleaning up all windows currently displaying the buffer to be killed. */) BVAR (b, name) = Qnil; BLOCK_INPUT; - if (! b->base_buffer) + if (b->base_buffer) + { + /* Notify our base buffer that we don't share the text anymore. */ + eassert (b->indirections == -1); + b->base_buffer->indirections--; + eassert (b->base_buffer->indirections >= 0); + } + else + /* No one shares our buffer text, can free it. */ free_buffer_text (b); if (b->newline_cache) @@ -1701,8 +1767,8 @@ record_buffer (Lisp_Object buffer) Vinhibit_quit = tem; /* Update buffer list of selected frame. */ - f->buffer_list = Fcons (buffer, Fdelq (buffer, f->buffer_list)); - f->buried_buffer_list = Fdelq (buffer, f->buried_buffer_list); + FSET (f, buffer_list, Fcons (buffer, Fdelq (buffer, FGET (f, buffer_list)))); + FSET (f, buried_buffer_list, Fdelq (buffer, FGET (f, buried_buffer_list))); /* Run buffer-list-update-hook. */ if (!NILP (Vrun_hooks)) @@ -1739,8 +1805,9 @@ DEFUN ("bury-buffer-internal", Fbury_buffer_internal, Sbury_buffer_internal, Vinhibit_quit = tem; /* Update buffer lists of selected frame. */ - f->buffer_list = Fdelq (buffer, f->buffer_list); - f->buried_buffer_list = Fcons (buffer, Fdelq (buffer, f->buried_buffer_list)); + FSET (f, buffer_list, Fdelq (buffer, FGET (f, buffer_list))); + FSET (f, buried_buffer_list, + Fcons (buffer, Fdelq (buffer, FGET (f, buried_buffer_list)))); /* Run buffer-list-update-hook. */ if (!NILP (Vrun_hooks)) @@ -2033,7 +2100,7 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, { /* This is probably harder to make work. */ struct buffer *other; - for (other = all_buffers; other; other = other->header.next.buffer) + FOR_EACH_BUFFER (other) if (other->base_buffer == other_buffer || other->base_buffer == current_buffer) error ("One of the buffers to swap has indirect buffers"); @@ -2070,6 +2137,7 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, swapfield (zv_byte, ptrdiff_t); eassert (!current_buffer->base_buffer); eassert (!other_buffer->base_buffer); + swapfield (indirections, ptrdiff_t); current_buffer->clip_changed = 1; other_buffer->clip_changed = 1; swapfield (newline_cache, struct region_cache *); swapfield (width_run_cache, struct region_cache *); @@ -2125,12 +2193,13 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, while (NILP (Fmemq (w, ws))) { ws = Fcons (w, ws); - if (MARKERP (XWINDOW (w)->pointm) - && (EQ (XWINDOW (w)->buffer, buf1) - || EQ (XWINDOW (w)->buffer, buf2))) - Fset_marker (XWINDOW (w)->pointm, - make_number (BUF_BEGV (XBUFFER (XWINDOW (w)->buffer))), - XWINDOW (w)->buffer); + if (MARKERP (WGET (XWINDOW (w), pointm)) + && (EQ (WGET (XWINDOW (w), buffer), buf1) + || EQ (WGET (XWINDOW (w), buffer), buf2))) + Fset_marker (WGET (XWINDOW (w), pointm), + make_number + (BUF_BEGV (XBUFFER (WGET (XWINDOW (w), buffer)))), + WGET (XWINDOW (w), buffer)); w = Fnext_window (w, Qt, Qt); } } @@ -2410,7 +2479,7 @@ current buffer is cleared. */) /* Copy this buffer's new multibyte status into all of its indirect buffers. */ - for (other = all_buffers; other; other = other->header.next.buffer) + FOR_EACH_BUFFER (other) if (other->base_buffer == current_buffer && !NILP (BVAR (other, name))) { BVAR (other, enable_multibyte_characters) @@ -2779,11 +2848,11 @@ mouse_face_overlay_overlaps (Lisp_Object overlay) Lisp_Object *v, tem; size = 10; - v = (Lisp_Object *) alloca (size * sizeof *v); + v = alloca (size * sizeof *v); n = overlays_in (start, end, 0, &v, &size, NULL, NULL); if (n > size) { - v = (Lisp_Object *) alloca (n * sizeof *v); + v = alloca (n * sizeof *v); overlays_in (start, end, 0, &v, &n, NULL, NULL); } @@ -2810,8 +2879,7 @@ overlay_touches_p (ptrdiff_t pos) ptrdiff_t endpos; XSETMISC (overlay ,tail); - if (!OVERLAYP (overlay)) - abort (); + eassert (OVERLAYP (overlay)); endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); if (endpos < pos) @@ -2825,8 +2893,7 @@ overlay_touches_p (ptrdiff_t pos) ptrdiff_t startpos; XSETMISC (overlay, tail); - if (!OVERLAYP (overlay)) - abort (); + eassert (OVERLAYP (overlay)); startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); if (pos < startpos) @@ -2871,8 +2938,7 @@ ptrdiff_t sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) { ptrdiff_t i, j; - struct sortvec *sortvec; - sortvec = (struct sortvec *) alloca (noverlays * sizeof (struct sortvec)); + struct sortvec *sortvec = alloca (noverlays * sizeof *sortvec); /* Put the valid and relevant overlays into sortvec. */ @@ -2882,7 +2948,7 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) Lisp_Object overlay; overlay = overlay_vec[i]; - if (OVERLAY_VALID (overlay) + if (OVERLAYP (overlay) && OVERLAY_POSITION (OVERLAY_START (overlay)) > 0 && OVERLAY_POSITION (OVERLAY_END (overlay)) > 0) { @@ -3153,22 +3219,7 @@ recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos) { next = tail->next; XSETMISC (overlay, tail); - - /* If the overlay is not valid, get rid of it. */ - if (!OVERLAY_VALID (overlay)) -#if 1 - abort (); -#else - { - /* Splice the cons cell TAIL out of overlays_before. */ - if (!NILP (prev)) - XCDR (prev) = next; - else - buf->overlays_before = next; - tail = prev; - continue; - } -#endif + eassert (OVERLAYP (overlay)); beg = OVERLAY_START (overlay); end = OVERLAY_END (overlay); @@ -3193,7 +3244,7 @@ recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos) Lisp_Object otherbeg, otheroverlay; XSETMISC (otheroverlay, other); - eassert (OVERLAY_VALID (otheroverlay)); + eassert (OVERLAYP (otheroverlay)); otherbeg = OVERLAY_START (otheroverlay); if (OVERLAY_POSITION (otherbeg) >= where) @@ -3221,22 +3272,7 @@ recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos) { next = tail->next; XSETMISC (overlay, tail); - - /* If the overlay is not valid, get rid of it. */ - if (!OVERLAY_VALID (overlay)) -#if 1 - abort (); -#else - { - /* Splice the cons cell TAIL out of overlays_after. */ - if (!NILP (prev)) - XCDR (prev) = next; - else - buf->overlays_after = next; - tail = prev; - continue; - } -#endif + eassert (OVERLAYP (overlay)); beg = OVERLAY_START (overlay); end = OVERLAY_END (overlay); @@ -3266,7 +3302,7 @@ recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos) Lisp_Object otherend, otheroverlay; XSETMISC (otheroverlay, other); - eassert (OVERLAY_VALID (otheroverlay)); + eassert (OVERLAYP (otheroverlay)); otherend = OVERLAY_END (otheroverlay); if (OVERLAY_POSITION (otherend) <= where) @@ -3597,12 +3633,7 @@ for the rear of the overlay advance when text is inserted there if (!NILP (rear_advance)) XMARKER (end)->insertion_type = 1; - overlay = allocate_misc (); - XMISCTYPE (overlay) = Lisp_Misc_Overlay; - XOVERLAY (overlay)->start = beg; - XOVERLAY (overlay)->end = end; - XOVERLAY (overlay)->plist = Qnil; - XOVERLAY (overlay)->next = NULL; + overlay = build_overlay (beg, end, Qnil); /* Put the new overlay on the wrong list. */ end = OVERLAY_END (overlay); @@ -3644,7 +3675,7 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end) /* If this is a buffer not in the selected window, we must do other windows. */ - if (buf != XBUFFER (XWINDOW (selected_window)->buffer)) + if (buf != XBUFFER (WGET (XWINDOW (selected_window), buffer))) windows_or_buffers_changed = 1; /* If multiple windows show this buffer, we must do other windows. */ else if (buffer_shared > 1) @@ -3657,18 +3688,17 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end) ++BUF_OVERLAY_MODIFF (buf); } - +/* Remove OVERLAY from LIST. */ + static struct Lisp_Overlay * unchain_overlay (struct Lisp_Overlay *list, struct Lisp_Overlay *overlay) { - struct Lisp_Overlay *tmp, *prev; - for (tmp = list, prev = NULL; tmp; prev = tmp, tmp = tmp->next) - if (tmp == overlay) + register struct Lisp_Overlay *tail, **prev = &list; + + for (tail = list; tail; prev = &tail->next, tail = *prev) + if (tail == overlay) { - if (prev) - prev->next = tmp->next; - else - list = tmp->next; + *prev = overlay->next; overlay->next = NULL; break; } @@ -3807,11 +3837,7 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0, = unchain_overlay (b->overlays_after, XOVERLAY (overlay)); eassert (XOVERLAY (overlay)->next == NULL); - modify_overlay (b, - marker_position (OVERLAY_START (overlay)), - marker_position (OVERLAY_END (overlay))); - Fset_marker (OVERLAY_START (overlay), Qnil, Qnil); - Fset_marker (OVERLAY_END (overlay), Qnil, Qnil); + drop_overlay (b, XOVERLAY (overlay)); /* When deleting an overlay with before or after strings, turn off display optimizations for the affected buffer, on the basis that @@ -3863,7 +3889,7 @@ OVERLAY. */) { CHECK_OVERLAY (overlay); - return Fcopy_sequence (XOVERLAY (overlay)->plist); + return Fcopy_sequence (MVAR (XOVERLAY (overlay), plist)); } @@ -3879,7 +3905,7 @@ DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0, len = 10; /* We can't use alloca here because overlays_at can call xrealloc. */ - overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object)); + overlay_vec = xmalloc (len * sizeof *overlay_vec); /* Put all the overlays we want in a vector in overlay_vec. Store the length in len. */ @@ -3910,7 +3936,7 @@ end of the buffer. */) CHECK_NUMBER_COERCE_MARKER (end); len = 10; - overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object)); + overlay_vec = xmalloc (len * sizeof *overlay_vec); /* Put all the overlays we want in a vector in overlay_vec. Store the length in len. */ @@ -3938,7 +3964,7 @@ the value is (point-max). */) CHECK_NUMBER_COERCE_MARKER (pos); len = 10; - overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object)); + overlay_vec = xmalloc (len * sizeof *overlay_vec); /* Put all the overlays we want in a vector in overlay_vec. Store the length in len. @@ -3982,7 +4008,7 @@ the value is (point-min). */) return pos; len = 10; - overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object)); + overlay_vec = xmalloc (len * sizeof *overlay_vec); /* Put all the overlays we want in a vector in overlay_vec. Store the length in len. @@ -4039,7 +4065,7 @@ DEFUN ("overlay-get", Foverlay_get, Soverlay_get, 2, 2, 0, (Lisp_Object overlay, Lisp_Object prop) { CHECK_OVERLAY (overlay); - return lookup_char_property (XOVERLAY (overlay)->plist, prop, 0); + return lookup_char_property (MVAR (XOVERLAY (overlay), plist), prop, 0); } DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0, @@ -4054,7 +4080,7 @@ VALUE will be returned.*/) buffer = Fmarker_buffer (OVERLAY_START (overlay)); - for (tail = XOVERLAY (overlay)->plist; + for (tail = MVAR (XOVERLAY (overlay), plist); CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail))) if (EQ (XCAR (tail), prop)) @@ -4065,8 +4091,8 @@ VALUE will be returned.*/) } /* It wasn't in the list, so add it to the front. */ changed = !NILP (value); - XOVERLAY (overlay)->plist - = Fcons (prop, Fcons (value, XOVERLAY (overlay)->plist)); + MVAR (XOVERLAY (overlay), plist) + = Fcons (prop, Fcons (value, MVAR (XOVERLAY (overlay), plist))); found: if (! NILP (buffer)) { @@ -4237,11 +4263,11 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, int after, First copy the vector contents, in case some of these hooks do subsequent modification of the buffer. */ ptrdiff_t size = last_overlay_modification_hooks_used; - Lisp_Object *copy = (Lisp_Object *) alloca (size * sizeof (Lisp_Object)); + Lisp_Object *copy = alloca (size * sizeof *copy); ptrdiff_t i; memcpy (copy, XVECTOR (last_overlay_modification_hooks)->contents, - size * sizeof (Lisp_Object)); + size * word_size); gcpro1.var = copy; gcpro1.nvars = size; @@ -4856,6 +4882,11 @@ void init_buffer_once (void) { int idx; + /* If you add, remove, or reorder Lisp_Objects in a struct buffer, make + sure that this is still correct. Otherwise, mark_vectorlike may not + trace all Lisp_Objects in buffer_defaults and buffer_local_symbols. */ + const int pvecsize + = (offsetof (struct buffer, own_text) - header_size) / word_size; memset (buffer_permanent_local_flags, 0, sizeof buffer_permanent_local_flags); @@ -4870,18 +4901,21 @@ init_buffer_once (void) /* Prevent GC from getting confused. */ buffer_defaults.text = &buffer_defaults.own_text; buffer_local_symbols.text = &buffer_local_symbols.own_text; + /* No one will share the text with these buffers, but let's play it safe. */ + buffer_defaults.indirections = 0; + buffer_local_symbols.indirections = 0; BUF_INTERVALS (&buffer_defaults) = 0; BUF_INTERVALS (&buffer_local_symbols) = 0; - XSETPVECTYPESIZE (&buffer_defaults, PVEC_BUFFER, 0); + XSETPVECTYPESIZE (&buffer_defaults, PVEC_BUFFER, pvecsize); XSETBUFFER (Vbuffer_defaults, &buffer_defaults); - XSETPVECTYPESIZE (&buffer_local_symbols, PVEC_BUFFER, 0); + XSETPVECTYPESIZE (&buffer_local_symbols, PVEC_BUFFER, pvecsize); XSETBUFFER (Vbuffer_local_symbols, &buffer_local_symbols); /* Set up the default values of various buffer slots. */ /* Must do these before making the first buffer! */ /* real setup is done in bindings.el */ - BVAR (&buffer_defaults, mode_line_format) = make_pure_c_string ("%-"); + BVAR (&buffer_defaults, mode_line_format) = build_pure_c_string ("%-"); BVAR (&buffer_defaults, header_line_format) = Qnil; BVAR (&buffer_defaults, abbrev_mode) = Qnil; BVAR (&buffer_defaults, overwrite_mode) = Qnil; @@ -4937,7 +4971,7 @@ init_buffer_once (void) The local flag bits are in the local_var_flags slot of the buffer. */ /* Nothing can work if this isn't true */ - { verify (sizeof (EMACS_INT) == sizeof (Lisp_Object)); } + { verify (sizeof (EMACS_INT) == word_size); } /* 0 means not a lisp var, -1 means always local, else mask */ memset (&buffer_local_flags, 0, sizeof buffer_local_flags); @@ -5011,7 +5045,7 @@ init_buffer_once (void) current_buffer = 0; all_buffers = 0; - QSFundamental = make_pure_c_string ("Fundamental"); + QSFundamental = build_pure_c_string ("Fundamental"); Qfundamental_mode = intern_c_string ("fundamental-mode"); BVAR (&buffer_defaults, major_mode) = Qfundamental_mode; @@ -5026,10 +5060,10 @@ init_buffer_once (void) Fput (Qkill_buffer_hook, Qpermanent_local, Qt); /* super-magic invisible buffer */ - Vprin1_to_string_buffer = Fget_buffer_create (make_pure_c_string (" prin1")); + Vprin1_to_string_buffer = Fget_buffer_create (build_pure_c_string (" prin1")); Vbuffer_alist = Qnil; - Fset_buffer (Fget_buffer_create (make_pure_c_string ("*scratch*"))); + Fset_buffer (Fget_buffer_create (build_pure_c_string ("*scratch*"))); inhibit_modification_hooks = 0; } @@ -5048,7 +5082,7 @@ init_buffer (void) Map new memory. */ struct buffer *b; - for (b = all_buffers; b; b = b->header.next.buffer) + FOR_EACH_BUFFER (b) if (b->text->beg == NULL) enlarge_buffer_text (b, 0); } @@ -5069,14 +5103,15 @@ init_buffer (void) if (!(IS_DIRECTORY_SEP (pwd[len - 1]))) { /* Grow buffer to add directory separator and '\0'. */ - pwd = (char *) realloc (pwd, len + 2); + pwd = realloc (pwd, len + 2); if (!pwd) fatal ("`get_current_dir_name' failed: %s\n", strerror (errno)); pwd[len] = DIRECTORY_SEP; pwd[len + 1] = '\0'; + len++; } - BVAR (current_buffer, directory) = make_unibyte_string (pwd, strlen (pwd)); + BVAR (current_buffer, directory) = make_unibyte_string (pwd, len); if (! NILP (BVAR (&buffer_defaults, enable_multibyte_characters))) /* At this moment, we still don't know how to decode the directory name. So, we keep the bytes in multibyte form so @@ -5181,9 +5216,9 @@ syms_of_buffer (void) DEFSYM (Qkill_buffer_query_functions, "kill-buffer-query-functions"); Fput (Qprotected_field, Qerror_conditions, - pure_cons (Qprotected_field, pure_cons (Qerror, Qnil))); + listn (CONSTYPE_PURE, 2, Qprotected_field, Qerror)); Fput (Qprotected_field, Qerror_message, - make_pure_c_string ("Attempt to modify a protected field")); + build_pure_c_string ("Attempt to modify a protected field")); DEFVAR_BUFFER_DEFAULTS ("default-mode-line-format", mode_line_format, @@ -5426,17 +5461,17 @@ Use the command `abbrev-mode' to change this variable. */); doc: /* Non-nil if searches and matches should ignore case. */); DEFVAR_PER_BUFFER ("fill-column", &BVAR (current_buffer, fill_column), - make_number (LISP_INT_TAG), + make_number (Lisp_Int0), doc: /* Column beyond which automatic line-wrapping should happen. Interactively, you can set the buffer local value using \\[set-fill-column]. */); DEFVAR_PER_BUFFER ("left-margin", &BVAR (current_buffer, left_margin), - make_number (LISP_INT_TAG), + make_number (Lisp_Int0), doc: /* Column for the default `indent-line-function' to indent to. Linefeed indents to this column in Fundamental mode. */); DEFVAR_PER_BUFFER ("tab-width", &BVAR (current_buffer, tab_width), - make_number (LISP_INT_TAG), + make_number (Lisp_Int0), doc: /* Distance between tab stops (for display of tab characters), in columns. This should be an integer greater than zero. */); @@ -5557,7 +5592,7 @@ If it is nil, that means don't auto-save this buffer. */); Backing up is done before the first time the file is saved. */); DEFVAR_PER_BUFFER ("buffer-saved-size", &BVAR (current_buffer, save_length), - make_number (LISP_INT_TAG), + make_number (Lisp_Int0), doc: /* Length of current buffer when last read in, saved or auto-saved. 0 initially. -1 means auto-saving turned off until next real save. @@ -6006,7 +6041,6 @@ and `bury-buffer-internal'. */); defsubr (&Smake_indirect_buffer); defsubr (&Sgenerate_new_buffer_name); defsubr (&Sbuffer_name); -/*defsubr (&Sbuffer_number);*/ defsubr (&Sbuffer_file_name); defsubr (&Sbuffer_base_buffer); defsubr (&Sbuffer_local_value);