Mercurial > vim
comparison src/textprop.c @ 29788:d08aa1bfe319 v9.0.0233
patch 9.0.0233: removing multiple text properties takes many calls
Commit: https://github.com/vim/vim/commit/a7704226a26b95b15bf87d3a3a5128e23e4aaa06
Author: Ben Jackson <puremourning@gmail.com>
Date: Sat Aug 20 20:54:51 2022 +0100
patch 9.0.0233: removing multiple text properties takes many calls
Problem: Removing multiple text properties takes many calls.
Solution: Pass a list to prop_remove(). (Ben Jackson, closes https://github.com/vim/vim/issues/10945)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 20 Aug 2022 22:00:03 +0200 |
parents | 7e2321707fea |
children | bbe62ea78aac |
comparison
equal
deleted
inserted
replaced
29787:f3901ba52a12 | 29788:d08aa1bfe319 |
---|---|
1008 emsg(_(e_need_at_least_one_of_id_or_type)); | 1008 emsg(_(e_need_at_least_one_of_id_or_type)); |
1009 return; | 1009 return; |
1010 } | 1010 } |
1011 if (both && (!id_found || type_id == -1)) | 1011 if (both && (!id_found || type_id == -1)) |
1012 { | 1012 { |
1013 emsg(_(e_need_id_and_type_with_both)); | 1013 emsg(_(e_need_id_and_type_or_types_with_both)); |
1014 return; | 1014 return; |
1015 } | 1015 } |
1016 | 1016 |
1017 lnum_start = lnum; | 1017 lnum_start = lnum; |
1018 | 1018 |
1376 linenr_T last_changed = 0; | 1376 linenr_T last_changed = 0; |
1377 dict_T *dict; | 1377 dict_T *dict; |
1378 buf_T *buf = curbuf; | 1378 buf_T *buf = curbuf; |
1379 int do_all; | 1379 int do_all; |
1380 int id = -MAXCOL; | 1380 int id = -MAXCOL; |
1381 int type_id = -1; | 1381 int type_id = -1; // for a single "type" |
1382 int *type_ids = NULL; // array, for a list of "types", allocated | |
1383 int num_type_ids = 0; // number of elements in "type_ids" | |
1382 int both; | 1384 int both; |
1383 int did_remove_text = FALSE; | 1385 int did_remove_text = FALSE; |
1384 | 1386 |
1385 rettv->vval.v_number = 0; | 1387 rettv->vval.v_number = 0; |
1386 | 1388 |
1418 | 1420 |
1419 do_all = dict_get_bool(dict, "all", FALSE); | 1421 do_all = dict_get_bool(dict, "all", FALSE); |
1420 | 1422 |
1421 if (dict_has_key(dict, "id")) | 1423 if (dict_has_key(dict, "id")) |
1422 id = dict_get_number(dict, "id"); | 1424 id = dict_get_number(dict, "id"); |
1425 | |
1426 // if a specific type was supplied "type": check that (and ignore "types". | |
1427 // Otherwise check against the list of "types". | |
1423 if (dict_has_key(dict, "type")) | 1428 if (dict_has_key(dict, "type")) |
1424 { | 1429 { |
1425 char_u *name = dict_get_string(dict, "type", FALSE); | 1430 char_u *name = dict_get_string(dict, "type", FALSE); |
1426 proptype_T *type = lookup_prop_type(name, buf); | 1431 proptype_T *type = lookup_prop_type(name, buf); |
1427 | 1432 |
1428 if (type == NULL) | 1433 if (type == NULL) |
1429 return; | 1434 return; |
1430 type_id = type->pt_id; | 1435 type_id = type->pt_id; |
1431 } | 1436 } |
1437 if (dict_has_key(dict, "types")) | |
1438 { | |
1439 typval_T types; | |
1440 listitem_T *li = NULL; | |
1441 | |
1442 dict_get_tv(dict, "types", &types); | |
1443 if (types.v_type == VAR_LIST && types.vval.v_list->lv_len > 0) | |
1444 { | |
1445 type_ids = alloc( sizeof(int) * types.vval.v_list->lv_len ); | |
1446 | |
1447 FOR_ALL_LIST_ITEMS(types.vval.v_list, li) | |
1448 { | |
1449 proptype_T *prop_type; | |
1450 | |
1451 if (li->li_tv.v_type != VAR_STRING) | |
1452 continue; | |
1453 | |
1454 prop_type = lookup_prop_type(li->li_tv.vval.v_string, buf); | |
1455 | |
1456 if (!prop_type) | |
1457 goto cleanup_prop_remove; | |
1458 | |
1459 type_ids[num_type_ids++] = prop_type->pt_id; | |
1460 } | |
1461 } | |
1462 } | |
1432 both = dict_get_bool(dict, "both", FALSE); | 1463 both = dict_get_bool(dict, "both", FALSE); |
1433 | 1464 |
1434 if (id == -MAXCOL && type_id == -1) | 1465 if (id == -MAXCOL && (type_id == -1 && num_type_ids == 0)) |
1435 { | 1466 { |
1436 emsg(_(e_need_at_least_one_of_id_or_type)); | 1467 emsg(_(e_need_at_least_one_of_id_or_type)); |
1437 return; | 1468 goto cleanup_prop_remove; |
1438 } | 1469 } |
1439 if (both && (id == -MAXCOL || type_id == -1)) | 1470 if (both && (id == -MAXCOL || (type_id == -1 && num_type_ids == 0))) |
1440 { | 1471 { |
1441 emsg(_(e_need_id_and_type_with_both)); | 1472 emsg(_(e_need_id_and_type_or_types_with_both)); |
1442 return; | 1473 goto cleanup_prop_remove; |
1474 } | |
1475 if (type_id != -1 && num_type_ids > 0) | |
1476 { | |
1477 emsg(_(e_cannot_specify_both_type_and_types)); | |
1478 goto cleanup_prop_remove; | |
1443 } | 1479 } |
1444 | 1480 |
1445 if (end == 0) | 1481 if (end == 0) |
1446 end = buf->b_ml.ml_line_count; | 1482 end = buf->b_ml.ml_line_count; |
1447 for (lnum = start; lnum <= end; ++lnum) | 1483 for (lnum = start; lnum <= end; ++lnum) |
1462 / sizeof(textprop_T); ++idx) | 1498 / sizeof(textprop_T); ++idx) |
1463 { | 1499 { |
1464 char_u *cur_prop = buf->b_ml.ml_line_ptr + len | 1500 char_u *cur_prop = buf->b_ml.ml_line_ptr + len |
1465 + idx * sizeof(textprop_T); | 1501 + idx * sizeof(textprop_T); |
1466 size_t taillen; | 1502 size_t taillen; |
1503 int matches_id = 0; | |
1504 int matches_type = 0; | |
1467 | 1505 |
1468 mch_memmove(&textprop, cur_prop, sizeof(textprop_T)); | 1506 mch_memmove(&textprop, cur_prop, sizeof(textprop_T)); |
1469 if (both ? textprop.tp_id == id && textprop.tp_type == type_id | 1507 |
1470 : textprop.tp_id == id || textprop.tp_type == type_id) | 1508 matches_id = textprop.tp_id == id; |
1509 if (num_type_ids > 0) | |
1510 { | |
1511 int idx2; | |
1512 | |
1513 for (idx2 = 0; !matches_type && idx2 < num_type_ids; ++idx2) | |
1514 matches_type = textprop.tp_type == type_ids[idx2]; | |
1515 } | |
1516 else | |
1517 { | |
1518 matches_type = textprop.tp_type == type_id; | |
1519 } | |
1520 | |
1521 if (both ? matches_id && matches_type | |
1522 : matches_id || matches_type) | |
1471 { | 1523 { |
1472 if (!(buf->b_ml.ml_flags & ML_LINE_DIRTY)) | 1524 if (!(buf->b_ml.ml_flags & ML_LINE_DIRTY)) |
1473 { | 1525 { |
1474 char_u *newptr = alloc(buf->b_ml.ml_line_len); | 1526 char_u *newptr = alloc(buf->b_ml.ml_line_len); |
1475 | 1527 |
1476 // need to allocate the line to be able to change it | 1528 // need to allocate the line to be able to change it |
1477 if (newptr == NULL) | 1529 if (newptr == NULL) |
1478 return; | 1530 goto cleanup_prop_remove; |
1479 mch_memmove(newptr, buf->b_ml.ml_line_ptr, | 1531 mch_memmove(newptr, buf->b_ml.ml_line_ptr, |
1480 buf->b_ml.ml_line_len); | 1532 buf->b_ml.ml_line_len); |
1481 if (buf->b_ml.ml_flags & ML_ALLOCATED) | 1533 if (buf->b_ml.ml_flags & ML_ALLOCATED) |
1482 vim_free(buf->b_ml.ml_line_ptr); | 1534 vim_free(buf->b_ml.ml_line_ptr); |
1483 buf->b_ml.ml_line_ptr = newptr; | 1535 buf->b_ml.ml_line_ptr = newptr; |
1535 // Reduce the growarray size for NULL pointers at the end. | 1587 // Reduce the growarray size for NULL pointers at the end. |
1536 while (gap->ga_len > 0 | 1588 while (gap->ga_len > 0 |
1537 && ((char_u **)gap->ga_data)[gap->ga_len - 1] == NULL) | 1589 && ((char_u **)gap->ga_data)[gap->ga_len - 1] == NULL) |
1538 --gap->ga_len; | 1590 --gap->ga_len; |
1539 } | 1591 } |
1592 | |
1593 cleanup_prop_remove: | |
1594 vim_free(type_ids); | |
1540 } | 1595 } |
1541 | 1596 |
1542 /* | 1597 /* |
1543 * Common for f_prop_type_add() and f_prop_type_change(). | 1598 * Common for f_prop_type_add() and f_prop_type_change(). |
1544 */ | 1599 */ |