X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/eceeb5fca618f3bc0743c2388148dd758229c7c9..8707c1e56ca83a0a34785e451dcef428c60242fe:/src/buffer.c diff --git a/src/buffer.c b/src/buffer.c index 2ddbc69948..fab7330b19 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 @@ -33,8 +35,8 @@ along with GNU Emacs. If not, see . */ #include "intervals.h" #include "window.h" #include "commands.h" -#include "buffer.h" #include "character.h" +#include "buffer.h" #include "region-cache.h" #include "indent.h" #include "blockinput.h" @@ -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); @@ -154,8 +154,8 @@ Lisp_Object Qinsert_behind_hooks; 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 *, EMACS_INT, EMACS_INT); -static Lisp_Object buffer_lisp_local_variables (struct buffer *); +static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t); +static Lisp_Object buffer_lisp_local_variables (struct buffer *, int); /* For debugging; temporary. See set_buffer_internal. */ /* Lisp_Object Qlisp_mode, Vcheck_symbol; */ @@ -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; @@ -358,7 +360,7 @@ even if it is dead. The return value is never nil. */) BUF_CHARS_MODIFF (b) = 1; BUF_OVERLAY_MODIFF (b) = 1; BUF_SAVE_MODIFF (b) = 1; - BUF_INTERVALS (b) = 0; + buffer_set_intervals (b, NULL); BUF_UNCHANGED_MODIFIED (b) = 1; BUF_OVERLAY_UNCHANGED_MODIFIED (b) = 1; BUF_END_UNCHANGED (b) = 0; @@ -382,7 +384,7 @@ even if it is dead. The return value is never nil. */) BVAR (b, zv_marker) = Qnil; name = Fcopy_sequence (buffer_or_name); - STRING_SET_INTERVALS (name, NULL_INTERVAL); + string_set_intervals (name, NULL); BVAR (b, name) = name; BVAR (b, undo_list) = (SREF (name, 0) != ' ') ? Qnil : Qt; @@ -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; - EMACS_INT 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 (list->start)); + m = XMARKER (list->start); + start = build_marker (b, m->charpos, m->bytepos); + XMARKER (start)->insertion_type = m->insertion_type; + + eassert (MARKERP (list->end)); + m = XMARKER (list->end); + end = build_marker (b, m->charpos, m->bytepos); + XMARKER (end)->insertion_type = m->insertion_type; + overlay = build_overlay (start, end, Fcopy_sequence (list->plist)); if (tail) tail = tail->next = XOVERLAY (overlay); else @@ -460,16 +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); - - /* buffer-local Lisp variables start at `undo_list', - tho only the ones from `name' on are GC'd normally. */ - for (offset = PER_BUFFER_VAR_OFFSET (FIRST_FIELD_PER_BUFFER); - offset <= PER_BUFFER_VAR_OFFSET (LAST_FIELD_PER_BUFFER); - offset += sizeof (Lisp_Object)) + FOR_EACH_PER_BUFFER_OBJECT_AT (offset) { Lisp_Object obj; @@ -481,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; @@ -496,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); } @@ -577,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; @@ -600,7 +589,7 @@ CLONE nil means the indirect buffer's state is reset to default values. */) all_buffers = b; name = Fcopy_sequence (name); - STRING_SET_INTERVALS (name, NULL_INTERVAL); + string_set_intervals (name, NULL); BVAR (b, name) = name; reset_buffer (b); @@ -621,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 @@ -673,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 (ov->start))); + modify_overlay (b, marker_position (ov->start), + marker_position (ov->end)); + Fset_marker (ov->start, Qnil, Qnil); + Fset_marker (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 @@ -709,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; - b->modtime = 0; + b->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS); b->modtime_size = -1; XSETFASTINT (BVAR (b, save_length), 0); b->last_window_start = 1; @@ -820,14 +815,8 @@ reset_buffer_local_variables (register struct buffer *b, int permanent_too) if (permanent_too || buffer_permanent_local_flags[i] == 0) SET_PER_BUFFER_VALUE_P (b, i, 0); - /* For each slot that has a default value, - copy that into the slot. */ - - /* buffer-local Lisp variables start at `undo_list', - tho only the ones from `name' on are GC'd normally. */ - for (offset = PER_BUFFER_VAR_OFFSET (FIRST_FIELD_PER_BUFFER); - offset <= PER_BUFFER_VAR_OFFSET (LAST_FIELD_PER_BUFFER); - offset += sizeof (Lisp_Object)) + /* For each slot that has a default value, copy that into the slot. */ + FOR_EACH_PER_BUFFER_OBJECT_AT (offset) { int idx = PER_BUFFER_IDX (offset); if ((idx > 0 @@ -848,12 +837,16 @@ 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; - EMACS_INT count; - char number[INT_BUFSIZE_BOUND (EMACS_INT) + sizeof "<>"]; + register Lisp_Object gentemp, tem, tem2; + ptrdiff_t count; + char number[INT_BUFSIZE_BOUND (ptrdiff_t) + sizeof "<>"]; CHECK_STRING (name); @@ -864,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, "<%"pI"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; @@ -932,6 +938,21 @@ DEFUN ("buffer-local-value", Fbuffer_local_value, If VARIABLE does not have a buffer-local binding in BUFFER, the value is the default binding of the variable. */) (register Lisp_Object variable, register Lisp_Object buffer) +{ + register Lisp_Object result = buffer_local_value_1 (variable, buffer); + + if (EQ (result, Qunbound)) + xsignal1 (Qvoid_variable, variable); + + return result; +} + + +/* Like Fbuffer_local_value, but return Qunbound if the variable is + locally unbound. */ + +Lisp_Object +buffer_local_value_1 (Lisp_Object variable, Lisp_Object buffer) { register struct buffer *buf; register Lisp_Object result; @@ -985,18 +1006,17 @@ is the default binding of the variable. */) default: abort (); } - if (!EQ (result, Qunbound)) - return result; - - xsignal1 (Qvoid_variable, variable); + return result; } /* 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; @@ -1016,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); @@ -1045,18 +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; - /* buffer-local Lisp variables start at `undo_list', - tho only the ones from `name' on are GC'd normally. */ - for (offset = PER_BUFFER_VAR_OFFSET (FIRST_FIELD_PER_BUFFER); - offset <= PER_BUFFER_VAR_OFFSET (LAST_FIELD_PER_BUFFER); - /* sizeof EMACS_INT == sizeof Lisp_Object */ - offset += (sizeof (EMACS_INT))) + FOR_EACH_PER_BUFFER_OBJECT_AT (offset) { idx = PER_BUFFER_IDX (offset); if ((idx == -1 || PER_BUFFER_VALUE_P (buf, idx)) @@ -1418,28 +1433,71 @@ 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\ -See `kill-buffer'." - */ +/* 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; +} + DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 0, 1, "bKill buffer: ", - doc: /* Kill buffer BUFFER-OR-NAME. + doc: /* Kill the buffer specified by BUFFER-OR-NAME. The argument may be a buffer or the name of an existing buffer. Argument nil or omitted means kill the current buffer. Return t if the buffer is actually killed, nil otherwise. -This function calls `replace-buffer-in-windows' for cleaning up all -windows currently displaying the buffer to be killed. The functions in -`kill-buffer-query-functions' are called with the buffer to be killed as -the current buffer. If any of them returns nil, the buffer is not -killed. The hook `kill-buffer-hook' is run before the buffer is -actually killed. The buffer being killed will be current while the hook -is running. +The functions in `kill-buffer-query-functions' are called with the +buffer to be killed as the current buffer. If any of them returns nil, +the buffer is not killed. The hook `kill-buffer-hook' is run before the +buffer is actually killed. The buffer being killed will be current +while the hook is running. Functions called by any of these hooks are +supposed to not change the current buffer. Any processes that have this buffer as the `process-buffer' are killed -with SIGHUP. */) +with SIGHUP. This function calls `replace-buffer-in-windows' for +cleaning up all windows currently displaying the buffer to be killed. */) (Lisp_Object buffer_or_name) { Lisp_Object buffer; @@ -1475,7 +1533,7 @@ with SIGHUP. */) /* Run hooks with the buffer to be killed the current buffer. */ { - int count = SPECPDL_INDEX (); + ptrdiff_t count = SPECPDL_INDEX (); Lisp_Object arglist[1]; record_unwind_protect (save_excursion_restore, save_excursion_save ()); @@ -1493,6 +1551,10 @@ with SIGHUP. */) unbind_to (count, Qnil); } + /* If the hooks have killed the buffer, exit now. */ + if (NILP (BVAR (b, name))) + return Qt; + /* We have no more questions to ask. Verify that it is valid to kill the buffer. This must be done after the questions since anything can happen within do_yes_or_no_p. */ @@ -1501,22 +1563,18 @@ with SIGHUP. */) if (EQ (buffer, XWINDOW (minibuf_window)->buffer)) return Qnil; - if (NILP (BVAR (b, name))) - 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); @@ -1524,6 +1582,10 @@ with SIGHUP. */) } UNGCPRO; + + /* Exit if we now have killed the base buffer (Bug#11665). */ + if (NILP (BVAR (b, name))) + return Qt; } /* Run replace_buffer_in_windows before making another buffer current @@ -1532,9 +1594,12 @@ with SIGHUP. */) buffer. (Bug#10114) */ replace_buffer_in_windows (buffer); - /* Make this buffer not be current. - In the process, notice if this is the sole visible buffer - and give up if so. */ + /* Exit if replacing the buffer in windows has killed our buffer. */ + if (NILP (BVAR (b, name))) + return Qt; + + /* Make this buffer not be current. Exit if it is the sole visible + buffer. */ if (b == current_buffer) { tem = Fother_buffer (buffer, Qnil, Qnil); @@ -1543,15 +1608,12 @@ with SIGHUP. */) return Qnil; } - /* Notice if the buffer to kill is the sole visible buffer - when we're currently in the mini-buffer, and give up if so. */ + /* 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)) - { - tem = Fother_buffer (buffer, Qnil, Qnil); - if (EQ (buffer, tem)) - return Qnil; - } + if (EQ (tem, XWINDOW (minibuf_window)->buffer) + && EQ (buffer, Fother_buffer (buffer, Qnil, Qnil))) + return Qnil; /* Now there is no question: we can kill the buffer. */ @@ -1564,11 +1626,10 @@ with SIGHUP. */) kill_buffer_processes (buffer); UNGCPRO; - /* Killing buffer processes may run sentinels which may - have called kill-buffer. */ - + /* Killing buffer processes may run sentinels which may have killed + our buffer. */ if (NILP (BVAR (b, name))) - return Qnil; + return Qt; /* These may run Lisp code and into infinite loops (if someone insisted on circular lists) so allow quitting here. */ @@ -1580,8 +1641,7 @@ with SIGHUP. */) Vinhibit_quit = Qt; /* Remove the buffer from the list of all buffers. */ Vbuffer_alist = Fdelq (Frassq (buffer, Vbuffer_alist), Vbuffer_alist); - /* If replace_buffer_in_windows didn't do its job correctly fix that - now. */ + /* If replace_buffer_in_windows didn't do its job fix that now. */ replace_buffer_in_windows_safely (buffer); Vinhibit_quit = tem; @@ -1599,6 +1659,10 @@ with SIGHUP. */) internal_delete_file (BVAR (b, auto_save_file_name)); } + /* Deleting an auto-save file could have killed our buffer. */ + if (NILP (BVAR (b, name))) + return Qt; + if (b->base_buffer) { /* Unchain all markers that belong to this indirect buffer. @@ -1624,7 +1688,7 @@ with SIGHUP. */) m = next; } BUF_MARKERS (b) = NULL; - BUF_INTERVALS (b) = NULL_INTERVAL; + buffer_set_intervals (b, NULL); /* Perhaps we should explicitly free the interval tree here... */ } @@ -1639,7 +1703,15 @@ with SIGHUP. */) 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) @@ -1695,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, f->buffer_list))); + FSET (f, buried_buffer_list, Fdelq (buffer, f->buried_buffer_list)); /* Run buffer-list-update-hook. */ if (!NILP (Vrun_hooks)) @@ -1733,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, f->buffer_list)); + FSET (f, buried_buffer_list, + Fcons (buffer, Fdelq (buffer, f->buried_buffer_list))); /* Run buffer-list-update-hook. */ if (!NILP (Vrun_hooks)) @@ -1751,7 +1824,7 @@ Use this function before selecting the buffer, since it may need to inspect the current buffer's major mode. */) (Lisp_Object buffer) { - int count; + ptrdiff_t count; Lisp_Object function; CHECK_BUFFER (buffer); @@ -1963,16 +2036,15 @@ validate_region (register Lisp_Object *b, register Lisp_Object *e) tem = *b; *b = *e; *e = tem; } - if (!(BEGV <= XINT (*b) && XINT (*b) <= XINT (*e) - && XINT (*e) <= ZV)) + if (! (BEGV <= XINT (*b) && XINT (*e) <= ZV)) args_out_of_range (*b, *e); } /* Advance BYTE_POS up to a character boundary and return the adjusted position. */ -static EMACS_INT -advance_to_char_boundary (EMACS_INT byte_pos) +static ptrdiff_t +advance_to_char_boundary (ptrdiff_t byte_pos) { int c; @@ -1985,7 +2057,7 @@ advance_to_char_boundary (EMACS_INT byte_pos) { /* We should advance BYTE_POS only when C is a constituent of a multibyte sequence. */ - EMACS_INT orig_byte_pos = byte_pos; + ptrdiff_t orig_byte_pos = byte_pos; do { @@ -2028,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"); @@ -2051,20 +2123,21 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, eassert (current_buffer->text == ¤t_buffer->own_text); eassert (other_buffer->text == &other_buffer->own_text); #ifdef REL_ALLOC - r_alloc_reset_variable ((POINTER_TYPE **) ¤t_buffer->own_text.beg, - (POINTER_TYPE **) &other_buffer->own_text.beg); - r_alloc_reset_variable ((POINTER_TYPE **) &other_buffer->own_text.beg, - (POINTER_TYPE **) ¤t_buffer->own_text.beg); + r_alloc_reset_variable ((void **) ¤t_buffer->own_text.beg, + (void **) &other_buffer->own_text.beg); + r_alloc_reset_variable ((void **) &other_buffer->own_text.beg, + (void **) ¤t_buffer->own_text.beg); #endif /* REL_ALLOC */ - swapfield (pt, EMACS_INT); - swapfield (pt_byte, EMACS_INT); - swapfield (begv, EMACS_INT); - swapfield (begv_byte, EMACS_INT); - swapfield (zv, EMACS_INT); - swapfield (zv_byte, EMACS_INT); + swapfield (pt, ptrdiff_t); + swapfield (pt_byte, ptrdiff_t); + swapfield (begv, ptrdiff_t); + swapfield (begv_byte, ptrdiff_t); + swapfield (zv, ptrdiff_t); + 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 *); @@ -2072,7 +2145,7 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, other_buffer->prevent_redisplay_optimizations_p = 1; swapfield (overlays_before, struct Lisp_Overlay *); swapfield (overlays_after, struct Lisp_Overlay *); - swapfield (overlay_center, EMACS_INT); + swapfield (overlay_center, ptrdiff_t); swapfield_ (undo_list, Lisp_Object); swapfield_ (mark, Lisp_Object); swapfield_ (enable_multibyte_characters, Lisp_Object); @@ -2124,7 +2197,8 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, && (EQ (XWINDOW (w)->buffer, buf1) || EQ (XWINDOW (w)->buffer, buf2))) Fset_marker (XWINDOW (w)->pointm, - make_number (BUF_BEGV (XBUFFER (XWINDOW (w)->buffer))), + make_number + (BUF_BEGV (XBUFFER (XWINDOW (w)->buffer))), XWINDOW (w)->buffer); w = Fnext_window (w, Qt, Qt); } @@ -2155,7 +2229,7 @@ current buffer is cleared. */) { struct Lisp_Marker *tail, *markers; struct buffer *other; - EMACS_INT begv, zv; + ptrdiff_t begv, zv; int narrowed = (BEG != BEGV || Z != ZV); int modified_p = !NILP (Fbuffer_modified_p (Qnil)); Lisp_Object old_undo = BVAR (current_buffer, undo_list); @@ -2187,7 +2261,7 @@ current buffer is cleared. */) if (NILP (flag)) { - EMACS_INT pos, stop; + ptrdiff_t pos, stop; unsigned char *p; /* Do this first, so it can use CHAR_TO_BYTE @@ -2251,8 +2325,8 @@ current buffer is cleared. */) } else { - EMACS_INT pt = PT; - EMACS_INT pos, stop; + ptrdiff_t pt = PT; + ptrdiff_t pos, stop; unsigned char *p, *pend; /* Be sure not to have a multibyte sequence striding over the GAP. @@ -2268,7 +2342,7 @@ current buffer is cleared. */) while (! CHAR_HEAD_P (*q) && q > BEG_ADDR) q--; if (LEADING_CODE_P (*q)) { - EMACS_INT new_gpt = GPT_BYTE - (GPT_ADDR - q); + ptrdiff_t new_gpt = GPT_BYTE - (GPT_ADDR - q); move_gap_both (new_gpt, new_gpt); } @@ -2352,8 +2426,8 @@ current buffer is cleared. */) ZV = chars_in_text (BEG_ADDR, ZV_BYTE - BEG_BYTE) + BEG; { - EMACS_INT byte = advance_to_char_boundary (PT_BYTE); - EMACS_INT position; + ptrdiff_t byte = advance_to_char_boundary (PT_BYTE); + ptrdiff_t position; if (byte > GPT_BYTE) position = chars_in_text (GAP_END_ADDR, byte - GPT_BYTE) + GPT; @@ -2405,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) @@ -2517,20 +2591,20 @@ swap_out_buffer_local_variables (struct buffer *b) ptrdiff_t overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, ptrdiff_t *len_ptr, - EMACS_INT *next_ptr, EMACS_INT *prev_ptr, int change_req) + ptrdiff_t *next_ptr, ptrdiff_t *prev_ptr, int change_req) { Lisp_Object overlay, start, end; struct Lisp_Overlay *tail; ptrdiff_t idx = 0; ptrdiff_t len = *len_ptr; Lisp_Object *vec = *vec_ptr; - EMACS_INT next = ZV; - EMACS_INT prev = BEGV; + ptrdiff_t next = ZV; + ptrdiff_t prev = BEGV; int inhibit_storing = 0; for (tail = current_buffer->overlays_before; tail; tail = tail->next) { - EMACS_INT startpos, endpos; + ptrdiff_t startpos, endpos; XSETMISC (overlay, tail); @@ -2578,7 +2652,7 @@ overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, for (tail = current_buffer->overlays_after; tail; tail = tail->next) { - EMACS_INT startpos, endpos; + ptrdiff_t startpos, endpos; XSETMISC (overlay, tail); @@ -2651,21 +2725,21 @@ overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, static ptrdiff_t overlays_in (EMACS_INT beg, EMACS_INT end, int extend, Lisp_Object **vec_ptr, ptrdiff_t *len_ptr, - EMACS_INT *next_ptr, EMACS_INT *prev_ptr) + ptrdiff_t *next_ptr, ptrdiff_t *prev_ptr) { Lisp_Object overlay, ostart, oend; struct Lisp_Overlay *tail; ptrdiff_t idx = 0; ptrdiff_t len = *len_ptr; Lisp_Object *vec = *vec_ptr; - EMACS_INT next = ZV; - EMACS_INT prev = BEGV; + ptrdiff_t next = ZV; + ptrdiff_t prev = BEGV; int inhibit_storing = 0; int end_is_Z = end == Z; for (tail = current_buffer->overlays_before; tail; tail = tail->next) { - EMACS_INT startpos, endpos; + ptrdiff_t startpos, endpos; XSETMISC (overlay, tail); @@ -2712,7 +2786,7 @@ overlays_in (EMACS_INT beg, EMACS_INT end, int extend, for (tail = current_buffer->overlays_after; tail; tail = tail->next) { - EMACS_INT startpos, endpos; + ptrdiff_t startpos, endpos; XSETMISC (overlay, tail); @@ -2768,17 +2842,17 @@ overlays_in (EMACS_INT beg, EMACS_INT end, int extend, int mouse_face_overlay_overlaps (Lisp_Object overlay) { - EMACS_INT start = OVERLAY_POSITION (OVERLAY_START (overlay)); - EMACS_INT end = OVERLAY_POSITION (OVERLAY_END (overlay)); + ptrdiff_t start = OVERLAY_POSITION (OVERLAY_START (overlay)); + ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay)); ptrdiff_t n, i, size; 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); } @@ -2795,18 +2869,17 @@ mouse_face_overlay_overlaps (Lisp_Object overlay) /* Fast function to just test if we're at an overlay boundary. */ int -overlay_touches_p (EMACS_INT pos) +overlay_touches_p (ptrdiff_t pos) { Lisp_Object overlay; struct Lisp_Overlay *tail; for (tail = current_buffer->overlays_before; tail; tail = tail->next) { - EMACS_INT endpos; + ptrdiff_t endpos; XSETMISC (overlay ,tail); - if (!OVERLAYP (overlay)) - abort (); + eassert (OVERLAYP (overlay)); endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); if (endpos < pos) @@ -2817,11 +2890,10 @@ overlay_touches_p (EMACS_INT pos) for (tail = current_buffer->overlays_after; tail; tail = tail->next) { - EMACS_INT startpos; + ptrdiff_t startpos; XSETMISC (overlay, tail); - if (!OVERLAYP (overlay)) - abort (); + eassert (OVERLAYP (overlay)); startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); if (pos < startpos) @@ -2835,7 +2907,7 @@ overlay_touches_p (EMACS_INT pos) struct sortvec { Lisp_Object overlay; - EMACS_INT beg, end; + ptrdiff_t beg, end; EMACS_INT priority; }; @@ -2866,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. */ @@ -2877,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) { @@ -2958,7 +3029,7 @@ static void record_overlay_string (struct sortstrlist *ssl, Lisp_Object str, Lisp_Object str2, Lisp_Object pri, ptrdiff_t size) { - EMACS_INT nbytes; + ptrdiff_t nbytes; if (ssl->used == ssl->size) ssl->buf = xpalloc (ssl->buf, &ssl->size, 5, -1, sizeof *ssl->buf); @@ -3008,12 +3079,12 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str, PSTR, if that variable is non-null. The string may be overwritten by subsequent calls. */ -EMACS_INT -overlay_strings (EMACS_INT pos, struct window *w, unsigned char **pstr) +ptrdiff_t +overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr) { Lisp_Object overlay, window, str; struct Lisp_Overlay *ov; - EMACS_INT startpos, endpos; + ptrdiff_t startpos, endpos; int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); overlay_heads.used = overlay_heads.bytes = 0; @@ -3083,7 +3154,7 @@ overlay_strings (EMACS_INT pos, struct window *w, unsigned char **pstr) if (overlay_heads.bytes || overlay_tails.bytes) { Lisp_Object tem; - EMACS_INT i; + ptrdiff_t i; unsigned char *p; ptrdiff_t total; @@ -3097,7 +3168,7 @@ overlay_strings (EMACS_INT pos, struct window *w, unsigned char **pstr) p = overlay_str_buf; for (i = overlay_tails.used; --i >= 0;) { - EMACS_INT nbytes; + ptrdiff_t nbytes; tem = overlay_tails.buf[i].string; nbytes = copy_text (SDATA (tem), p, SBYTES (tem), @@ -3106,7 +3177,7 @@ overlay_strings (EMACS_INT pos, struct window *w, unsigned char **pstr) } for (i = 0; i < overlay_heads.used; ++i) { - EMACS_INT nbytes; + ptrdiff_t nbytes; tem = overlay_heads.buf[i].string; nbytes = copy_text (SDATA (tem), p, SBYTES (tem), @@ -3133,7 +3204,7 @@ overlay_strings (EMACS_INT pos, struct window *w, unsigned char **pstr) /* Shift overlays in BUF's overlay lists, to center the lists at POS. */ void -recenter_overlay_lists (struct buffer *buf, EMACS_INT pos) +recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos) { Lisp_Object overlay, beg, end; struct Lisp_Overlay *prev, *tail, *next; @@ -3148,22 +3219,7 @@ recenter_overlay_lists (struct buffer *buf, EMACS_INT 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); @@ -3171,7 +3227,7 @@ recenter_overlay_lists (struct buffer *buf, EMACS_INT pos) if (OVERLAY_POSITION (end) > pos) { /* OVERLAY needs to be moved. */ - EMACS_INT where = OVERLAY_POSITION (beg); + ptrdiff_t where = OVERLAY_POSITION (beg); struct Lisp_Overlay *other, *other_prev; /* Splice the cons cell TAIL out of overlays_before. */ @@ -3188,7 +3244,7 @@ recenter_overlay_lists (struct buffer *buf, EMACS_INT pos) Lisp_Object otherbeg, otheroverlay; XSETMISC (otheroverlay, other); - eassert (OVERLAY_VALID (otheroverlay)); + eassert (OVERLAYP (otheroverlay)); otherbeg = OVERLAY_START (otheroverlay); if (OVERLAY_POSITION (otherbeg) >= where) @@ -3216,22 +3272,7 @@ recenter_overlay_lists (struct buffer *buf, EMACS_INT 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); @@ -3244,7 +3285,7 @@ recenter_overlay_lists (struct buffer *buf, EMACS_INT pos) if (OVERLAY_POSITION (end) <= pos) { /* OVERLAY needs to be moved. */ - EMACS_INT where = OVERLAY_POSITION (end); + ptrdiff_t where = OVERLAY_POSITION (end); struct Lisp_Overlay *other, *other_prev; /* Splice the cons cell TAIL out of overlays_after. */ @@ -3261,7 +3302,7 @@ recenter_overlay_lists (struct buffer *buf, EMACS_INT pos) Lisp_Object otherend, otheroverlay; XSETMISC (otheroverlay, other); - eassert (OVERLAY_VALID (otheroverlay)); + eassert (OVERLAYP (otheroverlay)); otherend = OVERLAY_END (otheroverlay); if (OVERLAY_POSITION (otherend) <= where) @@ -3282,7 +3323,7 @@ recenter_overlay_lists (struct buffer *buf, EMACS_INT pos) } void -adjust_overlays_for_insert (EMACS_INT pos, EMACS_INT length) +adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length) { /* After an insertion, the lists are still sorted properly, but we may need to update the value of the overlay center. */ @@ -3291,13 +3332,13 @@ adjust_overlays_for_insert (EMACS_INT pos, EMACS_INT length) } void -adjust_overlays_for_delete (EMACS_INT pos, EMACS_INT length) +adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length) { if (current_buffer->overlay_center < pos) /* The deletion was to our right. No change needed; the before- and after-lists are still consistent. */ ; - else if (current_buffer->overlay_center > pos + length) + else if (current_buffer->overlay_center - pos > length) /* The deletion was to our left. We need to adjust the center value to account for the change in position, but the lists are consistent given the new value. */ @@ -3316,7 +3357,7 @@ adjust_overlays_for_delete (EMACS_INT pos, EMACS_INT length) Such an overlay might even have negative size at this point. If so, we'll make the overlay empty. */ void -fix_start_end_in_overlays (register EMACS_INT start, register EMACS_INT end) +fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end) { Lisp_Object overlay; struct Lisp_Overlay *before_list IF_LINT (= NULL); @@ -3329,7 +3370,7 @@ fix_start_end_in_overlays (register EMACS_INT start, register EMACS_INT end) current_buffer->overlays_before or overlays_after, depending which loop we're in. */ struct Lisp_Overlay *tail, *parent; - EMACS_INT startpos, endpos; + ptrdiff_t startpos, endpos; /* This algorithm shifts links around instead of consing and GCing. The loop invariant is that before_list (resp. after_list) is a @@ -3463,12 +3504,12 @@ fix_start_end_in_overlays (register EMACS_INT start, register EMACS_INT end) was at PREV, and now is at POS. */ void -fix_overlays_before (struct buffer *bp, EMACS_INT prev, EMACS_INT pos) +fix_overlays_before (struct buffer *bp, ptrdiff_t prev, ptrdiff_t pos) { /* If parent is nil, replace overlays_before; otherwise, parent->next. */ struct Lisp_Overlay *tail = bp->overlays_before, *parent = NULL, *right_pair; Lisp_Object tem; - EMACS_INT end IF_LINT (= 0); + ptrdiff_t end IF_LINT (= 0); /* After the insertion, the several overlays may be in incorrect order. The possibility is that, in the list `overlays_before', @@ -3592,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); @@ -3626,11 +3662,11 @@ for the rear of the overlay advance when text is inserted there /* Mark a section of BUF as needing redisplay because of overlays changes. */ static void -modify_overlay (struct buffer *buf, EMACS_INT start, EMACS_INT end) +modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end) { if (start > end) { - EMACS_INT temp = start; + ptrdiff_t temp = start; start = end; end = temp; } @@ -3652,18 +3688,17 @@ modify_overlay (struct buffer *buf, EMACS_INT start, EMACS_INT 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; } @@ -3677,9 +3712,10 @@ If BUFFER is omitted, and OVERLAY is in no buffer, put it in the current buffer. */) (Lisp_Object overlay, Lisp_Object beg, Lisp_Object end, Lisp_Object buffer) { - struct buffer *b, *ob; + struct buffer *b, *ob = 0; Lisp_Object obuffer; - int count = SPECPDL_INDEX (); + ptrdiff_t count = SPECPDL_INDEX (); + ptrdiff_t n_beg, n_end, o_beg IF_LINT (= 0), o_end IF_LINT (= 0); CHECK_OVERLAY (overlay); if (NILP (buffer)) @@ -3688,6 +3724,9 @@ buffer. */) XSETBUFFER (buffer, current_buffer); CHECK_BUFFER (buffer); + if (NILP (Fbuffer_live_p (buffer))) + error ("Attempt to move overlay to a dead buffer"); + if (MARKERP (beg) && ! EQ (Fmarker_buffer (beg), buffer)) error ("Marker points into wrong buffer"); @@ -3698,9 +3737,6 @@ buffer. */) CHECK_NUMBER_COERCE_MARKER (beg); CHECK_NUMBER_COERCE_MARKER (end); - if (XINT (beg) == XINT (end) && ! NILP (Foverlay_get (overlay, Qevaporate))) - return Fdelete_overlay (overlay); - if (XINT (beg) > XINT (end)) { Lisp_Object temp; @@ -3711,61 +3747,57 @@ buffer. */) obuffer = Fmarker_buffer (OVERLAY_START (overlay)); b = XBUFFER (buffer); - ob = BUFFERP (obuffer) ? XBUFFER (obuffer) : (struct buffer *) 0; + + if (!NILP (obuffer)) + { + ob = XBUFFER (obuffer); + + o_beg = OVERLAY_POSITION (OVERLAY_START (overlay)); + o_end = OVERLAY_POSITION (OVERLAY_END (overlay)); + + ob->overlays_before = + unchain_overlay (ob->overlays_before, XOVERLAY (overlay)); + ob->overlays_after = + unchain_overlay (ob->overlays_after, XOVERLAY (overlay)); + eassert (XOVERLAY (overlay)->next == NULL); + } + + /* Set the overlay boundaries, which may clip them. */ + Fset_marker (OVERLAY_START (overlay), beg, buffer); + Fset_marker (OVERLAY_END (overlay), end, buffer); + + n_beg = marker_position (OVERLAY_START (overlay)); + n_end = marker_position (OVERLAY_END (overlay)); /* If the overlay has changed buffers, do a thorough redisplay. */ if (!EQ (buffer, obuffer)) { /* Redisplay where the overlay was. */ - if (!NILP (obuffer)) - { - EMACS_INT o_beg; - EMACS_INT o_end; - - o_beg = OVERLAY_POSITION (OVERLAY_START (overlay)); - o_end = OVERLAY_POSITION (OVERLAY_END (overlay)); - - modify_overlay (ob, o_beg, o_end); - } + if (ob) + modify_overlay (ob, o_beg, o_end); /* Redisplay where the overlay is going to be. */ - modify_overlay (b, XINT (beg), XINT (end)); + modify_overlay (b, n_beg, n_end); } else /* Redisplay the area the overlay has just left, or just enclosed. */ { - EMACS_INT o_beg, o_end; - - o_beg = OVERLAY_POSITION (OVERLAY_START (overlay)); - o_end = OVERLAY_POSITION (OVERLAY_END (overlay)); - - if (o_beg == XINT (beg)) - modify_overlay (b, o_end, XINT (end)); - else if (o_end == XINT (end)) - modify_overlay (b, o_beg, XINT (beg)); + if (o_beg == n_beg) + modify_overlay (b, o_end, n_end); + else if (o_end == n_end) + modify_overlay (b, o_beg, n_beg); else - { - if (XINT (beg) < o_beg) o_beg = XINT (beg); - if (XINT (end) > o_end) o_end = XINT (end); - modify_overlay (b, o_beg, o_end); - } - } - - if (!NILP (obuffer)) - { - ob->overlays_before - = unchain_overlay (ob->overlays_before, XOVERLAY (overlay)); - ob->overlays_after - = unchain_overlay (ob->overlays_after, XOVERLAY (overlay)); - eassert (XOVERLAY (overlay)->next == NULL); + modify_overlay (b, min (o_beg, n_beg), max (o_end, n_end)); } - Fset_marker (OVERLAY_START (overlay), beg, buffer); - Fset_marker (OVERLAY_END (overlay), end, buffer); + /* Delete the overlay if it is empty after clipping and has the + evaporate property. */ + if (n_beg == n_end && !NILP (Foverlay_get (overlay, Qevaporate))) + return unbind_to (count, Fdelete_overlay (overlay)); - /* Put the overlay on the wrong list. */ - end = OVERLAY_END (overlay); - if (OVERLAY_POSITION (end) < b->overlay_center) + /* Put the overlay into the new buffer's overlay lists, first on the + wrong list. */ + if (n_end < b->overlay_center) { XOVERLAY (overlay)->next = b->overlays_after; b->overlays_after = XOVERLAY (overlay); @@ -3788,7 +3820,7 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0, { Lisp_Object buffer; struct buffer *b; - int count = SPECPDL_INDEX (); + ptrdiff_t count = SPECPDL_INDEX (); CHECK_OVERLAY (overlay); @@ -3799,14 +3831,13 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0, b = XBUFFER (buffer); specbind (Qinhibit_quit, Qt); - b->overlays_before = unchain_overlay (b->overlays_before,XOVERLAY (overlay)); - b->overlays_after = unchain_overlay (b->overlays_after, XOVERLAY (overlay)); + b->overlays_before + = unchain_overlay (b->overlays_before, XOVERLAY (overlay)); + b->overlays_after + = 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 @@ -3874,12 +3905,12 @@ 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. */ noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, - (EMACS_INT *) 0, (EMACS_INT *) 0, 0); + 0, 0, 0); /* Make a list of them all. */ result = Flist (noverlays, overlay_vec); @@ -3905,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. */ @@ -3927,26 +3958,26 @@ the value is (point-max). */) (Lisp_Object pos) { ptrdiff_t i, len, noverlays; - EMACS_INT endpos; + ptrdiff_t endpos; Lisp_Object *overlay_vec; 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. endpos gets the position where the next overlay starts. */ noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, - &endpos, (EMACS_INT *) 0, 1); + &endpos, 0, 1); /* If any of these overlays ends before endpos, use its ending point instead. */ for (i = 0; i < noverlays; i++) { Lisp_Object oend; - EMACS_INT oendpos; + ptrdiff_t oendpos; oend = OVERLAY_END (overlay_vec[i]); oendpos = OVERLAY_POSITION (oend); @@ -3965,7 +3996,7 @@ If there are no overlay boundaries from (point-min) to POS, the value is (point-min). */) (Lisp_Object pos) { - EMACS_INT prevpos; + ptrdiff_t prevpos; Lisp_Object *overlay_vec; ptrdiff_t len; @@ -3977,13 +4008,13 @@ 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. prevpos gets the position of the previous change. */ overlays_at (XINT (pos), 1, &overlay_vec, &len, - (EMACS_INT *) 0, &prevpos, 1); + 0, &prevpos, 1); xfree (overlay_vec); return make_number (prevpos); @@ -4021,9 +4052,11 @@ That makes overlay lookup faster for positions near POS (but perhaps slower for positions far away from POS). */) (Lisp_Object pos) { + ptrdiff_t p; CHECK_NUMBER_COERCE_MARKER (pos); - recenter_overlay_lists (current_buffer, XINT (pos)); + p = clip_to_bounds (PTRDIFF_MIN, XINT (pos), PTRDIFF_MAX); + recenter_overlay_lists (current_buffer, p); return Qnil; } @@ -4058,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)); + set_overlay_plist + (overlay, Fcons (prop, Fcons (value, XOVERLAY (overlay)->plist))); found: if (! NILP (buffer)) { @@ -4090,7 +4123,7 @@ VALUE will be returned.*/) static Lisp_Object last_overlay_modification_hooks; /* Number of elements actually used in last_overlay_modification_hooks. */ -static int last_overlay_modification_hooks_used; +static ptrdiff_t last_overlay_modification_hooks_used; /* Add one functionlist/overlay pair to the end of last_overlay_modification_hooks. */ @@ -4098,11 +4131,11 @@ static int last_overlay_modification_hooks_used; static void add_overlay_mod_hooklist (Lisp_Object functionlist, Lisp_Object overlay) { - int oldsize = ASIZE (last_overlay_modification_hooks); + ptrdiff_t oldsize = ASIZE (last_overlay_modification_hooks); - if (last_overlay_modification_hooks_used == oldsize) - last_overlay_modification_hooks = larger_vector - (last_overlay_modification_hooks, oldsize * 2, Qnil); + if (oldsize - 1 <= last_overlay_modification_hooks_used) + last_overlay_modification_hooks = + larger_vector (last_overlay_modification_hooks, 2, -1); ASET (last_overlay_modification_hooks, last_overlay_modification_hooks_used, functionlist); last_overlay_modification_hooks_used++; ASET (last_overlay_modification_hooks, last_overlay_modification_hooks_used, @@ -4151,7 +4184,7 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, int after, last_overlay_modification_hooks_used = 0; for (tail = current_buffer->overlays_before; tail; tail = tail->next) { - EMACS_INT startpos, endpos; + ptrdiff_t startpos, endpos; Lisp_Object ostart, oend; XSETMISC (overlay, tail); @@ -4188,7 +4221,7 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, int after, for (tail = current_buffer->overlays_after; tail; tail = tail->next) { - EMACS_INT startpos, endpos; + ptrdiff_t startpos, endpos; Lisp_Object ostart, oend; XSETMISC (overlay, tail); @@ -4229,12 +4262,12 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, int after, /* Call the functions recorded in last_overlay_modification_hooks. First copy the vector contents, in case some of these hooks do subsequent modification of the buffer. */ - int size = last_overlay_modification_hooks_used; - Lisp_Object *copy = (Lisp_Object *) alloca (size * sizeof (Lisp_Object)); - int i; + ptrdiff_t size = last_overlay_modification_hooks_used; + 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; @@ -4271,7 +4304,7 @@ call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, int after, /* Delete any zero-sized overlays at position POS, if the `evaporate' property is set. */ void -evaporate_overlays (EMACS_INT pos) +evaporate_overlays (ptrdiff_t pos) { Lisp_Object overlay, hit_list; struct Lisp_Overlay *tail; @@ -4280,7 +4313,7 @@ evaporate_overlays (EMACS_INT pos) if (pos <= current_buffer->overlay_center) for (tail = current_buffer->overlays_before; tail; tail = tail->next) { - EMACS_INT endpos; + ptrdiff_t endpos; XSETMISC (overlay, tail); endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); if (endpos < pos) @@ -4292,7 +4325,7 @@ evaporate_overlays (EMACS_INT pos) else for (tail = current_buffer->overlays_after; tail; tail = tail->next) { - EMACS_INT startpos; + ptrdiff_t startpos; XSETMISC (overlay, tail); startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); if (startpos > pos) @@ -4383,7 +4416,7 @@ struct mmap_region /* Pointer to the location holding the address of the memory allocated with the mmap'd block. The variable actually points after this structure. */ - POINTER_TYPE **var; + void **var; /* Next and previous in list of all mmap'd regions. */ struct mmap_region *next, *prev; @@ -4430,7 +4463,7 @@ static int mmap_initialized_p; to the start of the user-visible part of the region. */ #define MMAP_USER_AREA(P) \ - ((POINTER_TYPE *) ((char *) (P) + MMAP_REGION_STRUCT_SIZE)) + ((void *) ((char *) (P) + MMAP_REGION_STRUCT_SIZE)) #define MEM_ALIGN sizeof (double) @@ -4479,7 +4512,7 @@ mmap_init (void) is at END - 1. */ static struct mmap_region * -mmap_find (POINTER_TYPE *start, POINTER_TYPE *end) +mmap_find (void *start, void *end) { struct mmap_region *r; char *s = (char *) start, *e = (char *) end; @@ -4517,7 +4550,7 @@ mmap_free_1 (struct mmap_region *r) else mmap_regions = r->next; - if (munmap ((POINTER_TYPE *) r, r->nbytes_mapped) == -1) + if (munmap (r, r->nbytes_mapped) == -1) { fprintf (stderr, "munmap: %s\n", emacs_strerror (errno)); return 0; @@ -4559,13 +4592,13 @@ mmap_enlarge (struct mmap_region *r, int npages) I'm not sure this is worth doing, let's see. */ if (!MMAP_ALLOCATED_P (region_end, region_end + nbytes)) { - POINTER_TYPE *p; + void *p; p = mmap (region_end, nbytes, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, mmap_fd, 0); if (p == MAP_FAILED) ; /* fprintf (stderr, "mmap: %s\n", emacs_strerror (errno)); */ - else if (p != (POINTER_TYPE *) region_end) + else if (p != region_end) { /* Kernels are free to choose a different address. In that case, unmap what we've mapped above; we have @@ -4627,8 +4660,8 @@ mmap_set_vars (int restore_p) If we can't allocate the necessary memory, set *VAR to null, and return null. */ -static POINTER_TYPE * -mmap_alloc (POINTER_TYPE **var, size_t nbytes) +static void * +mmap_alloc (void **var, size_t nbytes) { void *p; size_t map; @@ -4669,7 +4702,7 @@ mmap_alloc (POINTER_TYPE **var, size_t nbytes) PTR. Store 0 in *PTR to show there's no block allocated. */ static void -mmap_free (POINTER_TYPE **var) +mmap_free (void **var) { mmap_init (); @@ -4686,10 +4719,10 @@ mmap_free (POINTER_TYPE **var) and return this value. If more memory cannot be allocated, then leave *VAR unchanged, and return null. */ -static POINTER_TYPE * -mmap_realloc (POINTER_TYPE **var, size_t nbytes) +static void * +mmap_realloc (void **var, size_t nbytes) { - POINTER_TYPE *result; + void *result; mmap_init (); @@ -4708,7 +4741,7 @@ mmap_realloc (POINTER_TYPE **var, size_t nbytes) if (room < nbytes) { /* Must enlarge. */ - POINTER_TYPE *old_ptr = *var; + void *old_ptr = *var; /* Try to map additional pages at the end of the region. If that fails, allocate a new region, copy data @@ -4770,13 +4803,13 @@ mmap_realloc (POINTER_TYPE **var, size_t nbytes) static void alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes) { - POINTER_TYPE *p; + void *p; BLOCK_INPUT; #if defined USE_MMAP_FOR_BUFFERS - p = mmap_alloc ((POINTER_TYPE **) &b->text->beg, nbytes); + p = mmap_alloc ((void **) &b->text->beg, nbytes); #elif defined REL_ALLOC - p = r_alloc ((POINTER_TYPE **) &b->text->beg, nbytes); + p = r_alloc ((void **) &b->text->beg, nbytes); #else p = xmalloc (nbytes); #endif @@ -4795,16 +4828,16 @@ alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes) shrink it. */ void -enlarge_buffer_text (struct buffer *b, EMACS_INT delta) +enlarge_buffer_text (struct buffer *b, ptrdiff_t delta) { - POINTER_TYPE *p; + void *p; ptrdiff_t nbytes = (BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1 + delta); BLOCK_INPUT; #if defined USE_MMAP_FOR_BUFFERS - p = mmap_realloc ((POINTER_TYPE **) &b->text->beg, nbytes); + p = mmap_realloc ((void **) &b->text->beg, nbytes); #elif defined REL_ALLOC - p = r_re_alloc ((POINTER_TYPE **) &b->text->beg, nbytes); + p = r_re_alloc ((void **) &b->text->beg, nbytes); #else p = xrealloc (b->text->beg, nbytes); #endif @@ -4828,9 +4861,9 @@ free_buffer_text (struct buffer *b) BLOCK_INPUT; #if defined USE_MMAP_FOR_BUFFERS - mmap_free ((POINTER_TYPE **) &b->text->beg); + mmap_free ((void **) &b->text->beg); #elif defined REL_ALLOC - r_alloc_free ((POINTER_TYPE **) &b->text->beg); + r_alloc_free ((void **) &b->text->beg); #else xfree (b->text->beg); #endif @@ -4849,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); @@ -4863,27 +4901,28 @@ 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; - BUF_INTERVALS (&buffer_defaults) = 0; - BUF_INTERVALS (&buffer_local_symbols) = 0; - XSETPVECTYPESIZE (&buffer_defaults, PVEC_BUFFER, 0); + /* No one will share the text with these buffers, but let's play it safe. */ + buffer_defaults.indirections = 0; + buffer_local_symbols.indirections = 0; + buffer_set_intervals (&buffer_defaults, NULL); + buffer_set_intervals (&buffer_local_symbols, NULL); + 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; BVAR (&buffer_defaults, case_fold_search) = Qt; BVAR (&buffer_defaults, auto_fill_function) = Qnil; BVAR (&buffer_defaults, selective_display) = Qnil; -#ifndef old BVAR (&buffer_defaults, selective_display_ellipses) = Qt; -#endif BVAR (&buffer_defaults, abbrev_table) = Qnil; BVAR (&buffer_defaults, display_table) = Qnil; BVAR (&buffer_defaults, undo_list) = Qnil; @@ -4932,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); @@ -4962,9 +5001,7 @@ init_buffer_once (void) XSETFASTINT (BVAR (&buffer_local_flags, case_fold_search), idx); ++idx; XSETFASTINT (BVAR (&buffer_local_flags, auto_fill_function), idx); ++idx; XSETFASTINT (BVAR (&buffer_local_flags, selective_display), idx); ++idx; -#ifndef old XSETFASTINT (BVAR (&buffer_local_flags, selective_display_ellipses), idx); ++idx; -#endif XSETFASTINT (BVAR (&buffer_local_flags, tab_width), idx); ++idx; XSETFASTINT (BVAR (&buffer_local_flags, truncate_lines), idx); ++idx; XSETFASTINT (BVAR (&buffer_local_flags, word_wrap), idx); ++idx; @@ -5008,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; @@ -5023,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; } @@ -5045,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); } @@ -5066,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 @@ -5178,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, @@ -5328,31 +5366,40 @@ the mode line appears at the bottom. */); DEFVAR_PER_BUFFER ("mode-line-format", &BVAR (current_buffer, mode_line_format), Qnil, doc: /* Template for displaying mode line for current buffer. -Each buffer has its own value of this variable. -Value may be nil, a string, a symbol or a list or cons cell. + +The value may be nil, a string, a symbol or a list. + A value of nil means don't display a mode line. -For a symbol, its value is used (but it is ignored if t or nil). - A string appearing directly as the value of a symbol is processed verbatim - in that the %-constructs below are not recognized. - Note that unless the symbol is marked as a `risky-local-variable', all - properties in any strings, as well as all :eval and :propertize forms - in the value of that symbol will be ignored. -For a list of the form `(:eval FORM)', FORM is evaluated and the result - is used as a mode line element. Be careful--FORM should not load any files, - because that can cause an infinite recursion. -For a list of the form `(:propertize ELT PROPS...)', ELT is displayed - with the specified properties PROPS applied. -For a list whose car is a symbol, the symbol's value is taken, - and if that is non-nil, the cadr of the list is processed recursively. - Otherwise, the caddr of the list (if there is one) is processed. -For a list whose car is a string or list, each element is processed - recursively and the results are effectively concatenated. -For a list whose car is an integer, the cdr of the list is processed - and padded (if the number is positive) or truncated (if negative) - to the width specified by that number. + +For any symbol other than t or nil, the symbol's value is processed as + a mode line construct. As a special exception, if that value is a + string, the string is processed verbatim, without handling any + %-constructs (see below). Also, unless the symbol has a non-nil + `risky-local-variable' property, all properties in any strings, as + well as all :eval and :propertize forms in the value, are ignored. + +A list whose car is a string or list is processed by processing each + of the list elements recursively, as separate mode line constructs, + and concatenating the results. + +A list of the form `(:eval FORM)' is processed by evaluating FORM and + using the result as a mode line construct. Be careful--FORM should + not load any files, because that can cause an infinite recursion. + +A list of the form `(:propertize ELT PROPS...)' is processed by + processing ELT as the mode line construct, and adding the text + properties PROPS to the result. + +A list whose car is a symbol is processed by examining the symbol's + value, and, if that value is non-nil, processing the cadr of the list + recursively; and if that value is nil, processing the caddr of the + list recursively. + +A list whose car is an integer is processed by processing the cadr of + the list, and padding (if the number is positive) or truncating (if + negative) to the width specified by that number. + A string is printed verbatim in the mode line except for %-constructs: - (%-constructs are allowed when the string is the entire mode-line-format - or when it is found in a cons-cell or a list) %b -- print buffer name. %f -- print visited file name. %F -- print frame name. %* -- print %, * or hyphen. %+ -- print *, % or hyphen. @@ -5414,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. */); @@ -5500,7 +5547,13 @@ This variable has no effect if long lines are truncated (see `truncate-lines' and `truncate-partial-width-windows'). If you use word-wrapping, you might want to reduce the value of `truncate-partial-width-windows', since wrapping can make text readable -in narrower windows. */); +in narrower windows. + +Instead of setting this variable directly, most users should use +Visual Line mode . Visual Line mode, when enabled, sets `word-wrap' +to t, and additionally redefines simple editing commands to act on +visual lines rather than logical lines. See the documentation of +`visual-line-mode'. */); DEFVAR_PER_BUFFER ("default-directory", &BVAR (current_buffer, directory), make_number (Lisp_String), @@ -5539,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. @@ -5557,12 +5610,10 @@ A value of t means that the character ^M makes itself and all the rest of the line invisible; also, when saving the buffer in a file, save the ^M as a newline. */); -#ifndef old DEFVAR_PER_BUFFER ("selective-display-ellipses", &BVAR (current_buffer, selective_display_ellipses), Qnil, doc: /* Non-nil means display ... on previous line when a line is invisible. */); -#endif DEFVAR_PER_BUFFER ("overwrite-mode", &BVAR (current_buffer, overwrite_mode), Qnil, doc: /* Non-nil if self-insertion should replace existing text. @@ -5797,9 +5848,9 @@ An entry (TEXT . POSITION) represents the deletion of the string TEXT from (abs POSITION). If POSITION is positive, point was at the front of the text being deleted; if negative, point was at the end. -An entry (t HIGH . LOW) indicates that the buffer previously had -\"unmodified\" status. HIGH and LOW are the high and low 16-bit portions -of the visited file's modification time, as of that time. If the +An entry (t HIGH LOW USEC PSEC) indicates that the buffer was previously +unmodified; (HIGH LOW USEC PSEC) is in the same style as (current-time) +and is the visited file's modification time, as of that time. If the modification time of the most recent save is different, this entry is obsolete. @@ -5963,7 +6014,9 @@ Use Custom to set this variable and update the display." */); DEFVAR_LISP ("kill-buffer-query-functions", Vkill_buffer_query_functions, doc: /* List of functions called with no args to query before killing a buffer. The buffer being killed will be current while the functions are running. -If any of them returns nil, the buffer is not killed. */); + +If any of them returns nil, the buffer is not killed. Functions run by +this hook are supposed to not change the current buffer. */); Vkill_buffer_query_functions = Qnil; DEFVAR_LISP ("change-major-mode-hook", Vchange_major_mode_hook, @@ -5988,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);