|
1 To: [email protected] |
|
2 Subject: Patch 7.2.080 |
|
3 Fcc: outbox |
|
4 From: Bram Moolenaar <[email protected]> |
|
5 Mime-Version: 1.0 |
|
6 Content-Type: text/plain; charset=ISO-8859-1 |
|
7 Content-Transfer-Encoding: 8bit |
|
8 ------------ |
|
9 |
|
10 Patch 7.2.080 |
|
11 Problem: When typing a composing character just after starting completion |
|
12 may access memory before its allocation point. (Dominique Pelle) |
|
13 Solution: Don't delete before the completion start column. Add extra checks |
|
14 for the offset not being negative. |
|
15 Files: src/edit.c |
|
16 |
|
17 |
|
18 *** ../vim-7.2.079/src/edit.c Wed Aug 6 18:56:55 2008 |
|
19 --- src/edit.c Tue Jan 13 12:05:57 2009 |
|
20 *************** |
|
21 *** 147,152 **** |
|
22 --- 147,153 ---- |
|
23 static int ins_compl_bs __ARGS((void)); |
|
24 static void ins_compl_new_leader __ARGS((void)); |
|
25 static void ins_compl_addleader __ARGS((int c)); |
|
26 + static int ins_compl_len __ARGS((void)); |
|
27 static void ins_compl_restart __ARGS((void)); |
|
28 static void ins_compl_set_original_text __ARGS((char_u *str)); |
|
29 static void ins_compl_addfrommatch __ARGS((void)); |
|
30 *************** |
|
31 *** 197,203 **** |
|
32 static void mb_replace_pop_ins __ARGS((int cc)); |
|
33 #endif |
|
34 static void replace_flush __ARGS((void)); |
|
35 ! static void replace_do_bs __ARGS((void)); |
|
36 #ifdef FEAT_CINDENT |
|
37 static int cindent_on __ARGS((void)); |
|
38 #endif |
|
39 --- 198,205 ---- |
|
40 static void mb_replace_pop_ins __ARGS((int cc)); |
|
41 #endif |
|
42 static void replace_flush __ARGS((void)); |
|
43 ! static void replace_do_bs __ARGS((int limit_col)); |
|
44 ! static int del_char_after_col __ARGS((int limit_col)); |
|
45 #ifdef FEAT_CINDENT |
|
46 static int cindent_on __ARGS((void)); |
|
47 #endif |
|
48 *************** |
|
49 *** 1933,1938 **** |
|
50 --- 1935,1942 ---- |
|
51 /* |
|
52 * Backspace the cursor until the given column. Handles REPLACE and VREPLACE |
|
53 * modes correctly. May also be used when not in insert mode at all. |
|
54 + * Will attempt not to go before "col" even when there is a composing |
|
55 + * character. |
|
56 */ |
|
57 void |
|
58 backspace_until_column(col) |
|
59 *************** |
|
60 *** 1942,1954 **** |
|
61 { |
|
62 curwin->w_cursor.col--; |
|
63 if (State & REPLACE_FLAG) |
|
64 ! replace_do_bs(); |
|
65 ! else |
|
66 ! (void)del_char(FALSE); |
|
67 } |
|
68 } |
|
69 #endif |
|
70 |
|
71 #if defined(FEAT_INS_EXPAND) || defined(PROTO) |
|
72 /* |
|
73 * CTRL-X pressed in Insert mode. |
|
74 --- 1946,1994 ---- |
|
75 { |
|
76 curwin->w_cursor.col--; |
|
77 if (State & REPLACE_FLAG) |
|
78 ! replace_do_bs(col); |
|
79 ! else if (!del_char_after_col(col)) |
|
80 ! break; |
|
81 } |
|
82 } |
|
83 #endif |
|
84 |
|
85 + /* |
|
86 + * Like del_char(), but make sure not to go before column "limit_col". |
|
87 + * Only matters when there are composing characters. |
|
88 + * Return TRUE when something was deleted. |
|
89 + */ |
|
90 + static int |
|
91 + del_char_after_col(limit_col) |
|
92 + int limit_col; |
|
93 + { |
|
94 + #ifdef FEAT_MBYTE |
|
95 + if (enc_utf8 && limit_col >= 0) |
|
96 + { |
|
97 + int ecol = curwin->w_cursor.col + 1; |
|
98 + |
|
99 + /* Make sure the cursor is at the start of a character, but |
|
100 + * skip forward again when going too far back because of a |
|
101 + * composing character. */ |
|
102 + mb_adjust_cursor(); |
|
103 + while (curwin->w_cursor.col < limit_col) |
|
104 + { |
|
105 + int l = utf_ptr2len(ml_get_cursor()); |
|
106 + |
|
107 + if (l == 0) /* end of line */ |
|
108 + break; |
|
109 + curwin->w_cursor.col += l; |
|
110 + } |
|
111 + if (*ml_get_cursor() == NUL || curwin->w_cursor.col == ecol) |
|
112 + return FALSE; |
|
113 + del_bytes((long)(ecol - curwin->w_cursor.col), FALSE, TRUE); |
|
114 + } |
|
115 + else |
|
116 + #endif |
|
117 + (void)del_char(FALSE); |
|
118 + return TRUE; |
|
119 + } |
|
120 + |
|
121 #if defined(FEAT_INS_EXPAND) || defined(PROTO) |
|
122 /* |
|
123 * CTRL-X pressed in Insert mode. |
|
124 *************** |
|
125 *** 2418,2424 **** |
|
126 { |
|
127 had_match = (curwin->w_cursor.col > compl_col); |
|
128 ins_compl_delete(); |
|
129 ! ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); |
|
130 ins_redraw(FALSE); |
|
131 |
|
132 /* When the match isn't there (to avoid matching itself) remove it |
|
133 --- 2458,2464 ---- |
|
134 { |
|
135 had_match = (curwin->w_cursor.col > compl_col); |
|
136 ins_compl_delete(); |
|
137 ! ins_bytes(compl_leader + ins_compl_len()); |
|
138 ins_redraw(FALSE); |
|
139 |
|
140 /* When the match isn't there (to avoid matching itself) remove it |
|
141 *************** |
|
142 *** 2470,2476 **** |
|
143 *p = NUL; |
|
144 had_match = (curwin->w_cursor.col > compl_col); |
|
145 ins_compl_delete(); |
|
146 ! ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); |
|
147 ins_redraw(FALSE); |
|
148 |
|
149 /* When the match isn't there (to avoid matching itself) remove it |
|
150 --- 2510,2516 ---- |
|
151 *p = NUL; |
|
152 had_match = (curwin->w_cursor.col > compl_col); |
|
153 ins_compl_delete(); |
|
154 ! ins_bytes(compl_leader + ins_compl_len()); |
|
155 ins_redraw(FALSE); |
|
156 |
|
157 /* When the match isn't there (to avoid matching itself) remove it |
|
158 *************** |
|
159 *** 3209,3215 **** |
|
160 { |
|
161 ins_compl_del_pum(); |
|
162 ins_compl_delete(); |
|
163 ! ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); |
|
164 compl_used_match = FALSE; |
|
165 |
|
166 if (compl_started) |
|
167 --- 3249,3255 ---- |
|
168 { |
|
169 ins_compl_del_pum(); |
|
170 ins_compl_delete(); |
|
171 ! ins_bytes(compl_leader + ins_compl_len()); |
|
172 compl_used_match = FALSE; |
|
173 |
|
174 if (compl_started) |
|
175 *************** |
|
176 *** 3264,3269 **** |
|
177 --- 3304,3323 ---- |
|
178 } |
|
179 |
|
180 /* |
|
181 + * Return the length of the completion, from the completion start column to |
|
182 + * the cursor column. Making sure it never goes below zero. |
|
183 + */ |
|
184 + static int |
|
185 + ins_compl_len() |
|
186 + { |
|
187 + int off = curwin->w_cursor.col - compl_col; |
|
188 + |
|
189 + if (off < 0) |
|
190 + return 0; |
|
191 + return off; |
|
192 + } |
|
193 + |
|
194 + /* |
|
195 * Append one character to the match leader. May reduce the number of |
|
196 * matches. |
|
197 */ |
|
198 *************** |
|
199 *** 3621,3630 **** |
|
200 { |
|
201 ins_compl_delete(); |
|
202 if (compl_leader != NULL) |
|
203 ! ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); |
|
204 else if (compl_first_match != NULL) |
|
205 ! ins_bytes(compl_orig_text |
|
206 ! + curwin->w_cursor.col - compl_col); |
|
207 retval = TRUE; |
|
208 } |
|
209 |
|
210 --- 3675,3683 ---- |
|
211 { |
|
212 ins_compl_delete(); |
|
213 if (compl_leader != NULL) |
|
214 ! ins_bytes(compl_leader + ins_compl_len()); |
|
215 else if (compl_first_match != NULL) |
|
216 ! ins_bytes(compl_orig_text + ins_compl_len()); |
|
217 retval = TRUE; |
|
218 } |
|
219 |
|
220 *************** |
|
221 *** 4256,4262 **** |
|
222 static void |
|
223 ins_compl_insert() |
|
224 { |
|
225 ! ins_bytes(compl_shown_match->cp_str + curwin->w_cursor.col - compl_col); |
|
226 if (compl_shown_match->cp_flags & ORIGINAL_TEXT) |
|
227 compl_used_match = FALSE; |
|
228 else |
|
229 --- 4309,4315 ---- |
|
230 static void |
|
231 ins_compl_insert() |
|
232 { |
|
233 ! ins_bytes(compl_shown_match->cp_str + ins_compl_len()); |
|
234 if (compl_shown_match->cp_flags & ORIGINAL_TEXT) |
|
235 compl_used_match = FALSE; |
|
236 else |
|
237 *************** |
|
238 *** 4425,4431 **** |
|
239 if (!compl_get_longest || compl_used_match) |
|
240 ins_compl_insert(); |
|
241 else |
|
242 ! ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); |
|
243 } |
|
244 else |
|
245 compl_used_match = FALSE; |
|
246 --- 4478,4484 ---- |
|
247 if (!compl_get_longest || compl_used_match) |
|
248 ins_compl_insert(); |
|
249 else |
|
250 ! ins_bytes(compl_leader + ins_compl_len()); |
|
251 } |
|
252 else |
|
253 compl_used_match = FALSE; |
|
254 *************** |
|
255 *** 7123,7131 **** |
|
256 * cc == 0: character was inserted, delete it |
|
257 * cc > 0: character was replaced, put cc (first byte of original char) back |
|
258 * and check for more characters to be put back |
|
259 */ |
|
260 static void |
|
261 ! replace_do_bs() |
|
262 { |
|
263 int cc; |
|
264 #ifdef FEAT_VREPLACE |
|
265 --- 7176,7187 ---- |
|
266 * cc == 0: character was inserted, delete it |
|
267 * cc > 0: character was replaced, put cc (first byte of original char) back |
|
268 * and check for more characters to be put back |
|
269 + * When "limit_col" is >= 0, don't delete before this column. Matters when |
|
270 + * using composing characters, use del_char_after_col() instead of del_char(). |
|
271 */ |
|
272 static void |
|
273 ! replace_do_bs(limit_col) |
|
274 ! int limit_col; |
|
275 { |
|
276 int cc; |
|
277 #ifdef FEAT_VREPLACE |
|
278 *************** |
|
279 *** 7153,7159 **** |
|
280 #ifdef FEAT_MBYTE |
|
281 if (has_mbyte) |
|
282 { |
|
283 ! del_char(FALSE); |
|
284 # ifdef FEAT_VREPLACE |
|
285 if (State & VREPLACE_FLAG) |
|
286 orig_len = (int)STRLEN(ml_get_cursor()); |
|
287 --- 7209,7215 ---- |
|
288 #ifdef FEAT_MBYTE |
|
289 if (has_mbyte) |
|
290 { |
|
291 ! (void)del_char_after_col(limit_col); |
|
292 # ifdef FEAT_VREPLACE |
|
293 if (State & VREPLACE_FLAG) |
|
294 orig_len = (int)STRLEN(ml_get_cursor()); |
|
295 *************** |
|
296 *** 7203,7209 **** |
|
297 changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); |
|
298 } |
|
299 else if (cc == 0) |
|
300 ! (void)del_char(FALSE); |
|
301 } |
|
302 |
|
303 #ifdef FEAT_CINDENT |
|
304 --- 7259,7265 ---- |
|
305 changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); |
|
306 } |
|
307 else if (cc == 0) |
|
308 ! (void)del_char_after_col(limit_col); |
|
309 } |
|
310 |
|
311 #ifdef FEAT_CINDENT |
|
312 *************** |
|
313 *** 8239,8245 **** |
|
314 * Replace mode */ |
|
315 if (curwin->w_cursor.lnum != Insstart.lnum |
|
316 || curwin->w_cursor.col >= Insstart.col) |
|
317 ! replace_do_bs(); |
|
318 } |
|
319 else |
|
320 (void)del_char(FALSE); |
|
321 --- 8295,8301 ---- |
|
322 * Replace mode */ |
|
323 if (curwin->w_cursor.lnum != Insstart.lnum |
|
324 || curwin->w_cursor.col >= Insstart.col) |
|
325 ! replace_do_bs(-1); |
|
326 } |
|
327 else |
|
328 (void)del_char(FALSE); |
|
329 *************** |
|
330 *** 8556,8562 **** |
|
331 break; |
|
332 } |
|
333 if (State & REPLACE_FLAG) |
|
334 ! replace_do_bs(); |
|
335 else |
|
336 { |
|
337 #ifdef FEAT_MBYTE |
|
338 --- 8612,8618 ---- |
|
339 break; |
|
340 } |
|
341 if (State & REPLACE_FLAG) |
|
342 ! replace_do_bs(-1); |
|
343 else |
|
344 { |
|
345 #ifdef FEAT_MBYTE |
|
346 *** ../vim-7.2.079/src/version.c Tue Jan 6 16:13:42 2009 |
|
347 --- src/version.c Tue Jan 13 12:25:29 2009 |
|
348 *************** |
|
349 *** 678,679 **** |
|
350 --- 678,681 ---- |
|
351 { /* Add new patch number below this line */ |
|
352 + /**/ |
|
353 + 80, |
|
354 /**/ |
|
355 |
|
356 -- |
|
357 At some point in the project somebody will start whining about the need to |
|
358 determine the project "requirements". This involves interviewing people who |
|
359 don't know what they want but, curiously, know exactly when they need it. |
|
360 (Scott Adams - The Dilbert principle) |
|
361 |
|
362 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\ |
|
363 /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ |
|
364 \\\ download, build and distribute -- http://www.A-A-P.org /// |
|
365 \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |