summaryrefslogtreecommitdiff
path: root/src/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/buffer.c')
-rw-r--r--src/buffer.c152
1 files changed, 87 insertions, 65 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 92ed405b6f7..f1cb4d50414 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -51,11 +51,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "w32heap.h" /* for mmap_* */
#endif
-/* First buffer in chain of all buffers (in reverse order of creation).
- Threaded through ->header.next.buffer. */
-
-struct buffer *all_buffers;
-
/* This structure holds the default values of the buffer-local variables
defined with DEFVAR_PER_BUFFER, that have special slots in each buffer.
The default value occupies the same slot in this structure
@@ -124,6 +119,7 @@ static void free_buffer_text (struct buffer *b);
static struct Lisp_Overlay * copy_overlays (struct buffer *, struct Lisp_Overlay *);
static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t);
static Lisp_Object buffer_lisp_local_variables (struct buffer *, bool);
+static Lisp_Object buffer_local_variables_1 (struct buffer *buf, int offset, Lisp_Object sym);
static void
CHECK_OVERLAY (Lisp_Object x)
@@ -131,6 +127,23 @@ CHECK_OVERLAY (Lisp_Object x)
CHECK_TYPE (OVERLAYP (x), Qoverlayp, x);
}
+/* Convert the position POS to an EMACS_INT that fits in a fixnum.
+ Yield POS's value if POS is already a fixnum, POS's marker position
+ if POS is a marker, and MOST_NEGATIVE_FIXNUM or
+ MOST_POSITIVE_FIXNUM if POS is a negative or positive bignum.
+ Signal an error if POS is not of the proper form. */
+
+EMACS_INT
+fix_position (Lisp_Object pos)
+{
+ if (FIXNUMP (pos))
+ return XFIXNUM (pos);
+ if (MARKERP (pos))
+ return marker_position (pos);
+ CHECK_TYPE (BIGNUMP (pos), Qinteger_or_marker_p, pos);
+ return !NILP (Fnatnump (pos)) ? MOST_POSITIVE_FIXNUM : MOST_NEGATIVE_FIXNUM;
+}
+
/* These setters are used only in this file, so they can be private.
The public setters are inline functions defined in buffer.h. */
static void
@@ -1288,6 +1301,25 @@ buffer_lisp_local_variables (struct buffer *buf, bool clone)
return result;
}
+
+/* If the variable at position index OFFSET in buffer BUF has a
+ buffer-local value, return (name . value). If SYM is non-nil,
+ it replaces name. */
+
+static Lisp_Object
+buffer_local_variables_1 (struct buffer *buf, int offset, Lisp_Object sym)
+{
+ int idx = PER_BUFFER_IDX (offset);
+ if ((idx == -1 || PER_BUFFER_VALUE_P (buf, idx))
+ && SYMBOLP (PER_BUFFER_SYMBOL (offset)))
+ {
+ sym = NILP (sym) ? PER_BUFFER_SYMBOL (offset) : sym;
+ Lisp_Object val = per_buffer_value (buf, offset);
+ return EQ (val, Qunbound) ? sym : Fcons (sym, val);
+ }
+ return Qnil;
+}
+
DEFUN ("buffer-local-variables", Fbuffer_local_variables,
Sbuffer_local_variables, 0, 1, 0,
doc: /* Return an alist of variables that are buffer-local in BUFFER.
@@ -1299,25 +1331,25 @@ No argument or nil as argument means use current buffer as BUFFER. */)
{
struct buffer *buf = decode_buffer (buffer);
Lisp_Object result = buffer_lisp_local_variables (buf, 0);
+ Lisp_Object tem;
/* Add on all the variables stored in special slots. */
{
- int offset, idx;
+ int offset;
FOR_EACH_PER_BUFFER_OBJECT_AT (offset)
{
- idx = PER_BUFFER_IDX (offset);
- if ((idx == -1 || PER_BUFFER_VALUE_P (buf, idx))
- && SYMBOLP (PER_BUFFER_SYMBOL (offset)))
- {
- Lisp_Object sym = PER_BUFFER_SYMBOL (offset);
- Lisp_Object val = per_buffer_value (buf, offset);
- result = Fcons (EQ (val, Qunbound) ? sym : Fcons (sym, val),
- result);
- }
+ tem = buffer_local_variables_1 (buf, offset, Qnil);
+ if (!NILP (tem))
+ result = Fcons (tem, result);
}
}
+ tem = buffer_local_variables_1 (buf, PER_BUFFER_VAR_OFFSET (undo_list),
+ intern ("buffer-undo-list"));
+ if (!NILP (tem))
+ result = Fcons (tem, result);
+
return result;
}
@@ -1769,15 +1801,11 @@ cleaning up all windows currently displaying the buffer to be killed. */)
ask questions or their hooks get errors. */
if (!b->base_buffer && b->indirections > 0)
{
- struct buffer *other;
+ Lisp_Object tail, other;
- FOR_EACH_BUFFER (other)
- if (other->base_buffer == b)
- {
- Lisp_Object buf;
- XSETBUFFER (buf, other);
- Fkill_buffer (buf);
- }
+ FOR_EACH_LIVE_BUFFER (tail, other)
+ if (XBUFFER (other)->base_buffer == b)
+ Fkill_buffer (other);
/* Exit if we now have killed the base buffer (Bug#11665). */
if (!BUFFER_LIVE_P (b))
@@ -1832,6 +1860,9 @@ cleaning up all windows currently displaying the buffer to be killed. */)
tem = Vinhibit_quit;
Vinhibit_quit = Qt;
+ /* Once the buffer is removed from Vbuffer_alist, its undo_list field is
+ not traced by the GC in the same way. So set it to nil early. */
+ bset_undo_list (b, Qnil);
/* 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 fix that now. */
@@ -1946,7 +1977,6 @@ cleaning up all windows currently displaying the buffer to be killed. */)
}
bset_width_table (b, Qnil);
unblock_input ();
- bset_undo_list (b, Qnil);
/* Run buffer-list-update-hook. */
if (!NILP (Vrun_hooks) && !b->inhibit_buffer_hooks)
@@ -2257,19 +2287,20 @@ so the buffer is truly empty after this. */)
}
void
-validate_region (register Lisp_Object *b, register Lisp_Object *e)
+validate_region (Lisp_Object *b, Lisp_Object *e)
{
- CHECK_FIXNUM_COERCE_MARKER (*b);
- CHECK_FIXNUM_COERCE_MARKER (*e);
+ EMACS_INT beg = fix_position (*b), end = fix_position (*e);
- if (XFIXNUM (*b) > XFIXNUM (*e))
+ if (end < beg)
{
- Lisp_Object tem;
- tem = *b; *b = *e; *e = tem;
+ EMACS_INT tem = beg; beg = end; end = tem;
}
- if (! (BEGV <= XFIXNUM (*b) && XFIXNUM (*e) <= ZV))
+ if (! (BEGV <= beg && end <= ZV))
args_out_of_range_3 (Fcurrent_buffer (), *b, *e);
+
+ *b = make_fixnum (beg);
+ *e = make_fixnum (end);
}
/* Advance BYTE_POS up to a character boundary
@@ -2297,7 +2328,7 @@ advance_to_char_boundary (ptrdiff_t byte_pos)
c = FETCH_BYTE (byte_pos);
}
while (! CHAR_HEAD_P (c) && byte_pos > BEG);
- INC_POS (byte_pos);
+ byte_pos += next_char_len (byte_pos);
if (byte_pos < orig_byte_pos)
byte_pos = orig_byte_pos;
/* If C is a constituent of a multibyte sequence, BYTE_POS was
@@ -2333,10 +2364,10 @@ results, see Info node `(elisp)Swapping Text'. */)
error ("Cannot swap indirect buffers's text");
{ /* This is probably harder to make work. */
- struct buffer *other;
- FOR_EACH_BUFFER (other)
- if (other->base_buffer == other_buffer
- || other->base_buffer == current_buffer)
+ Lisp_Object tail, other;
+ FOR_EACH_LIVE_BUFFER (tail, other)
+ if (XBUFFER (other)->base_buffer == other_buffer
+ || XBUFFER (other)->base_buffer == current_buffer)
error ("One of the buffers to swap has indirect buffers");
}
@@ -2484,7 +2515,7 @@ current buffer is cleared. */)
(Lisp_Object flag)
{
struct Lisp_Marker *tail, *markers;
- struct buffer *other;
+ Lisp_Object btail, other;
ptrdiff_t begv, zv;
bool narrowed = (BEG != BEGV || Z != ZV);
bool modified_p = !NILP (Fbuffer_modified_p (Qnil));
@@ -2541,8 +2572,6 @@ current buffer is cleared. */)
p = BEG_ADDR;
while (1)
{
- int c, bytes;
-
if (pos == stop)
{
if (pos == Z)
@@ -2554,7 +2583,7 @@ current buffer is cleared. */)
p++, pos++;
else if (CHAR_BYTE8_HEAD_P (*p))
{
- c = STRING_CHAR_AND_LENGTH (p, bytes);
+ int bytes, c = string_char_and_length (p, &bytes);
/* Delete all bytes for this 8-bit character but the
last one, and change the last one to the character
code. */
@@ -2571,7 +2600,7 @@ current buffer is cleared. */)
}
else
{
- bytes = BYTES_BY_CHAR_HEAD (*p);
+ int bytes = BYTES_BY_CHAR_HEAD (*p);
p += bytes, pos += bytes;
}
}
@@ -2625,8 +2654,7 @@ current buffer is cleared. */)
if (ASCII_CHAR_P (*p))
p++, pos++;
else if (EQ (flag, Qt)
- && ! CHAR_BYTE8_HEAD_P (*p)
- && (bytes = MULTIBYTE_LENGTH (p, pend)) > 0)
+ && 0 < (bytes = multibyte_length (p, pend, true, false)))
p += bytes, pos += bytes;
else
{
@@ -2737,13 +2765,16 @@ current buffer is cleared. */)
/* Copy this buffer's new multibyte status
into all of its indirect buffers. */
- FOR_EACH_BUFFER (other)
- if (other->base_buffer == current_buffer && BUFFER_LIVE_P (other))
- {
- BVAR (other, enable_multibyte_characters)
- = BVAR (current_buffer, enable_multibyte_characters);
- other->prevent_redisplay_optimizations_p = 1;
- }
+ FOR_EACH_LIVE_BUFFER (btail, other)
+ {
+ struct buffer *o = XBUFFER (other);
+ if (o->base_buffer == current_buffer && BUFFER_LIVE_P (o))
+ {
+ BVAR (o, enable_multibyte_characters)
+ = BVAR (current_buffer, enable_multibyte_characters);
+ o->prevent_redisplay_optimizations_p = true;
+ }
+ }
/* Restore the modifiedness of the buffer. */
if (!modified_p && !NILP (Fbuffer_modified_p (Qnil)))
@@ -5309,8 +5340,6 @@ init_buffer_once (void)
Vbuffer_alist = Qnil;
current_buffer = 0;
pdumper_remember_lv_ptr_raw (&current_buffer, Lisp_Vectorlike);
- all_buffers = 0;
- pdumper_remember_lv_ptr_raw (&all_buffers, Lisp_Vectorlike);
QSFundamental = build_pure_c_string ("Fundamental");
@@ -5341,7 +5370,7 @@ init_buffer (void)
#ifdef USE_MMAP_FOR_BUFFERS
if (dumped_with_unexec_p ())
{
- struct buffer *b;
+ Lisp_Object tail, buffer;
#ifndef WINDOWSNT
/* These must be reset in the dumped Emacs, to avoid stale
@@ -5363,23 +5392,13 @@ init_buffer (void)
" *code-conversion-work*". They are created by
init_buffer_once and init_window_once (which are not called
in the dumped Emacs), and by the first call to coding.c routines. */
- FOR_EACH_BUFFER (b)
+ FOR_EACH_LIVE_BUFFER (tail, buffer)
{
+ struct buffer *b = XBUFFER (buffer);
b->text->beg = NULL;
enlarge_buffer_text (b, 0);
}
}
- else
- {
- struct buffer *b;
-
- /* Only buffers with allocated buffer text should be present at
- this point in temacs. */
- FOR_EACH_BUFFER (b)
- {
- eassert (b->text->beg != NULL);
- }
- }
#endif /* USE_MMAP_FOR_BUFFERS */
AUTO_STRING (scratch, "*scratch*");
@@ -6247,6 +6266,9 @@ 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
+ (box . SIZE) display a filled box cursor, but make it
+ hollow if cursor is under masked image larger than
+ SIZE pixels in either dimension.
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