/* Buffer manipulation primitives for GNU Emacs.
- Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993
+ Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "window.h"
#include "commands.h"
#include "buffer.h"
-#include "syntax.h"
#include "indent.h"
#include "blockinput.h"
Any non-nil value means ignore buffer-read-only. */
Lisp_Object Vinhibit_read_only;
+/* List of functions to call that can query about killing a buffer.
+ If any of these functions returns nil, we don't kill it. */
+Lisp_Object Vkill_buffer_query_functions;
+
/* List of functions to call before changing an unmodified buffer. */
Lisp_Object Vfirst_change_hook;
Lisp_Object Qfirst_change_hook;
Lisp_Object Qkill_buffer_hook;
+Lisp_Object Qget_file_buffer;
+
Lisp_Object Qoverlayp;
+Lisp_Object Qpriority, Qwindow;
+
Lisp_Object Qmodification_hooks;
Lisp_Object Qinsert_in_front_hooks;
Lisp_Object Qinsert_behind_hooks;
/* For debugging; temporary. See set_buffer_internal. */
/* Lisp_Object Qlisp_mode, Vcheck_symbol; */
+#ifdef MSDOS
+Lisp_Object Qbuffer_file_type;
+#endif
+
nsberror (spec)
Lisp_Object spec;
{
DEFUN ("get-file-buffer", Fget_file_buffer, Sget_file_buffer, 1, 1, 0,
"Return the buffer visiting file FILENAME (a string).\n\
+The buffer's `buffer-file-name' must match exactly the expansion of FILENAME.\n\
If there is no such live buffer, return nil.")
(filename)
register Lisp_Object filename;
{
register Lisp_Object tail, buf, tem;
+ Lisp_Object handler;
+
CHECK_STRING (filename, 0);
filename = Fexpand_file_name (filename, Qnil);
+ /* If the file name has special constructs in it,
+ call the corresponding file handler. */
+ handler = Ffind_file_name_handler (filename);
+ if (!NILP (handler))
+ return call2 (handler, Qget_file_buffer, filename);
+
for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
{
buf = Fcdr (XCONS (tail)->car);
CHECK_STRING (name, 0);
tem = Fget_buffer (name);
- if (XBUFFER (tem) == current_buffer)
+ /* Don't short-circuit if UNIQUE is t. That is a useful way to rename
+ the buffer automatically so you can create another with the original name.
+ It makes UNIQUE equivalent to
+ (rename-buffer (generate-new-buffer-name NAME)). */
+ if (NILP (unique) && XBUFFER (tem) == current_buffer)
return current_buffer->name;
if (!NILP (tem))
{
return Fget_buffer_create (build_string ("*scratch*"));
}
\f
-DEFUN ("buffer-disable-undo", Fbuffer_disable_undo, Sbuffer_disable_undo, 1,1,
+DEFUN ("buffer-disable-undo", Fbuffer_disable_undo, Sbuffer_disable_undo, 0, 1,
0,
- "Make BUFFER stop keeping undo information.")
+ "Make BUFFER stop keeping undo information.\n\
+No argument or nil as argument means do this for the current buffer.")
(buffer)
register Lisp_Object buffer;
{
return Qnil;
}
- /* Run kill-buffer hook with the buffer to be killed the current buffer. */
+ /* Run hooks with the buffer to be killed the current buffer. */
{
register Lisp_Object val;
int count = specpdl_ptr - specpdl;
+ Lisp_Object list;
record_unwind_protect (save_excursion_restore, save_excursion_save ());
set_buffer_internal (b);
- call1 (Vrun_hooks, Qkill_buffer_hook);
+
+ /* First run the query functions; if any query is answered no,
+ don't kill the buffer. */
+ for (list = Vkill_buffer_query_functions; !NILP (list); list = Fcdr (list))
+ {
+ tem = call0 (Fcar (list));
+ if (NILP (tem))
+ return unbind_to (count, Qnil);
+ }
+
+ /* Then run the hooks. */
+ if (!NILP (Vrun_hooks))
+ call1 (Vrun_hooks, Qkill_buffer_hook);
unbind_to (count, Qnil);
}
{
register Lisp_Object alist, sym, tem;
Lisp_Object oalist;
+
+ if (!NILP (Vrun_hooks))
+ call1 (Vrun_hooks, intern ("change-major-mode-hook"));
oalist = current_buffer->local_var_alist;
/* Make sure no local variables remain set up with this buffer
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;
+ XCONS (XCONS (tem)->car)->cdr
+ = do_symval_forwarding (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. */
return idx;
}
\f
+struct sortvec
+{
+ Lisp_Object overlay;
+ int beg, end;
+ int priority;
+};
+
+static int
+compare_overlays (s1, s2)
+ struct sortvec *s1, *s2;
+{
+ if (s1->priority != s2->priority)
+ return s1->priority - s2->priority;
+ if (s1->beg != s2->beg)
+ return s1->beg - s2->beg;
+ if (s1->end != s2->end)
+ return s2->end - s1->end;
+ return 0;
+}
+
+/* Sort an array of overlays by priority. The array is modified in place.
+ The return value is the new size; this may be smaller than the original
+ size if some of the overlays were invalid or were window-specific. */
+int
+sort_overlays (overlay_vec, noverlays, w)
+ Lisp_Object *overlay_vec;
+ int noverlays;
+ struct window *w;
+{
+ int i, j;
+ struct sortvec *sortvec;
+ sortvec = (struct sortvec *) alloca (noverlays * sizeof (struct sortvec));
+
+ /* Put the valid and relevant overlays into sortvec. */
+
+ for (i = 0, j = 0; i < noverlays; i++)
+ {
+ Lisp_Object tem;
+ Lisp_Object overlay = overlay_vec[i];
+
+ if (OVERLAY_VALID (overlay)
+ && OVERLAY_POSITION (OVERLAY_START (overlay)) > 0
+ && OVERLAY_POSITION (OVERLAY_END (overlay)) > 0)
+ {
+ /* If we're interested in a specific window, then ignore
+ overlays that are limited to some other window. */
+ if (w)
+ {
+ Lisp_Object window;
+
+ window = Foverlay_get (overlay, Qwindow);
+ if (XTYPE (window) == Lisp_Window && XWINDOW (window) != w)
+ continue;
+ }
+
+ /* This overlay is good and counts: put it into sortvec. */
+ sortvec[j].overlay = overlay;
+ sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay));
+ sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay));
+ tem = Foverlay_get (overlay, Qpriority);
+ if (INTEGERP (tem))
+ sortvec[j].priority = XINT (tem);
+ else
+ sortvec[j].priority = 0;
+ j++;
+ }
+ }
+ noverlays = j;
+
+ /* Sort the overlays into the proper order: increasing priority. */
+
+ if (noverlays > 1)
+ qsort (sortvec, noverlays, sizeof (struct sortvec), compare_overlays);
+
+ for (i = 0; i < noverlays; i++)
+ overlay_vec[i] = sortvec[i].overlay;
+ return (noverlays);
+}
+\f
/* Shift overlays in BUF's overlay lists, to center the lists at POS. */
void
buffer_defaults.truncate_lines = Qnil;
buffer_defaults.ctl_arrow = Qt;
+#ifdef MSDOS
+ buffer_defaults.buffer_file_type = 0; /* TEXT */
+#endif
XFASTINT (buffer_defaults.fill_column) = 70;
XFASTINT (buffer_defaults.left_margin) = 0;
XFASTINT (buffer_local_flags.abbrev_table) = 0x1000;
XFASTINT (buffer_local_flags.display_table) = 0x2000;
XFASTINT (buffer_local_flags.syntax_table) = 0x8000;
+#ifdef MSDOS
+ XFASTINT (buffer_local_flags.buffer_file_type) = 0x4000;
+#endif
Vbuffer_alist = Qnil;
current_buffer = 0;
Qinsert_in_front_hooks = intern ("insert-in-front-hooks");
staticpro (&Qinsert_behind_hooks);
Qinsert_behind_hooks = intern ("insert-behind-hooks");
+ staticpro (&Qget_file_buffer);
+ Qget_file_buffer = intern ("get-file-buffer");
+ Qpriority = intern ("priority");
+ staticpro (&Qpriority);
+ Qwindow = intern ("window");
+ staticpro (&Qwindow);
Qoverlayp = intern ("overlayp");
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. */
"Default value of `case-fold-search' for buffers that don't override it.\n\
This is the same as (default-value 'case-fold-search).");
+#ifdef MSDOS
+ DEFVAR_LISP_NOPRO ("default-buffer-file-type",
+ &buffer_defaults.buffer_file_type,
+ "Default file type for buffers that do not override it.\n\
+This is the same as (default-value 'buffer-file-type).\n\
+The file type is nil for text, t for binary.");
+#endif
+
DEFVAR_PER_BUFFER ("mode-line-format", ¤t_buffer->mode_line_format,
Qnil, 0);
%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. %l -- print the current line number.\n\
- %p -- print percent of buffer above top of window, or top, bot or all.\n\
+ %p -- print percent of buffer above top of window, or Top, Bot or All.\n\
+ %p -- print percent of buffer above bottom of window, perhaps plus Top,\n\
+ or print Bottom or All.\n\
%n -- print Narrow if appropriate.\n\
+ %t -- print T if files is text, B if binary.\n\
%[ -- print one [ for each recursive editing level. %] similar.\n\
%% -- print %. %- -- print infinitely many dashes.\n\
Decimal digits after the % specify field width to which to pad.");
`truncate-partial-width-windows' if that variable is non-nil\n\
and this buffer is not full-frame width.");
+#ifdef MSDOS
+ DEFVAR_PER_BUFFER ("buffer-file-type", ¤t_buffer->buffer_file_type,
+ Qnil,
+ "*If visited file is text, nil; otherwise, t.");
+#endif
+
DEFVAR_PER_BUFFER ("default-directory", ¤t_buffer->directory,
make_number (Lisp_String),
"Name of default directory of current buffer. Should end with slash.\n\
Each window can have its own, overriding display table.");
#endif
DEFVAR_PER_BUFFER ("buffer-display-table", ¤t_buffer->display_table,
- Qnil, "");
+ Qnil, 0);
/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
"Don't ask.");
If the value of the variable is t, undo information is not recorded.");
#endif
DEFVAR_PER_BUFFER ("buffer-undo-list", ¤t_buffer->undo_list, Qnil,
- "");
+ 0);
DEFVAR_PER_BUFFER ("mark-active", ¤t_buffer->mark_active, Qnil,
"Non-nil means the mark and region are currently active in this buffer.\n\
is a member of the list.");
Vinhibit_read_only = Qnil;
+ 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;
+
defsubr (&Sbuffer_list);
defsubr (&Sget_buffer);
defsubr (&Sget_file_buffer);
initial_define_key (control_x_map, 'b', "switch-to-buffer");
initial_define_key (control_x_map, 'k', "kill-buffer");
initial_define_key (control_x_map, Ctl ('B'), "list-buffers");
+
+ /* This must not be in syms_of_buffer, because Qdisabled is not
+ initialized when that function gets called. */
+ Fput (intern ("erase-buffer"), Qdisabled, Qt);
}