diff options
| author | Juanma Barranquero | 2014-03-26 16:57:13 +0100 |
|---|---|---|
| committer | Juanma Barranquero | 2014-03-26 16:57:13 +0100 |
| commit | 16adf2e6eb1ddf0b32ebea2d5ce8fa1e4c226614 (patch) | |
| tree | 29b782fd6e7c44a834dd09442a551520e30bcbd6 /src | |
| parent | 5af73b0fe8975eeb47fb270819b4143c18d71caa (diff) | |
| parent | 196716cf35f81bea108c3b75362e92c86ed1c016 (diff) | |
| download | emacs-16adf2e6eb1ddf0b32ebea2d5ce8fa1e4c226614.tar.gz emacs-16adf2e6eb1ddf0b32ebea2d5ce8fa1e4c226614.zip | |
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 @@ | |||
| 1 | 2014-03-26 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix core dump in char-equal (Bug#17011). | ||
| 4 | * editfns.c (Fchar_equal): Do not use MAKE_CHAR_MULTIBYTE in | ||
| 5 | unibyte buffers, as we can't tell whether the characters are | ||
| 6 | actually unibyte. | ||
| 7 | |||
| 8 | * insdel.c (adjust_markers_for_delete): Remove unused local. | ||
| 9 | |||
| 10 | 2014-03-26 Barry O'Reilly <gundaetiapo@gmail.com> | ||
| 11 | |||
| 12 | Have (MARKER . ADJUSTMENT) undo records always be immediately | ||
| 13 | after their corresponding (TEXT . POS) record in undo list. | ||
| 14 | (Bug#16818) | ||
| 15 | * lisp.h (record-delete): New arg record_markers. | ||
| 16 | (record_marker_adjustment): No longer needed outside undo.c. | ||
| 17 | * insdel.c (adjust_markers_for_delete): Move calculation of marker | ||
| 18 | adjustments to undo.c's record_marker_adjustments. Note that | ||
| 19 | fileio.c's decide_coding_unwind is another caller to | ||
| 20 | adjust_markers_for_delete. Because it has undo list bound to t, | ||
| 21 | it does not rely on adjust_markers_for_delete to record marker | ||
| 22 | adjustments. | ||
| 23 | (del_range_2): Swap call to record_delete and | ||
| 24 | adjust_markers_for_delete so as undo marker adjustments are | ||
| 25 | recorded before current deletion's adjustments, as before. | ||
| 26 | (adjust_after_replace): | ||
| 27 | (replace_range): Pass value for new record_markers arg to | ||
| 28 | delete_record. | ||
| 29 | * undo.c (record_marker_adjustment): Renamed to | ||
| 30 | record_marker_adjustments and made static. | ||
| 31 | (record_delete): Check record_markers arg and call | ||
| 32 | record_marker_adjustments. | ||
| 33 | (record_change): Pass value for new record_markers arg to | ||
| 34 | delete_record. | ||
| 35 | (record_point): at_boundary calculation no longer needs to account | ||
| 36 | for marker adjustments. | ||
| 37 | |||
| 38 | 2014-03-26 Martin Rudalics <rudalics@gmx.at> | ||
| 39 | |||
| 40 | * w32term.c (x_set_window_size): Refine fix from 2014-03-14 | ||
| 41 | (Bug#17077). | ||
| 42 | |||
| 43 | 2014-03-26 Glenn Morris <rgm@gnu.org> | ||
| 44 | |||
| 45 | * fileio.c (Ffile_symlink_p): Doc fix. (Bug#17073) | ||
| 46 | |||
| 47 | 2014-03-26 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 48 | |||
| 49 | * buffer.c (struct sortvec): Add field `spriority'. | ||
| 50 | (compare_overlays): Use it. | ||
| 51 | (sort_overlays): Set it. | ||
| 52 | |||
| 53 | 2014-03-26 Eli Zaretskii <eliz@gnu.org> | ||
| 54 | |||
| 55 | * xdisp.c (redisplay_window): If all previous attempts to find the | ||
| 56 | cursor row failed, try a few alternatives before falling back to | ||
| 57 | the top-most row of the window. Use row_containing_pos. (Bug#17047) | ||
| 58 | |||
| 1 | 2014-03-26 Juanma Barranquero <lekktu@gmail.com> | 59 | 2014-03-26 Juanma Barranquero <lekktu@gmail.com> |
| 2 | 60 | ||
| 3 | * image.c (x_bitmap_height, x_bitmap_width) [HAVE_X_WINDOWS]: | 61 | * 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 | |||
| 3142 | Lisp_Object overlay; | 3142 | Lisp_Object overlay; |
| 3143 | ptrdiff_t beg, end; | 3143 | ptrdiff_t beg, end; |
| 3144 | EMACS_INT priority; | 3144 | EMACS_INT priority; |
| 3145 | EMACS_INT spriority; /* Secondary priority. */ | ||
| 3145 | }; | 3146 | }; |
| 3146 | 3147 | ||
| 3147 | static int | 3148 | static int |
| @@ -3149,19 +3150,28 @@ compare_overlays (const void *v1, const void *v2) | |||
| 3149 | { | 3150 | { |
| 3150 | const struct sortvec *s1 = v1; | 3151 | const struct sortvec *s1 = v1; |
| 3151 | const struct sortvec *s2 = v2; | 3152 | const struct sortvec *s2 = v2; |
| 3153 | /* Return 1 if s1 should take precedence, -1 if v2 should take precedence, | ||
| 3154 | and 0 if they're equal. */ | ||
| 3152 | if (s1->priority != s2->priority) | 3155 | if (s1->priority != s2->priority) |
| 3153 | return s1->priority < s2->priority ? -1 : 1; | 3156 | return s1->priority < s2->priority ? -1 : 1; |
| 3154 | if (s1->beg != s2->beg) | 3157 | /* If the priority is equal, give precedence to the one not covered by the |
| 3155 | return s1->beg < s2->beg ? -1 : 1; | 3158 | other. If neither covers the other, obey spriority. */ |
| 3156 | if (s1->end != s2->end) | 3159 | else if (s1->beg < s2->beg) |
| 3160 | return (s1->end < s2->end && s1->spriority > s2->spriority ? 1 : -1); | ||
| 3161 | else if (s1->beg > s2->beg) | ||
| 3162 | return (s1->end > s2->end && s1->spriority < s2->spriority ? -1 : 1); | ||
| 3163 | else if (s1->end != s2->end) | ||
| 3157 | return s2->end < s1->end ? -1 : 1; | 3164 | return s2->end < s1->end ? -1 : 1; |
| 3158 | /* Avoid the non-determinism of qsort by choosing an arbitrary ordering | 3165 | else if (s1->spriority != s2->spriority) |
| 3159 | between "equal" overlays. The result can still change between | 3166 | return (s1->spriority < s2->spriority ? -1 : 1); |
| 3160 | invocations of Emacs, but it won't change in the middle of | 3167 | else if (EQ (s1->overlay, s2->overlay)) |
| 3161 | `find_field' (bug#6830). */ | 3168 | return 0; |
| 3162 | if (!EQ (s1->overlay, s2->overlay)) | 3169 | else |
| 3170 | /* Avoid the non-determinism of qsort by choosing an arbitrary ordering | ||
| 3171 | between "equal" overlays. The result can still change between | ||
| 3172 | invocations of Emacs, but it won't change in the middle of | ||
| 3173 | `find_field' (bug#6830). */ | ||
| 3163 | return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1; | 3174 | return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1; |
| 3164 | return 0; | ||
| 3165 | } | 3175 | } |
| 3166 | 3176 | ||
| 3167 | /* Sort an array of overlays by priority. The array is modified in place. | 3177 | /* 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) | |||
| 3204 | sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay)); | 3214 | sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay)); |
| 3205 | sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay)); | 3215 | sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay)); |
| 3206 | tem = Foverlay_get (overlay, Qpriority); | 3216 | tem = Foverlay_get (overlay, Qpriority); |
| 3207 | if (INTEGERP (tem)) | 3217 | if (NILP (tem)) |
| 3208 | sortvec[j].priority = XINT (tem); | 3218 | { |
| 3209 | else | 3219 | sortvec[j].priority = 0; |
| 3210 | sortvec[j].priority = 0; | 3220 | sortvec[j].spriority = 0; |
| 3221 | } | ||
| 3222 | else if (INTEGERP (tem)) | ||
| 3223 | { | ||
| 3224 | sortvec[j].priority = XINT (tem); | ||
| 3225 | sortvec[j].spriority = 0; | ||
| 3226 | } | ||
| 3227 | else if (CONSP (tem)) | ||
| 3228 | { | ||
| 3229 | Lisp_Object car = XCAR (tem); | ||
| 3230 | Lisp_Object cdr = XCDR (tem); | ||
| 3231 | sortvec[j].priority = INTEGERP (car) ? XINT (car) : 0; | ||
| 3232 | sortvec[j].spriority = INTEGERP (cdr) ? XINT (cdr) : 0; | ||
| 3233 | } | ||
| 3211 | j++; | 3234 | j++; |
| 3212 | } | 3235 | } |
| 3213 | } | 3236 | } |
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. */) | |||
| 4377 | if (NILP (BVAR (current_buffer, case_fold_search))) | 4377 | if (NILP (BVAR (current_buffer, case_fold_search))) |
| 4378 | return Qnil; | 4378 | return Qnil; |
| 4379 | 4379 | ||
| 4380 | /* FIXME: When enable-multibyte-characters is nil, it's still possible | ||
| 4381 | to manipulate multibyte chars, which means there is a bug for chars | ||
| 4382 | in the range 128-255 as we can't tell whether they are eight-bit | ||
| 4383 | bytes or Latin-1 chars. For now, assume the latter. See Bug#17011. | ||
| 4384 | Also see casefiddle.c's casify_object, which has a similar problem. */ | ||
| 4380 | i1 = XFASTINT (c1); | 4385 | i1 = XFASTINT (c1); |
| 4381 | if (NILP (BVAR (current_buffer, enable_multibyte_characters)) | ||
| 4382 | && ! ASCII_CHAR_P (i1)) | ||
| 4383 | { | ||
| 4384 | MAKE_CHAR_MULTIBYTE (i1); | ||
| 4385 | } | ||
| 4386 | i2 = XFASTINT (c2); | 4386 | i2 = XFASTINT (c2); |
| 4387 | if (NILP (BVAR (current_buffer, enable_multibyte_characters)) | ||
| 4388 | && ! ASCII_CHAR_P (i2)) | ||
| 4389 | { | ||
| 4390 | MAKE_CHAR_MULTIBYTE (i2); | ||
| 4391 | } | ||
| 4392 | return (downcase (i1) == downcase (i2) ? Qt : Qnil); | 4387 | return (downcase (i1) == downcase (i2) ? Qt : Qnil); |
| 4393 | } | 4388 | } |
| 4394 | 4389 | ||
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, | |||
| 2682 | The value is the link target, as a string. | 2682 | The value is the link target, as a string. |
| 2683 | Otherwise it returns nil. | 2683 | Otherwise it returns nil. |
| 2684 | 2684 | ||
| 2685 | This function returns t when given the name of a symlink that | 2685 | This function does not check whether the link target exists. */) |
| 2686 | points to a nonexistent file. */) | ||
| 2687 | (Lisp_Object filename) | 2686 | (Lisp_Object filename) |
| 2688 | { | 2687 | { |
| 2689 | Lisp_Object handler; | 2688 | 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 | |||
| 214 | adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte, | 214 | adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte, |
| 215 | ptrdiff_t to, ptrdiff_t to_byte) | 215 | ptrdiff_t to, ptrdiff_t to_byte) |
| 216 | { | 216 | { |
| 217 | Lisp_Object marker; | 217 | struct Lisp_Marker *m; |
| 218 | register struct Lisp_Marker *m; | 218 | ptrdiff_t charpos; |
| 219 | register ptrdiff_t charpos; | ||
| 220 | 219 | ||
| 221 | for (m = BUF_MARKERS (current_buffer); m; m = m->next) | 220 | for (m = BUF_MARKERS (current_buffer); m; m = m->next) |
| 222 | { | 221 | { |
| @@ -233,34 +232,9 @@ adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte, | |||
| 233 | /* Here's the case where a marker is inside text being deleted. */ | 232 | /* Here's the case where a marker is inside text being deleted. */ |
| 234 | else if (charpos > from) | 233 | else if (charpos > from) |
| 235 | { | 234 | { |
| 236 | if (! m->insertion_type) | ||
| 237 | { /* Normal markers will end up at the beginning of the | ||
| 238 | re-inserted text after undoing a deletion, and must be | ||
| 239 | adjusted to move them to the correct place. */ | ||
| 240 | XSETMISC (marker, m); | ||
| 241 | record_marker_adjustment (marker, from - charpos); | ||
| 242 | } | ||
| 243 | else if (charpos < to) | ||
| 244 | { /* Before-insertion markers will automatically move forward | ||
| 245 | upon re-inserting the deleted text, so we have to arrange | ||
| 246 | for them to move backward to the correct position. */ | ||
| 247 | XSETMISC (marker, m); | ||
| 248 | record_marker_adjustment (marker, to - charpos); | ||
| 249 | } | ||
| 250 | m->charpos = from; | 235 | m->charpos = from; |
| 251 | m->bytepos = from_byte; | 236 | m->bytepos = from_byte; |
| 252 | } | 237 | } |
| 253 | /* Here's the case where a before-insertion marker is immediately | ||
| 254 | before the deleted region. */ | ||
| 255 | else if (charpos == from && m->insertion_type) | ||
| 256 | { | ||
| 257 | /* Undoing the change uses normal insertion, which will | ||
| 258 | incorrectly make MARKER move forward, so we arrange for it | ||
| 259 | to then move backward to the correct place at the beginning | ||
| 260 | of the deleted region. */ | ||
| 261 | XSETMISC (marker, m); | ||
| 262 | record_marker_adjustment (marker, to - from); | ||
| 263 | } | ||
| 264 | } | 238 | } |
| 265 | } | 239 | } |
| 266 | 240 | ||
| @@ -1219,7 +1193,7 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte, | |||
| 1219 | from + len, from_byte + len_byte, 0); | 1193 | from + len, from_byte + len_byte, 0); |
| 1220 | 1194 | ||
| 1221 | if (nchars_del > 0) | 1195 | if (nchars_del > 0) |
| 1222 | record_delete (from, prev_text); | 1196 | record_delete (from, prev_text, false); |
| 1223 | record_insert (from, len); | 1197 | record_insert (from, len); |
| 1224 | 1198 | ||
| 1225 | if (len > nchars_del) | 1199 | if (len > nchars_del) |
| @@ -1384,7 +1358,7 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new, | |||
| 1384 | if (!NILP (deletion)) | 1358 | if (!NILP (deletion)) |
| 1385 | { | 1359 | { |
| 1386 | record_insert (from + SCHARS (deletion), inschars); | 1360 | record_insert (from + SCHARS (deletion), inschars); |
| 1387 | record_delete (from, deletion); | 1361 | record_delete (from, deletion, false); |
| 1388 | } | 1362 | } |
| 1389 | 1363 | ||
| 1390 | GAP_SIZE -= outgoing_insbytes; | 1364 | GAP_SIZE -= outgoing_insbytes; |
| @@ -1716,13 +1690,14 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte, | |||
| 1716 | else | 1690 | else |
| 1717 | deletion = Qnil; | 1691 | deletion = Qnil; |
| 1718 | 1692 | ||
| 1719 | /* Relocate all markers pointing into the new, larger gap | 1693 | /* Record marker adjustments, and text deletion into undo |
| 1720 | to point at the end of the text before the gap. | 1694 | history. */ |
| 1721 | Do this before recording the deletion, | 1695 | record_delete (from, deletion, true); |
| 1722 | so that undo handles this after reinserting the text. */ | 1696 | |
| 1697 | /* Relocate all markers pointing into the new, larger gap to point | ||
| 1698 | at the end of the text before the gap. */ | ||
| 1723 | adjust_markers_for_delete (from, from_byte, to, to_byte); | 1699 | adjust_markers_for_delete (from, from_byte, to, to_byte); |
| 1724 | 1700 | ||
| 1725 | record_delete (from, deletion); | ||
| 1726 | MODIFF++; | 1701 | MODIFF++; |
| 1727 | CHARS_MODIFF = MODIFF; | 1702 | CHARS_MODIFF = MODIFF; |
| 1728 | 1703 | ||
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); | |||
| 4199 | extern Lisp_Object Qapply; | 4199 | extern Lisp_Object Qapply; |
| 4200 | extern Lisp_Object Qinhibit_read_only; | 4200 | extern Lisp_Object Qinhibit_read_only; |
| 4201 | extern void truncate_undo_list (struct buffer *); | 4201 | extern void truncate_undo_list (struct buffer *); |
| 4202 | extern void record_marker_adjustment (Lisp_Object, ptrdiff_t); | ||
| 4203 | extern void record_insert (ptrdiff_t, ptrdiff_t); | 4202 | extern void record_insert (ptrdiff_t, ptrdiff_t); |
| 4204 | extern void record_delete (ptrdiff_t, Lisp_Object); | 4203 | extern void record_delete (ptrdiff_t, Lisp_Object, bool); |
| 4205 | extern void record_first_change (void); | 4204 | extern void record_first_change (void); |
| 4206 | extern void record_change (ptrdiff_t, ptrdiff_t); | 4205 | extern void record_change (ptrdiff_t, ptrdiff_t); |
| 4207 | extern void record_property_change (ptrdiff_t, ptrdiff_t, | 4206 | 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) | |||
| 75 | Fundo_boundary (); | 75 | Fundo_boundary (); |
| 76 | last_undo_buffer = current_buffer; | 76 | last_undo_buffer = current_buffer; |
| 77 | 77 | ||
| 78 | if (CONSP (BVAR (current_buffer, undo_list))) | 78 | at_boundary = ! CONSP (BVAR (current_buffer, undo_list)) |
| 79 | { | 79 | || NILP (XCAR (BVAR (current_buffer, undo_list))); |
| 80 | /* Set AT_BOUNDARY only when we have nothing other than | ||
| 81 | marker adjustment before undo boundary. */ | ||
| 82 | |||
| 83 | Lisp_Object tail = BVAR (current_buffer, undo_list), elt; | ||
| 84 | |||
| 85 | while (1) | ||
| 86 | { | ||
| 87 | if (NILP (tail)) | ||
| 88 | elt = Qnil; | ||
| 89 | else | ||
| 90 | elt = XCAR (tail); | ||
| 91 | if (NILP (elt) || ! (CONSP (elt) && MARKERP (XCAR (elt)))) | ||
| 92 | break; | ||
| 93 | tail = XCDR (tail); | ||
| 94 | } | ||
| 95 | at_boundary = NILP (elt); | ||
| 96 | } | ||
| 97 | else | ||
| 98 | at_boundary = 1; | ||
| 99 | 80 | ||
| 100 | if (MODIFF <= SAVE_MODIFF) | 81 | if (MODIFF <= SAVE_MODIFF) |
| 101 | record_first_change (); | 82 | record_first_change (); |
| @@ -147,11 +128,61 @@ record_insert (ptrdiff_t beg, ptrdiff_t length) | |||
| 147 | Fcons (Fcons (lbeg, lend), BVAR (current_buffer, undo_list))); | 128 | Fcons (Fcons (lbeg, lend), BVAR (current_buffer, undo_list))); |
| 148 | } | 129 | } |
| 149 | 130 | ||
| 150 | /* Record that a deletion is about to take place, | 131 | /* Record the fact that markers in the region of FROM, TO are about to |
| 151 | of the characters in STRING, at location BEG. */ | 132 | be adjusted. This is done only when a marker points within text |
| 133 | being deleted, because that's the only case where an automatic | ||
| 134 | marker adjustment won't be inverted automatically by undoing the | ||
| 135 | buffer modification. */ | ||
| 136 | |||
| 137 | static void | ||
| 138 | record_marker_adjustments (ptrdiff_t from, ptrdiff_t to) | ||
| 139 | { | ||
| 140 | Lisp_Object marker; | ||
| 141 | register struct Lisp_Marker *m; | ||
| 142 | register ptrdiff_t charpos, adjustment; | ||
| 143 | |||
| 144 | /* Allocate a cons cell to be the undo boundary after this command. */ | ||
| 145 | if (NILP (pending_boundary)) | ||
| 146 | pending_boundary = Fcons (Qnil, Qnil); | ||
| 147 | |||
| 148 | if (current_buffer != last_undo_buffer) | ||
| 149 | Fundo_boundary (); | ||
| 150 | last_undo_buffer = current_buffer; | ||
| 151 | |||
| 152 | for (m = BUF_MARKERS (current_buffer); m; m = m->next) | ||
| 153 | { | ||
| 154 | charpos = m->charpos; | ||
| 155 | eassert (charpos <= Z); | ||
| 156 | |||
| 157 | if (from <= charpos && charpos <= to) | ||
| 158 | { | ||
| 159 | /* insertion_type nil markers will end up at the beginning of | ||
| 160 | the re-inserted text after undoing a deletion, and must be | ||
| 161 | adjusted to move them to the correct place. | ||
| 162 | |||
| 163 | insertion_type t markers will automatically move forward | ||
| 164 | upon re-inserting the deleted text, so we have to arrange | ||
| 165 | for them to move backward to the correct position. */ | ||
| 166 | adjustment = (m->insertion_type ? to : from) - charpos; | ||
| 167 | |||
| 168 | if (adjustment) | ||
| 169 | { | ||
| 170 | XSETMISC (marker, m); | ||
| 171 | bset_undo_list | ||
| 172 | (current_buffer, | ||
| 173 | Fcons (Fcons (marker, make_number (adjustment)), | ||
| 174 | BVAR (current_buffer, undo_list))); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | /* Record that a deletion is about to take place, of the characters in | ||
| 181 | STRING, at location BEG. Optionally record adjustments for markers | ||
| 182 | in the region STRING occupies in the current buffer. */ | ||
| 152 | 183 | ||
| 153 | void | 184 | void |
| 154 | record_delete (ptrdiff_t beg, Lisp_Object string) | 185 | record_delete (ptrdiff_t beg, Lisp_Object string, bool record_markers) |
| 155 | { | 186 | { |
| 156 | Lisp_Object sbeg; | 187 | Lisp_Object sbeg; |
| 157 | 188 | ||
| @@ -169,34 +200,15 @@ record_delete (ptrdiff_t beg, Lisp_Object string) | |||
| 169 | record_point (beg); | 200 | record_point (beg); |
| 170 | } | 201 | } |
| 171 | 202 | ||
| 172 | bset_undo_list | 203 | /* primitive-undo assumes marker adjustments are recorded |
| 173 | (current_buffer, | 204 | immediately before the deletion is recorded. See bug 16818 |
| 174 | Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list))); | 205 | discussion. */ |
| 175 | } | 206 | if (record_markers) |
| 176 | 207 | record_marker_adjustments (beg, beg + SCHARS (string)); | |
| 177 | /* Record the fact that MARKER is about to be adjusted by ADJUSTMENT. | ||
| 178 | This is done only when a marker points within text being deleted, | ||
| 179 | because that's the only case where an automatic marker adjustment | ||
| 180 | won't be inverted automatically by undoing the buffer modification. */ | ||
| 181 | |||
| 182 | void | ||
| 183 | record_marker_adjustment (Lisp_Object marker, ptrdiff_t adjustment) | ||
| 184 | { | ||
| 185 | if (EQ (BVAR (current_buffer, undo_list), Qt)) | ||
| 186 | return; | ||
| 187 | |||
| 188 | /* Allocate a cons cell to be the undo boundary after this command. */ | ||
| 189 | if (NILP (pending_boundary)) | ||
| 190 | pending_boundary = Fcons (Qnil, Qnil); | ||
| 191 | |||
| 192 | if (current_buffer != last_undo_buffer) | ||
| 193 | Fundo_boundary (); | ||
| 194 | last_undo_buffer = current_buffer; | ||
| 195 | 208 | ||
| 196 | bset_undo_list | 209 | bset_undo_list |
| 197 | (current_buffer, | 210 | (current_buffer, |
| 198 | Fcons (Fcons (marker, make_number (adjustment)), | 211 | Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list))); |
| 199 | BVAR (current_buffer, undo_list))); | ||
| 200 | } | 212 | } |
| 201 | 213 | ||
| 202 | /* Record that a replacement is about to take place, | 214 | /* Record that a replacement is about to take place, |
| @@ -206,7 +218,7 @@ record_marker_adjustment (Lisp_Object marker, ptrdiff_t adjustment) | |||
| 206 | void | 218 | void |
| 207 | record_change (ptrdiff_t beg, ptrdiff_t length) | 219 | record_change (ptrdiff_t beg, ptrdiff_t length) |
| 208 | { | 220 | { |
| 209 | record_delete (beg, make_buffer_string (beg, beg + length, 1)); | 221 | record_delete (beg, make_buffer_string (beg, beg + length, 1), false); |
| 210 | record_insert (beg, length); | 222 | record_insert (beg, length); |
| 211 | } | 223 | } |
| 212 | 224 | ||
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 | |||
| 5653 | 5653 | ||
| 5654 | compute_fringe_widths (f, 0); | 5654 | compute_fringe_widths (f, 0); |
| 5655 | 5655 | ||
| 5656 | if (pixelwise) | 5656 | if (frame_resize_pixelwise) |
| 5657 | { | 5657 | { |
| 5658 | pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); | 5658 | if (pixelwise) |
| 5659 | pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); | 5659 | { |
| 5660 | pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); | ||
| 5661 | pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); | ||
| 5662 | } | ||
| 5663 | else | ||
| 5664 | { | ||
| 5665 | pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); | ||
| 5666 | pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); | ||
| 5667 | } | ||
| 5660 | } | 5668 | } |
| 5661 | else | 5669 | else |
| 5662 | { | 5670 | { |
| 5663 | pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); | ||
| 5664 | pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); | ||
| 5665 | } | ||
| 5666 | |||
| 5667 | if (!frame_resize_pixelwise) | ||
| 5668 | { | ||
| 5669 | /* If we don't resize frames pixelwise, round sizes to multiples | 5671 | /* If we don't resize frames pixelwise, round sizes to multiples |
| 5670 | of character sizes here. Otherwise, when enforcing size hints | 5672 | of character sizes here. Otherwise, when enforcing size hints |
| 5671 | while processing WM_WINDOWPOSCHANGING in w32_wnd_proc, we might | 5673 | while processing WM_WINDOWPOSCHANGING in w32_wnd_proc, we might |
| 5672 | clip our frame rectangle to a multiple of the frame's character | 5674 | clip our frame rectangle to a multiple of the frame's character |
| 5673 | size and subsequently lose our mode line or scroll bar. | 5675 | size and subsequently lose our mode line or scroll bar. |
| 5674 | Bug#16923 could be one possible consequence of this. */ | 5676 | Bug#16923 could be one possible consequence of this. Carefully |
| 5677 | reverse-engineer what WM_WINDOWPOSCHANGING does here since | ||
| 5678 | otherwise we might make our frame too small, see Bug#17077. */ | ||
| 5675 | int unit_width = FRAME_COLUMN_WIDTH (f); | 5679 | int unit_width = FRAME_COLUMN_WIDTH (f); |
| 5676 | int unit_height = FRAME_LINE_HEIGHT (f); | 5680 | int unit_height = FRAME_LINE_HEIGHT (f); |
| 5677 | 5681 | ||
| 5678 | pixelwidth = (pixelwidth / unit_width) * unit_width; | 5682 | pixelwidth = (((((pixelwise ? width : (width * FRAME_COLUMN_WIDTH (f))) |
| 5679 | pixelheight = (pixelheight / unit_height) * unit_height; | 5683 | + FRAME_TOTAL_FRINGE_WIDTH (f)) |
| 5684 | / unit_width) * unit_width) | ||
| 5685 | + FRAME_SCROLL_BAR_AREA_WIDTH (f) | ||
| 5686 | + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); | ||
| 5687 | |||
| 5688 | pixelheight = ((((pixelwise ? height : (height * FRAME_LINE_HEIGHT (f))) | ||
| 5689 | / unit_height) * unit_height) | ||
| 5690 | + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); | ||
| 5680 | } | 5691 | } |
| 5681 | 5692 | ||
| 5682 | f->win_gravity = NorthWestGravity; | 5693 | 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) | |||
| 16400 | /* Consider the following case: Window starts at BEGV, there is | 16400 | /* Consider the following case: Window starts at BEGV, there is |
| 16401 | invisible, intangible text at BEGV, so that display starts at | 16401 | invisible, intangible text at BEGV, so that display starts at |
| 16402 | some point START > BEGV. It can happen that we are called with | 16402 | some point START > BEGV. It can happen that we are called with |
| 16403 | PT somewhere between BEGV and START. Try to handle that case. */ | 16403 | PT somewhere between BEGV and START. Try to handle that case, |
| 16404 | and similar ones. */ | ||
| 16404 | if (w->cursor.vpos < 0) | 16405 | if (w->cursor.vpos < 0) |
| 16405 | { | 16406 | { |
| 16406 | struct glyph_row *row = w->current_matrix->rows; | 16407 | /* First, try locating the proper glyph row for PT. */ |
| 16407 | if (row->mode_line_p) | 16408 | struct glyph_row *row = |
| 16408 | ++row; | 16409 | row_containing_pos (w, PT, w->current_matrix->rows, NULL, 0); |
| 16410 | |||
| 16411 | /* Sometimes point is at the beginning of invisible text that is | ||
| 16412 | before the 1st character displayed in the row. In that case, | ||
| 16413 | row_containing_pos fails to find the row, because no glyphs | ||
| 16414 | with appropriate buffer positions are present in the row. | ||
| 16415 | Therefore, we next try to find the row which shows the 1st | ||
| 16416 | position after the invisible text. */ | ||
| 16417 | if (!row) | ||
| 16418 | { | ||
| 16419 | Lisp_Object val = | ||
| 16420 | get_char_property_and_overlay (make_number (PT), Qinvisible, | ||
| 16421 | Qnil, NULL); | ||
| 16422 | |||
| 16423 | if (TEXT_PROP_MEANS_INVISIBLE (val)) | ||
| 16424 | { | ||
| 16425 | ptrdiff_t alt_pos; | ||
| 16426 | Lisp_Object invis_end = | ||
| 16427 | Fnext_single_char_property_change (make_number (PT), Qinvisible, | ||
| 16428 | Qnil, Qnil); | ||
| 16429 | |||
| 16430 | if (NATNUMP (invis_end)) | ||
| 16431 | alt_pos = XFASTINT (invis_end); | ||
| 16432 | else | ||
| 16433 | alt_pos = ZV; | ||
| 16434 | row = row_containing_pos (w, alt_pos, w->current_matrix->rows, | ||
| 16435 | NULL, 0); | ||
| 16436 | } | ||
| 16437 | } | ||
| 16438 | /* Finally, fall back on the first row of the window after the | ||
| 16439 | header line (if any). This is slightly better than not | ||
| 16440 | displaying the cursor at all. */ | ||
| 16441 | if (!row) | ||
| 16442 | { | ||
| 16443 | row = w->current_matrix->rows; | ||
| 16444 | if (row->mode_line_p) | ||
| 16445 | ++row; | ||
| 16446 | } | ||
| 16409 | set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); | 16447 | set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); |
| 16410 | } | 16448 | } |
| 16411 | 16449 | ||