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 */