Mercurial > vim
comparison src/textprop.c @ 29552:89a97f70e8eb v9.0.0117
patch 9.0.0117: text of removed textprop with text is not freed
Commit: https://github.com/vim/vim/commit/3a4cd39d476474e20e88ebf120ca6070cc0d0072
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jul 30 22:17:18 2022 +0100
patch 9.0.0117: text of removed textprop with text is not freed
Problem: Text of removed textprop with text is not freed.
Solution: Free the text when the property is removed. Reduce the array size
to ignore NULLs at the end.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 30 Jul 2022 23:30:05 +0200 |
parents | 057c26b5c33a |
children | 14b139cbec49 |
comparison
equal
deleted
inserted
replaced
29551:79f45796181b | 29552:89a97f70e8eb |
---|---|
1231 linenr_T first_changed = 0; | 1231 linenr_T first_changed = 0; |
1232 linenr_T last_changed = 0; | 1232 linenr_T last_changed = 0; |
1233 dict_T *dict; | 1233 dict_T *dict; |
1234 buf_T *buf = curbuf; | 1234 buf_T *buf = curbuf; |
1235 int do_all; | 1235 int do_all; |
1236 int id = -1; | 1236 int id = -MAXCOL; |
1237 int type_id = -1; | 1237 int type_id = -1; |
1238 int both; | 1238 int both; |
1239 int did_remove_text = FALSE; | |
1239 | 1240 |
1240 rettv->vval.v_number = 0; | 1241 rettv->vval.v_number = 0; |
1241 | 1242 |
1242 if (in_vim9script() | 1243 if (in_vim9script() |
1243 && (check_for_dict_arg(argvars, 0) == FAIL | 1244 && (check_for_dict_arg(argvars, 0) == FAIL |
1284 return; | 1285 return; |
1285 type_id = type->pt_id; | 1286 type_id = type->pt_id; |
1286 } | 1287 } |
1287 both = dict_get_bool(dict, "both", FALSE); | 1288 both = dict_get_bool(dict, "both", FALSE); |
1288 | 1289 |
1289 if (id == -1 && type_id == -1) | 1290 if (id == -MAXCOL && type_id == -1) |
1290 { | 1291 { |
1291 emsg(_(e_need_at_least_one_of_id_or_type)); | 1292 emsg(_(e_need_at_least_one_of_id_or_type)); |
1292 return; | 1293 return; |
1293 } | 1294 } |
1294 if (both && (id == -1 || type_id == -1)) | 1295 if (both && (id == -MAXCOL || type_id == -1)) |
1295 { | 1296 { |
1296 emsg(_(e_need_id_and_type_with_both)); | 1297 emsg(_(e_need_id_and_type_with_both)); |
1297 return; | 1298 return; |
1298 } | 1299 } |
1299 | 1300 |
1348 mch_memmove(cur_prop, cur_prop + sizeof(textprop_T), | 1349 mch_memmove(cur_prop, cur_prop + sizeof(textprop_T), |
1349 taillen); | 1350 taillen); |
1350 buf->b_ml.ml_line_len -= sizeof(textprop_T); | 1351 buf->b_ml.ml_line_len -= sizeof(textprop_T); |
1351 --idx; | 1352 --idx; |
1352 | 1353 |
1354 if (textprop.tp_id < 0) | |
1355 { | |
1356 garray_T *gap = &buf->b_textprop_text; | |
1357 int ii = -textprop.tp_id - 1; | |
1358 | |
1359 // negative ID: property with text - free the text | |
1360 if (ii < gap->ga_len) | |
1361 { | |
1362 char_u **p = ((char_u **)gap->ga_data) + ii; | |
1363 vim_free(*p); | |
1364 *p = NULL; | |
1365 did_remove_text = TRUE; | |
1366 } | |
1367 } | |
1368 | |
1353 if (first_changed == 0) | 1369 if (first_changed == 0) |
1354 first_changed = lnum; | 1370 first_changed = lnum; |
1355 last_changed = lnum; | 1371 last_changed = lnum; |
1356 ++rettv->vval.v_number; | 1372 ++rettv->vval.v_number; |
1357 if (!do_all) | 1373 if (!do_all) |
1358 break; | 1374 break; |
1359 } | 1375 } |
1360 } | 1376 } |
1361 } | 1377 } |
1362 } | 1378 } |
1379 | |
1363 if (first_changed > 0) | 1380 if (first_changed > 0) |
1364 { | 1381 { |
1365 changed_lines_buf(buf, first_changed, last_changed + 1, 0); | 1382 changed_lines_buf(buf, first_changed, last_changed + 1, 0); |
1366 redraw_buf_later(buf, VALID); | 1383 redraw_buf_later(buf, VALID); |
1384 } | |
1385 | |
1386 if (did_remove_text) | |
1387 { | |
1388 garray_T *gap = &buf->b_textprop_text; | |
1389 | |
1390 // Reduce the growarray size for NULL pointers at the end. | |
1391 while (gap->ga_len > 0 | |
1392 && ((char_u **)gap->ga_data)[gap->ga_len - 1] == NULL) | |
1393 --gap->ga_len; | |
1367 } | 1394 } |
1368 } | 1395 } |
1369 | 1396 |
1370 /* | 1397 /* |
1371 * Common for f_prop_type_add() and f_prop_type_change(). | 1398 * Common for f_prop_type_add() and f_prop_type_change(). |