Mercurial > vim
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); |