aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJuanma Barranquero2014-03-26 16:57:13 +0100
committerJuanma Barranquero2014-03-26 16:57:13 +0100
commit16adf2e6eb1ddf0b32ebea2d5ce8fa1e4c226614 (patch)
tree29b782fd6e7c44a834dd09442a551520e30bcbd6 /src
parent5af73b0fe8975eeb47fb270819b4143c18d71caa (diff)
parent196716cf35f81bea108c3b75362e92c86ed1c016 (diff)
downloademacs-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/ChangeLog58
-rw-r--r--src/buffer.c49
-rw-r--r--src/editfns.c15
-rw-r--r--src/fileio.c3
-rw-r--r--src/insdel.c45
-rw-r--r--src/lisp.h3
-rw-r--r--src/undo.c112
-rw-r--r--src/w32term.c35
-rw-r--r--src/xdisp.c46
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 @@
12014-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
102014-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
382014-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
432014-03-26 Glenn Morris <rgm@gnu.org>
44
45 * fileio.c (Ffile_symlink_p): Doc fix. (Bug#17073)
46
472014-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
532014-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
12014-03-26 Juanma Barranquero <lekktu@gmail.com> 592014-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
3147static int 3148static 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,
2682The value is the link target, as a string. 2682The value is the link target, as a string.
2683Otherwise it returns nil. 2683Otherwise it returns nil.
2684 2684
2685This function returns t when given the name of a symlink that 2685This function does not check whether the link target exists. */)
2686points 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
214adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte, 214adjust_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);
4199extern Lisp_Object Qapply; 4199extern Lisp_Object Qapply;
4200extern Lisp_Object Qinhibit_read_only; 4200extern Lisp_Object Qinhibit_read_only;
4201extern void truncate_undo_list (struct buffer *); 4201extern void truncate_undo_list (struct buffer *);
4202extern void record_marker_adjustment (Lisp_Object, ptrdiff_t);
4203extern void record_insert (ptrdiff_t, ptrdiff_t); 4202extern void record_insert (ptrdiff_t, ptrdiff_t);
4204extern void record_delete (ptrdiff_t, Lisp_Object); 4203extern void record_delete (ptrdiff_t, Lisp_Object, bool);
4205extern void record_first_change (void); 4204extern void record_first_change (void);
4206extern void record_change (ptrdiff_t, ptrdiff_t); 4205extern void record_change (ptrdiff_t, ptrdiff_t);
4207extern void record_property_change (ptrdiff_t, ptrdiff_t, 4206extern 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
137static void
138record_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
153void 184void
154record_delete (ptrdiff_t beg, Lisp_Object string) 185record_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
182void
183record_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)
206void 218void
207record_change (ptrdiff_t beg, ptrdiff_t length) 219record_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