/* Buffer manipulation primitives for GNU Emacs.
- Copyright (C) 1985, 1986, 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
#include "buffer.h"
#include "syntax.h"
#include "indent.h"
+#include "blockinput.h"
struct buffer *current_buffer; /* the current buffer */
buffer_slot_type_mismatch will signal an error. */
struct buffer buffer_local_types;
-/* Nonzero means don't allow modification of protected fields. */
-
-int check_protected_fields;
-
Lisp_Object Fset_buffer ();
void set_buffer_internal ();
+static void call_overlay_mod_hooks ();
/* Alist of all buffer names vs the buffers. */
/* This used to be a variable, but is no longer,
Lisp_Object Vbefore_change_function;
Lisp_Object Vafter_change_function;
-/* Function to call before changing an unmodified buffer. */
-Lisp_Object Vfirst_change_function;
+Lisp_Object Vtransient_mark_mode;
+
+/* t means ignore all read-only text properties.
+ A list means ignore such a property if its value is a member of the list.
+ Any non-nil value means ignore buffer-read-only. */
+Lisp_Object Vinhibit_read_only;
+
+/* List of functions to call before changing an unmodified buffer. */
+Lisp_Object Vfirst_change_hook;
+Lisp_Object Qfirst_change_hook;
Lisp_Object Qfundamental_mode, Qmode_class, Qpermanent_local;
Lisp_Object Qkill_buffer_hook;
+Lisp_Object Qoverlayp;
+
/* For debugging; temporary. See set_buffer_internal. */
/* Lisp_Object Qlisp_mode, Vcheck_symbol; */
if (!NILP (buf))
return buf;
- b = (struct buffer *) malloc (sizeof (struct buffer));
- if (!b)
- memory_full ();
+ b = (struct buffer *) xmalloc (sizeof (struct buffer));
BUF_GAP_SIZE (b) = 20;
+ BLOCK_INPUT;
BUFFER_ALLOC (BUF_BEG_ADDR (b), BUF_GAP_SIZE (b));
+ UNBLOCK_INPUT;
if (! BUF_BEG_ADDR (b))
memory_full ();
b->auto_save_modified = 0;
b->auto_save_file_name = Qnil;
b->read_only = Qnil;
- b->fieldlist = Qnil;
+ b->overlays_before = Qnil;
+ b->overlays_after = Qnil;
+ XFASTINT (b->overlay_center) = 1;
+ b->mark_active = Qnil;
/* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
INITIALIZE_INTERVAL (b, NULL_INTERVAL);
reset_buffer_local_variables(b);
}
-reset_buffer_local_variables(b)
+reset_buffer_local_variables (b)
register struct buffer *b;
{
register int offset;
rename the buffer properly. */
DEFUN ("generate-new-buffer-name", Fgenerate_new_buffer_name, Sgenerate_new_buffer_name,
- 1, 1, 0,
+ 1, 2, 0,
"Return a string that is the name of no existing buffer based on NAME.\n\
If there is no live buffer named NAME, then return NAME.\n\
Otherwise modify name by appending `<NUMBER>', incrementing NUMBER\n\
-until an unused name is found, and then return that name.")
- (name)
- register Lisp_Object name;
+until an unused name is found, and then return that name.\n\
+Optional second argument IGNORE specifies a name that is okay to use\n\
+\(if it is in the sequence to be tried)\n\
+even if a buffer with that name exists.")
+ (name, ignore)
+ register Lisp_Object name, ignore;
{
register Lisp_Object gentemp, tem;
int count;
{
sprintf (number, "<%d>", ++count);
gentemp = concat2 (name, build_string (number));
+ tem = Fstring_equal (gentemp, ignore);
+ if (!NILP (tem))
+ return gentemp;
tem = Fget_buffer (gentemp);
if (NILP (tem))
return gentemp;
}
\f
DEFUN ("rename-buffer", Frename_buffer, Srename_buffer, 1, 2,
- "sRename buffer (to new name): ",
+ "sRename buffer (to new name): \nP",
"Change current buffer's name to NEWNAME (a string).\n\
-If second arg DISTINGUISH is nil or omitted, it is an error if a\n\
+If second arg UNIQUE is nil or omitted, it is an error if a\n\
buffer named NEWNAME already exists.\n\
-If DISTINGUISH is non-nil, come up with a new name using\n\
+If UNIQUE is non-nil, come up with a new name using\n\
`generate-new-buffer-name'.\n\
-Return the name we actually gave the buffer.\n\
+Interactively, you can set UNIQUE with a prefix argument.\n\
+We return the name we actually gave the buffer.\n\
This does not change the name of the visited file (if any).")
- (name, distinguish)
- register Lisp_Object name, distinguish;
+ (name, unique)
+ register Lisp_Object name, unique;
{
register Lisp_Object tem, buf;
return current_buffer->name;
if (!NILP (tem))
{
- if (!NILP (distinguish))
- name = Fgenerate_new_buffer_name (name);
+ if (!NILP (unique))
+ name = Fgenerate_new_buffer_name (name, current_buffer->name);
else
error ("Buffer name \"%s\" is in use", XSTRING (name)->data);
}
current_buffer->name = name;
+
+ /* Catch redisplay's attention. Unless we do this, the mode lines for
+ any windows displaying current_buffer will stay unchanged. */
+ update_mode_lines++;
+
XSET (buf, Lisp_Buffer, current_buffer);
Fsetcar (Frassq (buf, Vbuffer_alist), name);
if (NILP (current_buffer->filename) && !NILP (current_buffer->auto_save_file_name))
if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
continue;
if (NILP (visible_ok))
- tem = Fget_buffer_window (buf, Qnil);
+ tem = Fget_buffer_window (buf, Qt);
else
tem = Qnil;
if (NILP (tem))
/* Perhaps we should explicitly free the interval tree here... */
b->name = Qnil;
+ BLOCK_INPUT;
BUFFER_FREE (BUF_BEG_ADDR (b));
+ UNBLOCK_INPUT;
b->undo_list = Qnil;
return Qt;
record_buffer (buf);
Fset_window_buffer (EQ (selected_window, minibuf_window)
- ? Fnext_window (minibuf_window, Qnil) : selected_window,
+ ? Fnext_window (minibuf_window, Qnil, Qnil)
+ : selected_window,
buf);
- return Qnil;
+ return buf;
}
DEFUN ("pop-to-buffer", Fpop_to_buffer, Spop_to_buffer, 1, 2, 0,
Fset_buffer (buf);
record_buffer (buf);
Fselect_window (Fdisplay_buffer (buf, other));
- return Qnil;
+ return buf;
}
DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
"Signal a `buffer-read-only' error if the current buffer is read-only.")
()
{
- while (!NILP (current_buffer->read_only))
+ if (!NILP (current_buffer->read_only)
+ && NILP (Vinhibit_read_only))
Fsignal (Qbuffer_read_only, (Fcons (Fcurrent_buffer (), Qnil)));
return Qnil;
}
XSET (buf, Lisp_Buffer, current_buffer);
/* If we're burying the current buffer, unshow it. */
- Fswitch_to_buffer (Fother_buffer (buf), Qnil);
+ Fswitch_to_buffer (Fother_buffer (buf, Qnil), Qnil);
}
else
{
return Qnil;
}
\f
-DEFUN ("erase-buffer", Ferase_buffer, Serase_buffer, 0, 0, 0,
+DEFUN ("erase-buffer", Ferase_buffer, Serase_buffer, 0, 0, "*",
"Delete the entire contents of the current buffer.\n\
Any clipping restriction in effect (see `narrow-to-region') is removed,\n\
so the buffer is truly empty after this.")
register Lisp_Object tail, tem, buf;
Lisp_Object col1, col2, col3, minspace;
register struct buffer *old = current_buffer, *b;
- int desired_point = 0;
+ Lisp_Object desired_point;
Lisp_Object other_file_symbol;
+ desired_point = Qnil;
other_file_symbol = intern ("list-buffers-directory");
XFASTINT (col1) = 19;
continue;
/* Identify the current buffer. */
if (b == old)
- desired_point = point;
+ XFASTINT (desired_point) = point;
write_string (b == old ? "." : " ", -1);
/* Identify modified buffers */
write_string (BUF_MODIFF (b) > b->save_modified ? "*" : " ", -1);
current_buffer->read_only = Qt;
set_buffer_internal (old);
-/* Foo. This doesn't work since temp_output_buffer_show sets point to 1
- if (desired_point)
- XBUFFER (Vstandard_output)->text.pointloc = desired_point;
- */
- return Qnil;
+ return desired_point;
}
DEFUN ("list-buffers", Flist_buffers, Slist_buffers, 0, 1, "P",
(files)
Lisp_Object files;
{
- internal_with_output_to_temp_buffer ("*Buffer List*",
- list_buffers_1, files);
- return Qnil;
+ Lisp_Object desired_point;
+
+ desired_point =
+ internal_with_output_to_temp_buffer ("*Buffer List*",
+ list_buffers_1, files);
+
+ if (NUMBERP (desired_point))
+ {
+ int count = specpdl_ptr - specpdl;
+ record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+ Fset_buffer (build_string ("*Buffer List*"));
+ SET_PT (XINT (desired_point));
+ return unbind_to (count, Qnil);
+ }
}
DEFUN ("kill-all-local-variables", Fkill_all_local_variables, Skill_all_local_variables,
Set it up for the current buffer with the default value. */
tem = XCONS (XCONS (XSYMBOL (sym)->value)->cdr)->cdr;
+ /* Store the symbol's current value into the alist entry
+ it is currently set up for. This is so that, if the
+ local is marked permanent, and we make it local again below,
+ we don't lose the value. */
+ XCONS (XCONS (tem)->car)->cdr = XCONS (XSYMBOL (sym)->value)->car;
+ /* Switch to the symbol's default-value alist entry. */
XCONS (tem)->car = tem;
+ /* Mark it as current for the current buffer. */
XCONS (XCONS (XSYMBOL (sym)->value)->cdr)->car = Fcurrent_buffer ();
+ /* Store the current value into any forwarding in the symbol. */
store_symval_forwarding (sym, XCONS (XSYMBOL (sym)->value)->car,
XCONS (tem)->cdr);
}
return Qnil;
}
\f
-DEFUN ("region-fields", Fregion_fields, Sregion_fields, 2, 4, "",
- "Return list of fields overlapping a given portion of a buffer.\n\
-The portion is specified by arguments START, END and BUFFER.\n\
-BUFFER defaults to the current buffer.\n\
-Optional 4th arg ERROR-CHECK non nil means just report an error\n\
-if any protected fields overlap this portion.")
- (start, end, buffer, error_check)
- Lisp_Object start, end, buffer, error_check;
+/* Find all the overlays in the current buffer that contain position POS.
+ Return the number found, and store them in a vector in *VEC_PTR.
+ Store in *LEN_PTR the size allocated for the vector.
+ Store in *NEXT_PTR the next position after POS where an overlay starts,
+ or ZV if there are no more overlays.
+
+ *VEC_PTR and *LEN_PTR should contain a valid vector and size
+ when this function is called.
+
+ If EXTEND is non-zero, we make the vector bigger if necessary.
+ If EXTEND is zero, we never extend the vector,
+ and we store only as many overlays as will fit.
+ But we still return the total number of overlays. */
+
+int
+overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr)
+ int pos;
+ int extend;
+ Lisp_Object **vec_ptr;
+ int *len_ptr;
+ int *next_ptr;
{
- register int start_loc, end_loc;
- Lisp_Object fieldlist;
- Lisp_Object collector;
-
- if (NILP (buffer))
- fieldlist = current_buffer->fieldlist;
- else
+ Lisp_Object tail, overlay, start, end, result;
+ int idx = 0;
+ int len = *len_ptr;
+ Lisp_Object *vec = *vec_ptr;
+ int next = ZV;
+ int inhibit_storing = 0;
+
+ for (tail = current_buffer->overlays_before;
+ CONSP (tail);
+ tail = XCONS (tail)->cdr)
{
- CHECK_BUFFER (buffer, 1);
- fieldlist = XBUFFER (buffer)->fieldlist;
- }
+ int startpos;
- CHECK_NUMBER_COERCE_MARKER (start, 2);
- start_loc = XINT (start);
+ overlay = XCONS (tail)->car;
+ if (! OVERLAY_VALID (overlay))
+ abort ();
- CHECK_NUMBER_COERCE_MARKER (end, 2);
- end_loc = XINT (end);
-
- collector = Qnil;
-
- while (XTYPE (fieldlist) == Lisp_Cons)
+ start = OVERLAY_START (overlay);
+ end = OVERLAY_END (overlay);
+ if (OVERLAY_POSITION (end) <= pos)
+ break;
+ startpos = OVERLAY_POSITION (start);
+ if (startpos <= pos)
+ {
+ if (idx == len)
+ {
+ /* The supplied vector is full.
+ Either make it bigger, or don't store any more in it. */
+ if (extend)
+ {
+ *len_ptr = len *= 2;
+ vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
+ *vec_ptr = vec;
+ }
+ else
+ inhibit_storing = 1;
+ }
+
+ if (!inhibit_storing)
+ vec[idx] = overlay;
+ /* Keep counting overlays even if we can't return them all. */
+ idx++;
+ }
+ else if (startpos < next)
+ next = startpos;
+ }
+
+ for (tail = current_buffer->overlays_after;
+ CONSP (tail);
+ tail = XCONS (tail)->cdr)
{
- register Lisp_Object field;
- register int field_start, field_end;
+ int startpos;
- field = XCONS (fieldlist)->car;
- field_start = marker_position (FIELD_START_MARKER (field)) - 1;
- field_end = marker_position (FIELD_END_MARKER (field));
+ overlay = XCONS (tail)->car;
+ if (! OVERLAY_VALID (overlay))
+ abort ();
- if ((start_loc < field_start && end_loc > field_start)
- || (start_loc >= field_start && start_loc < field_end))
+ start = OVERLAY_START (overlay);
+ end = OVERLAY_END (overlay);
+ startpos = OVERLAY_POSITION (start);
+ if (pos < startpos)
+ {
+ if (startpos < next)
+ next = startpos;
+ break;
+ }
+ if (pos < OVERLAY_POSITION (end))
{
- if (!NILP (error_check))
+ if (idx == len)
{
- if (!NILP (FIELD_PROTECTED_FLAG (field)))
+ if (extend)
{
- struct gcpro gcpro1;
- GCPRO1 (fieldlist);
- Fsignal (Qprotected_field, Fcons (field, Qnil));
- UNGCPRO;
+ *len_ptr = len *= 2;
+ vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
+ *vec_ptr = vec;
}
+ else
+ inhibit_storing = 1;
}
+
+ if (!inhibit_storing)
+ vec[idx] = overlay;
+ idx++;
+ }
+ }
+
+ *next_ptr = next;
+ return idx;
+}
+\f
+/* Shift overlays in BUF's overlay lists, to center the lists at POS. */
+
+void
+recenter_overlay_lists (buf, pos)
+ struct buffer *buf;
+ int pos;
+{
+ Lisp_Object overlay, tail, next, prev, beg, end;
+
+ /* See if anything in overlays_before should move to overlays_after. */
+
+ /* We don't strictly need prev in this loop; it should always be nil.
+ But we use it for symmetry and in case that should cease to be true
+ with some future change. */
+ prev = Qnil;
+ for (tail = buf->overlays_before;
+ CONSP (tail);
+ prev = tail, tail = next)
+ {
+ next = XCONS (tail)->cdr;
+ overlay = XCONS (tail)->car;
+
+ /* If the overlay is not valid, get rid of it. */
+ if (!OVERLAY_VALID (overlay))
+#if 1
+ abort ();
+#else
+ {
+ /* Splice the cons cell TAIL out of overlays_before. */
+ if (!NILP (prev))
+ XCONS (prev)->cdr = next;
else
- collector = Fcons (field, collector);
+ buf->overlays_before = next;
+ tail = prev;
+ continue;
}
-
- fieldlist = XCONS (fieldlist)->cdr;
+#endif
+
+ beg = OVERLAY_START (overlay);
+ end = OVERLAY_END (overlay);
+
+ if (OVERLAY_POSITION (end) > pos)
+ {
+ /* OVERLAY needs to be moved. */
+ int where = OVERLAY_POSITION (beg);
+ Lisp_Object other, other_prev;
+
+ /* Splice the cons cell TAIL out of overlays_before. */
+ if (!NILP (prev))
+ XCONS (prev)->cdr = next;
+ else
+ buf->overlays_before = next;
+
+ /* Search thru overlays_after for where to put it. */
+ other_prev = Qnil;
+ for (other = buf->overlays_after;
+ CONSP (other);
+ other_prev = other, other = XCONS (other)->cdr)
+ {
+ Lisp_Object otherbeg, otheroverlay, follower;
+ int win;
+
+ otheroverlay = XCONS (other)->car;
+ if (! OVERLAY_VALID (otheroverlay))
+ abort ();
+
+ otherbeg = OVERLAY_START (otheroverlay);
+ if (OVERLAY_POSITION (otherbeg) >= where)
+ break;
+ }
+
+ /* Add TAIL to overlays_after before OTHER. */
+ XCONS (tail)->cdr = other;
+ if (!NILP (other_prev))
+ XCONS (other_prev)->cdr = tail;
+ else
+ buf->overlays_after = tail;
+ tail = prev;
+ }
+ else
+ /* We've reached the things that should stay in overlays_before.
+ All the rest of overlays_before must end even earlier,
+ so stop now. */
+ break;
+ }
+
+ /* See if anything in overlays_after should be in overlays_before. */
+ prev = Qnil;
+ for (tail = buf->overlays_after;
+ CONSP (tail);
+ prev = tail, tail = next)
+ {
+ next = XCONS (tail)->cdr;
+ overlay = XCONS (tail)->car;
+
+ /* If the overlay is not valid, get rid of it. */
+ if (!OVERLAY_VALID (overlay))
+#if 1
+ abort ();
+#else
+ {
+ /* Splice the cons cell TAIL out of overlays_after. */
+ if (!NILP (prev))
+ XCONS (prev)->cdr = next;
+ else
+ buf->overlays_after = next;
+ tail = prev;
+ continue;
+ }
+#endif
+
+ beg = OVERLAY_START (overlay);
+ end = OVERLAY_END (overlay);
+
+ /* Stop looking, when we know that nothing further
+ can possibly end before POS. */
+ if (OVERLAY_POSITION (beg) > pos)
+ break;
+
+ if (OVERLAY_POSITION (end) <= pos)
+ {
+ /* OVERLAY needs to be moved. */
+ int where = OVERLAY_POSITION (end);
+ Lisp_Object other, other_prev;
+
+ /* Splice the cons cell TAIL out of overlays_after. */
+ if (!NILP (prev))
+ XCONS (prev)->cdr = next;
+ else
+ buf->overlays_after = next;
+
+ /* Search thru overlays_before for where to put it. */
+ other_prev = Qnil;
+ for (other = buf->overlays_before;
+ CONSP (other);
+ other_prev = other, other = XCONS (other)->cdr)
+ {
+ Lisp_Object otherend, otheroverlay;
+ int win;
+
+ otheroverlay = XCONS (other)->car;
+ if (! OVERLAY_VALID (otheroverlay))
+ abort ();
+
+ otherend = OVERLAY_END (otheroverlay);
+ if (OVERLAY_POSITION (otherend) <= where)
+ break;
+ }
+
+ /* Add TAIL to overlays_before before OTHER. */
+ XCONS (tail)->cdr = other;
+ if (!NILP (other_prev))
+ XCONS (other_prev)->cdr = tail;
+ else
+ buf->overlays_before = tail;
+ tail = prev;
+ }
+ }
+
+ XFASTINT (buf->overlay_center) = pos;
+}
+\f
+DEFUN ("overlayp", Foverlayp, Soverlayp, 1, 1, 0,
+ "Return t if OBJECT is an overlay.")
+ (object)
+ Lisp_Object object;
+{
+ return (OVERLAYP (object) ? Qt : Qnil);
+}
+
+DEFUN ("make-overlay", Fmake_overlay, Smake_overlay, 2, 3, 0,
+ "Create a new overlay with range BEG to END in BUFFER.\n\
+If omitted, BUFFER defaults to the current buffer.\n\
+BEG and END may be integers or markers.")
+ (beg, end, buffer)
+ Lisp_Object beg, end, buffer;
+{
+ Lisp_Object overlay;
+ struct buffer *b;
+
+ if (NILP (buffer))
+ XSET (buffer, Lisp_Buffer, current_buffer);
+ else
+ CHECK_BUFFER (buffer, 2);
+ if (MARKERP (beg)
+ && ! EQ (Fmarker_buffer (beg), buffer))
+ error ("Marker points into wrong buffer");
+ if (MARKERP (end)
+ && ! EQ (Fmarker_buffer (end), buffer))
+ error ("Marker points into wrong buffer");
+
+ CHECK_NUMBER_COERCE_MARKER (beg, 1);
+ CHECK_NUMBER_COERCE_MARKER (end, 1);
+
+ if (XINT (beg) > XINT (end))
+ {
+ Lisp_Object temp = beg;
+ beg = end; end = temp;
+ }
+
+ b = XBUFFER (buffer);
+
+ beg = Fset_marker (Fmake_marker (), beg, buffer);
+ end = Fset_marker (Fmake_marker (), end, buffer);
+
+ overlay = Fcons (Fcons (beg, end), Qnil);
+ XSETTYPE (overlay, Lisp_Overlay);
+
+ /* Put the new overlay on the wrong list. */
+ end = OVERLAY_END (overlay);
+ if (OVERLAY_POSITION (end) < XINT (b->overlay_center))
+ b->overlays_after = Fcons (overlay, b->overlays_after);
+ else
+ b->overlays_before = Fcons (overlay, b->overlays_before);
+
+ /* This puts it in the right list, and in the right order. */
+ recenter_overlay_lists (b, XINT (b->overlay_center));
+
+ /* We don't need to redisplay the region covered by the overlay, because
+ the overlay has no properties at the moment. */
+
+ return overlay;
+}
+
+DEFUN ("move-overlay", Fmove_overlay, Smove_overlay, 3, 4, 0,
+ "Set the endpoints of OVERLAY to BEG and END in BUFFER.\n\
+If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now.\n\
+If BUFFER is omitted, and OVERLAY is in no buffer, put it in the current\n\
+buffer.")
+ (overlay, beg, end, buffer)
+ Lisp_Object overlay, beg, end, buffer;
+{
+ struct buffer *b, *ob;
+ Lisp_Object obuffer;
+ int count = specpdl_ptr - specpdl;
+
+ CHECK_OVERLAY (overlay, 0);
+ if (NILP (buffer))
+ buffer = Fmarker_buffer (OVERLAY_START (overlay));
+ if (NILP (buffer))
+ XSET (buffer, Lisp_Buffer, current_buffer);
+ CHECK_BUFFER (buffer, 3);
+
+ if (MARKERP (beg)
+ && ! EQ (Fmarker_buffer (beg), buffer))
+ error ("Marker points into wrong buffer");
+ if (MARKERP (end)
+ && ! EQ (Fmarker_buffer (end), buffer))
+ error ("Marker points into wrong buffer");
+
+ CHECK_NUMBER_COERCE_MARKER (beg, 1);
+ CHECK_NUMBER_COERCE_MARKER (end, 1);
+
+ specbind (Qinhibit_quit, Qt);
+
+ if (XINT (beg) > XINT (end))
+ {
+ Lisp_Object temp = beg;
+ beg = end; end = temp;
+ }
+
+ obuffer = Fmarker_buffer (OVERLAY_START (overlay));
+ b = XBUFFER (buffer);
+ ob = XBUFFER (obuffer);
+
+ /* If the overlay has changed buffers, do a thorough redisplay. */
+ if (!EQ (buffer, obuffer))
+ windows_or_buffers_changed = 1;
+ else
+ /* Redisplay the area the overlay has just left, or just enclosed. */
+ {
+ Lisp_Object o_beg = OVERLAY_START (overlay);
+ Lisp_Object o_end = OVERLAY_END (overlay);
+ int change_beg, change_end;
+
+ o_beg = OVERLAY_POSITION (o_beg);
+ o_end = OVERLAY_POSITION (o_end);
+
+ if (XINT (o_beg) == XINT (beg))
+ redisplay_region (b, XINT (o_end), XINT (end));
+ else if (XINT (o_end) == XINT (end))
+ redisplay_region (b, XINT (o_beg), XINT (beg));
+ else
+ {
+ if (XINT (beg) < XINT (o_beg)) o_beg = beg;
+ if (XINT (end) > XINT (o_end)) o_end = end;
+ redisplay_region (b, XINT (o_beg), XINT (o_end));
+ }
+ }
+
+ if (!NILP (obuffer))
+ {
+ ob->overlays_before = Fdelq (overlay, ob->overlays_before);
+ ob->overlays_after = Fdelq (overlay, ob->overlays_after);
+ }
+
+ Fset_marker (OVERLAY_START (overlay), beg, buffer);
+ Fset_marker (OVERLAY_END (overlay), end, buffer);
+
+ /* Put the overlay on the wrong list. */
+ end = OVERLAY_END (overlay);
+ if (OVERLAY_POSITION (end) < XINT (b->overlay_center))
+ b->overlays_after = Fcons (overlay, b->overlays_after);
+ else
+ b->overlays_before = Fcons (overlay, b->overlays_before);
+
+ /* This puts it in the right list, and in the right order. */
+ recenter_overlay_lists (b, XINT (b->overlay_center));
+
+ return unbind_to (count, overlay);
+}
+
+DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
+ "Delete the overlay OVERLAY from its buffer.")
+ (overlay)
+ Lisp_Object overlay;
+{
+ Lisp_Object buffer;
+ struct buffer *b;
+ int count = specpdl_ptr - specpdl;
+
+ CHECK_OVERLAY (overlay, 0);
+
+ buffer = Fmarker_buffer (OVERLAY_START (overlay));
+ if (NILP (buffer))
+ return Qnil;
+
+ b = XBUFFER (buffer);
+
+ specbind (Qinhibit_quit, Qt);
+
+ b->overlays_before = Fdelq (overlay, b->overlays_before);
+ b->overlays_after = Fdelq (overlay, b->overlays_after);
+
+ redisplay_region (b,
+ OVERLAY_POSITION (OVERLAY_START (overlay)),
+ OVERLAY_POSITION (OVERLAY_END (overlay)));
+
+ Fset_marker (OVERLAY_START (overlay), Qnil, Qnil);
+ Fset_marker (OVERLAY_END (overlay), Qnil, Qnil);
+
+ return unbind_to (count, Qnil);
+}
+\f
+/* Overlay dissection functions. */
+
+DEFUN ("overlay-start", Foverlay_start, Soverlay_start, 1, 1, 0,
+ "Return the position at which OVERLAY starts.")
+ (overlay)
+ Lisp_Object overlay;
+{
+ CHECK_OVERLAY (overlay, 0);
+
+ return (Fmarker_position (OVERLAY_START (overlay)));
+}
+
+DEFUN ("overlay-end", Foverlay_end, Soverlay_end, 1, 1, 0,
+ "Return the position at which OVERLAY ends.")
+ (overlay)
+ Lisp_Object overlay;
+{
+ CHECK_OVERLAY (overlay, 0);
+
+ return (Fmarker_position (OVERLAY_END (overlay)));
+}
+
+DEFUN ("overlay-buffer", Foverlay_buffer, Soverlay_buffer, 1, 1, 0,
+ "Return the buffer OVERLAY belongs to.")
+ (overlay)
+ Lisp_Object overlay;
+{
+ CHECK_OVERLAY (overlay, 0);
+
+ return Fmarker_buffer (OVERLAY_START (overlay));
+}
+
+DEFUN ("overlay-properties", Foverlay_properties, Soverlay_properties, 1, 1, 0,
+ "Return a list of the properties on OVERLAY.\n\
+This is a copy of OVERLAY's plist; modifying its conses has no effect on\n\
+OVERLAY.")
+ (overlay)
+ Lisp_Object overlay;
+{
+ CHECK_OVERLAY (overlay, 0);
+
+ return Fcopy_sequence (Fcdr_safe (XCONS (overlay)->cdr));
+}
+
+\f
+DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0,
+ "Return a list of the overlays that contain position POS.")
+ (pos)
+ Lisp_Object pos;
+{
+ int noverlays;
+ int endpos;
+ Lisp_Object *overlay_vec;
+ int len;
+ Lisp_Object result;
+
+ CHECK_NUMBER_COERCE_MARKER (pos, 0);
+
+ len = 10;
+ overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
+
+ /* Put all the overlays we want in a vector in overlay_vec.
+ Store the length in len. */
+ noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, &endpos);
+
+ /* Make a list of them all. */
+ result = Flist (noverlays, overlay_vec);
+
+ xfree (overlay_vec);
+ return result;
+}
+
+DEFUN ("next-overlay-change", Fnext_overlay_change, Snext_overlay_change,
+ 1, 1, 0,
+ "Return the next position after POS where an overlay starts or ends.")
+ (pos)
+ Lisp_Object pos;
+{
+ int noverlays;
+ int endpos;
+ Lisp_Object *overlay_vec;
+ int len;
+ Lisp_Object result;
+ int i;
+
+ CHECK_NUMBER_COERCE_MARKER (pos, 0);
+
+ len = 10;
+ overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
+
+ /* Put all the overlays we want in a vector in overlay_vec.
+ Store the length in len.
+ endpos gets the position where the next overlay starts. */
+ noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, &endpos);
+
+ /* If any of these overlays ends before endpos,
+ use its ending point instead. */
+ for (i = 0; i < noverlays; i++)
+ {
+ Lisp_Object oend;
+ int oendpos;
+
+ oend = OVERLAY_END (overlay_vec[i]);
+ oendpos = OVERLAY_POSITION (oend);
+ if (oendpos < endpos)
+ endpos = oendpos;
}
- return collector;
+ xfree (overlay_vec);
+ return make_number (endpos);
+}
+\f
+/* These functions are for debugging overlays. */
+
+DEFUN ("overlay-lists", Foverlay_lists, Soverlay_lists, 0, 0, 0,
+ "Return a pair of lists giving all the overlays of the current buffer.\n\
+The car has all the overlays before the overlay center;\n\
+the cdr has all the overlays before the overlay center.\n\
+Recentering overlays moves overlays between these lists.\n\
+The lists you get are copies, so that changing them has no effect.\n\
+However, the overlays you get are the real objects that the buffer uses.")
+ ()
+{
+ Lisp_Object before, after;
+ before = current_buffer->overlays_before;
+ if (CONSP (before))
+ before = Fcopy_sequence (before);
+ after = current_buffer->overlays_after;
+ if (CONSP (after))
+ after = Fcopy_sequence (after);
+
+ return Fcons (before, after);
+}
+
+DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0,
+ "Recenter the overlays of the current buffer around position POS.")
+ (pos)
+ Lisp_Object pos;
+{
+ CHECK_NUMBER_COERCE_MARKER (pos, 0);
+
+ recenter_overlay_lists (current_buffer, XINT (pos));
+ return Qnil;
+}
+\f
+DEFUN ("overlay-get", Foverlay_get, Soverlay_get, 2, 2, 0,
+ "Get the property of overlay OVERLAY with property name NAME.")
+ (overlay, prop)
+ Lisp_Object overlay, prop;
+{
+ Lisp_Object plist;
+
+ CHECK_OVERLAY (overlay, 0);
+
+ for (plist = Fcdr_safe (XCONS (overlay)->cdr);
+ CONSP (plist) && CONSP (XCONS (plist)->cdr);
+ plist = XCONS (XCONS (plist)->cdr)->cdr)
+ {
+ if (EQ (XCONS (plist)->car, prop))
+ return XCONS (XCONS (plist)->cdr)->car;
+ }
+
+ return Qnil;
+}
+
+DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
+ "Set one property of overlay OVERLAY: give property PROP value VALUE.")
+ (overlay, prop, value)
+ Lisp_Object overlay, prop, value;
+{
+ Lisp_Object plist, tail;
+
+ CHECK_OVERLAY (overlay, 0);
+
+ redisplay_region (XMARKER (OVERLAY_START (overlay))->buffer,
+ OVERLAY_POSITION (OVERLAY_START (overlay)),
+ OVERLAY_POSITION (OVERLAY_END (overlay)));
+
+ plist = Fcdr_safe (XCONS (overlay)->cdr);
+
+ for (tail = plist;
+ CONSP (tail) && CONSP (XCONS (tail)->cdr);
+ tail = XCONS (XCONS (tail)->cdr)->cdr)
+ {
+ if (EQ (XCONS (tail)->car, prop))
+ return XCONS (XCONS (tail)->cdr)->car = value;
+ }
+
+ if (! CONSP (XCONS (overlay)->cdr))
+ XCONS (overlay)->cdr = Fcons (Qnil, Qnil);
+
+ XCONS (XCONS (overlay)->cdr)->cdr
+ = Fcons (prop, Fcons (value, plist));
+
+ return value;
+}
+\f
+/* Run the modification-hooks of overlays that include
+ any part of the text in START to END.
+ Run the insert-before-hooks of overlay starting at END,
+ and the insert-after-hooks of overlay ending at START. */
+
+void
+verify_overlay_modification (start, end)
+ Lisp_Object start, end;
+{
+ Lisp_Object prop, overlay, tail;
+ int insertion = EQ (start, end);
+
+ for (tail = current_buffer->overlays_before;
+ CONSP (tail);
+ tail = XCONS (tail)->cdr)
+ {
+ int startpos, endpos;
+ int ostart, oend;
+
+ overlay = XCONS (tail)->car;
+
+ ostart = OVERLAY_START (overlay);
+ oend = OVERLAY_END (overlay);
+ endpos = OVERLAY_POSITION (oend);
+ if (XFASTINT (start) > endpos)
+ break;
+ startpos = OVERLAY_POSITION (ostart);
+ if (XFASTINT (end) == startpos && insertion)
+ {
+ prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
+ call_overlay_mod_hooks (prop, overlay, start, end);
+ }
+ if (XFASTINT (start) == endpos && insertion)
+ {
+ prop = Foverlay_get (overlay, Qinsert_behind_hooks);
+ call_overlay_mod_hooks (prop, overlay, start, end);
+ }
+ if (insertion
+ ? (XFASTINT (start) > startpos && XFASTINT (end) < endpos)
+ : (XFASTINT (start) >= startpos && XFASTINT (end) <= endpos))
+ {
+ prop = Foverlay_get (overlay, Qmodification_hooks);
+ call_overlay_mod_hooks (prop, overlay, start, end);
+ }
+ }
+
+ for (tail = current_buffer->overlays_after;
+ CONSP (tail);
+ tail = XCONS (tail)->cdr)
+ {
+ int startpos, endpos;
+ int ostart, oend;
+
+ overlay = XCONS (tail)->car;
+
+ ostart = OVERLAY_START (overlay);
+ oend = OVERLAY_END (overlay);
+ startpos = OVERLAY_POSITION (ostart);
+ if (XFASTINT (end) < startpos)
+ break;
+ if (XFASTINT (end) == startpos && insertion)
+ {
+ prop = Foverlay_get (overlay, Qinsert_in_front_hooks);
+ call_overlay_mod_hooks (prop, overlay, start, end);
+ }
+ if (XFASTINT (start) == endpos && insertion)
+ {
+ prop = Foverlay_get (overlay, Qinsert_behind_hooks);
+ call_overlay_mod_hooks (prop, overlay, start, end);
+ }
+ if (insertion
+ ? (XFASTINT (start) > startpos && XFASTINT (end) < endpos)
+ : (XFASTINT (start) >= startpos && XFASTINT (end) <= endpos))
+ {
+ prop = Foverlay_get (overlay, Qmodification_hooks);
+ call_overlay_mod_hooks (prop, overlay, start, end);
+ }
+ }
+}
+
+static void
+call_overlay_mod_hooks (list, overlay, start, end)
+ Lisp_Object list, overlay, start, end;
+{
+ struct gcpro gcpro1;
+ GCPRO1 (list);
+ while (!NILP (list))
+ {
+ call3 (Fcar (list), overlay, start, end);
+ list = Fcdr (list);
+ }
+ UNGCPRO;
}
\f
/* Somebody has tried to store NEWVAL into the buffer-local slot with
Lisp_Object valcontents, newval;
{
unsigned int offset = XUINT (valcontents);
- char *symbol_name =
+ unsigned char *symbol_name =
(XSYMBOL (*(Lisp_Object *)(offset + (char *)&buffer_local_symbols))
->name->data);
char *type_name;
case Lisp_Marker: type_name = "markers"; break;
case Lisp_Symbol: type_name = "symbols"; break;
case Lisp_Cons: type_name = "lists"; break;
- case Lisp_Vector: type_name = "vector"; break;
+ case Lisp_Vector: type_name = "vectors"; break;
default:
abort ();
}
#endif
buffer_defaults.abbrev_table = Qnil;
buffer_defaults.display_table = Qnil;
- buffer_defaults.fieldlist = Qnil;
buffer_defaults.undo_list = Qnil;
+ buffer_defaults.mark_active = Qnil;
+ buffer_defaults.overlays_before = Qnil;
+ buffer_defaults.overlays_after = Qnil;
+ XFASTINT (buffer_defaults.overlay_center) = 1;
XFASTINT (buffer_defaults.tab_width) = 8;
buffer_defaults.truncate_lines = Qnil;
XFASTINT (buffer_local_flags.major_mode) = -1;
XFASTINT (buffer_local_flags.mode_name) = -1;
XFASTINT (buffer_local_flags.undo_list) = -1;
+ XFASTINT (buffer_local_flags.mark_active) = -1;
XFASTINT (buffer_local_flags.mode_line_format) = 1;
XFASTINT (buffer_local_flags.abbrev_mode) = 2;
XFASTINT (buffer_local_flags.left_margin) = 0x800;
XFASTINT (buffer_local_flags.abbrev_table) = 0x1000;
XFASTINT (buffer_local_flags.display_table) = 0x2000;
- XFASTINT (buffer_local_flags.fieldlist) = 0x4000;
XFASTINT (buffer_local_flags.syntax_table) = 0x8000;
Vbuffer_alist = Qnil;
char buf[MAXPATHLEN+1];
char *pwd;
struct stat dotstat, pwdstat;
+ Lisp_Object temp;
Fset_buffer (Fget_buffer_create (build_string ("*scratch*")));
strcat (buf, "/");
#endif /* not VMS */
current_buffer->directory = build_string (buf);
+
+ temp = get_minibuffer (0);
+ XBUFFER (temp)->directory = current_buffer->directory;
}
/* initialize the buffer routines */
syms_of_buffer ()
{
+ extern Lisp_Object Qdisabled;
+
staticpro (&Vbuffer_defaults);
staticpro (&Vbuffer_local_symbols);
staticpro (&Qfundamental_mode);
staticpro (&Qprotected_field);
staticpro (&Qpermanent_local);
staticpro (&Qkill_buffer_hook);
+ staticpro (&Qoverlayp);
+
+ Qoverlayp = intern ("overlayp");
Fput (Qprotected_field, Qerror_conditions,
Fcons (Qprotected_field, Fcons (Qerror, Qnil)));
Fput (Qprotected_field, Qerror_message,
build_string ("Attempt to modify a protected field"));
+ Fput (intern ("erase-buffer"), Qdisabled, Qt);
+
/* All these use DEFVAR_LISP_NOPRO because the slots in
buffer_defaults will all be marked via Vbuffer_defaults. */
/* This doc string is too long for cpp; cpp dies if it isn't in a comment.
But make-docfile finds it!
DEFVAR_PER_BUFFER ("mode-line-format", ¤t_buffer->mode_line_format,
+ Qnil,
"Template for displaying mode line for current buffer.\n\
Each buffer has its own value of this variable.\n\
Value may be a string, a symbol or a list or cons cell.\n\
or when it is found in a cons-cell or a list)\n\
%b -- print buffer name. %f -- print visited file name.\n\
%* -- print *, % or hyphen. %m -- print value of mode-name (obsolete).\n\
- %s -- print process status. %M -- print value of global-mode-string. (obs)\n\
+ %s -- print process status. %l -- print the current line number.\n\
%p -- print percent of buffer above top of window, or top, bot or all.\n\
%n -- print Narrow if appropriate.\n\
%[ -- print one [ for each recursive editing level. %] similar.\n\
DEFVAR_PER_BUFFER ("overwrite-mode", ¤t_buffer->overwrite_mode, Qnil,
"Non-nil if self-insertion should replace existing text.\n\
+If non-nil and not `overwrite-mode-binary', self-insertion still\n\
+inserts at the end of a line, and inserts when point is before a tab,\n\
+until the tab is filled in.\n\
+If `overwrite-mode-binary', self-insertion replaces newlines and tabs too.\n\
Automatically becomes buffer-local when set in any fashion.");
DEFVAR_PER_BUFFER ("buffer-display-table", ¤t_buffer->display_table,
Automatically becomes buffer-local when set in any fashion.\n\
The display table is a vector created with `make-display-table'.\n\
The first 256 elements control how to display each possible text character.\n\
-The value should be a \"rope\" (see `make-rope') or nil;\n\
+Each value should be a vector of characters or nil;\n\
nil means display the character in the default fashion.\n\
-The remaining five elements are ropes that control the display of\n\
- the end of a truncated screen line (element 256);\n\
- the end of a continued line (element 257);\n\
- the escape character used to display character codes in octal (element 258);\n\
- the character used as an arrow for control characters (element 259);\n\
- the decoration indicating the presence of invisible lines (element 260).\n\
+The remaining five elements control the display of\n\
+ the end of a truncated screen line (element 256, a single character);\n\
+ the end of a continued line (element 257, a single character);\n\
+ the escape character used to display character codes in octal\n\
+ (element 258, a single character);\n\
+ the character used as an arrow for control characters (element 259,\n\
+ a single character);\n\
+ the decoration indicating the presence of invisible lines (element 260,\n\
+ a vector of characters).\n\
If this variable is nil, the value of `standard-display-table' is used.\n\
Each window can have its own, overriding display table.");
- DEFVAR_PER_BUFFER ("buffer-field-list", ¤t_buffer->fieldlist, Qnil,
- "List of fields in the current buffer. See `add-field'.");
-
- DEFVAR_BOOL ("check-protected-fields", check_protected_fields,
- "Non-nil means don't allow modification of a protected field.\n\
-See `add-field'.");
- check_protected_fields = 0;
-
/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
"Don't ask.");
*/
cause calls to any `before-change-function' or `after-change-function'.");
Vafter_change_function = Qnil;
- DEFVAR_LISP ("first-change-function", &Vfirst_change_function,
- "Function to call before changing a buffer which is unmodified.\n\
-The function is called, with no arguments, if it is non-nil.");
- Vfirst_change_function = Qnil;
+ DEFVAR_LISP ("first-change-hook", &Vfirst_change_hook,
+ "A list of functions to call before changing a buffer which is unmodified.\n\
+The functions are run using the `run-hooks' function.");
+ Vfirst_change_hook = Qnil;
+ Qfirst_change_hook = intern ("first-change-hook");
+ staticpro (&Qfirst_change_hook);
DEFVAR_PER_BUFFER ("buffer-undo-list", ¤t_buffer->undo_list, Qnil,
"List of undo entries in current buffer.\n\
modification count of the most recent save is different, this entry is\n\
obsolete.\n\
\n\
+An entry (nil PROP VAL BEG . END) indicates that a text property\n\
+was modified between BEG and END. PROP is the property name,\n\
+and VAL is the old value.\n\
+\n\
+An entry of the form POSITION indicates that point was at the buffer\n\
+location given by the integer. Undoing an entry of this form places\n\
+point at POSITION.\n\
+\n\
nil marks undo boundaries. The undo command treats the changes\n\
between two undo boundaries as a single step to be undone.\n\
\n\
-If the value of the variable is t, undo information is not recorded.\n\
-");
+If the value of the variable is t, undo information is not recorded.");
+
+ DEFVAR_PER_BUFFER ("mark-active", ¤t_buffer->mark_active, Qnil,
+ "Non-nil means the mark and region are currently active in this buffer.\n\
+Automatically local in all buffers.");
+
+ DEFVAR_LISP ("transient-mark-mode", &Vtransient_mark_mode,
+ "*Non-nil means deactivate the mark when the buffer contents change.");
+ Vtransient_mark_mode = Qnil;
+
+ DEFVAR_LISP ("inhibit-read-only", &Vinhibit_read_only,
+ "*Non-nil means disregard read-only status of buffers or characters.\n\
+If the value is t, disregard `buffer-read-only' and all `read-only'\n\
+text properties. If the value is a list, disregard `buffer-read-only'\n\
+and disregard a `read-only' text property if the property value\n\
+is a member of the list.");
+ Vinhibit_read_only = Qnil;
defsubr (&Sbuffer_list);
defsubr (&Sget_buffer);
defsubr (&Sbury_buffer);
defsubr (&Slist_buffers);
defsubr (&Skill_all_local_variables);
- defsubr (&Sregion_fields);
+
+ defsubr (&Soverlayp);
+ defsubr (&Smake_overlay);
+ defsubr (&Sdelete_overlay);
+ defsubr (&Smove_overlay);
+ defsubr (&Soverlay_start);
+ defsubr (&Soverlay_end);
+ defsubr (&Soverlay_buffer);
+ defsubr (&Soverlay_properties);
+ defsubr (&Soverlays_at);
+ defsubr (&Snext_overlay_change);
+ defsubr (&Soverlay_recenter);
+ defsubr (&Soverlay_lists);
+ defsubr (&Soverlay_get);
+ defsubr (&Soverlay_put);
}
keys_of_buffer ()