Prefer functions to macros in buffer.h
In buffer.h, prefer inline functions to function-like macros when either will do. This helps avoid confusion about how many times an arg is evaluated. On my platform, this patch improves performance of ‘make compile-always’ by 5.7%. Also, prefer enum constants to object-like macros when either will do. * src/buffer.h (BEG, BEG_BYTE, GAP_BYTES_DFL, GAP_BYTES_MIN) (MAX_PER_BUFFER_VARS, NONEXISTENT_MODTIME_NSECS) (UNKNOWN_MODTIME_NSECS, BUFFER_LISP_SIZE, BUFFER_REST_SIZE): Now enum constants, instead of macros. (BUFFER_CEILING_OF, BUFFER_FLOOR_OF, BUF_BEG, BUF_BEG_BYTE) (BUF_BEGV, BUF_BEGV_BYTE, BUF_PT, BUF_PT_BYTE, BUF_ZV) (BUF_ZV_BYTE, BUF_GPT_ADDR, BUF_Z_ADDR, BUF_GAP_END_ADDR) (BUF_COMPUTE_UNCHANGED, SET_PT, TEMP_SET_PT, SET_PT_BOTH) (TEMP_SET_PT_BOTH, BUF_TEMP_SET_PT, SET_BUF_BEGV, SET_BUF_ZV) (SET_BUF_BEGV_BOTH, SET_BUF_ZV_BOTH, SET_BUF_PT_BOTH) (BYTE_POS_ADDR, CHAR_POS_ADDR, CHAR_TO_BYTE, BYTE_TO_CHAR) (PTR_BYTE_POS, FETCH_CHAR, FETCH_CHAR_AS_MULTIBYTE) (BUF_BYTE_ADDRESS, BUF_CHAR_ADDRESS, BUF_PTR_BYTE_POS) (BUF_FETCH_CHAR, BUF_FETCH_CHAR_AS_MULTIBYTE, BUF_FETCH_BYTE) (BUFFER_PVEC_INIT, BUFFER_LIVE_P, BUFFER_HIDDEN_P) (BUFFER_CHECK_INDIRECTION, OVERLAY_POSITION, PER_BUFFER_VALUE_P) (SET_PER_BUFFER_VALUE_P, PER_BUFFER_IDX): Now inline functions instead of macros.
This commit is contained in:
parent
bbe45091de
commit
d84b4f83a5
1 changed files with 395 additions and 266 deletions
661
src/buffer.h
661
src/buffer.h
|
|
@ -31,12 +31,11 @@ INLINE_HEADER_BEGIN
|
|||
|
||||
/* Accessing the parameters of the current buffer. */
|
||||
|
||||
/* These macros come in pairs, one for the char position
|
||||
/* These constants and macros come in pairs, one for the char position
|
||||
and one for the byte position. */
|
||||
|
||||
/* Position of beginning of buffer. */
|
||||
#define BEG (1)
|
||||
#define BEG_BYTE (BEG)
|
||||
enum { BEG = 1, BEG_BYTE = BEG };
|
||||
|
||||
/* Position of beginning of accessible range of buffer. */
|
||||
#define BEGV (current_buffer->begv)
|
||||
|
|
@ -96,59 +95,7 @@ INLINE_HEADER_BEGIN
|
|||
|
||||
/* Modification count as of last visit or save. */
|
||||
#define SAVE_MODIFF (current_buffer->text->save_modiff)
|
||||
|
||||
/* BUFFER_CEILING_OF (resp. BUFFER_FLOOR_OF), when applied to n, return
|
||||
the max (resp. min) p such that
|
||||
|
||||
BYTE_POS_ADDR (p) - BYTE_POS_ADDR (n) == p - n */
|
||||
|
||||
#define BUFFER_CEILING_OF(BYTEPOS) \
|
||||
(((BYTEPOS) < GPT_BYTE && GPT < ZV ? GPT_BYTE : ZV_BYTE) - 1)
|
||||
#define BUFFER_FLOOR_OF(BYTEPOS) \
|
||||
(BEGV <= GPT && GPT_BYTE <= (BYTEPOS) ? GPT_BYTE : BEGV_BYTE)
|
||||
|
||||
/* Similar macros to operate on a specified buffer.
|
||||
Note that many of these evaluate the buffer argument more than once. */
|
||||
|
||||
/* Position of beginning of buffer. */
|
||||
#define BUF_BEG(buf) (BEG)
|
||||
#define BUF_BEG_BYTE(buf) (BEG_BYTE)
|
||||
|
||||
/* The BUF_BEGV[_BYTE], BUF_ZV[_BYTE], and BUF_PT[_BYTE] macros cannot
|
||||
be used for assignment; use SET_BUF_* macros below for that. */
|
||||
|
||||
/* Position of beginning of accessible range of buffer. */
|
||||
#define BUF_BEGV(buf) \
|
||||
(buf == current_buffer ? BEGV \
|
||||
: NILP (BVAR (buf, begv_marker)) ? buf->begv \
|
||||
: marker_position (BVAR (buf, begv_marker)))
|
||||
|
||||
#define BUF_BEGV_BYTE(buf) \
|
||||
(buf == current_buffer ? BEGV_BYTE \
|
||||
: NILP (BVAR (buf, begv_marker)) ? buf->begv_byte \
|
||||
: marker_byte_position (BVAR (buf, begv_marker)))
|
||||
|
||||
/* Position of point in buffer. */
|
||||
#define BUF_PT(buf) \
|
||||
(buf == current_buffer ? PT \
|
||||
: NILP (BVAR (buf, pt_marker)) ? buf->pt \
|
||||
: marker_position (BVAR (buf, pt_marker)))
|
||||
|
||||
#define BUF_PT_BYTE(buf) \
|
||||
(buf == current_buffer ? PT_BYTE \
|
||||
: NILP (BVAR (buf, pt_marker)) ? buf->pt_byte \
|
||||
: marker_byte_position (BVAR (buf, pt_marker)))
|
||||
|
||||
/* Position of end of accessible range of buffer. */
|
||||
#define BUF_ZV(buf) \
|
||||
(buf == current_buffer ? ZV \
|
||||
: NILP (BVAR (buf, zv_marker)) ? buf->zv \
|
||||
: marker_position (BVAR (buf, zv_marker)))
|
||||
|
||||
#define BUF_ZV_BYTE(buf) \
|
||||
(buf == current_buffer ? ZV_BYTE \
|
||||
: NILP (BVAR (buf, zv_marker)) ? buf->zv_byte \
|
||||
: marker_byte_position (BVAR (buf, zv_marker)))
|
||||
|
||||
/* Position of gap in buffer. */
|
||||
#define BUF_GPT(buf) ((buf)->text->gpt)
|
||||
|
|
@ -161,15 +108,6 @@ INLINE_HEADER_BEGIN
|
|||
/* Address of beginning of buffer. */
|
||||
#define BUF_BEG_ADDR(buf) ((buf)->text->beg)
|
||||
|
||||
/* Address of beginning of gap of buffer. */
|
||||
#define BUF_GPT_ADDR(buf) ((buf)->text->beg + (buf)->text->gpt_byte - BEG_BYTE)
|
||||
|
||||
/* Address of end of buffer. */
|
||||
#define BUF_Z_ADDR(buf) ((buf)->text->beg + (buf)->text->gap_size + (buf)->text->z_byte - BEG_BYTE)
|
||||
|
||||
/* Address of end of gap in buffer. */
|
||||
#define BUF_GAP_END_ADDR(buf) ((buf)->text->beg + (buf)->text->gpt_byte + (buf)->text->gap_size - BEG_BYTE)
|
||||
|
||||
/* Size of gap. */
|
||||
#define BUF_GAP_SIZE(buf) ((buf)->text->gap_size)
|
||||
|
||||
|
|
@ -209,43 +147,8 @@ INLINE_HEADER_BEGIN
|
|||
BUF_OVERLAY_UNCHANGED_MODIFIED (current_buffer)
|
||||
#define BEG_UNCHANGED BUF_BEG_UNCHANGED (current_buffer)
|
||||
#define END_UNCHANGED BUF_END_UNCHANGED (current_buffer)
|
||||
|
||||
/* Compute how many characters at the top and bottom of BUF are
|
||||
unchanged when the range START..END is modified. This computation
|
||||
must be done each time BUF is modified. */
|
||||
|
||||
#define BUF_COMPUTE_UNCHANGED(buf, start, end) \
|
||||
do \
|
||||
{ \
|
||||
if (BUF_UNCHANGED_MODIFIED (buf) == BUF_MODIFF (buf) \
|
||||
&& (BUF_OVERLAY_UNCHANGED_MODIFIED (buf) \
|
||||
== BUF_OVERLAY_MODIFF (buf))) \
|
||||
{ \
|
||||
BUF_BEG_UNCHANGED (buf) = (start) - BUF_BEG (buf); \
|
||||
BUF_END_UNCHANGED (buf) = BUF_Z (buf) - (end); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (BUF_Z (buf) - (end) < BUF_END_UNCHANGED (buf)) \
|
||||
BUF_END_UNCHANGED (buf) = BUF_Z (buf) - (end); \
|
||||
if ((start) - BUF_BEG (buf) < BUF_BEG_UNCHANGED (buf)) \
|
||||
BUF_BEG_UNCHANGED (buf) = (start) - BUF_BEG (buf); \
|
||||
} \
|
||||
} \
|
||||
while (false)
|
||||
|
||||
|
||||
/* Macros to set PT in the current buffer, or another buffer. */
|
||||
|
||||
#define SET_PT(position) (set_point (position))
|
||||
#define TEMP_SET_PT(position) (temp_set_point (current_buffer, (position)))
|
||||
|
||||
#define SET_PT_BOTH(position, byte) (set_point_both (position, byte))
|
||||
#define TEMP_SET_PT_BOTH(position, byte) \
|
||||
(temp_set_point_both (current_buffer, (position), (byte)))
|
||||
|
||||
#define BUF_TEMP_SET_PT(buffer, position) \
|
||||
(temp_set_point ((buffer), (position)))
|
||||
/* Functions to set PT in the current buffer, or another buffer. */
|
||||
|
||||
extern void set_point (ptrdiff_t);
|
||||
extern void temp_set_point (struct buffer *, ptrdiff_t);
|
||||
|
|
@ -255,39 +158,32 @@ extern void temp_set_point_both (struct buffer *,
|
|||
extern void set_point_from_marker (Lisp_Object);
|
||||
extern void enlarge_buffer_text (struct buffer *, ptrdiff_t);
|
||||
|
||||
INLINE void
|
||||
SET_PT (ptrdiff_t position)
|
||||
{
|
||||
set_point (position);
|
||||
}
|
||||
INLINE void
|
||||
TEMP_SET_PT (ptrdiff_t position)
|
||||
{
|
||||
temp_set_point (current_buffer, position);
|
||||
}
|
||||
INLINE void
|
||||
SET_PT_BOTH (ptrdiff_t position, ptrdiff_t byte)
|
||||
{
|
||||
set_point_both (position, byte);
|
||||
}
|
||||
INLINE void
|
||||
TEMP_SET_PT_BOTH (ptrdiff_t position, ptrdiff_t byte)
|
||||
{
|
||||
temp_set_point_both (current_buffer, position, byte);
|
||||
}
|
||||
INLINE void
|
||||
BUF_TEMP_SET_PT (struct buffer *buffer, ptrdiff_t position)
|
||||
{
|
||||
temp_set_point (buffer, position);
|
||||
}
|
||||
|
||||
/* Macros for setting the BEGV, ZV or PT of a given buffer.
|
||||
|
||||
The ..._BOTH macros take both a charpos and a bytepos,
|
||||
which must correspond to each other.
|
||||
|
||||
The macros without ..._BOTH take just a charpos,
|
||||
and compute the bytepos from it. */
|
||||
|
||||
#define SET_BUF_BEGV(buf, charpos) \
|
||||
((buf)->begv_byte = buf_charpos_to_bytepos ((buf), (charpos)), \
|
||||
(buf)->begv = (charpos))
|
||||
|
||||
#define SET_BUF_ZV(buf, charpos) \
|
||||
((buf)->zv_byte = buf_charpos_to_bytepos ((buf), (charpos)), \
|
||||
(buf)->zv = (charpos))
|
||||
|
||||
#define SET_BUF_BEGV_BOTH(buf, charpos, byte) \
|
||||
((buf)->begv = (charpos), \
|
||||
(buf)->begv_byte = (byte))
|
||||
|
||||
#define SET_BUF_ZV_BOTH(buf, charpos, byte) \
|
||||
((buf)->zv = (charpos), \
|
||||
(buf)->zv_byte = (byte))
|
||||
|
||||
#define SET_BUF_PT_BOTH(buf, charpos, byte) \
|
||||
((buf)->pt = (charpos), \
|
||||
(buf)->pt_byte = (byte))
|
||||
|
||||
/* Macros to access a character or byte in the current buffer,
|
||||
or convert between a byte position and an address.
|
||||
These macros do not check that the position is in range. */
|
||||
|
||||
/* Maximum number of bytes in a buffer.
|
||||
A buffer cannot contain more bytes than a 1-origin fixnum can represent,
|
||||
nor can it be so large that C pointer arithmetic stops working.
|
||||
|
|
@ -298,115 +194,21 @@ extern void enlarge_buffer_text (struct buffer *, ptrdiff_t);
|
|||
/* Maximum gap size after compact_buffer, in bytes. Also
|
||||
used in make_gap_larger to get some extra reserved space. */
|
||||
|
||||
#define GAP_BYTES_DFL 2000
|
||||
enum { GAP_BYTES_DFL = 2000 };
|
||||
|
||||
/* Minimum gap size after compact_buffer, in bytes. Also
|
||||
used in make_gap_smaller to avoid too small gap size. */
|
||||
|
||||
#define GAP_BYTES_MIN 20
|
||||
|
||||
/* Return the address of byte position N in current buffer. */
|
||||
|
||||
#define BYTE_POS_ADDR(n) \
|
||||
(((n) >= GPT_BYTE ? GAP_SIZE : 0) + (n) + BEG_ADDR - BEG_BYTE)
|
||||
|
||||
/* Return the address of char position N. */
|
||||
|
||||
#define CHAR_POS_ADDR(n) \
|
||||
(((n) >= GPT ? GAP_SIZE : 0) \
|
||||
+ buf_charpos_to_bytepos (current_buffer, n) \
|
||||
+ BEG_ADDR - BEG_BYTE)
|
||||
|
||||
/* Convert a character position to a byte position. */
|
||||
|
||||
#define CHAR_TO_BYTE(charpos) \
|
||||
(buf_charpos_to_bytepos (current_buffer, charpos))
|
||||
|
||||
/* Convert a byte position to a character position. */
|
||||
|
||||
#define BYTE_TO_CHAR(bytepos) \
|
||||
(buf_bytepos_to_charpos (current_buffer, bytepos))
|
||||
enum { GAP_BYTES_MIN = 20 };
|
||||
|
||||
/* For those very rare cases where you may have a "random" pointer into
|
||||
the middle of a multibyte char, this moves to the next boundary. */
|
||||
extern ptrdiff_t advance_to_char_boundary (ptrdiff_t byte_pos);
|
||||
|
||||
/* Convert PTR, the address of a byte in the buffer, into a byte position. */
|
||||
|
||||
#define PTR_BYTE_POS(ptr) \
|
||||
((ptr) - (current_buffer)->text->beg \
|
||||
- (ptr - (current_buffer)->text->beg <= GPT_BYTE - BEG_BYTE ? 0 : GAP_SIZE) \
|
||||
+ BEG_BYTE)
|
||||
|
||||
/* Return character at byte position POS. See the caveat WARNING for
|
||||
FETCH_MULTIBYTE_CHAR below. */
|
||||
|
||||
#define FETCH_CHAR(pos) \
|
||||
(!NILP (BVAR (current_buffer, enable_multibyte_characters)) \
|
||||
? FETCH_MULTIBYTE_CHAR ((pos)) \
|
||||
: FETCH_BYTE ((pos)))
|
||||
|
||||
/* Return the byte at byte position N. */
|
||||
/* Return the byte at byte position N.
|
||||
Do not check that the position is in range. */
|
||||
|
||||
#define FETCH_BYTE(n) *(BYTE_POS_ADDR ((n)))
|
||||
|
||||
/* Return character at byte position POS. If the current buffer is unibyte
|
||||
and the character is not ASCII, make the returning character
|
||||
multibyte. */
|
||||
|
||||
#define FETCH_CHAR_AS_MULTIBYTE(pos) \
|
||||
(!NILP (BVAR (current_buffer, enable_multibyte_characters)) \
|
||||
? FETCH_MULTIBYTE_CHAR ((pos)) \
|
||||
: UNIBYTE_TO_CHAR (FETCH_BYTE ((pos))))
|
||||
|
||||
|
||||
/* Macros for accessing a character or byte,
|
||||
or converting between byte positions and addresses,
|
||||
in a specified buffer. */
|
||||
|
||||
/* Return the address of character at byte position POS in buffer BUF.
|
||||
Note that both arguments can be computed more than once. */
|
||||
|
||||
#define BUF_BYTE_ADDRESS(buf, pos) \
|
||||
((buf)->text->beg + (pos) - BEG_BYTE \
|
||||
+ ((pos) >= (buf)->text->gpt_byte ? (buf)->text->gap_size : 0))
|
||||
|
||||
/* Return the address of character at char position POS in buffer BUF.
|
||||
Note that both arguments can be computed more than once. */
|
||||
|
||||
#define BUF_CHAR_ADDRESS(buf, pos) \
|
||||
((buf)->text->beg + buf_charpos_to_bytepos ((buf), (pos)) - BEG_BYTE \
|
||||
+ ((pos) >= (buf)->text->gpt ? (buf)->text->gap_size : 0))
|
||||
|
||||
/* Convert PTR, the address of a char in buffer BUF,
|
||||
into a character position. */
|
||||
|
||||
#define BUF_PTR_BYTE_POS(buf, ptr) \
|
||||
((ptr) - (buf)->text->beg \
|
||||
- (ptr - (buf)->text->beg <= BUF_GPT_BYTE (buf) - BEG_BYTE \
|
||||
? 0 : BUF_GAP_SIZE ((buf))) \
|
||||
+ BEG_BYTE)
|
||||
|
||||
/* Return the character at byte position POS in buffer BUF. */
|
||||
|
||||
#define BUF_FETCH_CHAR(buf, pos) \
|
||||
(!NILP (buf->enable_multibyte_characters) \
|
||||
? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \
|
||||
: BUF_FETCH_BYTE ((buf), (pos)))
|
||||
|
||||
/* Return character at byte position POS in buffer BUF. If BUF is
|
||||
unibyte and the character is not ASCII, make the returning
|
||||
character multibyte. */
|
||||
|
||||
#define BUF_FETCH_CHAR_AS_MULTIBYTE(buf, pos) \
|
||||
(! NILP (BVAR ((buf), enable_multibyte_characters)) \
|
||||
? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \
|
||||
: UNIBYTE_TO_CHAR (BUF_FETCH_BYTE ((buf), (pos))))
|
||||
|
||||
/* Return the byte at byte position N in buffer BUF. */
|
||||
|
||||
#define BUF_FETCH_BYTE(buf, n) \
|
||||
*(BUF_BYTE_ADDRESS ((buf), (n)))
|
||||
|
||||
/* Define the actual buffer data structures. */
|
||||
|
||||
|
|
@ -482,6 +284,13 @@ struct buffer_text
|
|||
|
||||
#define BVAR(buf, field) ((buf)->field ## _)
|
||||
|
||||
/* Max number of builtin per-buffer variables. */
|
||||
enum { MAX_PER_BUFFER_VARS = 50 };
|
||||
|
||||
/* Special values for struct buffer.modtime. */
|
||||
enum { NONEXISTENT_MODTIME_NSECS = -1 };
|
||||
enum { UNKNOWN_MODTIME_NSECS = -2 };
|
||||
|
||||
/* This is the structure that the buffer Lisp object points to. */
|
||||
|
||||
struct buffer
|
||||
|
|
@ -796,7 +605,6 @@ struct buffer
|
|||
for a buffer-local variable is stored in that variable's slot
|
||||
in buffer_local_flags as a Lisp integer. If the index is -1,
|
||||
this means the variable is always local in all buffers. */
|
||||
#define MAX_PER_BUFFER_VARS 50
|
||||
char local_flags[MAX_PER_BUFFER_VARS];
|
||||
|
||||
/* Set to the modtime of the visited file when read or written.
|
||||
|
|
@ -804,8 +612,6 @@ struct buffer
|
|||
visited file was nonexistent. modtime.tv_nsec ==
|
||||
UNKNOWN_MODTIME_NSECS means visited file modtime unknown;
|
||||
in no case complain about any mismatch on next save attempt. */
|
||||
#define NONEXISTENT_MODTIME_NSECS (-1)
|
||||
#define UNKNOWN_MODTIME_NSECS (-2)
|
||||
struct timespec modtime;
|
||||
|
||||
/* Size of the file when modtime was set. This is used to detect the
|
||||
|
|
@ -1018,49 +824,281 @@ bset_width_table (struct buffer *b, Lisp_Object val)
|
|||
b->width_table_ = val;
|
||||
}
|
||||
|
||||
/* BUFFER_CEILING_OF (resp. BUFFER_FLOOR_OF), when applied to n, return
|
||||
the max (resp. min) p such that
|
||||
|
||||
BYTE_POS_ADDR (p) - BYTE_POS_ADDR (n) == p - n */
|
||||
|
||||
INLINE ptrdiff_t
|
||||
BUFFER_CEILING_OF (ptrdiff_t bytepos)
|
||||
{
|
||||
return (bytepos < GPT_BYTE && GPT < ZV ? GPT_BYTE : ZV_BYTE) - 1;
|
||||
}
|
||||
|
||||
INLINE ptrdiff_t
|
||||
BUFFER_FLOOR_OF (ptrdiff_t bytepos)
|
||||
{
|
||||
return BEGV <= GPT && GPT_BYTE <= bytepos ? GPT_BYTE : BEGV_BYTE;
|
||||
}
|
||||
|
||||
/* The BUF_BEGV[_BYTE], BUF_ZV[_BYTE], and BUF_PT[_BYTE] functions cannot
|
||||
be used for assignment; use SET_BUF_* functions below for that. */
|
||||
|
||||
/* Position of beginning of accessible range of buffer. */
|
||||
INLINE ptrdiff_t
|
||||
BUF_BEGV (struct buffer *buf)
|
||||
{
|
||||
return (buf == current_buffer ? BEGV
|
||||
: NILP (BVAR (buf, begv_marker)) ? buf->begv
|
||||
: marker_position (BVAR (buf, begv_marker)));
|
||||
}
|
||||
|
||||
INLINE ptrdiff_t
|
||||
BUF_BEGV_BYTE (struct buffer *buf)
|
||||
{
|
||||
return (buf == current_buffer ? BEGV_BYTE
|
||||
: NILP (BVAR (buf, begv_marker)) ? buf->begv_byte
|
||||
: marker_byte_position (BVAR (buf, begv_marker)));
|
||||
}
|
||||
|
||||
/* Position of point in buffer. */
|
||||
INLINE ptrdiff_t
|
||||
BUF_PT (struct buffer *buf)
|
||||
{
|
||||
return (buf == current_buffer ? PT
|
||||
: NILP (BVAR (buf, pt_marker)) ? buf->pt
|
||||
: marker_position (BVAR (buf, pt_marker)));
|
||||
}
|
||||
|
||||
INLINE ptrdiff_t
|
||||
BUF_PT_BYTE (struct buffer *buf)
|
||||
{
|
||||
return (buf == current_buffer ? PT_BYTE
|
||||
: NILP (BVAR (buf, pt_marker)) ? buf->pt_byte
|
||||
: marker_byte_position (BVAR (buf, pt_marker)));
|
||||
}
|
||||
|
||||
/* Position of end of accessible range of buffer. */
|
||||
INLINE ptrdiff_t
|
||||
BUF_ZV (struct buffer *buf)
|
||||
{
|
||||
return (buf == current_buffer ? ZV
|
||||
: NILP (BVAR (buf, zv_marker)) ? buf->zv
|
||||
: marker_position (BVAR (buf, zv_marker)));
|
||||
}
|
||||
|
||||
INLINE ptrdiff_t
|
||||
BUF_ZV_BYTE (struct buffer *buf)
|
||||
{
|
||||
return (buf == current_buffer ? ZV_BYTE
|
||||
: NILP (BVAR (buf, zv_marker)) ? buf->zv_byte
|
||||
: marker_byte_position (BVAR (buf, zv_marker)));
|
||||
}
|
||||
|
||||
/* Similar functions to operate on a specified buffer. */
|
||||
|
||||
/* Position of beginning of buffer. */
|
||||
INLINE ptrdiff_t
|
||||
BUF_BEG (struct buffer *buf)
|
||||
{
|
||||
return BEG;
|
||||
}
|
||||
|
||||
INLINE ptrdiff_t
|
||||
BUF_BEG_BYTE (struct buffer *buf)
|
||||
{
|
||||
return BEG_BYTE;
|
||||
}
|
||||
|
||||
/* Address of beginning of gap of buffer. */
|
||||
INLINE unsigned char *
|
||||
BUF_GPT_ADDR (struct buffer *buf)
|
||||
{
|
||||
return buf->text->beg + buf->text->gpt_byte - BEG_BYTE;
|
||||
}
|
||||
|
||||
/* Address of end of buffer. */
|
||||
INLINE unsigned char *
|
||||
BUF_Z_ADDR (struct buffer *buf)
|
||||
{
|
||||
return buf->text->beg + buf->text->gap_size + buf->text->z_byte - BEG_BYTE;
|
||||
}
|
||||
|
||||
/* Address of end of gap in buffer. */
|
||||
INLINE unsigned char *
|
||||
BUF_GAP_END_ADDR (struct buffer *buf)
|
||||
{
|
||||
return buf->text->beg + buf->text->gpt_byte + buf->text->gap_size - BEG_BYTE;
|
||||
}
|
||||
|
||||
/* Compute how many characters at the top and bottom of BUF are
|
||||
unchanged when the range START..END is modified. This computation
|
||||
must be done each time BUF is modified. */
|
||||
|
||||
INLINE void
|
||||
BUF_COMPUTE_UNCHANGED (struct buffer *buf, ptrdiff_t start, ptrdiff_t end)
|
||||
{
|
||||
if (BUF_UNCHANGED_MODIFIED (buf) == BUF_MODIFF (buf)
|
||||
&& (BUF_OVERLAY_UNCHANGED_MODIFIED (buf)
|
||||
== BUF_OVERLAY_MODIFF (buf)))
|
||||
{
|
||||
buf->text->beg_unchanged = start - BUF_BEG (buf);
|
||||
buf->text->end_unchanged = BUF_Z (buf) - (end);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BUF_Z (buf) - end < BUF_END_UNCHANGED (buf))
|
||||
buf->text->end_unchanged = BUF_Z (buf) - end;
|
||||
if (start - BUF_BEG (buf) < BUF_BEG_UNCHANGED (buf))
|
||||
buf->text->beg_unchanged = start - BUF_BEG (buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Functions for setting the BEGV, ZV or PT of a given buffer.
|
||||
|
||||
The ..._BOTH functions take both a charpos and a bytepos,
|
||||
which must correspond to each other.
|
||||
|
||||
The functions without ..._BOTH take just a charpos,
|
||||
and compute the bytepos from it. */
|
||||
|
||||
INLINE void
|
||||
SET_BUF_BEGV (struct buffer *buf, ptrdiff_t charpos)
|
||||
{
|
||||
buf->begv_byte = buf_charpos_to_bytepos (buf, charpos);
|
||||
buf->begv = charpos;
|
||||
}
|
||||
|
||||
INLINE void
|
||||
SET_BUF_ZV (struct buffer *buf, ptrdiff_t charpos)
|
||||
{
|
||||
buf->zv_byte = buf_charpos_to_bytepos (buf, charpos);
|
||||
buf->zv = charpos;
|
||||
}
|
||||
|
||||
INLINE void
|
||||
SET_BUF_BEGV_BOTH (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t byte)
|
||||
{
|
||||
buf->begv = charpos;
|
||||
buf->begv_byte = byte;
|
||||
}
|
||||
|
||||
INLINE void
|
||||
SET_BUF_ZV_BOTH (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t byte)
|
||||
{
|
||||
buf->zv = charpos;
|
||||
buf->zv_byte = byte;
|
||||
}
|
||||
|
||||
INLINE void
|
||||
SET_BUF_PT_BOTH (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t byte)
|
||||
{
|
||||
buf->pt = charpos;
|
||||
buf->pt_byte = byte;
|
||||
}
|
||||
|
||||
/* Functions to access a character or byte in the current buffer,
|
||||
or convert between a byte position and an address.
|
||||
These functions do not check that the position is in range. */
|
||||
|
||||
/* Return the address of byte position N in current buffer. */
|
||||
|
||||
INLINE unsigned char *
|
||||
BYTE_POS_ADDR (ptrdiff_t n)
|
||||
{
|
||||
return (n < GPT_BYTE ? 0 : GAP_SIZE) + n + BEG_ADDR - BEG_BYTE;
|
||||
}
|
||||
|
||||
/* Return the address of char position N. */
|
||||
|
||||
INLINE unsigned char *
|
||||
CHAR_POS_ADDR (ptrdiff_t n)
|
||||
{
|
||||
return ((n < GPT ? 0 : GAP_SIZE)
|
||||
+ buf_charpos_to_bytepos (current_buffer, n)
|
||||
+ BEG_ADDR - BEG_BYTE);
|
||||
}
|
||||
|
||||
/* Convert a character position to a byte position. */
|
||||
|
||||
INLINE ptrdiff_t
|
||||
CHAR_TO_BYTE (ptrdiff_t charpos)
|
||||
{
|
||||
return buf_charpos_to_bytepos (current_buffer, charpos);
|
||||
}
|
||||
|
||||
/* Convert a byte position to a character position. */
|
||||
|
||||
INLINE ptrdiff_t
|
||||
BYTE_TO_CHAR (ptrdiff_t bytepos)
|
||||
{
|
||||
return buf_bytepos_to_charpos (current_buffer, bytepos);
|
||||
}
|
||||
|
||||
/* Convert PTR, the address of a byte in the buffer, into a byte position. */
|
||||
|
||||
INLINE ptrdiff_t
|
||||
PTR_BYTE_POS (unsigned char const *ptr)
|
||||
{
|
||||
ptrdiff_t byte = ptr - current_buffer->text->beg;
|
||||
return byte - (byte <= GPT_BYTE - BEG_BYTE ? 0 : GAP_SIZE) + BEG_BYTE;
|
||||
}
|
||||
|
||||
/* Number of Lisp_Objects at the beginning of struct buffer.
|
||||
If you add, remove, or reorder Lisp_Objects within buffer
|
||||
structure, make sure that this is still correct. */
|
||||
|
||||
#define BUFFER_LISP_SIZE \
|
||||
PSEUDOVECSIZE (struct buffer, cursor_in_non_selected_windows_)
|
||||
enum { BUFFER_LISP_SIZE = PSEUDOVECSIZE (struct buffer,
|
||||
cursor_in_non_selected_windows_) };
|
||||
|
||||
/* Allocated size of the struct buffer part beyond leading
|
||||
Lisp_Objects, in word_size units. */
|
||||
|
||||
#define BUFFER_REST_SIZE (VECSIZE (struct buffer) - BUFFER_LISP_SIZE)
|
||||
enum { BUFFER_REST_SIZE = VECSIZE (struct buffer) - BUFFER_LISP_SIZE };
|
||||
|
||||
/* Initialize the pseudovector header of buffer object. BUFFER_LISP_SIZE
|
||||
is required for GC, but BUFFER_REST_SIZE is set up just to be consistent
|
||||
with other pseudovectors. */
|
||||
|
||||
#define BUFFER_PVEC_INIT(b) \
|
||||
XSETPVECTYPESIZE (b, PVEC_BUFFER, BUFFER_LISP_SIZE, BUFFER_REST_SIZE)
|
||||
INLINE void
|
||||
BUFFER_PVEC_INIT (struct buffer *b)
|
||||
{
|
||||
XSETPVECTYPESIZE (b, PVEC_BUFFER, BUFFER_LISP_SIZE, BUFFER_REST_SIZE);
|
||||
}
|
||||
|
||||
/* Convenient check whether buffer B is live. */
|
||||
|
||||
#define BUFFER_LIVE_P(b) (!NILP (BVAR (b, name)))
|
||||
INLINE bool
|
||||
BUFFER_LIVE_P (struct buffer *b)
|
||||
{
|
||||
return !NILP (BVAR (b, name));
|
||||
}
|
||||
|
||||
/* Convenient check whether buffer B is hidden (i.e. its name
|
||||
starts with a space). Caller must ensure that B is live. */
|
||||
|
||||
#define BUFFER_HIDDEN_P(b) (SREF (BVAR (b, name), 0) == ' ')
|
||||
INLINE bool
|
||||
BUFFER_HIDDEN_P (struct buffer *b)
|
||||
{
|
||||
return SREF (BVAR (b, name), 0) == ' ';
|
||||
}
|
||||
|
||||
/* Verify indirection counters. */
|
||||
|
||||
#define BUFFER_CHECK_INDIRECTION(b) \
|
||||
do { \
|
||||
if (BUFFER_LIVE_P (b)) \
|
||||
{ \
|
||||
if (b->base_buffer) \
|
||||
{ \
|
||||
eassert (b->indirections == -1); \
|
||||
eassert (b->base_buffer->indirections > 0); \
|
||||
} \
|
||||
else \
|
||||
eassert (b->indirections >= 0); \
|
||||
} \
|
||||
} while (false)
|
||||
INLINE void
|
||||
BUFFER_CHECK_INDIRECTION (struct buffer *b)
|
||||
{
|
||||
if (BUFFER_LIVE_P (b))
|
||||
{
|
||||
if (b->base_buffer)
|
||||
{
|
||||
eassert (b->indirections == -1);
|
||||
eassert (b->base_buffer->indirections > 0);
|
||||
}
|
||||
else
|
||||
eassert (b->indirections >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Chain of all buffers, including killed ones. */
|
||||
|
||||
|
|
@ -1157,7 +1195,9 @@ record_unwind_current_buffer (void)
|
|||
|
||||
/* Get overlays at POSN into array OVERLAYS with NOVERLAYS elements.
|
||||
If NEXTP is non-NULL, return next overlay there.
|
||||
See overlay_at arg CHANGE_REQ for meaning of CHRQ arg. */
|
||||
See overlay_at arg CHANGE_REQ for meaning of CHRQ arg.
|
||||
This macro might evaluate its args multiple times,
|
||||
and it treat some args as lvalues. */
|
||||
|
||||
#define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq) \
|
||||
do { \
|
||||
|
|
@ -1207,6 +1247,10 @@ buffer_has_overlays (void)
|
|||
{
|
||||
return current_buffer->overlays_before || current_buffer->overlays_after;
|
||||
}
|
||||
|
||||
/* Functions for accessing a character or byte,
|
||||
or converting between byte positions and addresses,
|
||||
in a specified buffer. */
|
||||
|
||||
/* Return character code of multi-byte form at byte position POS. If POS
|
||||
doesn't point the head of valid multi-byte form, only the byte at
|
||||
|
|
@ -1232,6 +1276,80 @@ BUF_FETCH_MULTIBYTE_CHAR (struct buffer *buf, ptrdiff_t pos)
|
|||
return STRING_CHAR (p);
|
||||
}
|
||||
|
||||
/* Return character at byte position POS.
|
||||
If the current buffer is unibyte and the character is not ASCII,
|
||||
make the returning character multibyte. */
|
||||
|
||||
INLINE int
|
||||
FETCH_CHAR_AS_MULTIBYTE (ptrdiff_t pos)
|
||||
{
|
||||
return (!NILP (BVAR (current_buffer, enable_multibyte_characters))
|
||||
? FETCH_MULTIBYTE_CHAR (pos)
|
||||
: UNIBYTE_TO_CHAR (FETCH_BYTE (pos)));
|
||||
}
|
||||
|
||||
/* Return character at byte position POS.
|
||||
See the caveat WARNING for FETCH_MULTIBYTE_CHAR above. */
|
||||
|
||||
INLINE int
|
||||
FETCH_CHAR (ptrdiff_t pos)
|
||||
{
|
||||
return (!NILP (BVAR (current_buffer, enable_multibyte_characters))
|
||||
? FETCH_MULTIBYTE_CHAR (pos)
|
||||
: FETCH_BYTE (pos));
|
||||
}
|
||||
|
||||
/* Return the address of character at byte position POS in buffer BUF.
|
||||
Note that both arguments can be computed more than once. */
|
||||
|
||||
INLINE unsigned char *
|
||||
BUF_BYTE_ADDRESS (struct buffer *buf, ptrdiff_t pos)
|
||||
{
|
||||
return (buf->text->beg + pos - BEG_BYTE
|
||||
+ (pos < buf->text->gpt_byte ? 0 : buf->text->gap_size));
|
||||
}
|
||||
|
||||
/* Return the address of character at char position POS in buffer BUF.
|
||||
Note that both arguments can be computed more than once. */
|
||||
|
||||
INLINE unsigned char *
|
||||
BUF_CHAR_ADDRESS (struct buffer *buf, ptrdiff_t pos)
|
||||
{
|
||||
return (buf->text->beg + buf_charpos_to_bytepos (buf, pos) - BEG_BYTE
|
||||
+ (pos < buf->text->gpt ? 0 : buf->text->gap_size));
|
||||
}
|
||||
|
||||
/* Convert PTR, the address of a char in buffer BUF,
|
||||
into a character position. */
|
||||
|
||||
INLINE ptrdiff_t
|
||||
BUF_PTR_BYTE_POS (struct buffer *buf, unsigned char *ptr)
|
||||
{
|
||||
ptrdiff_t byte = ptr - buf->text->beg;
|
||||
return (byte - (byte <= BUF_GPT_BYTE (buf) - BEG_BYTE ? 0 : BUF_GAP_SIZE (buf))
|
||||
+ BEG_BYTE);
|
||||
}
|
||||
|
||||
/* Return the byte at byte position N in buffer BUF. */
|
||||
|
||||
INLINE unsigned char
|
||||
BUF_FETCH_BYTE (struct buffer *buf, ptrdiff_t n)
|
||||
{
|
||||
return *BUF_BYTE_ADDRESS (buf, n);
|
||||
}
|
||||
|
||||
/* Return character at byte position POS in buffer BUF. If BUF is
|
||||
unibyte and the character is not ASCII, make the returning
|
||||
character multibyte. */
|
||||
|
||||
INLINE int
|
||||
BUF_FETCH_CHAR_AS_MULTIBYTE (struct buffer *buf, ptrdiff_t pos)
|
||||
{
|
||||
return (! NILP (BVAR (buf, enable_multibyte_characters))
|
||||
? BUF_FETCH_MULTIBYTE_CHAR (buf, pos)
|
||||
: UNIBYTE_TO_CHAR (BUF_FETCH_BYTE (buf, pos)));
|
||||
}
|
||||
|
||||
/* Return number of windows showing B. */
|
||||
|
||||
INLINE int
|
||||
|
|
@ -1260,8 +1378,11 @@ buffer_window_count (struct buffer *b)
|
|||
/* Return the actual buffer position for the marker P.
|
||||
We assume you know which buffer it's pointing into. */
|
||||
|
||||
#define OVERLAY_POSITION(P) \
|
||||
(MARKERP (P) ? marker_position (P) : (emacs_abort (), 0))
|
||||
INLINE ptrdiff_t
|
||||
OVERLAY_POSITION (Lisp_Object p)
|
||||
{
|
||||
return marker_position (p);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
|
@ -1297,16 +1418,22 @@ extern bool valid_per_buffer_idx (int);
|
|||
/* Value is true if the variable with index IDX has a local value
|
||||
in buffer B. */
|
||||
|
||||
#define PER_BUFFER_VALUE_P(B, IDX) \
|
||||
(eassert (valid_per_buffer_idx (IDX)), \
|
||||
(B)->local_flags[IDX])
|
||||
INLINE bool
|
||||
PER_BUFFER_VALUE_P (struct buffer *b, int idx)
|
||||
{
|
||||
eassert (valid_per_buffer_idx (idx));
|
||||
return b->local_flags[idx];
|
||||
}
|
||||
|
||||
/* Set whether per-buffer variable with index IDX has a buffer-local
|
||||
value in buffer B. VAL zero means it hasn't. */
|
||||
|
||||
#define SET_PER_BUFFER_VALUE_P(B, IDX, VAL) \
|
||||
(eassert (valid_per_buffer_idx (IDX)), \
|
||||
(B)->local_flags[IDX] = (VAL))
|
||||
INLINE void
|
||||
SET_PER_BUFFER_VALUE_P (struct buffer *b, int idx, bool val)
|
||||
{
|
||||
eassert (valid_per_buffer_idx (idx));
|
||||
b->local_flags[idx] = val;
|
||||
}
|
||||
|
||||
/* Return the index value of the per-buffer variable at offset OFFSET
|
||||
in the buffer structure.
|
||||
|
|
@ -1326,11 +1453,13 @@ extern bool valid_per_buffer_idx (int);
|
|||
new buffer.
|
||||
|
||||
If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is
|
||||
zero, that is a bug */
|
||||
zero, that is a bug. */
|
||||
|
||||
|
||||
#define PER_BUFFER_IDX(OFFSET) \
|
||||
XFIXNUM (*(Lisp_Object *)((OFFSET) + (char *) &buffer_local_flags))
|
||||
INLINE int
|
||||
PER_BUFFER_IDX (ptrdiff_t offset)
|
||||
{
|
||||
return XFIXNUM (*(Lisp_Object *) (offset + (char *) &buffer_local_flags));
|
||||
}
|
||||
|
||||
/* Functions to get and set default value of the per-buffer
|
||||
variable at offset OFFSET in the buffer structure. */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue