X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/cd265ca60fa8bc6294137426e792b876d165f15e..b9598260f96ddc652cd82ab64bbe922ccfc48a29:/src/buffer.c diff --git a/src/buffer.c b/src/buffer.c index 922109ab28..e907c295e8 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,7 +1,7 @@ /* Buffer manipulation primitives for GNU Emacs. Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008 + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -26,11 +26,7 @@ along with GNU Emacs. If not, see . */ #include #include #include - -#ifndef USE_CRT_DLL -extern int errno; -#endif - +#include #ifdef HAVE_UNISTD_H #include @@ -82,9 +78,6 @@ static Lisp_Object Vbuffer_defaults; be a DEFVAR_PER_BUFFER for the slot, there is no default value for it; and the corresponding slot in buffer_defaults is not used. - If a slot is -2, then there is no DEFVAR_PER_BUFFER for it, - but there is a default value which is copied into each buffer. - If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is zero, that is a bug */ @@ -98,6 +91,12 @@ DECL_ALIGN (struct buffer, buffer_local_symbols); /* A Lisp_Object pointer to the above, used for staticpro */ static Lisp_Object Vbuffer_local_symbols; +/* Return the symbol of the per-buffer variable at offset OFFSET in + the buffer structure. */ + +#define PER_BUFFER_SYMBOL(OFFSET) \ + (*(Lisp_Object *)((OFFSET) + (char *) &buffer_local_symbols)) + /* Flags indicating which built-in buffer-local variables are permanent locals. */ static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS]; @@ -511,7 +510,7 @@ clone_per_buffer_values (from, to) continue; obj = PER_BUFFER_VALUE (from, offset); - if (MARKERP (obj)) + if (MARKERP (obj) && XMARKER (obj)->buffer == from) { struct Lisp_Marker *m = XMARKER (obj); obj = Fmake_marker (); @@ -697,13 +696,14 @@ reset_buffer (b) b->file_truename = Qnil; b->directory = (current_buffer) ? current_buffer->directory : Qnil; b->modtime = 0; + b->modtime_size = -1; XSETFASTINT (b->save_length, 0); b->last_window_start = 1; /* It is more conservative to start out "changed" than "unchanged". */ b->clip_changed = 0; b->prevent_redisplay_optimizations_p = 1; b->backed_up = Qnil; - b->auto_save_modified = 0; + BUF_AUTOSAVE_MODIFF (b) = 0; b->auto_save_failure_time = -1; b->auto_save_file_name = Qnil; b->read_only = Qnil; @@ -773,9 +773,7 @@ reset_buffer_local_variables (b, permanent_too) { Lisp_Object tmp, prop, last = Qnil; for (tmp = b->local_var_alist; CONSP (tmp); tmp = XCDR (tmp)) - if (CONSP (XCAR (tmp)) - && SYMBOLP (XCAR (XCAR (tmp))) - && !NILP (prop = Fget (XCAR (XCAR (tmp)), Qpermanent_local))) + if (!NILP (prop = Fget (XCAR (XCAR (tmp)), Qpermanent_local))) { /* If permanent-local, keep it. */ last = tmp; @@ -825,9 +823,7 @@ reset_buffer_local_variables (b, permanent_too) int idx = PER_BUFFER_IDX (offset); if ((idx > 0 && (permanent_too - || buffer_permanent_local_flags[idx] == 0)) - /* Is -2 used anywhere? */ - || idx == -2) + || buffer_permanent_local_flags[idx] == 0))) PER_BUFFER_VALUE (b, offset) = PER_BUFFER_DEFAULT (offset); } } @@ -877,7 +873,8 @@ it is in the sequence to be tried) even if a buffer with that name exists. */) DEFUN ("buffer-name", Fbuffer_name, Sbuffer_name, 0, 1, 0, doc: /* Return the name of BUFFER, as a string. -With no argument or nil as argument, return the name of the current buffer. */) +BUFFER defaults to the current buffer. +Return nil if BUFFER has been killed. */) (buffer) register Lisp_Object buffer; { @@ -940,59 +937,49 @@ is the default binding of the variable. */) CHECK_SYMBOL (variable); CHECK_BUFFER (buffer); buf = XBUFFER (buffer); + sym = XSYMBOL (variable); - sym = indirect_variable (XSYMBOL (variable)); - XSETSYMBOL (variable, sym); - - /* Look in local_var_list */ - result = Fassoc (variable, buf->local_var_alist); - if (NILP (result)) + start: + switch (sym->redirect) { - int offset, idx; - int found = 0; - - /* Look in special slots */ - /* buffer-local Lisp variables start at `undo_list', - tho only the ones from `name' on are GC'd normally. */ - for (offset = PER_BUFFER_VAR_OFFSET (undo_list); - offset < sizeof (struct buffer); - /* sizeof EMACS_INT == sizeof Lisp_Object */ - offset += (sizeof (EMACS_INT))) - { - idx = PER_BUFFER_IDX (offset); - if ((idx == -1 || PER_BUFFER_VALUE_P (buf, idx)) - && SYMBOLP (PER_BUFFER_SYMBOL (offset)) - && EQ (PER_BUFFER_SYMBOL (offset), variable)) - { - result = PER_BUFFER_VALUE (buf, offset); - found = 1; - break; - } - } - - if (!found) - result = Fdefault_value (variable); - } - else - { - Lisp_Object valcontents; - Lisp_Object current_alist_element; - - /* What binding is loaded right now? */ - valcontents = sym->value; - current_alist_element - = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr); - - /* The value of the currently loaded binding is not - stored in it, but rather in the realvalue slot. - Store that value into the binding it belongs to - in case that is the one we are about to use. */ + case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; + case SYMBOL_PLAINVAL: result = SYMBOL_VAL (sym); break; + case SYMBOL_LOCALIZED: + { /* Look in local_var_alist. */ + struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); + XSETSYMBOL (variable, sym); /* Update In case of aliasing. */ + result = Fassoc (variable, buf->local_var_alist); + if (!NILP (result)) + { + if (blv->fwd) + { /* What binding is loaded right now? */ + Lisp_Object current_alist_element = blv->valcell; - Fsetcdr (current_alist_element, - do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue)); + /* The value of the currently loaded binding is not + stored in it, but rather in the realvalue slot. + Store that value into the binding it belongs to + in case that is the one we are about to use. */ - /* Now get the (perhaps updated) value out of the binding. */ - result = XCDR (result); + XSETCDR (current_alist_element, + do_symval_forwarding (blv->fwd)); + } + /* Now get the (perhaps updated) value out of the binding. */ + result = XCDR (result); + } + else + result = Fdefault_value (variable); + break; + } + case SYMBOL_FORWARDED: + { + union Lisp_Fwd *fwd = SYMBOL_FWD (sym); + if (BUFFER_OBJFWDP (fwd)) + result = PER_BUFFER_VALUE (buf, XBUFFER_OBJFWD (fwd)->offset); + else + result = Fdefault_value (variable); + break; + } + default: abort (); } if (!EQ (result, Qunbound)) @@ -1027,12 +1014,7 @@ buffer_lisp_local_variables (buf) if (buf != current_buffer) val = XCDR (elt); - /* If symbol is unbound, put just the symbol in the list. */ - if (EQ (val, Qunbound)) - result = Fcons (XCAR (elt), result); - /* Otherwise, put (symbol . value) in the list. */ - else - result = Fcons (Fcons (XCAR (elt), val), result); + result = Fcons (Fcons (XCAR (elt), val), result); } return result; @@ -1130,7 +1112,25 @@ A non-nil FLAG means mark the buffer modified. */) } #endif /* CLASH_DETECTION */ - SAVE_MODIFF = NILP (flag) ? MODIFF : 0; + /* Here we have a problem. SAVE_MODIFF is used here to encode + buffer-modified-p (as SAVE_MODIFF=auto_save_modified + we risk changing recent-auto-save-p from nil to t. */ + SAVE_MODIFF = (NILP (flag) + /* FIXME: This unavoidably sets recent-auto-save-p to nil. */ + ? MODIFF + /* Let's try to preserve recent-auto-save-p. */ + : SAVE_MODIFF < MODIFF ? SAVE_MODIFF + /* If SAVE_MODIFF == auto_save_modified == MODIFF, + we can either decrease SAVE_MODIFF and auto_save_modified + or increase MODIFF. */ + : MODIFF++); /* Set update_mode_lines only if buffer is displayed in some window. Packages like jit-lock or lazy-lock preserve a buffer's modified @@ -1300,6 +1300,8 @@ If BUFFER is omitted or nil, some interesting buffer is returned. */) if (NILP (frame)) frame = selected_frame; + CHECK_FRAME (frame); + tail = Vbuffer_alist; pred = frame_buffer_predicate (frame); @@ -1539,8 +1541,8 @@ with SIGHUP. */) /* Delete any auto-save file, if we saved it in this session. But not if the buffer is modified. */ if (STRINGP (b->auto_save_file_name) - && b->auto_save_modified != 0 - && BUF_SAVE_MODIFF (b) < b->auto_save_modified + && BUF_AUTOSAVE_MODIFF (b) != 0 + && BUF_SAVE_MODIFF (b) < BUF_AUTOSAVE_MODIFF (b) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b) && NILP (Fsymbol_value (intern ("auto-save-visited-file-name")))) { @@ -1762,27 +1764,29 @@ switch_to_buffer_1 (buffer_or_name, norecord) DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2, "(list (read-buffer-to-switch \"Switch to buffer: \"))", - doc: /* Make BUFFER-OR-NAME current and display it in the selected window. -BUFFER-OR-NAME may be a buffer, a string, or nil. If BUFFER-OR-NAME is -nil, then this function chooses a buffer using `other-buffer'. If -BUFFER-OR-NAME is a string and does not identify an existing buffer, -then this function creates a buffer with that name. + doc: /* Make BUFFER-OR-NAME current and display it in selected window. +BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or +nil. Return the buffer switched to. + +If BUFFER-OR-NAME is a string and does not identify an existing +buffer, create a new buffer with that name. Interactively, if +`confirm-nonexistent-file-or-buffer' is non-nil, request +confirmation before creating a new buffer. If BUFFER-OR-NAME is +nil, switch to buffer returned by `other-buffer'. -Optional second arg NORECORD non-nil means do not put this buffer at the -front of the list of recently selected ones. This function returns the -buffer it switched to as a Lisp object. +Optional second arg NORECORD non-nil means do not put this buffer +at the front of the list of recently selected ones. This +function returns the buffer it switched to as a Lisp object. -If the selected window is the minibuffer window or dedicated to its -buffer, use `pop-to-buffer' for displaying the buffer. +If the selected window is the minibuffer window or dedicated to +its buffer, use `pop-to-buffer' for displaying the buffer. WARNING: This is NOT the way to work on another buffer temporarily -within a Lisp program! Use `set-buffer' instead. That avoids messing -with the window-buffer correspondences. */) +within a Lisp program! Use `set-buffer' instead. That avoids +messing with the window-buffer correspondences. */) (buffer_or_name, norecord) Lisp_Object buffer_or_name, norecord; { - char *err; - if (EQ (buffer_or_name, Fwindow_buffer (selected_window))) { /* Basically a NOP. Avoid signalling an error in the case where @@ -1796,9 +1800,11 @@ with the window-buffer correspondences. */) record_buffer (buffer_or_name); return Fset_buffer (buffer_or_name); } - - if (EQ (minibuf_window, selected_window) - || !NILP (Fwindow_dedicated_p (selected_window))) + else if (EQ (minibuf_window, selected_window) + /* If `dedicated' is neither nil nor t, it means it's + dedicatedness can be overridden by an explicit request + such as a call to switch-to-buffer. */ + || EQ (Fwindow_dedicated_p (selected_window), Qt)) /* We can't use the selected window so let `pop-to-buffer' try some other window. */ return call3 (intern ("pop-to-buffer"), buffer_or_name, Qnil, norecord); @@ -1840,8 +1846,7 @@ set_buffer_internal_1 (b) register struct buffer *b; { register struct buffer *old_buf; - register Lisp_Object tail, valcontents; - Lisp_Object tem; + register Lisp_Object tail; #ifdef USE_MMAP_FOR_BUFFERS if (b->text->beg == NULL) @@ -1913,30 +1918,21 @@ set_buffer_internal_1 (b) /* Look down buffer's list of local Lisp variables to find and update any that forward into C variables. */ - for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail)) + do { - valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))); - if ((BUFFER_LOCAL_VALUEP (valcontents)) - && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue, - (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem)))) - /* Just reference the variable - to cause it to become set for this buffer. */ - Fsymbol_value (XCAR (XCAR (tail))); + for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail)) + { + Lisp_Object var = XCAR (XCAR (tail)); + struct Lisp_Symbol *sym = XSYMBOL (var); + if (sym->redirect == SYMBOL_LOCALIZED /* Just to be sure. */ + && SYMBOL_BLV (sym)->fwd) + /* Just reference the variable + to cause it to become set for this buffer. */ + Fsymbol_value (var); + } } - /* Do the same with any others that were local to the previous buffer */ - - if (old_buf) - for (tail = old_buf->local_var_alist; CONSP (tail); tail = XCDR (tail)) - { - valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))); - if ((BUFFER_LOCAL_VALUEP (valcontents)) - && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue, - (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem)))) - /* Just reference the variable - to cause it to become set for this buffer. */ - Fsymbol_value (XCAR (XCAR (tail))); - } + while (b != old_buf && (b = old_buf, b)); } /* Switch to buffer B temporarily for redisplay purposes. @@ -2178,6 +2174,10 @@ advance_to_char_boundary (byte_pos) return byte_pos; } +#ifdef REL_ALLOC +extern void r_alloc_reset_variable P_ ((POINTER_TYPE *, POINTER_TYPE *)); +#endif /* REL_ALLOC */ + DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, 1, 1, 0, doc: /* Swap the text between current buffer and BUFFER. */) @@ -2188,6 +2188,9 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, CHECK_BUFFER (buffer); other_buffer = XBUFFER (buffer); + if (NILP (other_buffer->name)) + error ("Cannot swap a dead buffer's text"); + /* Actually, it probably works just fine. * if (other_buffer == current_buffer) * error ("Cannot swap a buffer's text with itself"); */ @@ -2216,6 +2219,13 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, swapfield (own_text, struct buffer_text); eassert (current_buffer->text == ¤t_buffer->own_text); eassert (other_buffer->text == &other_buffer->own_text); +#ifdef REL_ALLOC + r_alloc_reset_variable ((POINTER_TYPE **) ¤t_buffer->own_text.beg, + (POINTER_TYPE **) &other_buffer->own_text.beg); + r_alloc_reset_variable ((POINTER_TYPE **) &other_buffer->own_text.beg, + (POINTER_TYPE **) ¤t_buffer->own_text.beg); +#endif /* REL_ALLOC */ + swapfield (pt, EMACS_INT); swapfield (pt_byte, EMACS_INT); swapfield (begv, EMACS_INT); @@ -2234,11 +2244,9 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, swapfield (overlay_center, EMACS_INT); swapfield (undo_list, Lisp_Object); swapfield (mark, Lisp_Object); - if (MARKERP (current_buffer->mark) && XMARKER (current_buffer->mark)->buffer) - XMARKER (current_buffer->mark)->buffer = current_buffer; - if (MARKERP (other_buffer->mark) && XMARKER (other_buffer->mark)->buffer) - XMARKER (other_buffer->mark)->buffer = other_buffer; swapfield (enable_multibyte_characters, Lisp_Object); + swapfield (bidi_display_reordering, Lisp_Object); + swapfield (bidi_paragraph_direction, Lisp_Object); /* FIXME: Not sure what we should do with these *_marker fields. Hopefully they're just nil anyway. */ swapfield (pt_marker, Lisp_Object); @@ -2252,16 +2260,24 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, current_buffer->text->overlay_modiff++; other_buffer->text->overlay_modiff++; current_buffer->text->beg_unchanged = current_buffer->text->gpt; current_buffer->text->end_unchanged = current_buffer->text->gpt; - other_buffer->text->beg_unchanged = current_buffer->text->gpt; - other_buffer->text->end_unchanged = current_buffer->text->gpt; + other_buffer->text->beg_unchanged = other_buffer->text->gpt; + other_buffer->text->end_unchanged = other_buffer->text->gpt; { struct Lisp_Marker *m; for (m = BUF_MARKERS (current_buffer); m; m = m->next) if (m->buffer == other_buffer) m->buffer = current_buffer; + else + /* Since there's no indirect buffer in sight, markers on + BUF_MARKERS(buf) should either be for `buf' or dead. */ + eassert (!m->buffer); for (m = BUF_MARKERS (other_buffer); m; m = m->next) if (m->buffer == current_buffer) m->buffer = other_buffer; + else + /* Since there's no indirect buffer in sight, markers on + BUF_MARKERS(buf) should either be for `buf' or dead. */ + eassert (!m->buffer); } { /* Some of the C code expects that w->buffer == w->pointm->buffer. So since we just swapped the markers between the two buffers, we need @@ -2379,7 +2395,7 @@ current buffer is cleared. */) p++, pos++; else if (CHAR_BYTE8_HEAD_P (*p)) { - c = STRING_CHAR_AND_LENGTH (p, stop - pos, bytes); + c = STRING_CHAR_AND_LENGTH (p, bytes); /* Delete all bytes for this 8-bit character but the last one, and change the last one to the charcter code. */ @@ -2420,7 +2436,7 @@ current buffer is cleared. */) unsigned char *p = GPT_ADDR - 1; while (! CHAR_HEAD_P (*p) && p > BEG_ADDR) p--; - if (BASE_LEADING_CODE_P (*p)) + if (LEADING_CODE_P (*p)) { int new_gpt = GPT_BYTE - (GPT_ADDR - p); @@ -2449,7 +2465,9 @@ current buffer is cleared. */) if (ASCII_BYTE_P (*p)) p++, pos++; - else if (EQ (flag, Qt) && (bytes = MULTIBYTE_LENGTH (p, pend)) > 0) + else if (EQ (flag, Qt) + && ! CHAR_BYTE8_HEAD_P (*p) + && (bytes = MULTIBYTE_LENGTH (p, pend)) > 0) p += bytes, pos += bytes; else { @@ -2629,22 +2647,22 @@ static void swap_out_buffer_local_variables (b) struct buffer *b; { - Lisp_Object oalist, alist, sym, tem, buffer; + Lisp_Object oalist, alist, buffer; XSETBUFFER (buffer, b); oalist = b->local_var_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 (EQ (tem, buffer)) + Lisp_Object sym = XCAR (XCAR (alist)); + eassert (XSYMBOL (sym)->redirect == SYMBOL_LOCALIZED); + /* Need not do anything if some other buffer's binding is + now encached. */ + if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer)) { /* Symbol is set up for this buffer's old local value: swap it out! */ - swap_in_global_binding (sym); + swap_in_global_binding (XSYMBOL (sym)); } } } @@ -4321,7 +4339,7 @@ add_overlay_mod_hooklist (functionlist, overlay) int oldsize = XVECTOR (last_overlay_modification_hooks)->size; if (last_overlay_modification_hooks_used == oldsize) - last_overlay_modification_hooks = larger_vector + last_overlay_modification_hooks = larger_vector (last_overlay_modification_hooks, oldsize * 2, Qnil); ASET (last_overlay_modification_hooks, last_overlay_modification_hooks_used, functionlist); last_overlay_modification_hooks_used++; @@ -4542,7 +4560,7 @@ buffer_slot_type_mismatch (newval, type) switch (type) { - case Lisp_Int: predicate = Qintegerp; break; + case_Lisp_Int: predicate = Qintegerp; break; case Lisp_String: predicate = Qstringp; break; case Lisp_Symbol: predicate = Qsymbolp; break; default: abort (); @@ -4574,7 +4592,6 @@ buffer_slot_type_mismatch (newval, type) #endif #include -#include #if MAP_ANON == 0 #include @@ -5114,7 +5131,9 @@ init_buffer_once () /* Make sure all markable slots in buffer_defaults are initialized reasonably, so mark_buffer won't choke. */ reset_buffer (&buffer_defaults); + eassert (EQ (buffer_defaults.name, make_number (0))); reset_buffer_local_variables (&buffer_defaults, 1); + eassert (EQ (buffer_local_symbols.name, make_number (0))); reset_buffer (&buffer_local_symbols); reset_buffer_local_variables (&buffer_local_symbols, 1); /* Prevent GC from getting confused. */ @@ -5131,7 +5150,7 @@ init_buffer_once () /* Must do these before making the first buffer! */ /* real setup is done in bindings.el */ - buffer_defaults.mode_line_format = build_string ("%-"); + buffer_defaults.mode_line_format = make_pure_c_string ("%-"); buffer_defaults.header_line_format = Qnil; buffer_defaults.abbrev_mode = Qnil; buffer_defaults.overwrite_mode = Qnil; @@ -5155,7 +5174,8 @@ init_buffer_once () buffer_defaults.truncate_lines = Qnil; buffer_defaults.word_wrap = Qnil; buffer_defaults.ctl_arrow = Qt; - buffer_defaults.direction_reversed = Qnil; + buffer_defaults.bidi_display_reordering = Qnil; + buffer_defaults.bidi_paragraph_direction = Qnil; buffer_defaults.cursor_type = Qt; buffer_defaults.extra_line_spacing = Qnil; buffer_defaults.cursor_in_non_selected_windows = Qt; @@ -5240,7 +5260,8 @@ init_buffer_once () XSETFASTINT (buffer_local_flags.syntax_table, idx); ++idx; XSETFASTINT (buffer_local_flags.cache_long_line_scans, idx); ++idx; XSETFASTINT (buffer_local_flags.category_table, idx); ++idx; - XSETFASTINT (buffer_local_flags.direction_reversed, idx); ++idx; + XSETFASTINT (buffer_local_flags.bidi_display_reordering, idx); ++idx; + XSETFASTINT (buffer_local_flags.bidi_paragraph_direction, idx); ++idx; XSETFASTINT (buffer_local_flags.buffer_file_coding_system, idx); /* Make this one a permanent local. */ buffer_permanent_local_flags[idx++] = 1; @@ -5271,28 +5292,27 @@ init_buffer_once () current_buffer = 0; all_buffers = 0; - QSFundamental = build_string ("Fundamental"); + QSFundamental = make_pure_c_string ("Fundamental"); - Qfundamental_mode = intern ("fundamental-mode"); + Qfundamental_mode = intern_c_string ("fundamental-mode"); buffer_defaults.major_mode = Qfundamental_mode; - Qmode_class = intern ("mode-class"); + Qmode_class = intern_c_string ("mode-class"); - Qprotected_field = intern ("protected-field"); + Qprotected_field = intern_c_string ("protected-field"); - Qpermanent_local = intern ("permanent-local"); + Qpermanent_local = intern_c_string ("permanent-local"); - Qkill_buffer_hook = intern ("kill-buffer-hook"); + Qkill_buffer_hook = intern_c_string ("kill-buffer-hook"); Fput (Qkill_buffer_hook, Qpermanent_local, Qt); - Qucs_set_table_for_input = intern ("ucs-set-table-for-input"); - - Vprin1_to_string_buffer = Fget_buffer_create (build_string (" prin1")); + Qucs_set_table_for_input = intern_c_string ("ucs-set-table-for-input"); /* super-magic invisible buffer */ + Vprin1_to_string_buffer = Fget_buffer_create (make_pure_c_string (" prin1")); Vbuffer_alist = Qnil; - Fset_buffer (Fget_buffer_create (build_string ("*scratch*"))); + Fset_buffer (Fget_buffer_create (make_pure_c_string ("*scratch*"))); inhibit_modification_hooks = 0; } @@ -5332,7 +5352,9 @@ init_buffer () if (!(IS_DIRECTORY_SEP (pwd[len - 1]))) { /* Grow buffer to add directory separator and '\0'. */ - pwd = (char *) xrealloc (pwd, len + 2); + pwd = (char *) realloc (pwd, len + 2); + if (!pwd) + fatal ("`get_current_dir_name' failed: %s\n", strerror (errno)); pwd[len] = DIRECTORY_SEP; pwd[len + 1] = '\0'; } @@ -5368,33 +5390,42 @@ init_buffer () in the buffer that is current now. */ /* TYPE is nil for a general Lisp variable. - An integer specifies a type; then only LIsp values + 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. + 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) +#define DEFVAR_PER_BUFFER(lname, vname, type, doc) \ + do { \ + static struct Lisp_Buffer_Objfwd bo_fwd; \ + defvar_per_buffer (&bo_fwd, lname, vname, type, 0); \ + } while (0) static void -defvar_per_buffer (namestring, address, type, doc) +defvar_per_buffer (bo_fwd, namestring, address, type, doc) + struct Lisp_Buffer_Objfwd *bo_fwd; char *namestring; Lisp_Object *address; Lisp_Object type; char *doc; { - Lisp_Object sym, val; + struct Lisp_Symbol *sym; int offset; - sym = intern (namestring); - val = allocate_misc (); + sym = XSYMBOL (intern (namestring)); 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; + bo_fwd->type = Lisp_Fwd_Buffer_Obj; + bo_fwd->offset = offset; + bo_fwd->slottype = type; + sym->declared_special = 1; + sym->redirect = SYMBOL_FORWARDED; + { + /* I tried to do the job without a cast, but it seems impossible. + union Lisp_Fwd *fwd; &(fwd->u_buffer_objfwd) = bo_fwd; */ + SET_SYMBOL_FWD (sym, (union Lisp_Fwd *)bo_fwd); + } + XSETSYMBOL (PER_BUFFER_SYMBOL (offset), sym); if (PER_BUFFER_IDX (offset) == 0) /* Did a DEFVAR_PER_BUFFER without initializing the corresponding @@ -5419,45 +5450,45 @@ syms_of_buffer () staticpro (&Vbuffer_alist); staticpro (&Qprotected_field); staticpro (&Qpermanent_local); - Qpermanent_local_hook = intern ("permanent-local-hook"); + Qpermanent_local_hook = intern_c_string ("permanent-local-hook"); staticpro (&Qpermanent_local_hook); staticpro (&Qkill_buffer_hook); - Qoverlayp = intern ("overlayp"); + Qoverlayp = intern_c_string ("overlayp"); staticpro (&Qoverlayp); - Qevaporate = intern ("evaporate"); + Qevaporate = intern_c_string ("evaporate"); staticpro (&Qevaporate); - Qmodification_hooks = intern ("modification-hooks"); + Qmodification_hooks = intern_c_string ("modification-hooks"); staticpro (&Qmodification_hooks); - Qinsert_in_front_hooks = intern ("insert-in-front-hooks"); + Qinsert_in_front_hooks = intern_c_string ("insert-in-front-hooks"); staticpro (&Qinsert_in_front_hooks); - Qinsert_behind_hooks = intern ("insert-behind-hooks"); + Qinsert_behind_hooks = intern_c_string ("insert-behind-hooks"); staticpro (&Qinsert_behind_hooks); - Qget_file_buffer = intern ("get-file-buffer"); + Qget_file_buffer = intern_c_string ("get-file-buffer"); staticpro (&Qget_file_buffer); - Qpriority = intern ("priority"); + Qpriority = intern_c_string ("priority"); staticpro (&Qpriority); - Qwindow = intern ("window"); + Qwindow = intern_c_string ("window"); staticpro (&Qwindow); - Qbefore_string = intern ("before-string"); + Qbefore_string = intern_c_string ("before-string"); staticpro (&Qbefore_string); - Qafter_string = intern ("after-string"); + Qafter_string = intern_c_string ("after-string"); staticpro (&Qafter_string); - Qfirst_change_hook = intern ("first-change-hook"); + Qfirst_change_hook = intern_c_string ("first-change-hook"); staticpro (&Qfirst_change_hook); - Qbefore_change_functions = intern ("before-change-functions"); + Qbefore_change_functions = intern_c_string ("before-change-functions"); staticpro (&Qbefore_change_functions); - Qafter_change_functions = intern ("after-change-functions"); + Qafter_change_functions = intern_c_string ("after-change-functions"); staticpro (&Qafter_change_functions); /* The next one is initialized in init_buffer_once. */ staticpro (&Qucs_set_table_for_input); - Qkill_buffer_query_functions = intern ("kill-buffer-query-functions"); + Qkill_buffer_query_functions = intern_c_string ("kill-buffer-query-functions"); staticpro (&Qkill_buffer_query_functions); Fput (Qprotected_field, Qerror_conditions, - Fcons (Qprotected_field, Fcons (Qerror, Qnil))); + pure_cons (Qprotected_field, pure_cons (Qerror, Qnil))); Fput (Qprotected_field, Qerror_message, - build_string ("Attempt to modify a protected field")); + make_pure_c_string ("Attempt to modify a protected field")); /* All these use DEFVAR_LISP_NOPRO because the slots in buffer_defaults will all be marked via Vbuffer_defaults. */ @@ -5496,11 +5527,6 @@ This is the same as (default-value 'abbrev-mode). */); doc: /* Default value of `ctl-arrow' for buffers that do not override it. This is the same as (default-value 'ctl-arrow). */); - DEFVAR_LISP_NOPRO ("default-direction-reversed", - &buffer_defaults.direction_reversed, - doc: /* Default value of `direction-reversed' for buffers that do not override it. -This is the same as (default-value 'direction-reversed). */); - DEFVAR_LISP_NOPRO ("default-enable-multibyte-characters", &buffer_defaults.enable_multibyte_characters, doc: /* *Default value of `enable-multibyte-characters' for buffers not overriding it. @@ -5673,19 +5699,20 @@ A string is printed verbatim in the mode line except for %-constructs: Decimal digits after the % specify field width to which to pad. */); DEFVAR_LISP_NOPRO ("default-major-mode", &buffer_defaults.major_mode, - doc: /* *Major mode for new buffers. Defaults to `fundamental-mode'. -A value of nil means use current buffer's major mode, -provided it is not marked as "special". - -When a mode is used by default, `find-file' switches to it -before it reads the contents into the buffer and before -it finishes setting up the buffer. Thus, the mode and -its hooks should not expect certain variables such as -`buffer-read-only' and `buffer-file-coding-system' to be set up. */); + doc: /* *Value of `major-mode' for new buffers. */); DEFVAR_PER_BUFFER ("major-mode", ¤t_buffer->major_mode, make_number (Lisp_Symbol), - doc: /* Symbol for current buffer's major mode. */); + doc: /* Symbol for current buffer's major mode. +The default value (normally `fundamental-mode') affects new buffers. +A value of nil means to use the current buffer's major mode, provided +it is not marked as "special". + +When a mode is used by default, `find-file' switches to it before it +reads the contents into the buffer and before it finishes setting up +the buffer. Thus, the mode and its hooks should not expect certain +variables such as `buffer-read-only' and `buffer-file-coding-system' +to be set up. */); DEFVAR_PER_BUFFER ("mode-name", ¤t_buffer->mode_name, Qnil, @@ -5705,17 +5732,17 @@ Format with `format-mode-line' to produce a string value. */); doc: /* *Non-nil if searches and matches should ignore case. */); DEFVAR_PER_BUFFER ("fill-column", ¤t_buffer->fill_column, - make_number (Lisp_Int), + make_number (LISP_INT_TAG), doc: /* *Column beyond which automatic line-wrapping should happen. Interactively, you can set the buffer local value using \\[set-fill-column]. */); DEFVAR_PER_BUFFER ("left-margin", ¤t_buffer->left_margin, - make_number (Lisp_Int), + make_number (LISP_INT_TAG), doc: /* *Column for the default `indent-line-function' to indent to. Linefeed indents to this column in Fundamental mode. */); DEFVAR_PER_BUFFER ("tab-width", ¤t_buffer->tab_width, - make_number (Lisp_Int), + make_number (LISP_INT_TAG), doc: /* *Distance between tab stops (for display of tab characters), in columns. */); DEFVAR_PER_BUFFER ("ctl-arrow", ¤t_buffer->ctl_arrow, Qnil, @@ -5736,7 +5763,7 @@ use the function `set-buffer-multibyte' to change a buffer's representation. Changing its default value with `setq-default' is supported. See also variable `default-enable-multibyte-characters' and Info node `(elisp)Text Representations'. */); - XSYMBOL (intern ("enable-multibyte-characters"))->constant = 1; + XSYMBOL (intern_c_string ("enable-multibyte-characters"))->constant = 1; DEFVAR_PER_BUFFER ("buffer-file-coding-system", ¤t_buffer->buffer_file_coding_system, Qnil, @@ -5756,11 +5783,23 @@ The variable `coding-system-for-write', if non-nil, overrides this variable. This variable is never applied to a way of decoding a file while reading it. */); - DEFVAR_PER_BUFFER ("direction-reversed", ¤t_buffer->direction_reversed, - Qnil, - doc: /* *Non-nil means lines in the buffer are displayed right to left. */); + DEFVAR_PER_BUFFER ("bidi-display-reordering", + ¤t_buffer->bidi_display_reordering, Qnil, + doc: /* Non-nil means reorder bidirectional text for display in the visual order. */); - DEFVAR_PER_BUFFER ("truncate-lines", ¤t_buffer->truncate_lines, Qnil, + DEFVAR_PER_BUFFER ("bidi-paragraph-direction", + ¤t_buffer->bidi_paragraph_direction, Qnil, + doc: /* *If non-nil, forces directionality of text paragraphs in the buffer. + +If this is nil (the default), the direction of each paragraph is +determined by the first strong directional character of its text. +The values of `right-to-left' and `left-to-right' override that. +Any other value is treated as nil. + +This variable has no effect unless the buffer's value of +\`bidi-display-reordering' is non-nil. */); + + DEFVAR_PER_BUFFER ("truncate-lines", ¤t_buffer->truncate_lines, Qnil, doc: /* *Non-nil means do not display continuation lines. Instead, give each line of text just one screen line. @@ -5826,9 +5865,14 @@ If it is nil, that means don't auto-save this buffer. */); Backing up is done before the first time the file is saved. */); DEFVAR_PER_BUFFER ("buffer-saved-size", ¤t_buffer->save_length, - make_number (Lisp_Int), + make_number (LISP_INT_TAG), doc: /* Length of current buffer when last read in, saved or auto-saved. -0 initially. */); +0 initially. +-1 means auto-saving turned off until next real save. + +If you set this to -2, that means don't turn off auto-saving in this buffer +if its text size shrinks. If you use `buffer-swap-text' on a buffer, +you probably should set this to -2 in that buffer. */); DEFVAR_PER_BUFFER ("selective-display", ¤t_buffer->selective_display, Qnil, @@ -6213,13 +6257,15 @@ Values are interpreted as follows: (hbar . HEIGHT) display a horizontal bar cursor with height HEIGHT ANYTHING ELSE display a hollow box cursor -When the buffer is displayed in a nonselected window, -this variable has no effect; the cursor appears as a hollow box. */); +When the buffer is displayed in a non-selected window, the +cursor's appearance is instead controlled by the variable +`cursor-in-non-selected-windows'. */); DEFVAR_PER_BUFFER ("line-spacing", ¤t_buffer->extra_line_spacing, Qnil, doc: /* Additional space to put between lines when displaying a buffer. -The space is measured in pixels, and put below lines on window systems. +The space is measured in pixels, and put below lines on graphic displays, +see `display-graphic-p'. If value is a floating point number, it specifies the spacing relative to the default frame line height. A value of nil means add no extra space. */); @@ -6238,7 +6284,7 @@ If any of them returns nil, the buffer is not killed. */); doc: /* Normal hook run before changing the major mode of a buffer. The function `kill-all-local-variables' runs this before doing anything else. */); Vchange_major_mode_hook = Qnil; - Qchange_major_mode_hook = intern ("change-major-mode-hook"); + Qchange_major_mode_hook = intern_c_string ("change-major-mode-hook"); staticpro (&Qchange_major_mode_hook); defsubr (&Sbuffer_live_p); @@ -6300,7 +6346,7 @@ keys_of_buffer () /* This must not be in syms_of_buffer, because Qdisabled is not initialized when that function gets called. */ - Fput (intern ("erase-buffer"), Qdisabled, Qt); + Fput (intern_c_string ("erase-buffer"), Qdisabled, Qt); } /* arch-tag: e48569bf-69a9-4b65-a23b-8e68769436e1