Mirror of the Vim source from https://github.com/vim/vim
Revision | eff0d98467e32830ea7a4751ea7071eab640829b (tree) |
---|---|
Time | 2022-11-20 20:15:04 |
Author | Bram Moolenaar <Bram@vim....> |
Commiter | Bram Moolenaar |
patch 9.0.0914: deletebufline() may move marks in the wrong window
Commit: https://github.com/vim/vim/commit/228e422855d43965f2c3319ff0cdc26ea422c10f
Author: zeertzjq <zeertzjq@outlook.com>
Date: Sun Nov 20 11:13:17 2022 +0000
@@ -119,6 +119,59 @@ | ||
119 | 119 | } |
120 | 120 | } |
121 | 121 | |
122 | +typedef struct { | |
123 | + win_T *cob_curwin_save; | |
124 | + aco_save_T cob_aco; | |
125 | + int cob_using_aco; | |
126 | + int cob_save_VIsual_active; | |
127 | +} cob_T; | |
128 | + | |
129 | +/* | |
130 | + * Used before making a change in "buf", which is not the current one: Make | |
131 | + * "buf" the current buffer and find a window for this buffer, so that side | |
132 | + * effects are done correctly (e.g., adjusting marks). | |
133 | + * | |
134 | + * Information is saved in "cob" and MUST be restored by calling | |
135 | + * change_other_buffer_restore(). | |
136 | + */ | |
137 | + static void | |
138 | +change_other_buffer_prepare(cob_T *cob, buf_T *buf) | |
139 | +{ | |
140 | + CLEAR_POINTER(cob); | |
141 | + | |
142 | + // Set "curbuf" to the buffer being changed. Then make sure there is a | |
143 | + // window for it to handle any side effects. | |
144 | + cob->cob_save_VIsual_active = VIsual_active; | |
145 | + VIsual_active = FALSE; | |
146 | + cob->cob_curwin_save = curwin; | |
147 | + curbuf = buf; | |
148 | + find_win_for_curbuf(); // simplest: find existing window for "buf" | |
149 | + | |
150 | + if (curwin->w_buffer != buf) | |
151 | + { | |
152 | + // No existing window for this buffer. It is dangerous to have | |
153 | + // curwin->w_buffer differ from "curbuf", use the autocmd window. | |
154 | + curbuf = curwin->w_buffer; | |
155 | + aucmd_prepbuf(&cob->cob_aco, buf); | |
156 | + cob->cob_using_aco = TRUE; | |
157 | + } | |
158 | +} | |
159 | + | |
160 | + static void | |
161 | +change_other_buffer_restore(cob_T *cob) | |
162 | +{ | |
163 | + if (cob->cob_using_aco) | |
164 | + { | |
165 | + aucmd_restbuf(&cob->cob_aco); | |
166 | + } | |
167 | + else | |
168 | + { | |
169 | + curwin = cob->cob_curwin_save; | |
170 | + curbuf = curwin->w_buffer; | |
171 | + } | |
172 | + VIsual_active = cob->cob_save_VIsual_active; | |
173 | +} | |
174 | + | |
122 | 175 | /* |
123 | 176 | * Set line or list of lines in buffer "buf" to "lines". |
124 | 177 | * Any type is allowed and converted to a string. |
@@ -137,10 +190,6 @@ | ||
137 | 190 | listitem_T *li = NULL; |
138 | 191 | long added = 0; |
139 | 192 | linenr_T append_lnum; |
140 | - win_T *curwin_save = NULL; | |
141 | - aco_save_T aco; | |
142 | - int using_aco = FALSE; | |
143 | - int save_VIsual_active = VIsual_active; | |
144 | 193 | |
145 | 194 | // When using the current buffer ml_mfp will be set if needed. Useful when |
146 | 195 | // setline() is used on startup. For other buffers the buffer must be |
@@ -154,24 +203,11 @@ | ||
154 | 203 | return; |
155 | 204 | } |
156 | 205 | |
206 | + // After this don't use "return", goto "cleanup"! | |
207 | + cob_T cob; | |
157 | 208 | if (!is_curbuf) |
158 | - { | |
159 | - // Set "curbuf" to the buffer being changed. Then make sure there is a | |
160 | - // window for it to handle any side effects. | |
161 | - VIsual_active = FALSE; | |
162 | - curwin_save = curwin; | |
163 | - curbuf = buf; | |
164 | - find_win_for_curbuf(); // simplest: find existing window for "buf" | |
165 | - | |
166 | - if (curwin->w_buffer != buf) | |
167 | - { | |
168 | - // No existing window for this buffer. It is dangerous to have | |
169 | - // curwin->w_buffer differ from "curbuf", use the autocmd window. | |
170 | - curbuf = curwin->w_buffer; | |
171 | - aucmd_prepbuf(&aco, buf); | |
172 | - using_aco = TRUE; | |
173 | - } | |
174 | - } | |
209 | + // set "curbuf" to "buf" and find a window for this buffer | |
210 | + change_other_buffer_prepare(&cob, buf); | |
175 | 211 | |
176 | 212 | if (append) |
177 | 213 | // appendbufline() uses the line number below which we insert |
@@ -272,18 +308,7 @@ | ||
272 | 308 | |
273 | 309 | done: |
274 | 310 | if (!is_curbuf) |
275 | - { | |
276 | - if (using_aco) | |
277 | - { | |
278 | - aucmd_restbuf(&aco); | |
279 | - } | |
280 | - else | |
281 | - { | |
282 | - curwin = curwin_save; | |
283 | - curbuf = curwin->w_buffer; | |
284 | - } | |
285 | - VIsual_active = save_VIsual_active; | |
286 | - } | |
311 | + change_other_buffer_restore(&cob); | |
287 | 312 | } |
288 | 313 | |
289 | 314 | /* |
@@ -521,12 +546,9 @@ | ||
521 | 546 | linenr_T lnum; |
522 | 547 | long count; |
523 | 548 | int is_curbuf; |
524 | - buf_T *curbuf_save = NULL; | |
525 | - win_T *curwin_save = NULL; | |
526 | 549 | tabpage_T *tp; |
527 | 550 | win_T *wp; |
528 | 551 | int did_emsg_before = did_emsg; |
529 | - int save_VIsual_active = VIsual_active; | |
530 | 552 | |
531 | 553 | rettv->vval.v_number = 1; // FAIL by default |
532 | 554 |
@@ -539,7 +561,6 @@ | ||
539 | 561 | buf = tv_get_buf(&argvars[0], FALSE); |
540 | 562 | if (buf == NULL) |
541 | 563 | return; |
542 | - is_curbuf = buf == curbuf; | |
543 | 564 | |
544 | 565 | first = tv_get_lnum_buf(&argvars[1], buf); |
545 | 566 | if (did_emsg > did_emsg_before) |
@@ -554,14 +575,12 @@ | ||
554 | 575 | return; |
555 | 576 | |
556 | 577 | // After this don't use "return", goto "cleanup"! |
578 | + is_curbuf = buf == curbuf; | |
579 | + cob_T cob; | |
557 | 580 | if (!is_curbuf) |
558 | - { | |
559 | - VIsual_active = FALSE; | |
560 | - curbuf_save = curbuf; | |
561 | - curwin_save = curwin; | |
562 | - curbuf = buf; | |
563 | - find_win_for_curbuf(); | |
564 | - } | |
581 | + // set "curbuf" to "buf" and find a window for this buffer | |
582 | + change_other_buffer_prepare(&cob, buf); | |
583 | + | |
565 | 584 | if (last > curbuf->b_ml.ml_line_count) |
566 | 585 | last = curbuf->b_ml.ml_line_count; |
567 | 586 | count = last - first + 1; |
@@ -599,11 +618,7 @@ | ||
599 | 618 | |
600 | 619 | cleanup: |
601 | 620 | if (!is_curbuf) |
602 | - { | |
603 | - curbuf = curbuf_save; | |
604 | - curwin = curwin_save; | |
605 | - VIsual_active = save_VIsual_active; | |
606 | - } | |
621 | + change_other_buffer_restore(&cob); | |
607 | 622 | } |
608 | 623 | |
609 | 624 | /* |
@@ -98,12 +98,25 @@ | ||
98 | 98 | new |
99 | 99 | let b = bufnr('%') |
100 | 100 | hide |
101 | + | |
102 | + new | |
103 | + call setline(1, ['line1', 'line2', 'line3']) | |
104 | + normal! 2gggg | |
105 | + call assert_equal(2, line("''")) | |
106 | + | |
101 | 107 | call assert_equal(0, appendbufline(b, 0, ['foo', 'bar'])) |
102 | 108 | call assert_equal(['foo'], getbufline(b, 1)) |
103 | 109 | call assert_equal(['bar'], getbufline(b, 2)) |
104 | 110 | call assert_equal(['foo', 'bar'], getbufline(b, 1, 2)) |
111 | + call assert_equal(0, appendbufline(b, 0, 'baz')) | |
112 | + call assert_equal(['baz', 'foo', 'bar'], getbufline(b, 1, 3)) | |
113 | + | |
114 | + " appendbufline() in a hidden buffer shouldn't move marks in current window. | |
115 | + call assert_equal(2, line("''")) | |
116 | + bwipe! | |
117 | + | |
105 | 118 | exe "bd!" b |
106 | - call assert_equal([], getbufline(b, 1, 2)) | |
119 | + call assert_equal([], getbufline(b, 1, 3)) | |
107 | 120 | |
108 | 121 | split Xtest |
109 | 122 | call setline(1, ['a', 'b', 'c']) |
@@ -173,10 +186,21 @@ | ||
173 | 186 | let b = bufnr('%') |
174 | 187 | call setline(1, ['aaa', 'bbb', 'ccc']) |
175 | 188 | hide |
189 | + | |
190 | + new | |
191 | + call setline(1, ['line1', 'line2', 'line3']) | |
192 | + normal! 2gggg | |
193 | + call assert_equal(2, line("''")) | |
194 | + | |
176 | 195 | call assert_equal(0, deletebufline(b, 2)) |
177 | 196 | call assert_equal(['aaa', 'ccc'], getbufline(b, 1, 2)) |
178 | 197 | call assert_equal(0, deletebufline(b, 2, 8)) |
179 | 198 | call assert_equal(['aaa'], getbufline(b, 1, 2)) |
199 | + | |
200 | + " deletebufline() in a hidden buffer shouldn't move marks in current window. | |
201 | + call assert_equal(2, line("''")) | |
202 | + bwipe! | |
203 | + | |
180 | 204 | exe "bd!" b |
181 | 205 | call assert_equal(1, b->deletebufline(1)) |
182 | 206 |
@@ -696,6 +696,8 @@ | ||
696 | 696 | static int included_patches[] = |
697 | 697 | { /* Add new patch number below this line */ |
698 | 698 | /**/ |
699 | + 914, | |
700 | +/**/ | |
699 | 701 | 913, |
700 | 702 | /**/ |
701 | 703 | 912, |