diff options
Diffstat (limited to 'src/buffer.h')
-rw-r--r-- | src/buffer.h | 981 |
1 files changed, 644 insertions, 337 deletions
diff --git a/src/buffer.h b/src/buffer.h index ef31ad1ed9d..7d6c693b0f2 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -1,7 +1,6 @@ /* Header file for the buffer manipulation primitives. -Copyright (C) 1985-1986, 1993-1995, 1997-2017 Free Software Foundation, -Inc. +Copyright (C) 1985-2022 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -32,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) @@ -62,6 +60,14 @@ INLINE_HEADER_BEGIN /* Macros for the addresses of places in the buffer. */ +/* WARNING: Use the 'char *' pointers to buffer text with care in code + that could GC: GC can relocate buffer text, invalidating such + pointers. It is best to use character or byte position instead, + delaying the access through BYTE_POS_ADDR etc. pointers to the + latest possible moment. If you must use the 'char *' pointers + (e.g., for speed), be sure to adjust them after any call that could + potentially GC. */ + /* Address of beginning of buffer. */ #define BEG_ADDR (current_buffer->text->beg) @@ -97,59 +103,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) @@ -162,15 +116,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) @@ -204,6 +149,9 @@ INLINE_HEADER_BEGIN #define BUF_BEG_UNCHANGED(buf) ((buf)->text->beg_unchanged) #define BUF_END_UNCHANGED(buf) ((buf)->text->end_unchanged) +#define BUF_CHARS_UNCHANGED_MODIFIED(buf) \ + ((buf)->text->chars_unchanged_modified) + #define UNCHANGED_MODIFIED \ BUF_UNCHANGED_MODIFIED (current_buffer) #define OVERLAY_UNCHANGED_MODIFIED \ @@ -211,42 +159,10 @@ INLINE_HEADER_BEGIN #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) - +#define CHARS_UNCHANGED_MODIFIED \ + BUF_CHARS_UNCHANGED_MODIFIED (current_buffer) -/* 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); @@ -256,61 +172,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. */ - -/* Access a Lisp position value in POS, - and store the charpos in CHARPOS and the bytepos in BYTEPOS. */ - -#define DECODE_POSITION(charpos, bytepos, pos) \ - do \ - { \ - Lisp_Object __pos = (pos); \ - if (NUMBERP (__pos)) \ - { \ - charpos = __pos; \ - bytepos = buf_charpos_to_bytepos (current_buffer, __pos); \ - } \ - else if (MARKERP (__pos)) \ - { \ - charpos = marker_position (__pos); \ - bytepos = marker_byte_position (__pos); \ - } \ - else \ - wrong_type_argument (Qinteger_or_marker_p, __pos); \ - } \ - while (false) - /* 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. @@ -321,111 +208,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) +enum { GAP_BYTES_MIN = 20 }; -/* Convert a character position to a byte position. */ +/* 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); -#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)) - -/* 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. */ @@ -445,20 +242,21 @@ struct buffer_text ptrdiff_t gpt_byte; /* Byte pos of gap in buffer. */ ptrdiff_t z_byte; /* Byte pos of end of buffer. */ ptrdiff_t gap_size; /* Size of buffer's gap. */ - EMACS_INT modiff; /* This counts buffer-modification events - for this buffer. It is incremented for - each such event, and never otherwise - changed. */ - EMACS_INT chars_modiff; /* This is modified with character change + modiff_count modiff; /* This counts buffer-modification events + for this buffer. It is increased + logarithmically to the extent of the + modification for each such event, + and never otherwise changed. */ + modiff_count chars_modiff; /* This is modified with character change events for this buffer. It is set to modiff for each such event, and never otherwise changed. */ - EMACS_INT save_modiff; /* Previous value of modiff, as of last + modiff_count save_modiff; /* Previous value of modiff, as of last time buffer visited or saved a file. */ - EMACS_INT overlay_modiff; /* Counts modifications to overlays. */ + modiff_count overlay_modiff; /* Counts modifications to overlays. */ - EMACS_INT compact; /* Set to modiff each time when compact_buffer + modiff_count compact; /* Set to modiff each time when compact_buffer is called for this buffer. */ /* Minimum value of GPT - BEG since last redisplay that finished. */ @@ -469,12 +267,17 @@ struct buffer_text /* MODIFF as of last redisplay that finished; if it matches MODIFF, beg_unchanged and end_unchanged contain no useful information. */ - EMACS_INT unchanged_modified; + modiff_count unchanged_modified; /* BUF_OVERLAY_MODIFF of current buffer, as of last redisplay that finished; if it matches BUF_OVERLAY_MODIFF, beg_unchanged and end_unchanged contain no useful information. */ - EMACS_INT overlay_unchanged_modified; + modiff_count overlay_unchanged_modified; + + /* CHARS_MODIFF as of last redisplay that finished. It's used + when we only care about changes in actual buffer text, not in + any other kind of changes, like properties etc. */ + modiff_count chars_unchanged_modified; /* Properties of this buffer's text. */ INTERVAL intervals; @@ -501,11 +304,18 @@ 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 { - struct vectorlike_header header; + union vectorlike_header header; /* The name of this buffer. */ Lisp_Object name_; @@ -548,6 +358,9 @@ struct buffer /* Symbol naming major mode (e.g., lisp-mode). */ Lisp_Object major_mode_; + /* Symbol listing all currently enabled minor modes. */ + Lisp_Object local_minor_modes_; + /* Pretty name of major mode (e.g., "Lisp"). */ Lisp_Object mode_name_; @@ -558,6 +371,10 @@ struct buffer of windows. Nil means don't display that line. */ Lisp_Object header_line_format_; + /* Analogous to mode_line_format for the line displayed at the top + of windows. Nil means don't display that line. */ + Lisp_Object tab_line_format_; + /* Keys that are bound local to this buffer. */ Lisp_Object keymap_; @@ -625,9 +442,6 @@ struct buffer /* Non-nil means show ... at end of line followed by invisible lines. */ Lisp_Object selective_display_ellipses_; - /* Alist of (FUNCTION . STRING) for each minor mode enabled in buffer. */ - Lisp_Object minor_modes_; - /* t if "self-insertion" should overwrite; `binary' if it should also overwrite newlines and tabs - for editing executables and the like. */ Lisp_Object overwrite_mode_; @@ -764,8 +578,8 @@ struct buffer See `cursor-type' for other values. */ Lisp_Object cursor_in_non_selected_windows_; - /* No more Lisp_Object beyond this point. Except undo_list, - which is handled specially in Fgarbage_collect. */ + /* No more Lisp_Object beyond cursor_in_non_selected_windows_. + Except undo_list, which is handled specially in Fgarbage_collect. */ /* This structure holds the coordinates of the buffer contents in ordinary buffers. In indirect buffers, this is not used. */ @@ -776,9 +590,6 @@ struct buffer In an indirect buffer, this is the own_text field of another buffer. */ struct buffer_text *text; - /* Next buffer, in chain of all buffers, including killed ones. */ - struct buffer *next; - /* Char position of point in buffer. */ ptrdiff_t pt; @@ -815,7 +626,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. @@ -823,8 +633,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 @@ -835,11 +643,11 @@ struct buffer off_t modtime_size; /* The value of text->modiff at the last auto-save. */ - EMACS_INT auto_save_modified; + modiff_count auto_save_modified; /* The value of text->modiff at the last display error. Redisplay of this buffer is inhibited until it changes again. */ - EMACS_INT display_error_modiff; + modiff_count display_error_modiff; /* The time at which we detected a failure to auto-save, Or 0 if we didn't have a failure. */ @@ -878,6 +686,17 @@ struct buffer /* Non-zero whenever the narrowing is changed in this buffer. */ bool_bf clip_changed : 1; + /* Non-zero for internal or temporary buffers that don't need to + run hooks kill-buffer-hook, kill-buffer-query-functions, and + buffer-list-update-hook. This is used in coding.c to avoid + slowing down en/decoding when a lot of these hooks are + defined, as well as by with-temp-buffer, for example. */ + bool_bf inhibit_buffer_hooks : 1; + + /* Non-zero when the buffer contains long lines and specific + display optimizations must be used. */ + bool_bf long_line_optimizations_p : 1; + /* The inveral tree containing this buffer's overlays. */ struct interval_tree *overlays; @@ -913,7 +732,7 @@ INLINE struct buffer * XBUFFER (Lisp_Object a) { eassert (BUFFERP (a)); - return XUNTAG (a, Lisp_Vectorlike); + return XUNTAG (a, Lisp_Vectorlike, struct buffer); } /* Most code should use these functions to set Lisp fields in struct @@ -950,6 +769,16 @@ bset_display_count (struct buffer *b, Lisp_Object val) b->display_count_ = val; } INLINE void +bset_left_margin_cols (struct buffer *b, Lisp_Object val) +{ + b->left_margin_cols_ = val; +} +INLINE void +bset_right_margin_cols (struct buffer *b, Lisp_Object val) +{ + b->right_margin_cols_ = val; +} +INLINE void bset_display_time (struct buffer *b, Lisp_Object val) { b->display_time_ = val; @@ -1020,60 +849,284 @@ 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. */ + +/* See the important WARNING above about using the 'char *' pointers + returned by these functions. */ + +/* 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 \ - ((offsetof (struct buffer, own_text) - header_size) / word_size) +enum { BUFFER_LISP_SIZE = PSEUDOVECSIZE (struct buffer, + cursor_in_non_selected_windows_) }; -/* Size of the struct buffer part beyond leading Lisp_Objects, in word_size - units. Rounding is needed for --with-wide-int configuration. */ +/* Allocated size of the struct buffer part beyond leading + Lisp_Objects, in word_size units. */ -#define BUFFER_REST_SIZE \ - ((((sizeof (struct buffer) - offsetof (struct buffer, own_text)) \ - + (word_size - 1)) & ~(word_size - 1)) / word_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) - -/* Chain of all buffers, including killed ones. */ - -extern struct buffer *all_buffers; - -/* Used to iterate over the chain above. */ - -#define FOR_EACH_BUFFER(b) \ - for ((b) = all_buffers; (b); (b) = (b)->next) +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); + } +} /* This structure holds the default values of the buffer-local variables that have special slots in each buffer. @@ -1105,7 +1158,15 @@ extern struct buffer buffer_local_flags; that don't have such names. */ extern struct buffer buffer_local_symbols; + +/* verify_interval_modification saves insertion hooks here + to be run later by report_interval_modification. */ +extern Lisp_Object interval_insert_behind_hooks; +extern Lisp_Object interval_insert_in_front_hooks; + +extern EMACS_INT fix_position (Lisp_Object); +#define CHECK_FIXNUM_COERCE_MARKER(x) ((x) = make_fixnum (fix_position (x))) extern void delete_all_overlays (struct buffer *); extern void reset_buffer (struct buffer *); extern void compact_buffer (struct buffer *); @@ -1164,7 +1225,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, next) \ do { \ @@ -1213,6 +1276,10 @@ buffer_has_overlays (void) return current_buffer->overlays && (interval_tree_size (current_buffer->overlays) > 0); } + +/* 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 @@ -1238,6 +1305,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 @@ -1348,37 +1489,57 @@ buffer_overlay_iter_narrow (struct buffer *b, ptrdiff_t begin, ptrdiff_t end) /* Return the start of OV in its buffer, or -1 if OV is not associated with any buffer. */ -#define OVERLAY_START(OV) (overlay_start (XOVERLAY (OV))) +INLINE ptrdiff_t +OVERLAY_START (Lisp_Object ov) +{ + return overlay_start (XOVERLAY (ov)); +} /* Return the end of OV in its buffer, or -1. */ -#define OVERLAY_END(OV) (overlay_end (XOVERLAY (OV))) +INLINE ptrdiff_t +OVERLAY_END (Lisp_Object ov) +{ + return overlay_end (XOVERLAY (ov)); +} /* Return the plist of overlay OV. */ -#define OVERLAY_PLIST(OV) (XOVERLAY (OV)->plist) +INLINE Lisp_Object +OVERLAY_PLIST (Lisp_Object ov) +{ + return XOVERLAY (ov)->plist; +} /* Return the buffer of overlay OV. */ -#define OVERLAY_BUFFER(OV) (XOVERLAY (OV)->buffer) +INLINE struct buffer * +OVERLAY_BUFFER (Lisp_Object ov) +{ + return XOVERLAY (ov)->buffer; +} /* Return true, if OV's rear-advance is set. */ -#define OVERLAY_REAR_ADVANCE_P(OV) (XOVERLAY (OV)->interval->rear_advance) +INLINE bool +OVERLAY_REAR_ADVANCE_P (Lisp_Object ov) +{ + return XOVERLAY (ov)->interval->rear_advance; +} /* Return true, if OV's front-advance is set. */ -#define OVERLAY_FRONT_ADVANCE_P(OV) (XOVERLAY (OV)->interval->front_advance) +INLINE bool +OVERLAY_FRONT_ADVANCE_P (Lisp_Object ov) +{ + return XOVERLAY (ov)->interval->front_advance; +} /*********************************************************************** Buffer-local Variables ***********************************************************************/ -/* Number of per-buffer variables used. */ - -extern int last_per_buffer_idx; - /* Return the offset in bytes of member VAR of struct buffer from the start of a buffer structure. */ @@ -1403,23 +1564,27 @@ extern int last_per_buffer_idx; #define PER_BUFFER_VAR_IDX(VAR) \ PER_BUFFER_IDX (PER_BUFFER_VAR_OFFSET (VAR)) +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) \ - (((IDX) < 0 || IDX >= last_per_buffer_idx) \ - ? (emacs_abort (), false) \ - : ((B)->local_flags[IDX] != 0)) +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) \ - do { \ - if ((IDX) < 0 || (IDX) >= last_per_buffer_idx) \ - emacs_abort (); \ - (B)->local_flags[IDX] = (VAL); \ - } while (false) +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. @@ -1439,11 +1604,13 @@ extern int last_per_buffer_idx; 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) \ - XINT (*(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. */ @@ -1481,7 +1648,7 @@ downcase (int c) { Lisp_Object downcase_table = BVAR (current_buffer, downcase_table); Lisp_Object down = CHAR_TABLE_REF (downcase_table, c); - return NATNUMP (down) ? XFASTINT (down) : c; + return FIXNATP (down) ? XFIXNAT (down) : c; } /* Upcase a character C, or make no change if that cannot be done. */ @@ -1490,7 +1657,7 @@ upcase (int c) { Lisp_Object upcase_table = BVAR (current_buffer, upcase_table); Lisp_Object up = CHAR_TABLE_REF (upcase_table, c); - return NATNUMP (up) ? XFASTINT (up) : c; + return FIXNATP (up) ? XFIXNAT (up) : c; } /* True if C is upper case. */ @@ -1507,6 +1674,146 @@ lowercasep (int c) return !uppercasep (c) && upcase (c) != c; } +/* Return a non-outlandish value for the tab width. */ + +INLINE int +sanitize_tab_width (Lisp_Object width) +{ + return (FIXNUMP (width) && 0 < XFIXNUM (width) && XFIXNUM (width) <= 1000 + ? XFIXNUM (width) : 8); +} + +INLINE int +SANE_TAB_WIDTH (struct buffer *buf) +{ + return sanitize_tab_width (BVAR (buf, tab_width)); +} + +/* Return a non-outlandish value for a character width. */ + +INLINE int +sanitize_char_width (EMACS_INT width) +{ + return 0 <= width && width <= 1000 ? width : 1000; +} + +/* Return the width of character C. The width is measured by how many + columns C will occupy on the screen when displayed in the current + buffer. The name CHARACTER_WIDTH avoids a collision with <limits.h> + CHAR_WIDTH. */ + +INLINE int +CHARACTER_WIDTH (int c) +{ + return (0x20 <= c && c < 0x7f ? 1 + : 0x7f < c ? (sanitize_char_width + (XFIXNUM (CHAR_TABLE_REF (Vchar_width_table, c)))) + : c == '\t' ? SANE_TAB_WIDTH (current_buffer) + : c == '\n' ? 0 + : !NILP (BVAR (current_buffer, ctl_arrow)) ? 2 : 4); +} + + +/* Like fetch_string_char_advance, but fetch character from the current + buffer. */ + +INLINE int +fetch_char_advance (ptrdiff_t *charidx, ptrdiff_t *byteidx) +{ + int output; + ptrdiff_t c = *charidx, b = *byteidx; + c++; + unsigned char *chp = BYTE_POS_ADDR (b); + if (!NILP (BVAR (current_buffer, enable_multibyte_characters))) + { + int chlen; + output = string_char_and_length (chp, &chlen); + b += chlen; + } + else + { + output = *chp; + b++; + } + *charidx = c; + *byteidx = b; + return output; +} + + +/* Like fetch_char_advance, but assumes the current buffer is multibyte. */ + +INLINE int +fetch_char_advance_no_check (ptrdiff_t *charidx, ptrdiff_t *byteidx) +{ + int output; + ptrdiff_t c = *charidx, b = *byteidx; + c++; + unsigned char *chp = BYTE_POS_ADDR (b); + int chlen; + output = string_char_and_length (chp, &chlen); + b += chlen; + *charidx = c; + *byteidx = b; + return output; +} + +/* Return the number of bytes in the multibyte character in BUF + that starts at position POS_BYTE. This relies on the fact that + *GPT_ADDR and *Z_ADDR are always accessible and the values are + '\0'. No range checking of POS_BYTE. */ + +INLINE int +buf_next_char_len (struct buffer *buf, ptrdiff_t pos_byte) +{ + unsigned char *chp = BUF_BYTE_ADDRESS (buf, pos_byte); + return BYTES_BY_CHAR_HEAD (*chp); +} + +INLINE int +next_char_len (ptrdiff_t pos_byte) +{ + return buf_next_char_len (current_buffer, pos_byte); +} + +/* Return the number of bytes in the multibyte character in BUF just + before POS_BYTE. No range checking of POS_BYTE. */ + +INLINE int +buf_prev_char_len (struct buffer *buf, ptrdiff_t pos_byte) +{ + unsigned char *chp + = (BUF_BEG_ADDR (buf) + pos_byte - BEG_BYTE + + (pos_byte <= BUF_GPT_BYTE (buf) ? 0 : BUF_GAP_SIZE (buf))); + return raw_prev_char_len (chp); +} + +INLINE int +prev_char_len (ptrdiff_t pos_byte) +{ + return buf_prev_char_len (current_buffer, pos_byte); +} + +/* Increment both *CHARPOS and *BYTEPOS, each in the appropriate way. */ + +INLINE void +inc_both (ptrdiff_t *charpos, ptrdiff_t *bytepos) +{ + (*charpos)++; + (*bytepos) += (!NILP (BVAR (current_buffer, enable_multibyte_characters)) + ? next_char_len (*bytepos) : 1); +} + +/* Decrement both *CHARPOS and *BYTEPOS, each in the appropriate way. */ + +INLINE void +dec_both (ptrdiff_t *charpos, ptrdiff_t *bytepos) +{ + (*charpos)--; + (*bytepos) -= (!NILP (BVAR (current_buffer, enable_multibyte_characters)) + ? prev_char_len (*bytepos) : 1); +} + INLINE_HEADER_END int compare_overlays (const void *v1, const void *v2); |