Mercurial > vim
comparison src/memline.c @ 15292:ba6f0f1bb9d0 v8.1.0654
patch 8.1.0654: when deleting a line text property flags are not adjusted
commit https://github.com/vim/vim/commit/c1a9bc1a7284bd0e60f9bddfef6a4ee733bfc838
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Dec 28 21:59:29 2018 +0100
patch 8.1.0654: when deleting a line text property flags are not adjusted
Problem: When deleting a line text property flags are not adjusted.
Solution: Adjust text property flags in preceding and following lines.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 28 Dec 2018 22:00:05 +0100 |
parents | 27783a6f430b |
children | 2d8225cc1315 |
comparison
equal
deleted
inserted
replaced
15291:11c4950be418 | 15292:ba6f0f1bb9d0 |
---|---|
3212 curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; | 3212 curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; |
3213 | 3213 |
3214 return OK; | 3214 return OK; |
3215 } | 3215 } |
3216 | 3216 |
3217 #ifdef FEAT_TEXT_PROP | |
3218 /* | |
3219 * Adjust text properties in line "lnum" for a deleted line. | |
3220 * When "above" is true this is the line above the deleted line. | |
3221 * "del_props" are the properties of the deleted line. | |
3222 */ | |
3223 static void | |
3224 adjust_text_props_for_delete( | |
3225 buf_T *buf, | |
3226 linenr_T lnum, | |
3227 char_u *del_props, | |
3228 int del_props_len, | |
3229 int above) | |
3230 { | |
3231 int did_get_line = FALSE; | |
3232 int done_del; | |
3233 int done_this; | |
3234 textprop_T prop_del; | |
3235 textprop_T prop_this; | |
3236 bhdr_T *hp; | |
3237 DATA_BL *dp; | |
3238 int idx; | |
3239 int line_start; | |
3240 long line_size; | |
3241 int this_props_len; | |
3242 char_u *text; | |
3243 size_t textlen; | |
3244 int found; | |
3245 | |
3246 for (done_del = 0; done_del < del_props_len; done_del += sizeof(textprop_T)) | |
3247 { | |
3248 mch_memmove(&prop_del, del_props + done_del, sizeof(textprop_T)); | |
3249 if ((above && (prop_del.tp_flags & TP_FLAG_CONT_PREV) | |
3250 && !(prop_del.tp_flags & TP_FLAG_CONT_NEXT)) | |
3251 || (!above && (prop_del.tp_flags & TP_FLAG_CONT_NEXT) | |
3252 && !(prop_del.tp_flags & TP_FLAG_CONT_PREV))) | |
3253 { | |
3254 if (!did_get_line) | |
3255 { | |
3256 did_get_line = TRUE; | |
3257 if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL) | |
3258 return; | |
3259 | |
3260 dp = (DATA_BL *)(hp->bh_data); | |
3261 idx = lnum - buf->b_ml.ml_locked_low; | |
3262 line_start = ((dp->db_index[idx]) & DB_INDEX_MASK); | |
3263 if (idx == 0) // first line in block, text at the end | |
3264 line_size = dp->db_txt_end - line_start; | |
3265 else | |
3266 line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start; | |
3267 text = (char_u *)dp + line_start; | |
3268 textlen = STRLEN(text) + 1; | |
3269 if ((long)textlen >= line_size) | |
3270 { | |
3271 if (above) | |
3272 internal_error("no text property above deleted line"); | |
3273 else | |
3274 internal_error("no text property below deleted line"); | |
3275 return; | |
3276 } | |
3277 this_props_len = line_size - textlen; | |
3278 } | |
3279 | |
3280 found = FALSE; | |
3281 for (done_this = 0; done_this < this_props_len; done_this += sizeof(textprop_T)) | |
3282 { | |
3283 mch_memmove(&prop_this, text + textlen + done_del, sizeof(textprop_T)); | |
3284 if (prop_del.tp_id == prop_this.tp_id | |
3285 && prop_del.tp_type == prop_this.tp_type) | |
3286 { | |
3287 int flag = above ? TP_FLAG_CONT_NEXT : TP_FLAG_CONT_PREV; | |
3288 | |
3289 found = TRUE; | |
3290 if (prop_this.tp_flags & flag) | |
3291 { | |
3292 prop_this.tp_flags &= ~flag; | |
3293 mch_memmove(text + textlen + done_del, &prop_this, sizeof(textprop_T)); | |
3294 } | |
3295 else if (above) | |
3296 internal_error("text property above deleted line does not continue"); | |
3297 else | |
3298 internal_error("text property below deleted line does not continue"); | |
3299 } | |
3300 } | |
3301 if (!found) | |
3302 { | |
3303 if (above) | |
3304 internal_error("text property above deleted line not found"); | |
3305 else | |
3306 internal_error("text property below deleted line not found"); | |
3307 } | |
3308 | |
3309 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); | |
3310 } | |
3311 } | |
3312 } | |
3313 #endif | |
3314 | |
3217 /* | 3315 /* |
3218 * Delete line "lnum" in the current buffer. | 3316 * Delete line "lnum" in the current buffer. |
3219 * When "message" is TRUE may give a "No lines in buffer" message. | 3317 * When "message" is TRUE may give a "No lines in buffer" message. |
3220 * | 3318 * |
3221 * Check: The caller of this function should probably also call | 3319 * Check: The caller of this function should probably also call |
3243 int stack_idx; | 3341 int stack_idx; |
3244 int text_start; | 3342 int text_start; |
3245 int line_start; | 3343 int line_start; |
3246 long line_size; | 3344 long line_size; |
3247 int i; | 3345 int i; |
3346 int ret = FAIL; | |
3347 #ifdef FEAT_TEXT_PROP | |
3348 char_u *textprop_save = NULL; | |
3349 int textprop_save_len; | |
3350 #endif | |
3248 | 3351 |
3249 if (lnum < 1 || lnum > buf->b_ml.ml_line_count) | 3352 if (lnum < 1 || lnum > buf->b_ml.ml_line_count) |
3250 return FAIL; | 3353 return FAIL; |
3251 | 3354 |
3252 if (lowest_marked && lowest_marked > lnum) | 3355 if (lowest_marked && lowest_marked > lnum) |
3270 | 3373 |
3271 return i; | 3374 return i; |
3272 } | 3375 } |
3273 | 3376 |
3274 /* | 3377 /* |
3275 * find the data block containing the line | 3378 * Find the data block containing the line. |
3276 * This also fills the stack with the blocks from the root to the data block | 3379 * This also fills the stack with the blocks from the root to the data block. |
3277 * This also releases any locked block. | 3380 * This also releases any locked block.. |
3278 */ | 3381 */ |
3279 mfp = buf->b_ml.ml_mfp; | 3382 mfp = buf->b_ml.ml_mfp; |
3280 if (mfp == NULL) | 3383 if (mfp == NULL) |
3281 return FAIL; | 3384 return FAIL; |
3282 | 3385 |
3298 line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start; | 3401 line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start; |
3299 | 3402 |
3300 #ifdef FEAT_NETBEANS_INTG | 3403 #ifdef FEAT_NETBEANS_INTG |
3301 if (netbeans_active()) | 3404 if (netbeans_active()) |
3302 netbeans_removed(buf, lnum, 0, (long)line_size); | 3405 netbeans_removed(buf, lnum, 0, (long)line_size); |
3406 #endif | |
3407 #ifdef FEAT_TEXT_PROP | |
3408 // If there are text properties, make a copy, so that we can update | |
3409 // properties in preceding and following lines. | |
3410 if (buf->b_has_textprop) | |
3411 { | |
3412 size_t textlen = STRLEN((char_u *)dp + line_start) + 1; | |
3413 | |
3414 if ((long)textlen < line_size) | |
3415 { | |
3416 textprop_save_len = line_size - textlen; | |
3417 textprop_save = vim_memsave((char_u *)dp + line_start + textlen, | |
3418 textprop_save_len); | |
3419 } | |
3420 } | |
3303 #endif | 3421 #endif |
3304 | 3422 |
3305 /* | 3423 /* |
3306 * special case: If there is only one line in the data block it becomes empty. | 3424 * special case: If there is only one line in the data block it becomes empty. |
3307 * Then we have to remove the entry, pointing to this data block, from the | 3425 * Then we have to remove the entry, pointing to this data block, from the |
3320 { | 3438 { |
3321 buf->b_ml.ml_stack_top = 0; /* stack is invalid when failing */ | 3439 buf->b_ml.ml_stack_top = 0; /* stack is invalid when failing */ |
3322 ip = &(buf->b_ml.ml_stack[stack_idx]); | 3440 ip = &(buf->b_ml.ml_stack[stack_idx]); |
3323 idx = ip->ip_index; | 3441 idx = ip->ip_index; |
3324 if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) | 3442 if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) |
3325 return FAIL; | 3443 goto theend; |
3326 pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */ | 3444 pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */ |
3327 if (pp->pb_id != PTR_ID) | 3445 if (pp->pb_id != PTR_ID) |
3328 { | 3446 { |
3329 IEMSG(_("E317: pointer block id wrong 4")); | 3447 IEMSG(_("E317: pointer block id wrong 4")); |
3330 mf_put(mfp, hp, FALSE, FALSE); | 3448 mf_put(mfp, hp, FALSE, FALSE); |
3331 return FAIL; | 3449 goto theend; |
3332 } | 3450 } |
3333 count = --(pp->pb_count); | 3451 count = --(pp->pb_count); |
3334 if (count == 0) /* the pointer block becomes empty! */ | 3452 if (count == 0) /* the pointer block becomes empty! */ |
3335 mf_free(mfp, hp); | 3453 mf_free(mfp, hp); |
3336 else | 3454 else |
3382 } | 3500 } |
3383 | 3501 |
3384 #ifdef FEAT_BYTEOFF | 3502 #ifdef FEAT_BYTEOFF |
3385 ml_updatechunk(buf, lnum, line_size, ML_CHNK_DELLINE); | 3503 ml_updatechunk(buf, lnum, line_size, ML_CHNK_DELLINE); |
3386 #endif | 3504 #endif |
3387 return OK; | 3505 ret = OK; |
3388 } | 3506 |
3389 | 3507 theend: |
3390 /* | 3508 #ifdef FEAT_TEXT_PROP |
3391 * set the B_MARKED flag for line 'lnum' | 3509 if (textprop_save != NULL) |
3510 { | |
3511 // Adjust text properties in the line above and below. | |
3512 if (lnum > 1) | |
3513 adjust_text_props_for_delete(buf, lnum - 1, textprop_save, textprop_save_len, TRUE); | |
3514 if (lnum <= buf->b_ml.ml_line_count) | |
3515 adjust_text_props_for_delete(buf, lnum, textprop_save, textprop_save_len, FALSE); | |
3516 } | |
3517 vim_free(textprop_save); | |
3518 #endif | |
3519 return ret; | |
3520 } | |
3521 | |
3522 /* | |
3523 * set the DB_MARKED flag for line 'lnum' | |
3392 */ | 3524 */ |
3393 void | 3525 void |
3394 ml_setmarked(linenr_T lnum) | 3526 ml_setmarked(linenr_T lnum) |
3395 { | 3527 { |
3396 bhdr_T *hp; | 3528 bhdr_T *hp; |
3415 dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED; | 3547 dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED; |
3416 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY; | 3548 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY; |
3417 } | 3549 } |
3418 | 3550 |
3419 /* | 3551 /* |
3420 * find the first line with its B_MARKED flag set | 3552 * find the first line with its DB_MARKED flag set |
3421 */ | 3553 */ |
3422 linenr_T | 3554 linenr_T |
3423 ml_firstmarked(void) | 3555 ml_firstmarked(void) |
3424 { | 3556 { |
3425 bhdr_T *hp; | 3557 bhdr_T *hp; |
3648 | 3780 |
3649 return hp; | 3781 return hp; |
3650 } | 3782 } |
3651 | 3783 |
3652 /* | 3784 /* |
3653 * lookup line 'lnum' in a memline | 3785 * Lookup line 'lnum' in a memline. |
3654 * | 3786 * |
3655 * action: if ML_DELETE or ML_INSERT the line count is updated while searching | 3787 * action: if ML_DELETE or ML_INSERT the line count is updated while searching |
3656 * if ML_FLUSH only flush a locked block | 3788 * if ML_FLUSH only flush a locked block |
3657 * if ML_FIND just find the line | 3789 * if ML_FIND just find the line |
3658 * | 3790 * |