X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/f9e7c67e4ccdaf160c0506748f776d628a38eeba..4431e6d9b30062407a60897db58356a36cedf49f:/src/buffer.c diff --git a/src/buffer.c b/src/buffer.c index 21c42fc82b..64b1bce9b0 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,6 +1,7 @@ /* Buffer manipulation primitives for GNU Emacs. -Copyright (C) 1985-1989, 1993-1995, 1997-2012 Free Software Foundation, Inc. +Copyright (C) 1985-1989, 1993-1995, 1997-2013 Free Software Foundation, +Inc. This file is part of GNU Emacs. @@ -149,6 +150,12 @@ static struct Lisp_Overlay * copy_overlays (struct buffer *, struct Lisp_Overlay static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t); static Lisp_Object buffer_lisp_local_variables (struct buffer *, bool); +static void +CHECK_OVERLAY (Lisp_Object x) +{ + CHECK_TYPE (OVERLAYP (x), Qoverlayp, x); +} + /* These setters are used only in this file, so they can be private. */ static void bset_abbrev_mode (struct buffer *b, Lisp_Object val) @@ -371,9 +378,6 @@ bset_zv_marker (struct buffer *b, Lisp_Object val) b->INTERNAL_FIELD (zv_marker) = val; } -/* For debugging; temporary. See set_buffer_internal. */ -/* Lisp_Object Qlisp_mode, Vcheck_symbol; */ - void nsberror (Lisp_Object spec) { @@ -1341,7 +1345,7 @@ DEFUN ("set-buffer-modified-p", Fset_buffer_modified_p, Sset_buffer_modified_p, A non-nil FLAG means mark the buffer modified. */) (Lisp_Object flag) { - Lisp_Object fn, buffer, window; + Lisp_Object fn; #ifdef CLASH_DETECTION /* If buffer becoming modified, lock the file. @@ -1394,9 +1398,7 @@ A non-nil FLAG means mark the buffer modified. */) Ideally, I think there should be another mechanism for fontifying buffers without "modifying" buffers, or redisplay should be smarter about updating the `*' in mode lines. --gerd */ - XSETBUFFER (buffer, current_buffer); - window = Fget_buffer_window (buffer, Qt); - if (WINDOWP (window)) + if (buffer_window_count (current_buffer)) { ++update_mode_lines; current_buffer->prevent_redisplay_optimizations_p = 1; @@ -1543,7 +1545,7 @@ candidate_buffer (Lisp_Object b, Lisp_Object buffer) && BUFFER_LIVE_P (XBUFFER (b)) && !BUFFER_HIDDEN_P (XBUFFER (b))); } - + DEFUN ("other-buffer", Fother_buffer, Sother_buffer, 0, 3, 0, doc: /* Return most recently selected buffer other than BUFFER. Buffers not visible in windows are preferred to visible buffers, unless @@ -1683,17 +1685,13 @@ compact_buffer (struct buffer *buffer) if (!buffer->text->inhibit_shrinking) { /* If a buffer's gap size is more than 10% of the buffer - size, or larger than 2000 bytes, then shrink it - accordingly. Keep a minimum size of 20 bytes. */ - int size = min (2000, max (20, (buffer->text->z_byte / 10))); - - if (buffer->text->gap_size > size) - { - struct buffer *save_current = current_buffer; - current_buffer = buffer; - make_gap (-(buffer->text->gap_size - size)); - current_buffer = save_current; - } + size, or larger than GAP_BYTES_DFL bytes, then shrink it + accordingly. Keep a minimum size of GAP_BYTES_MIN bytes. */ + ptrdiff_t size = clip_to_bounds (GAP_BYTES_MIN, + BUF_Z_BYTE (buffer) / 10, + GAP_BYTES_DFL); + if (BUF_GAP_SIZE (buffer) > size) + make_gap_1 (buffer, -(BUF_GAP_SIZE (buffer) - size)); } BUF_COMPACT (buffer) = BUF_MODIFF (buffer); } @@ -1736,18 +1734,6 @@ cleaning up all windows currently displaying the buffer to be killed. */) if (!BUFFER_LIVE_P (b)) return Qnil; - /* Query if the buffer is still modified. */ - if (INTERACTIVE && !NILP (BVAR (b, filename)) - && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) - { - GCPRO1 (buffer); - tem = do_yes_or_no_p (format2 ("Buffer %s modified; kill anyway? ", - BVAR (b, name), make_number (0))); - UNGCPRO; - if (NILP (tem)) - return Qnil; - } - /* Run hooks with the buffer to be killed the current buffer. */ { ptrdiff_t count = SPECPDL_INDEX (); @@ -1763,6 +1749,22 @@ cleaning up all windows currently displaying the buffer to be killed. */) if (NILP (tem)) return unbind_to (count, Qnil); + /* Query if the buffer is still modified. */ + if (INTERACTIVE && !NILP (BVAR (b, filename)) + && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) + { + GCPRO1 (buffer); + tem = do_yes_or_no_p (format2 ("Buffer %s modified; kill anyway? ", + BVAR (b, name), make_number (0))); + UNGCPRO; + if (NILP (tem)) + return unbind_to (count, Qnil); + } + + /* If the hooks have killed the buffer, exit now. */ + if (!BUFFER_LIVE_P (b)) + return unbind_to (count, Qt); + /* Then run the hooks. */ Frun_hooks (1, &Qkill_buffer_hook); unbind_to (count, Qnil); @@ -1777,7 +1779,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) since anything can happen within do_yes_or_no_p. */ /* Don't kill the minibuffer now current. */ - if (EQ (buffer, XWINDOW (minibuf_window)->buffer)) + if (EQ (buffer, XWINDOW (minibuf_window)->contents)) return Qnil; /* When we kill an ordinary buffer which shares it's buffer text @@ -1828,7 +1830,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) /* If the buffer now current is shown in the minibuffer and our buffer is the sole other buffer give up. */ XSETBUFFER (tem, current_buffer); - if (EQ (tem, XWINDOW (minibuf_window)->buffer) + if (EQ (tem, XWINDOW (minibuf_window)->contents) && EQ (buffer, Fother_buffer (buffer, Qnil, Qnil))) return Qnil; @@ -2402,8 +2404,9 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, 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 + { /* Some of the C code expects that both window markers of a + live window points to that window's buffer. So since we + just swapped the markers between the two buffers, we need to undo the effect of this swap for window markers. */ Lisp_Object w = Fselected_window (), ws = Qnil; Lisp_Object buf1, buf2; @@ -2413,12 +2416,19 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, { ws = Fcons (w, ws); if (MARKERP (XWINDOW (w)->pointm) - && (EQ (XWINDOW (w)->buffer, buf1) - || EQ (XWINDOW (w)->buffer, buf2))) + && (EQ (XWINDOW (w)->contents, buf1) + || EQ (XWINDOW (w)->contents, buf2))) Fset_marker (XWINDOW (w)->pointm, make_number - (BUF_BEGV (XBUFFER (XWINDOW (w)->buffer))), - XWINDOW (w)->buffer); + (BUF_BEGV (XBUFFER (XWINDOW (w)->contents))), + XWINDOW (w)->contents); + if (MARKERP (XWINDOW (w)->start) + && (EQ (XWINDOW (w)->contents, buf1) + || EQ (XWINDOW (w)->contents, buf2))) + Fset_marker (XWINDOW (w)->start, + make_number + (XBUFFER (XWINDOW (w)->contents)->last_window_start), + XWINDOW (w)->contents); w = Fnext_window (w, Qt, Qt); } } @@ -3159,7 +3169,10 @@ ptrdiff_t sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) { ptrdiff_t i, j; - struct sortvec *sortvec = alloca (noverlays * sizeof *sortvec); + USE_SAFE_ALLOCA; + struct sortvec *sortvec; + + SAFE_NALLOCA (sortvec, 1, noverlays); /* Put the valid and relevant overlays into sortvec. */ @@ -3205,6 +3218,8 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) for (i = 0; i < noverlays; i++) overlay_vec[i] = sortvec[i].overlay; + + SAFE_FREE (); return (noverlays); } @@ -3896,7 +3911,7 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end) if (buffer_window_count (buf) > 0) { /* ... it's visible in other window than selected, */ - if (buf != XBUFFER (XWINDOW (selected_window)->buffer)) + if (buf != XBUFFER (XWINDOW (selected_window)->contents)) windows_or_buffers_changed = 1; /* ... or if we modify an overlay at the end of the buffer and so we cannot be sure that window end is still valid. */ @@ -4581,34 +4596,13 @@ evaporate_overlays (ptrdiff_t pos) for (; CONSP (hit_list); hit_list = XCDR (hit_list)) Fdelete_overlay (XCAR (hit_list)); } - -/* Somebody has tried to store a value with an unacceptable type - in the slot with offset OFFSET. */ -void -buffer_slot_type_mismatch (Lisp_Object newval, int type) -{ - Lisp_Object predicate; - - switch (type) - { - case_Lisp_Int: predicate = Qintegerp; break; - case Lisp_String: predicate = Qstringp; break; - case Lisp_Symbol: predicate = Qsymbolp; break; - default: emacs_abort (); - } - - wrong_type_argument (predicate, newval); -} - - /*********************************************************************** Allocation with mmap ***********************************************************************/ #ifdef USE_MMAP_FOR_BUFFERS -#include #include #ifndef MAP_ANON @@ -4623,8 +4617,6 @@ buffer_slot_type_mismatch (Lisp_Object newval, int type) #define MAP_FAILED ((void *) -1) #endif -#include - #if MAP_ANON == 0 #include #endif @@ -5375,25 +5367,23 @@ init_buffer (void) 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) \ - do { \ - static struct Lisp_Buffer_Objfwd bo_fwd; \ - defvar_per_buffer (&bo_fwd, lname, vname, type); \ +/* Similar to defvar_lisp but define a variable whose value is the + Lisp_Object stored in the current buffer. LNAME is the Lisp-level + variable name. VNAME is the name of the buffer slot. PREDICATE + is nil for a general Lisp variable. If PREDICATE is non-nil, then + only Lisp values that satisfies the PREDICATE are allowed (except + that nil is allowed too). DOC is a dummy where you write the doc + string as a comment. */ + +#define DEFVAR_PER_BUFFER(lname, vname, predicate, doc) \ + do { \ + static struct Lisp_Buffer_Objfwd bo_fwd; \ + defvar_per_buffer (&bo_fwd, lname, vname, predicate); \ } while (0) static void defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring, - Lisp_Object *address, Lisp_Object type) + Lisp_Object *address, Lisp_Object predicate) { struct Lisp_Symbol *sym; int offset; @@ -5403,7 +5393,7 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring, bo_fwd->type = Lisp_Fwd_Buffer_Obj; bo_fwd->offset = offset; - bo_fwd->slottype = type; + bo_fwd->predicate = predicate; sym->declared_special = 1; sym->redirect = SYMBOL_FORWARDED; { @@ -5518,6 +5508,8 @@ This is the same as (default-value 'left-margin). */); DEFVAR_BUFFER_DEFAULTS ("default-tab-width", tab_width, doc: /* Default value of `tab-width' for buffers that do not override it. +NOTE: This controls the display width of a TAB character, and not +the size of an indentation step. This is the same as (default-value 'tab-width). */); DEFVAR_BUFFER_DEFAULTS ("default-case-fold-search", @@ -5666,7 +5658,7 @@ Decimal digits after the % specify field width to which to pad. */); doc: /* Value of `major-mode' for new buffers. */); DEFVAR_PER_BUFFER ("major-mode", &BVAR (current_buffer, major_mode), - make_number (Lisp_Symbol), + Qsymbolp, 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 @@ -5697,18 +5689,20 @@ Use the command `abbrev-mode' to change this variable. */); doc: /* Non-nil if searches and matches should ignore case. */); DEFVAR_PER_BUFFER ("fill-column", &BVAR (current_buffer, fill_column), - make_number (Lisp_Int0), + Qintegerp, 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", &BVAR (current_buffer, left_margin), - make_number (Lisp_Int0), + Qintegerp, doc: /* Column for the default `indent-line-function' to indent to. Linefeed indents to this column in Fundamental mode. */); DEFVAR_PER_BUFFER ("tab-width", &BVAR (current_buffer, tab_width), - make_number (Lisp_Int0), + Qintegerp, doc: /* Distance between tab stops (for display of tab characters), in columns. +NOTE: This controls the display width of a TAB character, and not +the size of an indentation step. This should be an integer greater than zero. */); DEFVAR_PER_BUFFER ("ctl-arrow", &BVAR (current_buffer, ctl_arrow), Qnil, @@ -5792,7 +5786,7 @@ visual lines rather than logical lines. See the documentation of `visual-line-mode'. */); DEFVAR_PER_BUFFER ("default-directory", &BVAR (current_buffer, directory), - make_number (Lisp_String), + Qstringp, doc: /* Name of default directory of current buffer. Should end with slash. To interactively change the default directory, use command `cd'. */); @@ -5805,18 +5799,18 @@ NOTE: This variable is not a hook; its value may not be a list of functions. */); DEFVAR_PER_BUFFER ("buffer-file-name", &BVAR (current_buffer, filename), - make_number (Lisp_String), + Qstringp, doc: /* Name of file visited in current buffer, or nil if not visiting a file. */); DEFVAR_PER_BUFFER ("buffer-file-truename", &BVAR (current_buffer, file_truename), - make_number (Lisp_String), + Qstringp, doc: /* Abbreviated truename of file visited in current buffer, or nil if none. The truename of a file is calculated by `file-truename' and then abbreviated with `abbreviate-file-name'. */); DEFVAR_PER_BUFFER ("buffer-auto-save-file-name", &BVAR (current_buffer, auto_save_file_name), - make_number (Lisp_String), + Qstringp, doc: /* Name of file for auto-saving current buffer. If it is nil, that means don't auto-save this buffer. */); @@ -5828,7 +5822,7 @@ 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", &BVAR (current_buffer, save_length), - make_number (Lisp_Int0), + Qintegerp, doc: /* Length of current buffer when last read in, saved or auto-saved. 0 initially. -1 means auto-saving turned off until next real save. @@ -5898,34 +5892,49 @@ In addition, a char-table has six extra slots to control the display of: See also the functions `display-table-slot' and `set-display-table-slot'. */); DEFVAR_PER_BUFFER ("left-margin-width", &BVAR (current_buffer, left_margin_cols), - Qnil, + Qintegerp, doc: /* Width of left marginal area for display of a buffer. -A value of nil means no marginal area. */); +A value of nil means no marginal area. + +Setting this variable does not take effect until a new buffer is displayed +in a window. To make the change take effect, call `set-window-buffer'. */); DEFVAR_PER_BUFFER ("right-margin-width", &BVAR (current_buffer, right_margin_cols), - Qnil, + Qintegerp, doc: /* Width of right marginal area for display of a buffer. -A value of nil means no marginal area. */); +A value of nil means no marginal area. + +Setting this variable does not take effect until a new buffer is displayed +in a window. To make the change take effect, call `set-window-buffer'. */); DEFVAR_PER_BUFFER ("left-fringe-width", &BVAR (current_buffer, left_fringe_width), - Qnil, + Qintegerp, doc: /* Width of this buffer's left fringe (in pixels). A value of 0 means no left fringe is shown in this buffer's window. -A value of nil means to use the left fringe width from the window's frame. */); +A value of nil means to use the left fringe width from the window's frame. + +Setting this variable does not take effect until a new buffer is displayed +in a window. To make the change take effect, call `set-window-buffer'. */); DEFVAR_PER_BUFFER ("right-fringe-width", &BVAR (current_buffer, right_fringe_width), - Qnil, + Qintegerp, doc: /* Width of this buffer's right fringe (in pixels). A value of 0 means no right fringe is shown in this buffer's window. -A value of nil means to use the right fringe width from the window's frame. */); +A value of nil means to use the right fringe width from the window's frame. + +Setting this variable does not take effect until a new buffer is displayed +in a window. To make the change take effect, call `set-window-buffer'. */); DEFVAR_PER_BUFFER ("fringes-outside-margins", &BVAR (current_buffer, fringes_outside_margins), Qnil, doc: /* Non-nil means to display fringes outside display margins. -A value of nil means to display fringes between margins and buffer text. */); +A value of nil means to display fringes between margins and buffer text. + +Setting this variable does not take effect until a new buffer is displayed +in a window. To make the change take effect, call `set-window-buffer'. */); DEFVAR_PER_BUFFER ("scroll-bar-width", &BVAR (current_buffer, scroll_bar_width), - Qnil, + Qintegerp, doc: /* Width of this buffer's scroll bars in pixels. A value of nil means to use the scroll bar width from the window's frame. */); @@ -6005,7 +6014,7 @@ BITMAP is the corresponding fringe bitmap shown for the logical cursor type. */); DEFVAR_PER_BUFFER ("scroll-up-aggressively", - &BVAR (current_buffer, scroll_up_aggressively), Qnil, + &BVAR (current_buffer, scroll_up_aggressively), Qfloatp, doc: /* How far to scroll windows upward. If you move point off the bottom, the window scrolls automatically. This variable controls how far it scrolls. The value nil, the default, @@ -6018,7 +6027,7 @@ window scrolls by a full window height. Meaningful values are between 0.0 and 1.0, inclusive. */); DEFVAR_PER_BUFFER ("scroll-down-aggressively", - &BVAR (current_buffer, scroll_down_aggressively), Qnil, + &BVAR (current_buffer, scroll_down_aggressively), Qfloatp, doc: /* How far to scroll windows downward. If you move point off the top, the window scrolls automatically. This variable controls how far it scrolls. The value nil, the default, @@ -6030,10 +6039,6 @@ simple case that you moved off with C-b means scrolling just one line. window scrolls by a full window height. Meaningful values are between 0.0 and 1.0, inclusive. */); -/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol, - "Don't ask."); -*/ - DEFVAR_LISP ("before-change-functions", Vbefore_change_functions, doc: /* List of functions to call before each text change. Two arguments are passed to each function: the positions of @@ -6172,7 +6177,7 @@ then characters with property value PROP are invisible, and they have an ellipsis as well if ELLIPSIS is non-nil. */); DEFVAR_PER_BUFFER ("buffer-display-count", - &BVAR (current_buffer, display_count), Qnil, + &BVAR (current_buffer, display_count), Qintegerp, doc: /* A number incremented each time this buffer is displayed in a window. The function `set-window-buffer' increments it. */); @@ -6231,7 +6236,7 @@ cursor's appearance is instead controlled by the variable `cursor-in-non-selected-windows'. */); DEFVAR_PER_BUFFER ("line-spacing", - &BVAR (current_buffer, extra_line_spacing), Qnil, + &BVAR (current_buffer, extra_line_spacing), Qnumberp, doc: /* Additional space to put between lines when displaying a buffer. The space is measured in pixels, and put below lines on graphic displays, see `display-graphic-p'.