diff options
Diffstat (limited to 'src/buffer.c')
-rw-r--r-- | src/buffer.c | 237 |
1 files changed, 136 insertions, 101 deletions
diff --git a/src/buffer.c b/src/buffer.c index 6c31b83572d..57d88b0f791 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -100,17 +100,6 @@ DECL_ALIGN (struct buffer, buffer_local_symbols); /* A Lisp_Object pointer to the above, used for staticpro */ static Lisp_Object Vbuffer_local_symbols; -/* This structure holds the required types for the values in the - buffer-local slots. If a slot contains Qnil, then the - corresponding buffer slot may contain a value of any type. If a - slot contains an integer, then prospective values' tags must be - equal to that integer (except nil is always allowed). - When a tag does not match, the function - buffer_slot_type_mismatch will signal an error. - - If a slot here contains -1, the corresponding variable is read-only. */ -struct buffer buffer_local_types; - /* Flags indicating which built-in buffer-local variables are permanent locals. */ static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS]; @@ -119,12 +108,14 @@ static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS]; int last_per_buffer_idx; -Lisp_Object Fset_buffer (); -void set_buffer_internal (); -void set_buffer_internal_1 (); -static void call_overlay_mod_hooks (); -static void swap_out_buffer_local_variables (); -static void reset_buffer_local_variables (); +EXFUN (Fset_buffer, 1); +void set_buffer_internal P_ ((struct buffer *b)); +void set_buffer_internal_1 P_ ((struct buffer *b)); +static void call_overlay_mod_hooks P_ ((Lisp_Object list, Lisp_Object overlay, + int after, Lisp_Object arg1, + Lisp_Object arg2, Lisp_Object arg3)); +static void swap_out_buffer_local_variables P_ ((struct buffer *b)); +static void reset_buffer_local_variables P_ ((struct buffer *b, int permanent_too)); /* Alist of all buffer names vs the buffers. */ /* This used to be a variable, but is no longer, @@ -216,25 +207,38 @@ frame parameter come first, followed by the rest of the buffers. */) (frame) Lisp_Object frame; { - Lisp_Object framelist, general; + Lisp_Object general; general = Fmapcar (Qcdr, Vbuffer_alist); if (FRAMEP (frame)) { - Lisp_Object tail; + Lisp_Object framelist, prevlist, tail; + Lisp_Object args[3]; CHECK_FRAME (frame); framelist = Fcopy_sequence (XFRAME (frame)->buffer_list); + prevlist = Fnreverse (Fcopy_sequence (XFRAME (frame)->buried_buffer_list)); - /* Remove from GENERAL any buffer that duplicates one in FRAMELIST. */ + /* Remove from GENERAL any buffer that duplicates one in + FRAMELIST or PREVLIST. */ tail = framelist; - while (! NILP (tail)) + while (CONSP (tail)) + { + general = Fdelq (XCAR (tail), general); + tail = XCDR (tail); + } + tail = prevlist; + while (CONSP (tail)) { general = Fdelq (XCAR (tail), general); tail = XCDR (tail); } - return nconc2 (framelist, general); + + args[0] = framelist; + args[1] = general; + args[2] = prevlist; + return Fnconc (3, args); } return general; @@ -347,9 +351,7 @@ The value is never nil. */) if (SCHARS (name) == 0) error ("Empty string for buffer name is not allowed"); - b = (struct buffer *) allocate_buffer (); - - b->size = sizeof (struct buffer) / sizeof (EMACS_INT); + b = allocate_buffer (); /* An ordinary buffer uses its own struct buffer_text. */ b->text = &b->own_text; @@ -404,10 +406,7 @@ The value is never nil. */) STRING_SET_INTERVALS (name, NULL_INTERVAL); b->name = name; - if (SREF (name, 0) != ' ') - b->undo_list = Qnil; - else - b->undo_list = Qt; + b->undo_list = (SREF (name, 0) != ' ') ? Qnil : Qt; reset_buffer (b); reset_buffer_local_variables (b, 1); @@ -553,13 +552,11 @@ CLONE nil means the indirect buffer's state is reset to default values. */) if (SCHARS (name) == 0) error ("Empty string for buffer name is not allowed"); - b = (struct buffer *) allocate_buffer (); - b->size = sizeof (struct buffer) / sizeof (EMACS_INT); + b = allocate_buffer (); - if (XBUFFER (base_buffer)->base_buffer) - b->base_buffer = XBUFFER (base_buffer)->base_buffer; - else - b->base_buffer = XBUFFER (base_buffer); + b->base_buffer = (XBUFFER (base_buffer)->base_buffer + ? XBUFFER (base_buffer)->base_buffer + : XBUFFER (base_buffer)); /* Use the base buffer's text object. */ b->text = b->base_buffer->text; @@ -722,7 +719,7 @@ reset_buffer (b) it does not treat permanent locals consistently. Instead, use Fkill_all_local_variables. - If PERMANENT_TOO is 1, then we reset permanent built-in + If PERMANENT_TOO is 1, then we reset permanent buffer-local variables. If PERMANENT_TOO is 0, we preserve those. */ @@ -760,7 +757,23 @@ reset_buffer_local_variables (b, permanent_too) #endif /* Reset all (or most) per-buffer variables to their defaults. */ - b->local_var_alist = Qnil; + if (permanent_too) + b->local_var_alist = Qnil; + else + { + Lisp_Object tmp, last = Qnil; + for (tmp = b->local_var_alist; CONSP (tmp); tmp = XCDR (tmp)) + if (CONSP (XCAR (tmp)) + && SYMBOLP (XCAR (XCAR (tmp))) + && !NILP (Fget (XCAR (XCAR (tmp)), Qpermanent_local))) + /* If permanent-local, keep it. */ + last = tmp; + else if (NILP (last)) + b->local_var_alist = XCDR (tmp); + else + XSETCDR (last, XCDR (tmp)); + } + for (i = 0; i < last_per_buffer_idx; ++i) if (permanent_too || buffer_permanent_local_flags[i] == 0) SET_PER_BUFFER_VALUE_P (b, i, 0); @@ -890,8 +903,7 @@ is the default binding of the variable. */) CHECK_BUFFER (buffer); buf = XBUFFER (buffer); - if (SYMBOLP (variable)) - variable = indirect_variable (variable); + variable = indirect_variable (variable); /* Look in local_var_list */ result = Fassoc (variable, buf->local_var_alist); @@ -1176,7 +1188,9 @@ buffer as BUFFER. */) } DEFUN ("rename-buffer", Frename_buffer, Srename_buffer, 1, 2, - "sRename buffer (to new name): \nP", + "(list (read-string \"Rename buffer (to new name): \" \ + nil 'buffer-name-history (buffer-name (current-buffer))) \ + current-prefix-arg)", doc: /* Change current buffer's name to NEWNAME (a string). If second arg UNIQUE is nil or omitted, it is an error if a buffer named NEWNAME already exists. @@ -1584,6 +1598,23 @@ record_buffer (buf) XSETCDR (link, Vbuffer_alist); Vbuffer_alist = link; + /* Effectively do a delq on buried_buffer_list. */ + + prev = Qnil; + for (link = XFRAME (frame)->buried_buffer_list; CONSP (link); + link = XCDR (link)) + { + if (EQ (XCAR (link), buf)) + { + if (NILP (prev)) + XFRAME (frame)->buried_buffer_list = XCDR (link); + else + XSETCDR (prev, XCDR (XCDR (prev))); + break; + } + prev = link; + } + /* Now move this buffer to the front of frame_buffer_list also. */ prev = Qnil; @@ -1887,8 +1918,7 @@ set_buffer_internal_1 (b) for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail)) { valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))); - if ((BUFFER_LOCAL_VALUEP (valcontents) - || SOME_BUFFER_LOCAL_VALUEP (valcontents)) + if ((BUFFER_LOCAL_VALUEP (valcontents)) && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue, (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem)))) /* Just reference the variable @@ -1902,8 +1932,7 @@ set_buffer_internal_1 (b) for (tail = old_buf->local_var_alist; CONSP (tail); tail = XCDR (tail)) { valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))); - if ((BUFFER_LOCAL_VALUEP (valcontents) - || SOME_BUFFER_LOCAL_VALUEP (valcontents)) + if ((BUFFER_LOCAL_VALUEP (valcontents)) && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue, (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem)))) /* Just reference the variable @@ -2066,10 +2095,10 @@ selected window if it is displayed there. */) XSETCDR (link, Qnil); Vbuffer_alist = nconc2 (Vbuffer_alist, link); - /* Removing BUFFER from frame-specific lists - has the effect of putting BUFFER at the end - of the combined list in each frame. */ - frames_discard_buffer (buffer); + XFRAME (selected_frame)->buffer_list + = Fdelq (buffer, XFRAME (selected_frame)->buffer_list); + XFRAME (selected_frame)->buried_buffer_list + = Fcons (buffer, Fdelq (buffer, XFRAME (selected_frame)->buried_buffer_list)); } return Qnil; @@ -2443,14 +2472,10 @@ The first thing this function does is run the normal hook `change-major-mode-hook'. */) () { - register Lisp_Object alist, sym, tem; - Lisp_Object oalist; - if (!NILP (Vrun_hooks)) call1 (Vrun_hooks, Qchange_major_mode_hook); - oalist = current_buffer->local_var_alist; - /* Make sure none of the bindings in oalist + /* Make sure none of the bindings in local_var_alist remain swapped in, in their symbols. */ swap_out_buffer_local_variables (current_buffer); @@ -2459,20 +2484,6 @@ the normal hook `change-major-mode-hook'. */) reset_buffer_local_variables (current_buffer, 0); - /* Any which are supposed to be permanent, - make local again, with the same values they had. */ - - for (alist = oalist; !NILP (alist); alist = XCDR (alist)) - { - sym = XCAR (XCAR (alist)); - tem = Fget (sym, Qpermanent_local); - if (! NILP (tem)) - { - Fmake_local_variable (sym); - Fset (sym, XCDR (XCAR (alist))); - } - } - /* Force mode-line redisplay. Useful here because all major mode commands call this function. */ update_mode_lines++; @@ -2492,32 +2503,17 @@ swap_out_buffer_local_variables (b) XSETBUFFER (buffer, b); oalist = b->local_var_alist; - for (alist = oalist; !NILP (alist); alist = XCDR (alist)) + for (alist = oalist; CONSP (alist); alist = XCDR (alist)) { sym = XCAR (XCAR (alist)); /* Need not do anything if some other buffer's binding is now encached. */ tem = XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer; - if (BUFFERP (tem) && XBUFFER (tem) == current_buffer) + if (EQ (tem, buffer)) { - /* Symbol is set up for this buffer's old local value. - Set it up for the current buffer with the default value. */ - - tem = XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->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 - later in Fkill_all_local_variables, we don't lose the value. */ - XSETCDR (XCAR (tem), - do_symval_forwarding (XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->realvalue)); - /* Switch to the symbol's default-value alist entry. */ - XSETCAR (tem, tem); - /* Mark it as current for buffer B. */ - XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer = buffer; - /* Store the current value into any forwarding in the symbol. */ - store_symval_forwarding (sym, - XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->realvalue, - XCDR (tem), NULL); + /* Symbol is set up for this buffer's old local value: + swap it out! */ + swap_in_global_binding (sym); } } } @@ -4187,15 +4183,8 @@ add_overlay_mod_hooklist (functionlist, overlay) int oldsize = XVECTOR (last_overlay_modification_hooks)->size; if (last_overlay_modification_hooks_used == oldsize) - { - Lisp_Object old; - old = last_overlay_modification_hooks; - last_overlay_modification_hooks - = Fmake_vector (make_number (oldsize * 2), Qnil); - bcopy (XVECTOR (old)->contents, - XVECTOR (last_overlay_modification_hooks)->contents, - sizeof (Lisp_Object) * oldsize); - } + last_overlay_modification_hooks = larger_vector + (last_overlay_modification_hooks, oldsize * 2, Qnil); AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = functionlist; AREF (last_overlay_modification_hooks, last_overlay_modification_hooks_used++) = overlay; } @@ -4405,13 +4394,13 @@ evaporate_overlays (pos) in the slot with offset OFFSET. */ void -buffer_slot_type_mismatch (offset) - int offset; +buffer_slot_type_mismatch (sym, type) + Lisp_Object sym; + int type; { - Lisp_Object sym; char *type_name; - switch (XINT (PER_BUFFER_TYPE (offset))) + switch (type) { case Lisp_Int: type_name = "integers"; @@ -4429,7 +4418,6 @@ buffer_slot_type_mismatch (offset) abort (); } - sym = PER_BUFFER_SYMBOL (offset); error ("Only %s should be stored in the buffer-local variable %s", type_name, SDATA (SYMBOL_NAME (sym))); } @@ -5007,7 +4995,9 @@ init_buffer_once () buffer_local_symbols.text = &buffer_local_symbols.own_text; BUF_INTERVALS (&buffer_defaults) = 0; BUF_INTERVALS (&buffer_local_symbols) = 0; + XSETPVECTYPE (&buffer_defaults, PVEC_BUFFER); XSETBUFFER (Vbuffer_defaults, &buffer_defaults); + XSETPVECTYPE (&buffer_local_symbols, PVEC_BUFFER); XSETBUFFER (Vbuffer_local_symbols, &buffer_local_symbols); /* Set up the default values of various buffer slots. */ @@ -5246,6 +5236,46 @@ init_buffer () free (pwd); } +/* Similar to defvar_lisp but define a variable whose value is the Lisp + Object stored in the current buffer. address is the address of the slot + in the buffer that is current now. */ + +/* TYPE is nil for a general Lisp variable. + An integer specifies a type; then only LIsp values + with that type code are allowed (except that nil is allowed too). + LNAME is the LIsp-level variable name. + VNAME is the name of the buffer slot. + DOC is a dummy where you write the doc string as a comment. */ +#define DEFVAR_PER_BUFFER(lname, vname, type, doc) \ + defvar_per_buffer (lname, vname, type, 0) + +static void +defvar_per_buffer (namestring, address, type, doc) + char *namestring; + Lisp_Object *address; + Lisp_Object type; + char *doc; +{ + Lisp_Object sym, val; + int offset; + + sym = intern (namestring); + val = allocate_misc (); + offset = (char *)address - (char *)current_buffer; + + XMISCTYPE (val) = Lisp_Misc_Buffer_Objfwd; + XBUFFER_OBJFWD (val)->offset = offset; + XBUFFER_OBJFWD (val)->slottype = type; + SET_SYMBOL_VALUE (sym, val); + PER_BUFFER_SYMBOL (offset) = sym; + + if (PER_BUFFER_IDX (offset) == 0) + /* Did a DEFVAR_PER_BUFFER without initializing the corresponding + slot of buffer_local_flags */ + abort (); +} + + /* initialize the buffer routines */ void syms_of_buffer () @@ -5506,6 +5536,8 @@ A string is printed verbatim in the mode line except for %-constructs: %z -- print mnemonics of keyboard, terminal, and buffer coding systems. %Z -- like %z, but including the end-of-line format. %e -- print error message about full memory. + %@ -- print @ or hyphen. @ means that default-directory is on a + remote machine. %[ -- print one [ for each recursive editing level. %] similar. %% -- print %. %- -- print infinitely many dashes. Decimal digits after the % specify field width to which to pad. */); @@ -5529,6 +5561,9 @@ its hooks should not expect certain variables such as Qnil, doc: /* Pretty name of current buffer's major mode (a string). */); + DEFVAR_PER_BUFFER ("local-abbrev-table", ¤t_buffer->abbrev_table, Qnil, + doc: /* Local (mode-specific) abbrev table of current buffer. */); + DEFVAR_PER_BUFFER ("abbrev-mode", ¤t_buffer->abbrev_mode, Qnil, doc: /* Non-nil turns on automatic expansion of abbrevs as they are inserted. */); |