X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/c752cfa916879f7415990855b52862dd585242ec..cfbf790d80eaa399afceecd9a6c3e2e76bca59b0:/src/buffer.c?ds=inline diff --git a/src/buffer.c b/src/buffer.c index 187277d663..aa3fcf8c23 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,6 +1,7 @@ /* Buffer manipulation primitives for GNU Emacs. -Copyright (C) 1985-1989, 1993-1995, 1997-2012 Free Software Foundation, Inc. +Copyright (C) 1985-1989, 1993-1995, 1997-2013 Free Software Foundation, +Inc. This file is part of GNU Emacs. @@ -26,7 +27,6 @@ along with GNU Emacs. If not, see . */ #include #include #include -#include #include #include @@ -44,7 +44,7 @@ along with GNU Emacs. If not, see . */ #include "keymap.h" #include "frame.h" -struct buffer *current_buffer; /* the current buffer */ +struct buffer *current_buffer; /* The current buffer. */ /* First buffer in chain of all buffers (in reverse order of creation). Threaded through ->header.next.buffer. */ @@ -74,12 +74,12 @@ struct buffer alignas (GCALIGNMENT) buffer_defaults; and the corresponding slot in buffer_defaults is not used. If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is - zero, that is a bug */ + zero, that is a bug. */ 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. */ + buffer-local. It is indexed and accessed in the same way as the above. */ struct buffer alignas (GCALIGNMENT) buffer_local_symbols; @@ -108,7 +108,7 @@ static void call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, static void swap_out_buffer_local_variables (struct buffer *b); static void reset_buffer_local_variables (struct buffer *, bool); -/* Alist of all buffer names vs the buffers. */ +/* Alist of all buffer names vs the buffers. */ /* This used to be a variable, but is no longer, to prevent lossage due to user rplac'ing this alist or its elements. */ Lisp_Object Vbuffer_alist; @@ -127,7 +127,7 @@ static Lisp_Object Qpermanent_local_hook; static Lisp_Object Qprotected_field; -static Lisp_Object QSFundamental; /* A string "Fundamental" */ +static Lisp_Object QSFundamental; /* A string "Fundamental". */ static Lisp_Object Qkill_buffer_hook; static Lisp_Object Qbuffer_list_update_hook; @@ -151,230 +151,227 @@ static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t); static Lisp_Object buffer_lisp_local_variables (struct buffer *, bool); /* These setters are used only in this file, so they can be private. */ -static inline void +static void bset_abbrev_mode (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (abbrev_mode) = val; } -static inline void +static void bset_abbrev_table (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (abbrev_table) = val; } -static inline void +static void bset_auto_fill_function (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (auto_fill_function) = val; } -static inline void +static void bset_auto_save_file_format (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (auto_save_file_format) = val; } -static inline void +static void bset_auto_save_file_name (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (auto_save_file_name) = val; } -static inline void +static void bset_backed_up (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (backed_up) = val; } -static inline void +static void bset_begv_marker (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (begv_marker) = val; } -static inline void +static void bset_bidi_display_reordering (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (bidi_display_reordering) = val; } -static inline void +static void bset_buffer_file_coding_system (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (buffer_file_coding_system) = val; } -static inline void +static void bset_cache_long_line_scans (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (cache_long_line_scans) = val; } -static inline void +static void bset_case_fold_search (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (case_fold_search) = val; } -static inline void +static void bset_ctl_arrow (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (ctl_arrow) = val; } -static inline void +static void bset_cursor_in_non_selected_windows (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (cursor_in_non_selected_windows) = val; } -static inline void +static void bset_cursor_type (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (cursor_type) = val; } -static inline void +static void bset_display_table (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (display_table) = val; } -static inline void +static void bset_extra_line_spacing (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (extra_line_spacing) = val; } -static inline void +static void bset_file_format (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (file_format) = val; } -static inline void +static void bset_file_truename (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (file_truename) = val; } -static inline void +static void bset_fringe_cursor_alist (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (fringe_cursor_alist) = val; } -static inline void +static void bset_fringe_indicator_alist (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (fringe_indicator_alist) = val; } -static inline void +static void bset_fringes_outside_margins (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (fringes_outside_margins) = val; } -static inline void +static void bset_header_line_format (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (header_line_format) = val; } -static inline void +static void bset_indicate_buffer_boundaries (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (indicate_buffer_boundaries) = val; } -static inline void +static void bset_indicate_empty_lines (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (indicate_empty_lines) = val; } -static inline void +static void bset_invisibility_spec (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (invisibility_spec) = val; } -static inline void +static void bset_left_fringe_width (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (left_fringe_width) = val; } -static inline void +static void bset_major_mode (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (major_mode) = val; } -static inline void +static void bset_mark (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (mark) = val; } -static inline void +static void bset_minor_modes (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (minor_modes) = val; } -static inline void +static void bset_mode_line_format (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (mode_line_format) = val; } -static inline void +static void bset_mode_name (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (mode_name) = val; } -static inline void +static void bset_name (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (name) = val; } -static inline void +static void bset_overwrite_mode (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (overwrite_mode) = val; } -static inline void +static void bset_pt_marker (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (pt_marker) = val; } -static inline void +static void bset_right_fringe_width (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (right_fringe_width) = val; } -static inline void +static void bset_save_length (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (save_length) = val; } -static inline void +static void bset_scroll_bar_width (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (scroll_bar_width) = val; } -static inline void +static void bset_scroll_down_aggressively (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (scroll_down_aggressively) = val; } -static inline void +static void bset_scroll_up_aggressively (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (scroll_up_aggressively) = val; } -static inline void +static void bset_selective_display (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (selective_display) = val; } -static inline void +static void bset_selective_display_ellipses (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (selective_display_ellipses) = val; } -static inline void +static void bset_vertical_scroll_bar_type (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (vertical_scroll_bar_type) = val; } -static inline void +static void bset_word_wrap (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (word_wrap) = val; } -static inline void +static void bset_zv_marker (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (zv_marker) = val; } -/* For debugging; temporary. See set_buffer_internal. */ -/* Lisp_Object Qlisp_mode, Vcheck_symbol; */ - void nsberror (Lisp_Object spec) { @@ -388,7 +385,7 @@ DEFUN ("buffer-live-p", Fbuffer_live_p, Sbuffer_live_p, 1, 1, 0, Value is nil if OBJECT is not a buffer or if it has been killed. */) (Lisp_Object object) { - return ((BUFFERP (object) && ! NILP (BVAR (XBUFFER (object), name))) + return ((BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))) ? Qt : Qnil); } @@ -407,7 +404,6 @@ followed by the rest of the buffers. */) Lisp_Object framelist, prevlist, tail; Lisp_Object args[3]; - CHECK_FRAME (frame); framelist = Fcopy_sequence (XFRAME (frame)->buffer_list); prevlist = Fnreverse (Fcopy_sequence (XFRAME (frame)->buried_buffer_list)); @@ -549,13 +545,15 @@ even if it is dead. The return value is never nil. */) b->base_buffer = NULL; /* No one shares the text with us now. */ b->indirections = 0; + /* No one shows us now. */ + b->window_count = 0; BUF_GAP_SIZE (b) = 20; - BLOCK_INPUT; + block_input (); /* We allocate extra 1-byte at the tail and keep it always '\0' for anchoring a search. */ alloc_buffer_text (b, BUF_GAP_SIZE (b) + 1); - UNBLOCK_INPUT; + unblock_input (); if (! BUF_BEG_ADDR (b)) buffer_memory_full (BUF_GAP_SIZE (b) + 1); @@ -575,6 +573,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_COMPACT (b) = 1; set_buffer_intervals (b, NULL); BUF_UNCHANGED_MODIFIED (b) = 1; BUF_OVERLAY_UNCHANGED_MODIFIED (b) = 1; @@ -652,13 +651,13 @@ copy_overlays (struct buffer *b, struct Lisp_Overlay *list) /* Set an appropriate overlay of B. */ -static inline void +static void set_buffer_overlays_before (struct buffer *b, struct Lisp_Overlay *o) { b->overlays_before = o; } -static inline void +static void set_buffer_overlays_after (struct buffer *b, struct Lisp_Overlay *o) { b->overlays_after = o; @@ -776,7 +775,7 @@ CLONE nil means the indirect buffer's state is reset to default values. */) base_buffer = Fget_buffer (base_buffer); if (NILP (base_buffer)) error ("No such buffer: `%s'", SDATA (tem)); - if (NILP (BVAR (XBUFFER (base_buffer), name))) + if (!BUFFER_LIVE_P (XBUFFER (base_buffer))) error ("Base buffer has been killed"); if (SCHARS (name) == 0) @@ -796,6 +795,8 @@ CLONE nil means the indirect buffer's state is reset to default values. */) b->indirections = -1; /* Notify base buffer that we share the text now. */ b->base_buffer->indirections++; + /* Always -1 for an indirect buffer. */ + b->window_count = -1; b->pt = b->base_buffer->pt; b->begv = b->base_buffer->begv; @@ -898,6 +899,8 @@ delete_all_overlays (struct buffer *b) { struct Lisp_Overlay *ov, *next; + /* FIXME: Since each drop_overlay will scan BUF_MARKERS to unlink its + markers, we have an unneeded O(N^2) behavior here. */ for (ov = b->overlays_before; ov; ov = next) { drop_overlay (b, ov); @@ -1336,15 +1339,19 @@ DEFUN ("set-buffer-modified-p", Fset_buffer_modified_p, Sset_buffer_modified_p, A non-nil FLAG means mark the buffer modified. */) (Lisp_Object flag) { - Lisp_Object fn, buffer, window; + Lisp_Object fn; #ifdef CLASH_DETECTION /* If buffer becoming modified, lock the file. If buffer becoming unmodified, unlock the file. */ - fn = BVAR (current_buffer, file_truename); + struct buffer *b = current_buffer->base_buffer + ? current_buffer->base_buffer + : current_buffer; + + fn = BVAR (b, file_truename); /* Test buffer-file-name so that binding it to nil is effective. */ - if (!NILP (fn) && ! NILP (BVAR (current_buffer, filename))) + if (!NILP (fn) && ! NILP (BVAR (b, filename))) { bool already = SAVE_MODIFF < MODIFF; if (!already && !NILP (flag)) @@ -1385,9 +1392,7 @@ A non-nil FLAG means mark the buffer modified. */) Ideally, I think there should be another mechanism for fontifying buffers without "modifying" buffers, or redisplay should be smarter about updating the `*' in mode lines. --gerd */ - XSETBUFFER (buffer, current_buffer); - window = Fget_buffer_window (buffer, Qt); - if (WINDOWP (window)) + if (buffer_window_count (current_buffer)) { ++update_mode_lines; current_buffer->prevent_redisplay_optimizations_p = 1; @@ -1525,6 +1530,16 @@ This does not change the name of the visited file (if any). */) return BVAR (current_buffer, name); } +/* True if B can be used as 'other-than-BUFFER' buffer. */ + +static bool +candidate_buffer (Lisp_Object b, Lisp_Object buffer) +{ + return (BUFFERP (b) && !EQ (b, buffer) + && BUFFER_LIVE_P (XBUFFER (b)) + && !BUFFER_HIDDEN_P (XBUFFER (b))); +} + DEFUN ("other-buffer", Fother_buffer, Sother_buffer, 0, 3, 0, doc: /* Return most recently selected buffer other than BUFFER. Buffers not visible in windows are preferred to visible buffers, unless @@ -1538,23 +1553,15 @@ list first, followed by the list of all buffers. If no other buffer exists, return the buffer `*scratch*' (creating it if necessary). */) (register Lisp_Object buffer, Lisp_Object visible_ok, Lisp_Object frame) { - Lisp_Object tail, buf, pred; - Lisp_Object notsogood = Qnil; + struct frame *f = decode_any_frame (frame); + Lisp_Object tail = f->buffer_list, pred = f->buffer_predicate; + Lisp_Object buf, notsogood = Qnil; - if (NILP (frame)) - frame = selected_frame; - - CHECK_FRAME (frame); - - pred = frame_buffer_predicate (frame); /* Consider buffers that have been seen in the frame first. */ - tail = XFRAME (frame)->buffer_list; for (; CONSP (tail); tail = XCDR (tail)) { buf = XCAR (tail); - if (BUFFERP (buf) && !EQ (buf, buffer) - && !NILP (BVAR (XBUFFER (buf), name)) - && (SREF (BVAR (XBUFFER (buf), name), 0) != ' ') + if (candidate_buffer (buf, buffer) /* If the frame has a buffer_predicate, disregard buffers that don't fit the predicate. */ && (NILP (pred) || !NILP (call1 (pred, buf)))) @@ -1572,9 +1579,7 @@ exists, return the buffer `*scratch*' (creating it if necessary). */) for (; CONSP (tail); tail = XCDR (tail)) { buf = Fcdr (XCAR (tail)); - if (BUFFERP (buf) && !EQ (buf, buffer) - && !NILP (BVAR (XBUFFER (buf), name)) - && (SREF (BVAR (XBUFFER (buf), name), 0) != ' ') + if (candidate_buffer (buf, buffer) /* If the frame has a buffer_predicate, disregard buffers that don't fit the predicate. */ && (NILP (pred) || !NILP (call1 (pred, buf)))) @@ -1610,13 +1615,10 @@ other_buffer_safely (Lisp_Object buffer) { Lisp_Object tail, buf; - tail = Vbuffer_alist; - for (; CONSP (tail); tail = XCDR (tail)) + for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail)) { buf = Fcdr (XCAR (tail)); - if (BUFFERP (buf) && !EQ (buf, buffer) - && !NILP (BVAR (XBUFFER (buf), name)) - && (SREF (BVAR (XBUFFER (buf), name), 0) != ' ')) + if (candidate_buffer (buf, buffer)) return buf; } @@ -1658,20 +1660,13 @@ No argument or nil as argument means do this for the current buffer. */) void 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); + BUFFER_CHECK_INDIRECTION (buffer); /* Skip dead buffers, indirect buffers and buffers which aren't changed since last compaction. */ - if (!NILP (buffer->INTERNAL_FIELD (name)) + if (BUFFER_LIVE_P (buffer) && (buffer->base_buffer == NULL) - && (buffer->text->compact != buffer->text->modiff)) + && (BUF_COMPACT (buffer) != BUF_MODIFF (buffer))) { /* If a buffer's undo list is Qt, that means that undo is turned off in that buffer. Calling truncate_undo_list on @@ -1684,19 +1679,15 @@ compact_buffer (struct buffer *buffer) 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; - } + size, or larger than GAP_BYTES_DFL bytes, then shrink it + accordingly. Keep a minimum size of GAP_BYTES_MIN bytes. */ + ptrdiff_t size = clip_to_bounds (GAP_BYTES_MIN, + BUF_Z_BYTE (buffer) / 10, + GAP_BYTES_DFL); + if (BUF_GAP_SIZE (buffer) > size) + make_gap_1 (buffer, -(BUF_GAP_SIZE (buffer) - size)); } - buffer->text->compact = buffer->text->modiff; + BUF_COMPACT (buffer) = BUF_MODIFF (buffer); } } @@ -1734,7 +1725,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) b = XBUFFER (buffer); /* Avoid trouble for buffer already dead. */ - if (NILP (BVAR (b, name))) + if (!BUFFER_LIVE_P (b)) return Qnil; /* Query if the buffer is still modified. */ @@ -1770,7 +1761,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) } /* If the hooks have killed the buffer, exit now. */ - if (NILP (BVAR (b, name))) + if (!BUFFER_LIVE_P (b)) return Qt; /* We have no more questions to ask. Verify that it is valid @@ -1802,7 +1793,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) UNGCPRO; /* Exit if we now have killed the base buffer (Bug#11665). */ - if (NILP (BVAR (b, name))) + if (!BUFFER_LIVE_P (b)) return Qt; } @@ -1813,7 +1804,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) replace_buffer_in_windows (buffer); /* Exit if replacing the buffer in windows has killed our buffer. */ - if (NILP (BVAR (b, name))) + if (!BUFFER_LIVE_P (b)) return Qt; /* Make this buffer not be current. Exit if it is the sole visible @@ -1846,7 +1837,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) /* Killing buffer processes may run sentinels which may have killed our buffer. */ - if (NILP (BVAR (b, name))) + if (!BUFFER_LIVE_P (b)) return Qt; /* These may run Lisp code and into infinite loops (if someone @@ -1878,7 +1869,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) } /* Deleting an auto-save file could have killed our buffer. */ - if (NILP (BVAR (b, name))) + if (!BUFFER_LIVE_P (b)) return Qt; if (b->base_buffer) @@ -1886,12 +1877,16 @@ cleaning up all windows currently displaying the buffer to be killed. */) /* Unchain all markers that belong to this indirect buffer. Don't unchain the markers that belong to the base buffer or its other indirect buffers. */ - for (m = BUF_MARKERS (b); m; ) + struct Lisp_Marker **mp = &BUF_MARKERS (b); + while ((m = *mp)) { - struct Lisp_Marker *next = m->next; if (m->buffer == b) - unchain_marker (m); - m = next; + { + m->buffer = NULL; + *mp = m->next; + } + else + mp = &m->next; } } else @@ -1908,8 +1903,12 @@ cleaning up all windows currently displaying the buffer to be killed. */) BUF_MARKERS (b) = NULL; set_buffer_intervals (b, NULL); - /* Perhaps we should explicitly free the interval tree here... */ + /* Perhaps we should explicitly free the interval tree here... */ } + /* Since we've unlinked the markers, the overlays can't be here any more + either. */ + b->overlays_before = NULL; + b->overlays_after = NULL; /* Reset the local variables, so that this buffer's local values won't be protected from GC. They would be protected @@ -1920,17 +1919,23 @@ cleaning up all windows currently displaying the buffer to be killed. */) bset_name (b, Qnil); - BLOCK_INPUT; + block_input (); 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); + /* Make sure that we wasn't confused. */ + eassert (b->window_count == -1); } else - /* No one shares our buffer text, can free it. */ - free_buffer_text (b); + { + /* Make sure that no one shows us. */ + eassert (b->window_count == 0); + /* No one shares our buffer text, can free it. */ + free_buffer_text (b); + } if (b->newline_cache) { @@ -1943,7 +1948,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) b->width_run_cache = 0; } bset_width_table (b, Qnil); - UNBLOCK_INPUT; + unblock_input (); bset_undo_list (b, Qnil); /* Run buffer-list-update-hook. */ @@ -2037,7 +2042,7 @@ DEFUN ("bury-buffer-internal", Fbury_buffer_internal, Sbury_buffer_internal, DEFUN ("set-buffer-major-mode", Fset_buffer_major_mode, Sset_buffer_major_mode, 1, 1, 0, doc: /* Set an appropriate major mode for BUFFER. For the *scratch* buffer, use `initial-major-mode', otherwise choose a mode -according to `default-major-mode'. +according to the default value of `major-mode'. Use this function before selecting the buffer, since it may need to inspect the current buffer's major mode. */) (Lisp_Object buffer) @@ -2047,7 +2052,7 @@ the current buffer's major mode. */) CHECK_BUFFER (buffer); - if (NILP (BVAR (XBUFFER (buffer), name))) + if (!BUFFER_LIVE_P (XBUFFER (buffer))) error ("Attempt to set major mode for a dead buffer"); if (strcmp (SSDATA (BVAR (XBUFFER (buffer), name)), "*scratch*") == 0) @@ -2102,6 +2107,8 @@ set_buffer_internal_1 (register struct buffer *b) if (current_buffer == b) return; + BUFFER_CHECK_INDIRECTION (b); + old_buf = current_buffer; current_buffer = b; last_known_column_point = -1; /* invalidate indentation cache */ @@ -2173,7 +2180,7 @@ set_buffer_temp (struct buffer *b) DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0, doc: /* Make buffer BUFFER-OR-NAME current for editing operations. BUFFER-OR-NAME may be a buffer or the name of an existing buffer. See -also `save-excursion' when you want to make a buffer current +also `with-current-buffer' when you want to make a buffer current temporarily. This function does not display the buffer, so its effect ends when the current command terminates. Use `switch-to-buffer' or `pop-to-buffer' to switch buffers permanently. */) @@ -2183,7 +2190,7 @@ ends when the current command terminates. Use `switch-to-buffer' or buffer = Fget_buffer (buffer_or_name); if (NILP (buffer)) nsberror (buffer_or_name); - if (NILP (BVAR (XBUFFER (buffer), name))) + if (!BUFFER_LIVE_P (XBUFFER (buffer))) error ("Selecting deleted buffer"); set_buffer_internal (XBUFFER (buffer)); return buffer; @@ -2194,7 +2201,7 @@ ends when the current command terminates. Use `switch-to-buffer' or Lisp_Object set_buffer_if_live (Lisp_Object buffer) { - if (! NILP (BVAR (XBUFFER (buffer), name))) + if (BUFFER_LIVE_P (XBUFFER (buffer))) set_buffer_internal (XBUFFER (buffer)); return Qnil; } @@ -2289,7 +2296,7 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, CHECK_BUFFER (buffer); other_buffer = XBUFFER (buffer); - if (NILP (BVAR (other_buffer, name))) + if (!BUFFER_LIVE_P (other_buffer)) error ("Cannot swap a dead buffer's text"); /* Actually, it probably works just fine. @@ -2461,7 +2468,7 @@ current buffer is cleared. */) begv = BEGV, zv = ZV; if (narrowed) - Fwiden (); + error ("Changing multibyteness in a narrowed buffer"); if (NILP (flag)) { @@ -2677,15 +2684,16 @@ current buffer is cleared. */) UNGCPRO; - /* Changing the multibyteness of a buffer means that all windows - showing that buffer must be updated thoroughly. */ current_buffer->prevent_redisplay_optimizations_p = 1; - ++windows_or_buffers_changed; + + /* If buffer is shown in a window, let redisplay consider other windows. */ + if (buffer_window_count (current_buffer)) + ++windows_or_buffers_changed; /* Copy this buffer's new multibyte status into all of its indirect buffers. */ FOR_EACH_BUFFER (other) - if (other->base_buffer == current_buffer && !NILP (BVAR (other, name))) + if (other->base_buffer == current_buffer && BUFFER_LIVE_P (other)) { BVAR (other, enable_multibyte_characters) = BVAR (current_buffer, enable_multibyte_characters); @@ -3131,8 +3139,8 @@ compare_overlays (const void *v1, const void *v2) between "equal" overlays. The result can still change between invocations of Emacs, but it won't change in the middle of `find_field' (bug#6830). */ - if (XHASH (s1->overlay) != XHASH (s2->overlay)) - return XHASH (s1->overlay) < XHASH (s2->overlay) ? -1 : 1; + if (!EQ (s1->overlay, s2->overlay)) + return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1; return 0; } @@ -3143,7 +3151,10 @@ ptrdiff_t sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) { ptrdiff_t i, j; - struct sortvec *sortvec = alloca (noverlays * sizeof *sortvec); + USE_SAFE_ALLOCA; + struct sortvec *sortvec; + + SAFE_NALLOCA (sortvec, 1, noverlays); /* Put the valid and relevant overlays into sortvec. */ @@ -3189,6 +3200,8 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) for (i = 0; i < noverlays; i++) overlay_vec[i] = sortvec[i].overlay; + + SAFE_FREE (); return (noverlays); } @@ -3686,7 +3699,6 @@ fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end) beforep->next = current_buffer->overlays_before; set_buffer_overlays_before (current_buffer, before_list); } - recenter_overlay_lists (current_buffer, current_buffer->overlay_center); if (afterp) { @@ -3844,17 +3856,16 @@ for the rear of the overlay advance when text is inserted there end = OVERLAY_END (overlay); if (OVERLAY_POSITION (end) < b->overlay_center) { - if (b->overlays_after) - XOVERLAY (overlay)->next = b->overlays_after; + eassert (b->overlays_after || (XOVERLAY (overlay)->next == NULL)); + XOVERLAY (overlay)->next = b->overlays_after; set_buffer_overlays_after (b, XOVERLAY (overlay)); } else { - if (b->overlays_before) - XOVERLAY (overlay)->next = b->overlays_before; + eassert (b->overlays_before || (XOVERLAY (overlay)->next == NULL)); + XOVERLAY (overlay)->next = b->overlays_before; set_buffer_overlays_before (b, XOVERLAY (overlay)); } - /* This puts it in the right list, and in the right order. */ recenter_overlay_lists (b, b->overlay_center); @@ -3878,17 +3889,17 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end) BUF_COMPUTE_UNCHANGED (buf, start, end); - /* If this is a buffer not in the selected window, - we must do other windows. */ - if (buf != XBUFFER (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) - windows_or_buffers_changed = 1; - /* If we modify an overlay at the end of the buffer, we cannot - be sure that window end is still valid. */ - else if (end >= ZV && start <= ZV) - windows_or_buffers_changed = 1; + /* If BUF is visible, consider updating the display if ... */ + if (buffer_window_count (buf) > 0) + { + /* ... it's visible in other window than selected, */ + if (buf != XBUFFER (XWINDOW (selected_window)->buffer)) + windows_or_buffers_changed = 1; + /* ... or if we modify an overlay at the end of the buffer + and so we cannot be sure that window end is still valid. */ + else if (end >= ZV && start <= ZV) + windows_or_buffers_changed = 1; + } ++BUF_OVERLAY_MODIFF (buf); } @@ -4138,7 +4149,7 @@ DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0, /* 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, - 0, 0, 0); + NULL, NULL, 0); /* Make a list of them all. */ result = Flist (noverlays, overlay_vec); @@ -4567,27 +4578,7 @@ evaporate_overlays (ptrdiff_t pos) for (; CONSP (hit_list); hit_list = XCDR (hit_list)) Fdelete_overlay (XCAR (hit_list)); } - -/* Somebody has tried to store a value with an unacceptable type - in the slot with offset OFFSET. */ - -void -buffer_slot_type_mismatch (Lisp_Object newval, int type) -{ - Lisp_Object predicate; - switch (type) - { - case_Lisp_Int: predicate = Qintegerp; break; - case Lisp_String: predicate = Qstringp; break; - case Lisp_Symbol: predicate = Qsymbolp; break; - default: emacs_abort (); - } - - wrong_type_argument (predicate, newval); -} - - /*********************************************************************** Allocation with mmap ***********************************************************************/ @@ -5029,7 +5020,7 @@ alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes) { void *p; - BLOCK_INPUT; + block_input (); #if defined USE_MMAP_FOR_BUFFERS p = mmap_alloc ((void **) &b->text->beg, nbytes); #elif defined REL_ALLOC @@ -5040,12 +5031,12 @@ alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes) if (p == NULL) { - UNBLOCK_INPUT; + unblock_input (); memory_full (nbytes); } b->text->beg = (unsigned char *) p; - UNBLOCK_INPUT; + unblock_input (); } /* Enlarge buffer B's text buffer by DELTA bytes. DELTA < 0 means @@ -5057,7 +5048,7 @@ enlarge_buffer_text (struct buffer *b, ptrdiff_t delta) void *p; ptrdiff_t nbytes = (BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1 + delta); - BLOCK_INPUT; + block_input (); #if defined USE_MMAP_FOR_BUFFERS p = mmap_realloc ((void **) &b->text->beg, nbytes); #elif defined REL_ALLOC @@ -5068,12 +5059,12 @@ enlarge_buffer_text (struct buffer *b, ptrdiff_t delta) if (p == NULL) { - UNBLOCK_INPUT; + unblock_input (); memory_full (nbytes); } BUF_BEG_ADDR (b) = (unsigned char *) p; - UNBLOCK_INPUT; + unblock_input (); } @@ -5082,7 +5073,7 @@ enlarge_buffer_text (struct buffer *b, ptrdiff_t delta) static void free_buffer_text (struct buffer *b) { - BLOCK_INPUT; + block_input (); #if defined USE_MMAP_FOR_BUFFERS mmap_free ((void **) &b->text->beg); @@ -5093,7 +5084,7 @@ free_buffer_text (struct buffer *b) #endif BUF_BEG_ADDR (b) = NULL; - UNBLOCK_INPUT; + unblock_input (); } @@ -5106,11 +5097,6 @@ 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); @@ -5128,13 +5114,16 @@ init_buffer_once (void) /* No one will share the text with these buffers, but let's play it safe. */ buffer_defaults.indirections = 0; buffer_local_symbols.indirections = 0; + /* Likewise no one will display them. */ + buffer_defaults.window_count = 0; + buffer_local_symbols.window_count = 0; set_buffer_intervals (&buffer_defaults, NULL); set_buffer_intervals (&buffer_local_symbols, NULL); /* This is not strictly necessary, but let's make them initialized. */ bset_name (&buffer_defaults, build_pure_c_string (" *buffer-defaults*")); bset_name (&buffer_local_symbols, build_pure_c_string (" *buffer-local-symbols*")); - XSETPVECTYPESIZE (&buffer_defaults, PVEC_BUFFER, pvecsize); - XSETPVECTYPESIZE (&buffer_local_symbols, PVEC_BUFFER, pvecsize); + BUFFER_PVEC_INIT (&buffer_defaults); + BUFFER_PVEC_INIT (&buffer_local_symbols); /* Set up the default values of various buffer slots. */ /* Must do these before making the first buffer! */ @@ -5363,25 +5352,23 @@ init_buffer (void) free (pwd); } -/* Similar to defvar_lisp but define a variable whose value is the Lisp - Object stored in the current buffer. address is the address of the slot - in the buffer that is current now. */ - -/* TYPE is nil for a general Lisp variable. - An integer specifies a type; then only Lisp values - with that type code are allowed (except that nil is allowed too). - LNAME is the Lisp-level variable name. - VNAME is the name of the buffer slot. - DOC is a dummy where you write the doc string as a comment. */ -#define DEFVAR_PER_BUFFER(lname, vname, type, doc) \ - do { \ - static struct Lisp_Buffer_Objfwd bo_fwd; \ - defvar_per_buffer (&bo_fwd, lname, vname, type); \ +/* Similar to defvar_lisp but define a variable whose value is the + Lisp_Object stored in the current buffer. LNAME is the Lisp-level + variable name. VNAME is the name of the buffer slot. PREDICATE + is nil for a general Lisp variable. If PREDICATE is non-nil, then + only Lisp values that satisfies the PREDICATE are allowed (except + that nil is allowed too). DOC is a dummy where you write the doc + string as a comment. */ + +#define DEFVAR_PER_BUFFER(lname, vname, predicate, doc) \ + do { \ + static struct Lisp_Buffer_Objfwd bo_fwd; \ + defvar_per_buffer (&bo_fwd, lname, vname, predicate); \ } while (0) static void defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring, - Lisp_Object *address, Lisp_Object type) + Lisp_Object *address, Lisp_Object predicate) { struct Lisp_Symbol *sym; int offset; @@ -5391,7 +5378,7 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring, bo_fwd->type = Lisp_Fwd_Buffer_Obj; bo_fwd->offset = offset; - bo_fwd->slottype = type; + bo_fwd->predicate = predicate; sym->declared_special = 1; sym->redirect = SYMBOL_FORWARDED; { @@ -5654,7 +5641,7 @@ Decimal digits after the % specify field width to which to pad. */); doc: /* Value of `major-mode' for new buffers. */); DEFVAR_PER_BUFFER ("major-mode", &BVAR (current_buffer, major_mode), - make_number (Lisp_Symbol), + Qsymbolp, doc: /* Symbol for current buffer's major mode. The default value (normally `fundamental-mode') affects new buffers. A value of nil means to use the current buffer's major mode, provided @@ -5685,17 +5672,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_Int0), + Qintegerp, 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_Int0), + Qintegerp, 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_Int0), + Qintegerp, doc: /* Distance between tab stops (for display of tab characters), in columns. This should be an integer greater than zero. */); @@ -5780,7 +5767,7 @@ 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), + Qstringp, doc: /* Name of default directory of current buffer. Should end with slash. To interactively change the default directory, use command `cd'. */); @@ -5793,18 +5780,18 @@ NOTE: This variable is not a hook; its value may not be a list of functions. */); DEFVAR_PER_BUFFER ("buffer-file-name", &BVAR (current_buffer, filename), - make_number (Lisp_String), + Qstringp, doc: /* Name of file visited in current buffer, or nil if not visiting a file. */); DEFVAR_PER_BUFFER ("buffer-file-truename", &BVAR (current_buffer, file_truename), - make_number (Lisp_String), + Qstringp, doc: /* Abbreviated truename of file visited in current buffer, or nil if none. The truename of a file is calculated by `file-truename' and then abbreviated with `abbreviate-file-name'. */); DEFVAR_PER_BUFFER ("buffer-auto-save-file-name", &BVAR (current_buffer, auto_save_file_name), - make_number (Lisp_String), + Qstringp, doc: /* Name of file for auto-saving current buffer. If it is nil, that means don't auto-save this buffer. */); @@ -5816,7 +5803,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_Int0), + Qintegerp, 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. @@ -5886,23 +5873,23 @@ In addition, a char-table has six extra slots to control the display of: See also the functions `display-table-slot' and `set-display-table-slot'. */); DEFVAR_PER_BUFFER ("left-margin-width", &BVAR (current_buffer, left_margin_cols), - Qnil, + Qintegerp, doc: /* Width of left marginal area for display of a buffer. A value of nil means no marginal area. */); DEFVAR_PER_BUFFER ("right-margin-width", &BVAR (current_buffer, right_margin_cols), - Qnil, + Qintegerp, doc: /* Width of right marginal area for display of a buffer. A value of nil means no marginal area. */); DEFVAR_PER_BUFFER ("left-fringe-width", &BVAR (current_buffer, left_fringe_width), - Qnil, + Qintegerp, doc: /* Width of this buffer's left fringe (in pixels). A value of 0 means no left fringe is shown in this buffer's window. A value of nil means to use the left fringe width from the window's frame. */); DEFVAR_PER_BUFFER ("right-fringe-width", &BVAR (current_buffer, right_fringe_width), - Qnil, + Qintegerp, doc: /* Width of this buffer's right fringe (in pixels). A value of 0 means no right fringe is shown in this buffer's window. A value of nil means to use the right fringe width from the window's frame. */); @@ -5913,7 +5900,7 @@ A value of nil means to use the right fringe width from the window's frame. */) A value of nil means to display fringes between margins and buffer text. */); DEFVAR_PER_BUFFER ("scroll-bar-width", &BVAR (current_buffer, scroll_bar_width), - Qnil, + Qintegerp, doc: /* Width of this buffer's scroll bars in pixels. A value of nil means to use the scroll bar width from the window's frame. */); @@ -5993,7 +5980,7 @@ BITMAP is the corresponding fringe bitmap shown for the logical cursor type. */); DEFVAR_PER_BUFFER ("scroll-up-aggressively", - &BVAR (current_buffer, scroll_up_aggressively), Qnil, + &BVAR (current_buffer, scroll_up_aggressively), Qfloatp, doc: /* How far to scroll windows upward. If you move point off the bottom, the window scrolls automatically. This variable controls how far it scrolls. The value nil, the default, @@ -6006,7 +5993,7 @@ window scrolls by a full window height. Meaningful values are between 0.0 and 1.0, inclusive. */); DEFVAR_PER_BUFFER ("scroll-down-aggressively", - &BVAR (current_buffer, scroll_down_aggressively), Qnil, + &BVAR (current_buffer, scroll_down_aggressively), Qfloatp, doc: /* How far to scroll windows downward. If you move point off the top, the window scrolls automatically. This variable controls how far it scrolls. The value nil, the default, @@ -6018,10 +6005,6 @@ simple case that you moved off with C-b means scrolling just one line. window scrolls by a full window height. Meaningful values are between 0.0 and 1.0, inclusive. */); -/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol, - "Don't ask."); -*/ - DEFVAR_LISP ("before-change-functions", Vbefore_change_functions, doc: /* List of functions to call before each text change. Two arguments are passed to each function: the positions of @@ -6160,7 +6143,7 @@ then characters with property value PROP are invisible, and they have an ellipsis as well if ELLIPSIS is non-nil. */); DEFVAR_PER_BUFFER ("buffer-display-count", - &BVAR (current_buffer, display_count), Qnil, + &BVAR (current_buffer, display_count), Qintegerp, doc: /* A number incremented each time this buffer is displayed in a window. The function `set-window-buffer' increments it. */); @@ -6204,22 +6187,22 @@ is a member of the list. */); doc: /* Cursor to use when this buffer is in the selected window. Values are interpreted as follows: - t use the cursor specified for the frame - nil don't display a cursor - box display a filled box cursor - hollow display a hollow box cursor - bar display a vertical bar cursor with default width - (bar . WIDTH) display a vertical bar cursor with width WIDTH - hbar display a horizontal bar cursor with default height + t use the cursor specified for the frame + nil don't display a cursor + box display a filled box cursor + hollow display a hollow box cursor + bar display a vertical bar cursor with default width + (bar . WIDTH) display a vertical bar cursor with width WIDTH + hbar display a horizontal bar cursor with default height (hbar . HEIGHT) display a horizontal bar cursor with height HEIGHT - ANYTHING ELSE display a hollow box cursor + ANYTHING ELSE display a hollow box cursor When the buffer is displayed in a non-selected window, the cursor's appearance is instead controlled by the variable `cursor-in-non-selected-windows'. */); DEFVAR_PER_BUFFER ("line-spacing", - &BVAR (current_buffer, extra_line_spacing), Qnil, + &BVAR (current_buffer, extra_line_spacing), Qnumberp, doc: /* Additional space to put between lines when displaying a buffer. The space is measured in pixels, and put below lines on graphic displays, see `display-graphic-p'.