X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/81bf542040dab0b67396323c5f78a425cfb886be..2bfa3d3e1fb347ba76bddf77f3e288049635821d:/src/buffer.c diff --git a/src/buffer.c b/src/buffer.c index 42c4c1306a..7f0f2cc7d0 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,7 +1,6 @@ /* Buffer manipulation primitives for GNU Emacs. -Copyright (C) 1985-1989, 1993-1995, 1997-2014 Free Software Foundation, -Inc. +Copyright (C) 1985-1989, 1993-1995, 1997-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -42,6 +41,10 @@ along with GNU Emacs. If not, see . */ #include "keymap.h" #include "frame.h" +#ifdef WINDOWSNT +#include "w32heap.h" /* for mmap_* */ +#endif + struct buffer *current_buffer; /* The current buffer. */ /* First buffer in chain of all buffers (in reverse order of creation). @@ -1159,10 +1162,10 @@ DEFUN ("buffer-local-value", Fbuffer_local_value, Sbuffer_local_value, 2, 2, 0, doc: /* Return the value of VARIABLE in BUFFER. If VARIABLE does not have a buffer-local binding in BUFFER, the value -is the default binding of the variable. */) +is the default binding of the variable. */) (register Lisp_Object variable, register Lisp_Object buffer) { - register Lisp_Object result = buffer_local_value_1 (variable, buffer); + register Lisp_Object result = buffer_local_value (variable, buffer); if (EQ (result, Qunbound)) xsignal1 (Qvoid_variable, variable); @@ -1175,7 +1178,7 @@ is the default binding of the variable. */) locally unbound. */ Lisp_Object -buffer_local_value_1 (Lisp_Object variable, Lisp_Object buffer) +buffer_local_value (Lisp_Object variable, Lisp_Object buffer) { register struct buffer *buf; register Lisp_Object result; @@ -1380,7 +1383,6 @@ It is not ensured that mode lines will be updated to show the modified state of the current buffer. Use with care. */) (Lisp_Object flag) { -#ifdef CLASH_DETECTION Lisp_Object fn; /* If buffer becoming modified, lock the file. @@ -1400,7 +1402,6 @@ state of the current buffer. Use with care. */) else if (already && NILP (flag)) unlock_file (fn); } -#endif /* CLASH_DETECTION */ /* Here we have a problem. SAVE_MODIFF is used here to encode buffer-modified-p (as SAVE_MODIFFpriority != s2->priority) return s1->priority < s2->priority ? -1 : 1; - if (s1->beg != s2->beg) - return s1->beg < s2->beg ? -1 : 1; - if (s1->end != s2->end) + /* If the priority is equal, give precedence to the one not covered by the + other. If neither covers the other, obey spriority. */ + else if (s1->beg < s2->beg) + return (s1->end < s2->end && s1->spriority > s2->spriority ? 1 : -1); + else if (s1->beg > s2->beg) + return (s1->end > s2->end && s1->spriority < s2->spriority ? -1 : 1); + else if (s1->end != s2->end) return s2->end < s1->end ? -1 : 1; - /* Avoid the non-determinism of qsort by choosing an arbitrary ordering - between "equal" overlays. The result can still change between - invocations of Emacs, but it won't change in the middle of - `find_field' (bug#6830). */ - if (!EQ (s1->overlay, s2->overlay)) + else if (s1->spriority != s2->spriority) + return (s1->spriority < s2->spriority ? -1 : 1); + else if (EQ (s1->overlay, s2->overlay)) + return 0; + else + /* Avoid the non-determinism of qsort by choosing an arbitrary ordering + between "equal" overlays. The result can still change between + invocations of Emacs, but it won't change in the middle of + `find_field' (bug#6830). */ return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1; - return 0; } /* Sort an array of overlays by priority. The array is modified in place. @@ -3208,10 +3228,23 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) 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; + if (NILP (tem)) + { + sortvec[j].priority = 0; + sortvec[j].spriority = 0; + } + else if (INTEGERP (tem)) + { + sortvec[j].priority = XINT (tem); + sortvec[j].spriority = 0; + } + else if (CONSP (tem)) + { + Lisp_Object car = XCAR (tem); + Lisp_Object cdr = XCDR (tem); + sortvec[j].priority = INTEGERP (car) ? XINT (car) : 0; + sortvec[j].spriority = INTEGERP (cdr) ? XINT (cdr) : 0; + } j++; } } @@ -3309,17 +3342,18 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str, } } -/* Return the concatenation of the strings associated with overlays that - begin or end at POS, ignoring overlays that are specific to a window - other than W. The strings are concatenated in the appropriate order: - shorter overlays nest inside longer ones, and higher priority inside - lower. Normally all of the after-strings come first, but zero-sized - overlays have their after-strings ride along with the before-strings - because it would look strange to print them inside-out. +/* Concatenate the strings associated with overlays that begin or end + at POS, ignoring overlays that are specific to windows other than W. + The strings are concatenated in the appropriate order: shorter + overlays nest inside longer ones, and higher priority inside lower. + Normally all of the after-strings come first, but zero-sized + overlays have their after-strings ride along with the + before-strings because it would look strange to print them + inside-out. - Returns the string length, and stores the contents indirectly through - PSTR, if that variable is non-null. The string may be overwritten by - subsequent calls. */ + Returns the concatenated string's length, and return the pointer to + that string via PSTR, if that variable is non-NULL. The storage of + the concatenated strings may be overwritten by subsequent calls. */ ptrdiff_t overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr) @@ -3956,7 +3990,7 @@ buffer. */) { struct buffer *b, *ob = 0; Lisp_Object obuffer; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); ptrdiff_t n_beg, n_end, o_beg IF_LINT (= 0), o_end IF_LINT (= 0); CHECK_OVERLAY (overlay); @@ -4028,8 +4062,12 @@ buffer. */) /* Delete the overlay if it is empty after clipping and has the evaporate property. */ - if (n_beg == n_end && !NILP (Foverlay_get (overlay, Qevaporate))) - return unbind_to (count, Fdelete_overlay (overlay)); + if (n_beg == n_end && !NILP (Foverlay_get (overlay, Qevaporate))){ + + Lisp_Object tem0 = Fdelete_overlay (overlay); + dynwind_end (); + return tem0; + } /* Put the overlay into the new buffer's overlay lists, first on the wrong list. */ @@ -4047,7 +4085,8 @@ buffer. */) /* This puts it in the right list, and in the right order. */ recenter_overlay_lists (b, b->overlay_center); - return unbind_to (count, overlay); + dynwind_end (); + return overlay; } DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0, @@ -4056,13 +4095,15 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0, { Lisp_Object buffer; struct buffer *b; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); CHECK_OVERLAY (overlay); buffer = Fmarker_buffer (OVERLAY_START (overlay)); - if (NILP (buffer)) + if (NILP (buffer)) { + dynwind_end (); return Qnil; + } b = XBUFFER (buffer); specbind (Qinhibit_quit, Qt); @@ -4079,7 +4120,8 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0, || !NILP (Foverlay_get (overlay, Qafter_string)))) b->prevent_redisplay_optimizations_p = 1; - return unbind_to (count, Qnil); + dynwind_end (); + return Qnil; } DEFUN ("delete-all-overlays", Fdelete_all_overlays, Sdelete_all_overlays, 0, 1, 0, @@ -4144,9 +4186,10 @@ OVERLAY. */) } -DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0, - doc: /* Return a list of the overlays that contain the character at POS. */) - (Lisp_Object pos) +DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 2, 0, + doc: /* Return a list of the overlays that contain the character at POS. +If SORTED is non-nil, then sort them by decreasing priority. */) + (Lisp_Object pos, Lisp_Object sorted) { ptrdiff_t len, noverlays; Lisp_Object *overlay_vec; @@ -4166,6 +4209,10 @@ DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0, noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, NULL, NULL, 0); + if (!NILP (sorted)) + noverlays = sort_overlays (overlay_vec, noverlays, + WINDOWP (sorted) ? XWINDOW (sorted) : NULL); + /* Make a list of them all. */ result = Flist (noverlays, overlay_vec); @@ -4607,7 +4654,8 @@ evaporate_overlays (ptrdiff_t pos) Allocation with mmap ***********************************************************************/ -#ifdef USE_MMAP_FOR_BUFFERS +/* Note: WINDOWSNT implements this stuff on w32heap.c. */ +#if defined USE_MMAP_FOR_BUFFERS && !defined WINDOWSNT #include @@ -4673,11 +4721,6 @@ static struct mmap_region *mmap_regions; static int mmap_fd; -/* Temporary storage for mmap_set_vars, see there. */ - -static struct mmap_region *mmap_regions_1; -static int mmap_fd_1; - /* Page size on this system. */ static int mmap_page_size; @@ -4749,36 +4792,6 @@ mmap_init (void) mmap_page_size = getpagesize (); } -/* Return a region overlapping address range START...END, or null if - none. END is not including, i.e. the last byte in the range - is at END - 1. */ - -static struct mmap_region * -mmap_find (void *start, void *end) -{ - struct mmap_region *r; - char *s = start, *e = end; - - for (r = mmap_regions; r; r = r->next) - { - char *rstart = (char *) r; - char *rend = rstart + r->nbytes_mapped; - - if (/* First byte of range, i.e. START, in this region? */ - (s >= rstart && s < rend) - /* Last byte of range, i.e. END - 1, in this region? */ - || (e > rstart && e <= rend) - /* First byte of this region in the range? */ - || (rstart >= s && rstart < e) - /* Last byte of this region in the range? */ - || (rend > s && rend <= e)) - break; - } - - return r; -} - - /* Unmap a region. P is a pointer to the start of the user-araa of the region. */ @@ -4855,38 +4868,6 @@ mmap_enlarge (struct mmap_region *r, int npages) } -/* Set or reset variables holding references to mapped regions. - If not RESTORE_P, set all variables to null. If RESTORE_P, set all - variables to the start of the user-areas of mapped regions. - - This function is called from Fdump_emacs to ensure that the dumped - Emacs doesn't contain references to memory that won't be mapped - when Emacs starts. */ - -void -mmap_set_vars (bool restore_p) -{ - struct mmap_region *r; - - if (restore_p) - { - mmap_regions = mmap_regions_1; - mmap_fd = mmap_fd_1; - for (r = mmap_regions; r; r = r->next) - *r->var = MMAP_USER_AREA (r); - } - else - { - for (r = mmap_regions; r; r = r->next) - *r->var = NULL; - mmap_regions_1 = mmap_regions; - mmap_regions = NULL; - mmap_fd_1 = mmap_fd; - mmap_fd = -1; - } -} - - /* Allocate a block of storage large enough to hold NBYTES bytes of data. A pointer to the data is returned in *VAR. VAR is thus the address of some variable which will use the data area. @@ -5047,7 +5028,7 @@ alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes) #elif defined REL_ALLOC p = r_alloc ((void **) &b->text->beg, nbytes); #else - p = xmalloc (nbytes); + p = xmalloc_atomic (nbytes); #endif if (p == NULL) @@ -5304,23 +5285,57 @@ init_buffer_once (void) } void -init_buffer (void) +init_buffer (int initialized) { char *pwd; Lisp_Object temp; ptrdiff_t len; #ifdef USE_MMAP_FOR_BUFFERS - { - /* When using the ralloc implementation based on mmap(2), buffer - text pointers will have been set to null in the dumped Emacs. - Map new memory. */ - struct buffer *b; - - FOR_EACH_BUFFER (b) - if (b->text->beg == NULL) - enlarge_buffer_text (b, 0); - } + if (initialized) + { + struct buffer *b; + +#ifndef WINDOWSNT + /* These must be reset in the dumped Emacs, to avoid stale + references to mmap'ed memory from before the dump. + + WINDOWSNT doesn't need this because it doesn't track mmap'ed + regions by hand (see w32heap.c, which uses system APIs for + that purpose), and thus doesn't use mmap_regions. */ + mmap_regions = NULL; + mmap_fd = -1; +#endif + + /* The dumped buffers reference addresses of buffer text + recorded by temacs, that cannot be used by the dumped Emacs. + We map new memory for their text here. + + Implementation note: the buffers we carry from temacs are: + " prin1", "*scratch*", " *Minibuf-0*", "*Messages*", and + " *code-conversion-work*". They are created by + init_buffer_once and init_window_once (which are not called + in the dumped Emacs), and by the first call to coding.c routines. */ + FOR_EACH_BUFFER (b) + { + b->text->beg = NULL; + enlarge_buffer_text (b, 0); + } + } + else + { + struct buffer *b; + + /* Only buffers with allocated buffer text should be present at + this point in temacs. */ + FOR_EACH_BUFFER (b) + { + eassert (b->text->beg != NULL); + } + } +#else /* not USE_MMAP_FOR_BUFFERS */ + /* Avoid compiler warnings. */ + initialized = initialized; #endif /* USE_MMAP_FOR_BUFFERS */ Fset_buffer (Fget_buffer_create (build_string ("*scratch*"))); @@ -5413,6 +5428,8 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring, void syms_of_buffer (void) { +#include "buffer.x" + staticpro (&last_overlay_modification_hooks); last_overlay_modification_hooks = Fmake_vector (make_number (10), Qnil); @@ -6284,61 +6301,11 @@ The function `kill-all-local-variables' runs this before doing anything else. * DEFVAR_LISP ("buffer-list-update-hook", Vbuffer_list_update_hook, doc: /* Hook run when the buffer list changes. -Functions running this hook are `get-buffer-create', +Functions running this hook are, `get-buffer-create', `make-indirect-buffer', `rename-buffer', `kill-buffer', -and `bury-buffer-internal'. */); +`bury-buffer-internal' and `select-window'. */); Vbuffer_list_update_hook = Qnil; DEFSYM (Qbuffer_list_update_hook, "buffer-list-update-hook"); - - defsubr (&Sbuffer_live_p); - defsubr (&Sbuffer_list); - defsubr (&Sget_buffer); - defsubr (&Sget_file_buffer); - defsubr (&Sget_buffer_create); - defsubr (&Smake_indirect_buffer); - defsubr (&Sgenerate_new_buffer_name); - defsubr (&Sbuffer_name); - defsubr (&Sbuffer_file_name); - defsubr (&Sbuffer_base_buffer); - defsubr (&Sbuffer_local_value); - defsubr (&Sbuffer_local_variables); - defsubr (&Sbuffer_modified_p); - defsubr (&Sforce_mode_line_update); - defsubr (&Sset_buffer_modified_p); - defsubr (&Sbuffer_modified_tick); - defsubr (&Sbuffer_chars_modified_tick); - defsubr (&Srename_buffer); - defsubr (&Sother_buffer); - defsubr (&Sbuffer_enable_undo); - defsubr (&Skill_buffer); - defsubr (&Sbury_buffer_internal); - defsubr (&Sset_buffer_major_mode); - defsubr (&Scurrent_buffer); - defsubr (&Sset_buffer); - defsubr (&Sbarf_if_buffer_read_only); - defsubr (&Serase_buffer); - defsubr (&Sbuffer_swap_text); - defsubr (&Sset_buffer_multibyte); - defsubr (&Skill_all_local_variables); - - defsubr (&Soverlayp); - defsubr (&Smake_overlay); - defsubr (&Sdelete_overlay); - defsubr (&Sdelete_all_overlays); - defsubr (&Smove_overlay); - defsubr (&Soverlay_start); - defsubr (&Soverlay_end); - defsubr (&Soverlay_buffer); - defsubr (&Soverlay_properties); - defsubr (&Soverlays_at); - defsubr (&Soverlays_in); - defsubr (&Snext_overlay_change); - defsubr (&Sprevious_overlay_change); - defsubr (&Soverlay_recenter); - defsubr (&Soverlay_lists); - defsubr (&Soverlay_get); - defsubr (&Soverlay_put); - defsubr (&Srestore_buffer_modified_p); } void