comparison src/textprop.c @ 19534:36ec10251b2b v8.2.0324

patch 8.2.0324: text property not updated correctly when inserting/deleting Commit: https://github.com/vim/vim/commit/12f20038714928bfecdeee31ed1f927324542034 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Feb 26 22:06:00 2020 +0100 patch 8.2.0324: text property not updated correctly when inserting/deleting Problem: Text property not updated correctly when inserting/deleting. Solution: Use the right column when deleting. Make zero-width text properties respect start_incl and end_incl. (Axel Forsman, closes #5696, closes #5679)
author Bram Moolenaar <Bram@vim.org>
date Wed, 26 Feb 2020 22:15:04 +0100
parents 91bb12995034
children 67f39cb0a49c
comparison
equal deleted inserted replaced
19533:ffe25b424609 19534:36ec10251b2b
1230 int bytes_added, 1230 int bytes_added,
1231 int flags) 1231 int flags)
1232 { 1232 {
1233 int proplen; 1233 int proplen;
1234 char_u *props; 1234 char_u *props;
1235 textprop_T tmp_prop;
1236 proptype_T *pt; 1235 proptype_T *pt;
1237 int dirty = FALSE; 1236 int dirty = FALSE;
1238 int ri, wi; 1237 int ri, wi;
1239 size_t textlen; 1238 size_t textlen;
1240 1239
1247 textlen = curbuf->b_ml.ml_line_len - proplen * sizeof(textprop_T); 1246 textlen = curbuf->b_ml.ml_line_len - proplen * sizeof(textprop_T);
1248 1247
1249 wi = 0; // write index 1248 wi = 0; // write index
1250 for (ri = 0; ri < proplen; ++ri) 1249 for (ri = 0; ri < proplen; ++ri)
1251 { 1250 {
1252 int start_incl; 1251 textprop_T prop;
1253 1252 int start_incl, end_incl;
1254 mch_memmove(&tmp_prop, props + ri * sizeof(textprop_T), 1253 int can_drop;
1255 sizeof(textprop_T)); 1254
1256 pt = text_prop_type_by_id(curbuf, tmp_prop.tp_type); 1255 mch_memmove(&prop, props + ri * sizeof(textprop_T), sizeof(textprop_T));
1257 start_incl = (flags & APC_SUBSTITUTE) || 1256 pt = text_prop_type_by_id(curbuf, prop.tp_type);
1258 (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL)); 1257 start_incl = (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL))
1259 1258 || (flags & APC_SUBSTITUTE);
1260 if (bytes_added > 0 1259 end_incl = (pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL));
1261 && (tmp_prop.tp_col >= col + (start_incl ? 2 : 1))) 1260 // Do not drop zero-width props if they later can increase in size
1262 { 1261 can_drop = !(start_incl || end_incl);
1263 tmp_prop.tp_col += bytes_added; 1262
1263 if (bytes_added > 0)
1264 {
1265 if (col + 1 <= prop.tp_col
1266 - (start_incl || (prop.tp_len == 0 && end_incl)))
1267 {
1268 // Change is entirely before the text property: Only shift
1269 prop.tp_col += bytes_added;
1270 // Save for undo if requested and not done yet.
1271 if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
1272 u_savesub(lnum);
1273 dirty = TRUE;
1274 }
1275 else if (col + 1 < prop.tp_col + prop.tp_len + end_incl)
1276 {
1277 // Insertion was inside text property
1278 prop.tp_len += bytes_added;
1279 // Save for undo if requested and not done yet.
1280 if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
1281 u_savesub(lnum);
1282 dirty = TRUE;
1283 }
1284 }
1285 else if (prop.tp_col > col + 1)
1286 {
1287 int len_changed = FALSE;
1288
1289 if (prop.tp_col + bytes_added < col + 1)
1290 {
1291 prop.tp_len += (prop.tp_col - 1 - col) + bytes_added;
1292 prop.tp_col = col + 1;
1293 len_changed = TRUE;
1294 }
1295 else
1296 prop.tp_col += bytes_added;
1264 // Save for undo if requested and not done yet. 1297 // Save for undo if requested and not done yet.
1265 if ((flags & APC_SAVE_FOR_UNDO) && !dirty) 1298 if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
1266 u_savesub(lnum); 1299 u_savesub(lnum);
1267 dirty = TRUE; 1300 dirty = TRUE;
1268 } 1301 if (len_changed && prop.tp_len <= 0)
1269 else if (bytes_added <= 0 && (tmp_prop.tp_col > col + 1))
1270 {
1271 int len_changed = FALSE;
1272
1273 if (tmp_prop.tp_col + bytes_added < col + 1)
1274 { 1302 {
1275 tmp_prop.tp_len += (tmp_prop.tp_col - 1 - col) + bytes_added; 1303 prop.tp_len = 0;
1276 tmp_prop.tp_col = col + 1; 1304 if (can_drop)
1277 len_changed = TRUE; 1305 continue; // drop this text property
1278 } 1306 }
1307 }
1308 else if (prop.tp_len > 0 && prop.tp_col + prop.tp_len > col)
1309 {
1310 int after = col - bytes_added - (prop.tp_col - 1 + prop.tp_len);
1311
1312 if (after > 0)
1313 prop.tp_len += bytes_added + after;
1279 else 1314 else
1280 tmp_prop.tp_col += bytes_added; 1315 prop.tp_len += bytes_added;
1281 // Save for undo if requested and not done yet. 1316 // Save for undo if requested and not done yet.
1282 if ((flags & APC_SAVE_FOR_UNDO) && !dirty) 1317 if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
1283 u_savesub(lnum); 1318 u_savesub(lnum);
1284 dirty = TRUE; 1319 dirty = TRUE;
1285 if (len_changed && tmp_prop.tp_len <= 0) 1320 if (prop.tp_len <= 0 && can_drop)
1286 continue; // drop this text property 1321 continue; // drop this text property
1287 } 1322 }
1288 else if (tmp_prop.tp_len > 0 1323
1289 && tmp_prop.tp_col + tmp_prop.tp_len > col 1324 mch_memmove(props + wi * sizeof(textprop_T), &prop, sizeof(textprop_T));
1290 + ((pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL))
1291 ? 0 : 1))
1292 {
1293 int after = col - bytes_added
1294 - (tmp_prop.tp_col - 1 + tmp_prop.tp_len);
1295 if (after > 0)
1296 tmp_prop.tp_len += bytes_added + after;
1297 else
1298 tmp_prop.tp_len += bytes_added;
1299 // Save for undo if requested and not done yet.
1300 if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
1301 u_savesub(lnum);
1302 dirty = TRUE;
1303 if (tmp_prop.tp_len <= 0)
1304 continue; // drop this text property
1305 }
1306 mch_memmove(props + wi * sizeof(textprop_T), &tmp_prop,
1307 sizeof(textprop_T));
1308 ++wi; 1325 ++wi;
1309 } 1326 }
1310 if (dirty) 1327 if (dirty)
1311 { 1328 {
1312 colnr_T newlen = (int)textlen + wi * (colnr_T)sizeof(textprop_T); 1329 colnr_T newlen = (int)textlen + wi * (colnr_T)sizeof(textprop_T);