Lisp_Object Vbuffer_alist;
/* Functions to call before and after each text change. */
-Lisp_Object Vbefore_change_function;
-Lisp_Object Vafter_change_function;
Lisp_Object Vbefore_change_functions;
Lisp_Object Vafter_change_functions;
return buf;
}
-DEFUN ("make-indirect-buffer", Fmake_indirect_buffer, Smake_indirect_buffer, 2, 2,
+
+/* Clone per-buffer values of buffer FROM.
+
+ Buffer TO gets the same per-buffer values as FROM, with the
+ following exceptions: (1) TO's name is left untouched, (2) markers
+ are copied and made to refer to TO, and (3) overlay lists are
+ copied. */
+
+static void
+clone_per_buffer_values (from, to)
+ struct buffer *from, *to;
+{
+ Lisp_Object to_buffer;
+ int offset;
+
+ XSETBUFFER (to_buffer, to);
+
+ for (offset = PER_BUFFER_VAR_OFFSET (name) + sizeof (Lisp_Object);
+ offset < sizeof *to;
+ offset += sizeof (Lisp_Object))
+ {
+ Lisp_Object obj;
+
+ obj = PER_BUFFER_VALUE (from, offset);
+ if (MARKERP (obj))
+ {
+ struct Lisp_Marker *m = XMARKER (obj);
+ obj = Fmake_marker ();
+ XMARKER (obj)->insertion_type = m->insertion_type;
+ set_marker_both (obj, to_buffer, m->charpos, m->bytepos);
+ }
+
+ PER_BUFFER_VALUE (to, offset) = obj;
+ }
+
+ to->overlays_after = Fcopy_sequence (from->overlays_after);
+ to->overlays_before = Fcopy_sequence (to->overlays_before);
+ bcopy (from->local_flags, to->local_flags, sizeof to->local_flags);
+}
+
+
+DEFUN ("make-indirect-buffer", Fmake_indirect_buffer, Smake_indirect_buffer,
+ 2, 3,
"bMake indirect buffer (to buffer): \nBName of indirect buffer: ",
"Create and return an indirect buffer for buffer BASE-BUFFER, named NAME.\n\
BASE-BUFFER should be an existing buffer (or buffer name).\n\
-NAME should be a string which is not the name of an existing buffer.")
- (base_buffer, name)
- register Lisp_Object base_buffer, name;
+NAME should be a string which is not the name of an existing buffer.\n\
+Optional argument CLONE non-nil means preserve BASE-BUFFER's state,\n\
+such as major and minor modes, in the indirect buffer.\n\
+CLONE nil means the indirect buffer's state is reset to default values.")
+ (base_buffer, name, clone)
+ Lisp_Object base_buffer, name, clone;
{
- register Lisp_Object buf;
- register struct buffer *b;
+ Lisp_Object buf;
+ struct buffer *b;
buf = Fget_buffer (name);
if (!NILP (buf))
XMARKER (b->base_buffer->zv_marker)->insertion_type = 1;
}
- /* Give the indirect buffer markers for its narrowing. */
- b->pt_marker = Fmake_marker ();
- set_marker_both (b->pt_marker, buf, BUF_PT (b), BUF_PT_BYTE (b));
- b->begv_marker = Fmake_marker ();
- set_marker_both (b->begv_marker, buf, BUF_BEGV (b), BUF_BEGV_BYTE (b));
- b->zv_marker = Fmake_marker ();
- set_marker_both (b->zv_marker, buf, BUF_ZV (b), BUF_ZV_BYTE (b));
- XMARKER (b->zv_marker)->insertion_type = 1;
+ if (NILP (clone))
+ {
+ /* Give the indirect buffer markers for its narrowing. */
+ b->pt_marker = Fmake_marker ();
+ set_marker_both (b->pt_marker, buf, BUF_PT (b), BUF_PT_BYTE (b));
+ b->begv_marker = Fmake_marker ();
+ set_marker_both (b->begv_marker, buf, BUF_BEGV (b), BUF_BEGV_BYTE (b));
+ b->zv_marker = Fmake_marker ();
+ set_marker_both (b->zv_marker, buf, BUF_ZV (b), BUF_ZV_BYTE (b));
+ XMARKER (b->zv_marker)->insertion_type = 1;
+ }
+ else
+ clone_per_buffer_values (b->base_buffer, b);
return buf;
}
b->last_selected_window = Qnil;
XSETINT (b->display_count, 0);
b->display_time = Qnil;
- b->extra2 = Qnil;
- b->extra3 = Qnil;
b->enable_multibyte_characters = buffer_defaults.enable_multibyte_characters;
b->cursor_type = buffer_defaults.cursor_type;
+ b->extra_line_spacing = buffer_defaults.extra_line_spacing;
}
/* Reset buffer B's local variables info.
buffer = buf1;
}
- /* Move buffer to the end of the buffer list. */
- {
- register Lisp_Object aelt, link;
+ /* Move buffer to the end of the buffer list. Do nothing if the
+ buffer is killed. */
+ if (!NILP (XBUFFER (buffer)->name))
+ {
+ Lisp_Object aelt, link;
- aelt = Frassq (buffer, Vbuffer_alist);
- link = Fmemq (aelt, Vbuffer_alist);
- Vbuffer_alist = Fdelq (aelt, Vbuffer_alist);
- XCDR (link) = Qnil;
- Vbuffer_alist = nconc2 (Vbuffer_alist, link);
- }
+ aelt = Frassq (buffer, Vbuffer_alist);
+ link = Fmemq (aelt, Vbuffer_alist);
+ Vbuffer_alist = Fdelq (aelt, Vbuffer_alist);
+ XCDR (link) = Qnil;
+ Vbuffer_alist = nconc2 (Vbuffer_alist, link);
- frames_bury_buffer (buffer);
+ frames_bury_buffer (buffer);
+ }
return Qnil;
}
{
/* We should advance BYTE_POS only when C is a constituent of a
multibyte sequence. */
- DEC_POS (byte_pos);
+ int orig_byte_pos = byte_pos;
+
+ do
+ {
+ byte_pos--;
+ c = FETCH_BYTE (byte_pos);
+ }
+ while (! CHAR_HEAD_P (c) && byte_pos > BEG);
INC_POS (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
surely advance to the correct character boundary. If C is
not, BYTE_POS was unchanged. */
{
Lisp_Object tail, markers;
struct buffer *other;
+ int undo_enabled_p = !EQ (current_buffer->undo_list, Qt);
+ int begv = BEGV, zv = ZV;
+ int narrowed = (BEG != begv || Z != zv);
+ int modified_p = !NILP (Fbuffer_modified_p (Qnil));
if (current_buffer->base_buffer)
error ("Cannot do `set-buffer-multibyte' on an indirect buffer");
/* It would be better to update the list,
but this is good enough for now. */
- if (! EQ (current_buffer->undo_list, Qt))
- current_buffer->undo_list = Qnil;
+ if (undo_enabled_p)
+ current_buffer->undo_list = Qt;
/* If the cached position is for this buffer, clear it out. */
clear_charpos_cache (current_buffer);
+ if (narrowed)
+ Fwiden ();
+
if (NILP (flag))
{
+ int pos, stop;
+ unsigned char *p;
+
/* Do this first, so it can use CHAR_TO_BYTE
to calculate the old correspondences. */
set_intervals_multibyte (0);
XMARKER (tail)->charpos = XMARKER (tail)->bytepos;
tail = XMARKER (tail)->chain;
}
+
+ /* Convert multibyte form of 8-bit characters to unibyte. */
+ pos = BEG;
+ stop = GPT;
+ p = BEG_ADDR;
+ while (1)
+ {
+ int c, bytes;
+
+ if (pos == stop)
+ {
+ if (pos == Z)
+ break;
+ p = GAP_END_ADDR;
+ stop = Z;
+ }
+ if (MULTIBYTE_STR_AS_UNIBYTE_P (p, bytes))
+ p += bytes, pos += bytes;
+ else
+ {
+ c = STRING_CHAR (p, stop - pos);
+ /* Delete all bytes for this 8-bit character but the
+ last one, and change the last one to the charcter
+ code. */
+ bytes--;
+ del_range_2 (pos, pos, pos + bytes, pos + bytes, 0);
+ p = GAP_END_ADDR;
+ *p++ = c;
+ pos++;
+ if (begv > pos)
+ begv -= bytes;
+ if (zv > pos)
+ zv -= bytes;
+ stop = Z;
+ }
+ }
+ if (narrowed)
+ Fnarrow_to_region (make_number (begv), make_number (zv));
}
else
{
+ int pt = PT;
+ int pos, stop;
+ unsigned char *p;
+
/* Be sure not to have a multibyte sequence striding over the GAP.
- Ex: We change this: "...abc\201\241\241 _GAP_ \241\241\241..."
- to: "...abc _GAP_ \201\241\241\241\241\241..." */
+ Ex: We change this: "...abc\201 _GAP_ \241def..."
+ to: "...abc _GAP_ \201\241def..." */
if (GPT_BYTE > 1 && GPT_BYTE < Z_BYTE
&& ! CHAR_HEAD_P (*(GAP_END_ADDR)))
}
}
+ /* Make the buffer contents valid as multibyte by converting
+ 8-bit characters to multibyte form. */
+ pos = BEG;
+ stop = GPT;
+ p = BEG_ADDR;
+ while (1)
+ {
+ int bytes;
+
+ if (pos == stop)
+ {
+ if (pos == Z)
+ break;
+ p = GAP_END_ADDR;
+ stop = Z;
+ }
+
+ if (UNIBYTE_STR_AS_MULTIBYTE_P (p, stop - pos, bytes))
+ p += bytes, pos += bytes;
+ else
+ {
+ unsigned char tmp[MAX_MULTIBYTE_LENGTH];
+
+ bytes = CHAR_STRING (*p, tmp);
+ *p = tmp[0];
+ TEMP_SET_PT_BOTH (pos + 1, pos + 1);
+ bytes--;
+ insert_1_both (tmp + 1, bytes, bytes, 1, 0, 0);
+ /* Now the gap is after the just inserted data. */
+ pos = GPT;
+ p = GAP_END_ADDR;
+ if (pos <= begv)
+ begv += bytes;
+ if (pos <= zv)
+ zv += bytes;
+ if (pos <= pt)
+ pt += bytes;
+ stop = Z;
+ }
+ }
+
+ if (pt != PT)
+ TEMP_SET_PT (pt);
+
+ if (narrowed)
+ Fnarrow_to_region (make_number (begv), make_number (zv));
+
/* Do this first, so that chars_in_text asks the right question.
set_intervals_multibyte needs it too. */
current_buffer->enable_multibyte_characters = Qt;
set_intervals_multibyte (1);
}
+ if (undo_enabled_p)
+ current_buffer->undo_list = Qnil;
+
/* Changing the multibyteness of a buffer means that all windows
showing that buffer must be updated thoroughly. */
current_buffer->prevent_redisplay_optimizations_p = 1;
other->prevent_redisplay_optimizations_p = 1;
}
+ /* Restore the modifiedness of the buffer. */
+ if (!modified_p && !NILP (Fbuffer_modified_p (Qnil)))
+ Fset_buffer_modified_p (Qnil);
+
return flag;
}
\f
/* Set up the default values of various buffer slots. */
/* Must do these before making the first buffer! */
- /* real setup is done in loaddefs.el */
+ /* real setup is done in bindings.el */
buffer_defaults.mode_line_format = build_string ("%-");
buffer_defaults.header_line_format = Qnil;
buffer_defaults.abbrev_mode = Qnil;
buffer_defaults.ctl_arrow = Qt;
buffer_defaults.direction_reversed = Qnil;
buffer_defaults.cursor_type = Qt;
+ buffer_defaults.extra_line_spacing = Qnil;
#ifdef DOS_NT
buffer_defaults.buffer_file_type = Qnil; /* TEXT */
XSETFASTINT (buffer_local_flags.scroll_down_aggressively, idx); ++idx;
XSETFASTINT (buffer_local_flags.header_line_format, idx); ++idx;
XSETFASTINT (buffer_local_flags.cursor_type, idx); ++idx;
+ XSETFASTINT (buffer_local_flags.extra_line_spacing, idx); ++idx;
/* Need more room? */
if (idx >= MAX_PER_BUFFER_VARS)
"Default value of `cursor-type' for buffers that don't override it.\n\
This is the same as (default-value 'cursor-type).");
+ DEFVAR_LISP_NOPRO ("default-line-spacing",
+ &buffer_defaults.extra_line_spacing,
+ "Default value of `line-spacing' for buffers that don't override it.\n\
+This is the same as (default-value 'line-spacing).");
+
DEFVAR_LISP_NOPRO ("default-abbrev-mode",
&buffer_defaults.abbrev_mode,
"Default value of `abbrev-mode' for buffers that do not override it.\n\
DEFVAR_PER_BUFFER ("auto-fill-function", ¤t_buffer->auto_fill_function,
Qnil,
"Function called (if non-nil) to perform auto-fill.\n\
-It is called after self-inserting a space or newline.\n\
+It is called after self-inserting any character specified in\n\
+the `auto-fill-chars' table.\n\
Each buffer has its own value of this variable.\n\
NOTE: This variable is not a hook;\n\
its value may not be a list of functions.");
/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
"Don't ask.");
*/
- DEFVAR_LISP ("before-change-function", &Vbefore_change_function,
- "If non-nil, a function to call before each text change (obsolete).\n\
-Two arguments are passed to the function: the positions of\n\
-the beginning and end of the range of old text to be changed.\n\
-\(For an insertion, the beginning and end are at the same place.)\n\
-No information is given about the length of the text after the change.\n\
-\n\
-Buffer changes made while executing the `before-change-function'\n\
-don't call any before-change or after-change functions.\n\
-That's because these variables are temporarily set to nil.\n\
-As a result, a hook function cannot straightforwardly alter the value of\n\
-these variables. See the Emacs Lisp manual for a way of\n\
-accomplishing an equivalent result by using other variables.\n\n\
-This variable is obsolete; use `before-change-functions' instead.");
- Vbefore_change_function = Qnil;
-
- DEFVAR_LISP ("after-change-function", &Vafter_change_function,
- "If non-nil, a Function to call after each text change (obsolete).\n\
-Three arguments are passed to the function: the positions of\n\
-the beginning and end of the range of changed text,\n\
-and the length of the pre-change text replaced by that range.\n\
-\(For an insertion, the pre-change length is zero;\n\
-for a deletion, that length is the number of bytes deleted,\n\
-and the post-change beginning and end are at the same place.)\n\
-\n\
-Buffer changes made while executing the `after-change-function'\n\
-don't call any before-change or after-change functions.\n\
-That's because these variables are temporarily set to nil.\n\
-As a result, a hook function cannot straightforwardly alter the value of\n\
-these variables. See the Emacs Lisp manual for a way of\n\
-accomplishing an equivalent result by using other variables.\n\n\
-This variable is obsolete; use `after-change-functions' instead.");
- Vafter_change_function = Qnil;
DEFVAR_LISP ("before-change-functions", &Vbefore_change_functions,
"List of functions to call before each text change.\n\
(bar . WIDTH) display a bar cursor with width WIDTH\n\
others display a box cursor.");
+ DEFVAR_PER_BUFFER ("line-spacing",
+ ¤t_buffer->extra_line_spacing, Qnil,
+ "Additional space to put between lines when displaying a buffer.\n\
+The space is measured in pixels, and put below lines on window systems.");
+
DEFVAR_LISP ("kill-buffer-query-functions", &Vkill_buffer_query_functions,
"List of functions called with no args to query before killing a buffer.");
Vkill_buffer_query_functions = Qnil;