diff options
author | Juanma Barranquero <lekktu@gmail.com> | 2014-03-26 16:57:13 +0100 |
---|---|---|
committer | Juanma Barranquero <lekktu@gmail.com> | 2014-03-26 16:57:13 +0100 |
commit | 16adf2e6eb1ddf0b32ebea2d5ce8fa1e4c226614 (patch) | |
tree | 29b782fd6e7c44a834dd09442a551520e30bcbd6 /src | |
parent | 5af73b0fe8975eeb47fb270819b4143c18d71caa (diff) | |
parent | 196716cf35f81bea108c3b75362e92c86ed1c016 (diff) | |
download | emacs-16adf2e6eb1ddf0b32ebea2d5ce8fa1e4c226614.tar.gz |
Merge from emacs-24; up to 2014-03-23T23:14:52Z!yamaoka@jpl.org
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 58 | ||||
-rw-r--r-- | src/buffer.c | 49 | ||||
-rw-r--r-- | src/editfns.c | 15 | ||||
-rw-r--r-- | src/fileio.c | 3 | ||||
-rw-r--r-- | src/insdel.c | 45 | ||||
-rw-r--r-- | src/lisp.h | 3 | ||||
-rw-r--r-- | src/undo.c | 112 | ||||
-rw-r--r-- | src/w32term.c | 35 | ||||
-rw-r--r-- | src/xdisp.c | 46 |
9 files changed, 238 insertions, 128 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 84cd041c36c..996bbb78995 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,61 @@ +2014-03-26 Paul Eggert <eggert@cs.ucla.edu> + + Fix core dump in char-equal (Bug#17011). + * editfns.c (Fchar_equal): Do not use MAKE_CHAR_MULTIBYTE in + unibyte buffers, as we can't tell whether the characters are + actually unibyte. + + * insdel.c (adjust_markers_for_delete): Remove unused local. + +2014-03-26 Barry O'Reilly <gundaetiapo@gmail.com> + + Have (MARKER . ADJUSTMENT) undo records always be immediately + after their corresponding (TEXT . POS) record in undo list. + (Bug#16818) + * lisp.h (record-delete): New arg record_markers. + (record_marker_adjustment): No longer needed outside undo.c. + * insdel.c (adjust_markers_for_delete): Move calculation of marker + adjustments to undo.c's record_marker_adjustments. Note that + fileio.c's decide_coding_unwind is another caller to + adjust_markers_for_delete. Because it has undo list bound to t, + it does not rely on adjust_markers_for_delete to record marker + adjustments. + (del_range_2): Swap call to record_delete and + adjust_markers_for_delete so as undo marker adjustments are + recorded before current deletion's adjustments, as before. + (adjust_after_replace): + (replace_range): Pass value for new record_markers arg to + delete_record. + * undo.c (record_marker_adjustment): Renamed to + record_marker_adjustments and made static. + (record_delete): Check record_markers arg and call + record_marker_adjustments. + (record_change): Pass value for new record_markers arg to + delete_record. + (record_point): at_boundary calculation no longer needs to account + for marker adjustments. + +2014-03-26 Martin Rudalics <rudalics@gmx.at> + + * w32term.c (x_set_window_size): Refine fix from 2014-03-14 + (Bug#17077). + +2014-03-26 Glenn Morris <rgm@gnu.org> + + * fileio.c (Ffile_symlink_p): Doc fix. (Bug#17073) + +2014-03-26 Stefan Monnier <monnier@iro.umontreal.ca> + + * buffer.c (struct sortvec): Add field `spriority'. + (compare_overlays): Use it. + (sort_overlays): Set it. + +2014-03-26 Eli Zaretskii <eliz@gnu.org> + + * xdisp.c (redisplay_window): If all previous attempts to find the + cursor row failed, try a few alternatives before falling back to + the top-most row of the window. Use row_containing_pos. (Bug#17047) + 2014-03-26 Juanma Barranquero <lekktu@gmail.com> * image.c (x_bitmap_height, x_bitmap_width) [HAVE_X_WINDOWS]: diff --git a/src/buffer.c b/src/buffer.c index 5e923d26f3f..a22c6d7dd54 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -3142,6 +3142,7 @@ struct sortvec Lisp_Object overlay; ptrdiff_t beg, end; EMACS_INT priority; + EMACS_INT spriority; /* Secondary priority. */ }; static int @@ -3149,19 +3150,28 @@ compare_overlays (const void *v1, const void *v2) { const struct sortvec *s1 = v1; const struct sortvec *s2 = v2; + /* Return 1 if s1 should take precedence, -1 if v2 should take precedence, + and 0 if they're equal. */ if (s1->priority != 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. @@ -3204,10 +3214,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++; } } diff --git a/src/editfns.c b/src/editfns.c index 5018020a11b..1986ee53d23 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -4377,18 +4377,13 @@ Case is ignored if `case-fold-search' is non-nil in the current buffer. */) if (NILP (BVAR (current_buffer, case_fold_search))) return Qnil; + /* FIXME: When enable-multibyte-characters is nil, it's still possible + to manipulate multibyte chars, which means there is a bug for chars + in the range 128-255 as we can't tell whether they are eight-bit + bytes or Latin-1 chars. For now, assume the latter. See Bug#17011. + Also see casefiddle.c's casify_object, which has a similar problem. */ i1 = XFASTINT (c1); - if (NILP (BVAR (current_buffer, enable_multibyte_characters)) - && ! ASCII_CHAR_P (i1)) - { - MAKE_CHAR_MULTIBYTE (i1); - } i2 = XFASTINT (c2); - if (NILP (BVAR (current_buffer, enable_multibyte_characters)) - && ! ASCII_CHAR_P (i2)) - { - MAKE_CHAR_MULTIBYTE (i2); - } return (downcase (i1) == downcase (i2) ? Qt : Qnil); } diff --git a/src/fileio.c b/src/fileio.c index 152b7a8a8ed..4d27b58d2b7 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2682,8 +2682,7 @@ DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0, The value is the link target, as a string. Otherwise it returns nil. -This function returns t when given the name of a symlink that -points to a nonexistent file. */) +This function does not check whether the link target exists. */) (Lisp_Object filename) { Lisp_Object handler; diff --git a/src/insdel.c b/src/insdel.c index 5bd97f98613..9f9fcbd041f 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -214,9 +214,8 @@ void adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t to, ptrdiff_t to_byte) { - Lisp_Object marker; - register struct Lisp_Marker *m; - register ptrdiff_t charpos; + struct Lisp_Marker *m; + ptrdiff_t charpos; for (m = BUF_MARKERS (current_buffer); m; m = m->next) { @@ -233,34 +232,9 @@ adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte, /* Here's the case where a marker is inside text being deleted. */ else if (charpos > from) { - if (! m->insertion_type) - { /* Normal markers will end up at the beginning of the - re-inserted text after undoing a deletion, and must be - adjusted to move them to the correct place. */ - XSETMISC (marker, m); - record_marker_adjustment (marker, from - charpos); - } - else if (charpos < to) - { /* Before-insertion markers will automatically move forward - upon re-inserting the deleted text, so we have to arrange - for them to move backward to the correct position. */ - XSETMISC (marker, m); - record_marker_adjustment (marker, to - charpos); - } m->charpos = from; m->bytepos = from_byte; } - /* Here's the case where a before-insertion marker is immediately - before the deleted region. */ - else if (charpos == from && m->insertion_type) - { - /* Undoing the change uses normal insertion, which will - incorrectly make MARKER move forward, so we arrange for it - to then move backward to the correct place at the beginning - of the deleted region. */ - XSETMISC (marker, m); - record_marker_adjustment (marker, to - from); - } } } @@ -1219,7 +1193,7 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte, from + len, from_byte + len_byte, 0); if (nchars_del > 0) - record_delete (from, prev_text); + record_delete (from, prev_text, false); record_insert (from, len); if (len > nchars_del) @@ -1384,7 +1358,7 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new, if (!NILP (deletion)) { record_insert (from + SCHARS (deletion), inschars); - record_delete (from, deletion); + record_delete (from, deletion, false); } GAP_SIZE -= outgoing_insbytes; @@ -1716,13 +1690,14 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte, else deletion = Qnil; - /* Relocate all markers pointing into the new, larger gap - to point at the end of the text before the gap. - Do this before recording the deletion, - so that undo handles this after reinserting the text. */ + /* Record marker adjustments, and text deletion into undo + history. */ + record_delete (from, deletion, true); + + /* Relocate all markers pointing into the new, larger gap to point + at the end of the text before the gap. */ adjust_markers_for_delete (from, from_byte, to, to_byte); - record_delete (from, deletion); MODIFF++; CHARS_MODIFF = MODIFF; diff --git a/src/lisp.h b/src/lisp.h index 98f6c8b4d8d..07bf4646441 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4199,9 +4199,8 @@ extern void syms_of_macros (void); extern Lisp_Object Qapply; extern Lisp_Object Qinhibit_read_only; extern void truncate_undo_list (struct buffer *); -extern void record_marker_adjustment (Lisp_Object, ptrdiff_t); extern void record_insert (ptrdiff_t, ptrdiff_t); -extern void record_delete (ptrdiff_t, Lisp_Object); +extern void record_delete (ptrdiff_t, Lisp_Object, bool); extern void record_first_change (void); extern void record_change (ptrdiff_t, ptrdiff_t); extern void record_property_change (ptrdiff_t, ptrdiff_t, diff --git a/src/undo.c b/src/undo.c index 7286d40b2e5..2dde02b99a9 100644 --- a/src/undo.c +++ b/src/undo.c @@ -75,27 +75,8 @@ record_point (ptrdiff_t pt) Fundo_boundary (); last_undo_buffer = current_buffer; - if (CONSP (BVAR (current_buffer, undo_list))) - { - /* Set AT_BOUNDARY only when we have nothing other than - marker adjustment before undo boundary. */ - - Lisp_Object tail = BVAR (current_buffer, undo_list), elt; - - while (1) - { - if (NILP (tail)) - elt = Qnil; - else - elt = XCAR (tail); - if (NILP (elt) || ! (CONSP (elt) && MARKERP (XCAR (elt)))) - break; - tail = XCDR (tail); - } - at_boundary = NILP (elt); - } - else - at_boundary = 1; + at_boundary = ! CONSP (BVAR (current_buffer, undo_list)) + || NILP (XCAR (BVAR (current_buffer, undo_list))); if (MODIFF <= SAVE_MODIFF) record_first_change (); @@ -147,11 +128,61 @@ record_insert (ptrdiff_t beg, ptrdiff_t length) Fcons (Fcons (lbeg, lend), BVAR (current_buffer, undo_list))); } -/* Record that a deletion is about to take place, - of the characters in STRING, at location BEG. */ +/* Record the fact that markers in the region of FROM, TO are about to + be adjusted. This is done only when a marker points within text + being deleted, because that's the only case where an automatic + marker adjustment won't be inverted automatically by undoing the + buffer modification. */ + +static void +record_marker_adjustments (ptrdiff_t from, ptrdiff_t to) +{ + Lisp_Object marker; + register struct Lisp_Marker *m; + register ptrdiff_t charpos, adjustment; + + /* Allocate a cons cell to be the undo boundary after this command. */ + if (NILP (pending_boundary)) + pending_boundary = Fcons (Qnil, Qnil); + + if (current_buffer != last_undo_buffer) + Fundo_boundary (); + last_undo_buffer = current_buffer; + + for (m = BUF_MARKERS (current_buffer); m; m = m->next) + { + charpos = m->charpos; + eassert (charpos <= Z); + + if (from <= charpos && charpos <= to) + { + /* insertion_type nil markers will end up at the beginning of + the re-inserted text after undoing a deletion, and must be + adjusted to move them to the correct place. + + insertion_type t markers will automatically move forward + upon re-inserting the deleted text, so we have to arrange + for them to move backward to the correct position. */ + adjustment = (m->insertion_type ? to : from) - charpos; + + if (adjustment) + { + XSETMISC (marker, m); + bset_undo_list + (current_buffer, + Fcons (Fcons (marker, make_number (adjustment)), + BVAR (current_buffer, undo_list))); + } + } + } +} + +/* Record that a deletion is about to take place, of the characters in + STRING, at location BEG. Optionally record adjustments for markers + in the region STRING occupies in the current buffer. */ void -record_delete (ptrdiff_t beg, Lisp_Object string) +record_delete (ptrdiff_t beg, Lisp_Object string, bool record_markers) { Lisp_Object sbeg; @@ -169,34 +200,15 @@ record_delete (ptrdiff_t beg, Lisp_Object string) record_point (beg); } - bset_undo_list - (current_buffer, - Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list))); -} - -/* Record the fact that MARKER is about to be adjusted by ADJUSTMENT. - This is done only when a marker points within text being deleted, - because that's the only case where an automatic marker adjustment - won't be inverted automatically by undoing the buffer modification. */ - -void -record_marker_adjustment (Lisp_Object marker, ptrdiff_t adjustment) -{ - if (EQ (BVAR (current_buffer, undo_list), Qt)) - return; - - /* Allocate a cons cell to be the undo boundary after this command. */ - if (NILP (pending_boundary)) - pending_boundary = Fcons (Qnil, Qnil); - - if (current_buffer != last_undo_buffer) - Fundo_boundary (); - last_undo_buffer = current_buffer; + /* primitive-undo assumes marker adjustments are recorded + immediately before the deletion is recorded. See bug 16818 + discussion. */ + if (record_markers) + record_marker_adjustments (beg, beg + SCHARS (string)); bset_undo_list (current_buffer, - Fcons (Fcons (marker, make_number (adjustment)), - BVAR (current_buffer, undo_list))); + Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list))); } /* Record that a replacement is about to take place, @@ -206,7 +218,7 @@ record_marker_adjustment (Lisp_Object marker, ptrdiff_t adjustment) void record_change (ptrdiff_t beg, ptrdiff_t length) { - record_delete (beg, make_buffer_string (beg, beg + length, 1)); + record_delete (beg, make_buffer_string (beg, beg + length, 1), false); record_insert (beg, length); } diff --git a/src/w32term.c b/src/w32term.c index 52eccc27e81..e8ec99e762d 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -5653,30 +5653,41 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b compute_fringe_widths (f, 0); - if (pixelwise) + if (frame_resize_pixelwise) { - pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); - pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); + if (pixelwise) + { + pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); + pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); + } + else + { + pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); + pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); + } } else { - pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); - pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); - } - - if (!frame_resize_pixelwise) - { /* If we don't resize frames pixelwise, round sizes to multiples of character sizes here. Otherwise, when enforcing size hints while processing WM_WINDOWPOSCHANGING in w32_wnd_proc, we might clip our frame rectangle to a multiple of the frame's character size and subsequently lose our mode line or scroll bar. - Bug#16923 could be one possible consequence of this. */ + Bug#16923 could be one possible consequence of this. Carefully + reverse-engineer what WM_WINDOWPOSCHANGING does here since + otherwise we might make our frame too small, see Bug#17077. */ int unit_width = FRAME_COLUMN_WIDTH (f); int unit_height = FRAME_LINE_HEIGHT (f); - pixelwidth = (pixelwidth / unit_width) * unit_width; - pixelheight = (pixelheight / unit_height) * unit_height; + pixelwidth = (((((pixelwise ? width : (width * FRAME_COLUMN_WIDTH (f))) + + FRAME_TOTAL_FRINGE_WIDTH (f)) + / unit_width) * unit_width) + + FRAME_SCROLL_BAR_AREA_WIDTH (f) + + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); + + pixelheight = ((((pixelwise ? height : (height * FRAME_LINE_HEIGHT (f))) + / unit_height) * unit_height) + + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); } f->win_gravity = NorthWestGravity; diff --git a/src/xdisp.c b/src/xdisp.c index 6f39324d2f0..53bd46328f2 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -16400,12 +16400,50 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) /* Consider the following case: Window starts at BEGV, there is invisible, intangible text at BEGV, so that display starts at some point START > BEGV. It can happen that we are called with - PT somewhere between BEGV and START. Try to handle that case. */ + PT somewhere between BEGV and START. Try to handle that case, + and similar ones. */ if (w->cursor.vpos < 0) { - struct glyph_row *row = w->current_matrix->rows; - if (row->mode_line_p) - ++row; + /* First, try locating the proper glyph row for PT. */ + struct glyph_row *row = + row_containing_pos (w, PT, w->current_matrix->rows, NULL, 0); + + /* Sometimes point is at the beginning of invisible text that is + before the 1st character displayed in the row. In that case, + row_containing_pos fails to find the row, because no glyphs + with appropriate buffer positions are present in the row. + Therefore, we next try to find the row which shows the 1st + position after the invisible text. */ + if (!row) + { + Lisp_Object val = + get_char_property_and_overlay (make_number (PT), Qinvisible, + Qnil, NULL); + + if (TEXT_PROP_MEANS_INVISIBLE (val)) + { + ptrdiff_t alt_pos; + Lisp_Object invis_end = + Fnext_single_char_property_change (make_number (PT), Qinvisible, + Qnil, Qnil); + + if (NATNUMP (invis_end)) + alt_pos = XFASTINT (invis_end); + else + alt_pos = ZV; + row = row_containing_pos (w, alt_pos, w->current_matrix->rows, + NULL, 0); + } + } + /* Finally, fall back on the first row of the window after the + header line (if any). This is slightly better than not + displaying the cursor at all. */ + if (!row) + { + row = w->current_matrix->rows; + if (row->mode_line_p) + ++row; + } set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); } |