To: vim_dev@googlegroups.com Subject: Patch 8.1.0636 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.0636 Problem: line2byte() gives wrong values with text properties. (Bjorn Linse) Solution: Compute byte offsets differently when text properties were added. (closes #3718) Files: src/structs.h, src/textprop.c, src/proto/textprop.pro, src/memline.c, src/testdir/test_textprop.vim *** ../vim-8.1.0635/src/structs.h 2018-12-24 20:23:39.440716979 +0100 --- src/structs.h 2018-12-25 21:40:12.265965208 +0100 *************** *** 2411,2417 **** dict_T *b_vars; /* internal variables, local to buffer */ #endif #ifdef FEAT_TEXT_PROP ! hashtab_T *b_proptypes; /* text property types local to buffer */ #endif #if defined(FEAT_BEVAL) && defined(FEAT_EVAL) --- 2411,2418 ---- dict_T *b_vars; /* internal variables, local to buffer */ #endif #ifdef FEAT_TEXT_PROP ! int b_has_textprop; // TRUE when text props were added ! hashtab_T *b_proptypes; // text property types local to buffer #endif #if defined(FEAT_BEVAL) && defined(FEAT_EVAL) *** ../vim-8.1.0635/src/textprop.c 2018-12-24 23:05:08.546418665 +0100 --- src/textprop.c 2018-12-25 23:14:13.892679752 +0100 *************** *** 17,28 **** --- 17,32 ---- * Text properties have a type, which can be used to specify highlighting. * * TODO: + * - mismatch in column 1 being the first column + * - Let props overrule syntax HL. * - When deleting a line where a prop ended, adjust flag of previous line. * - When deleting a line where a prop started, adjust flag of next line. * - When inserting a line add props that continue from previous line. * - Adjust property column and length when text is inserted/deleted * - Add an arrray for global_proptypes, to quickly lookup a proptype by ID * - Add an arrray for b_proptypes, to quickly lookup a proptype by ID + * - Also test line2byte() with many lines, so that ml_updatechunk() is taken + * into account. * - add mechanism to keep track of changed lines. */ *************** *** 261,267 **** length = end_col - col + 1; else length = textlen - col + 1; ! if (length > textlen) length = textlen; // can include the end-of-line if (length < 1) length = 1; --- 265,271 ---- length = end_col - col + 1; else length = textlen - col + 1; ! if (length > (long)textlen) length = textlen; // can include the end-of-line if (length < 1) length = 1; *************** *** 308,327 **** buf->b_ml.ml_flags |= ML_LINE_DIRTY; } redraw_buf_later(buf, NOT_VALID); } /* - * Return TRUE if any text properties are defined globally or for buffer - * "buf". - */ - int - has_any_text_properties(buf_T *buf) - { - return buf->b_proptypes != NULL || global_proptypes != NULL; - } - - /* * Fetch the text properties for line "lnum" in buffer "buf". * Returns the number of text properties and, when non-zero, a pointer to the * first one in "props" (note that it is not aligned, therefore the char_u --- 312,322 ---- buf->b_ml.ml_flags |= ML_LINE_DIRTY; } + buf->b_has_textprop = TRUE; // this is never reset redraw_buf_later(buf, NOT_VALID); } /* * Fetch the text properties for line "lnum" in buffer "buf". * Returns the number of text properties and, when non-zero, a pointer to the * first one in "props" (note that it is not aligned, therefore the char_u *************** *** 334,341 **** size_t textlen; size_t proplen; ! // Be quick when no text property types are defined. ! if (!has_any_text_properties(buf)) return 0; // Fetch the line to get the ml_line_len field updated. --- 329,337 ---- size_t textlen; size_t proplen; ! // Be quick when no text property types have been defined or the buffer, ! // unless we are adding one. ! if (!buf->b_has_textprop && !will_change) return 0; // Fetch the line to get the ml_line_len field updated. *** ../vim-8.1.0635/src/proto/textprop.pro 2018-12-13 22:17:52.877941474 +0100 --- src/proto/textprop.pro 2018-12-25 21:49:21.845257609 +0100 *************** *** 1,6 **** /* textprop.c */ void f_prop_add(typval_T *argvars, typval_T *rettv); - int has_any_text_properties(buf_T *buf); int get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change); proptype_T *text_prop_type_by_id(buf_T *buf, int id); void f_prop_clear(typval_T *argvars, typval_T *rettv); --- 1,5 ---- *** ../vim-8.1.0635/src/memline.c 2018-12-16 14:37:35.845271247 +0100 --- src/memline.c 2018-12-25 23:10:04.682706053 +0100 *************** *** 3179,3192 **** curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY; #ifdef FEAT_TEXT_PROP ! if (has_any_text_properties(curbuf)) // Need to fetch the old line to copy over any text properties. ml_get_buf(curbuf, lnum, TRUE); #endif } #ifdef FEAT_TEXT_PROP ! if (has_any_text_properties(curbuf)) { size_t oldtextlen = STRLEN(curbuf->b_ml.ml_line_ptr) + 1; --- 3179,3192 ---- curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY; #ifdef FEAT_TEXT_PROP ! if (curbuf->b_has_textprop) // Need to fetch the old line to copy over any text properties. ml_get_buf(curbuf, lnum, TRUE); #endif } #ifdef FEAT_TEXT_PROP ! if (curbuf->b_has_textprop) { size_t oldtextlen = STRLEN(curbuf->b_ml.ml_line_ptr) + 1; *************** *** 5131,5136 **** --- 5131,5137 ---- { int count; /* number of entries in block */ int idx; + int end_idx; int text_end; int linecnt; *************** *** 5154,5176 **** (long)(buf->b_ml.ml_locked_low) + 1; idx = curline - buf->b_ml.ml_locked_low; curline = buf->b_ml.ml_locked_high + 1; ! if (idx == 0)/* first line in block, text at the end */ ! text_end = dp->db_txt_end; ! else ! text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK); ! /* Compute index of last line to use in this MEMLINE */ rest = count - idx; if (linecnt + rest > MLCS_MINL) { ! idx += MLCS_MINL - linecnt - 1; linecnt = MLCS_MINL; } else { ! idx = count - 1; linecnt += rest; } ! size += text_end - ((dp->db_index[idx]) & DB_INDEX_MASK); } buf->b_ml.ml_chunksize[curix].mlcs_numlines = linecnt; buf->b_ml.ml_chunksize[curix + 1].mlcs_numlines -= linecnt; --- 5155,5193 ---- (long)(buf->b_ml.ml_locked_low) + 1; idx = curline - buf->b_ml.ml_locked_low; curline = buf->b_ml.ml_locked_high + 1; ! ! // compute index of last line to use in this MEMLINE rest = count - idx; if (linecnt + rest > MLCS_MINL) { ! end_idx = idx + MLCS_MINL - linecnt - 1; linecnt = MLCS_MINL; } else { ! end_idx = count - 1; linecnt += rest; } ! #ifdef FEAT_TEXT_PROP ! if (buf->b_has_textprop) ! { ! int i; ! ! // We cannot use the text pointers to get the text length, ! // the text prop info would also be counted. Go over the ! // lines. ! for (i = end_idx; i < idx; ++i) ! size += STRLEN((char_u *)dp + (dp->db_index[i] & DB_INDEX_MASK)) + 1; ! } ! else ! #endif ! { ! if (idx == 0)/* first line in block, text at the end */ ! text_end = dp->db_txt_end; ! else ! text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK); ! size += text_end - ((dp->db_index[end_idx]) & DB_INDEX_MASK); ! } } buf->b_ml.ml_chunksize[curix].mlcs_numlines = linecnt; buf->b_ml.ml_chunksize[curix + 1].mlcs_numlines -= linecnt; *************** *** 5360,5366 **** idx++; } } ! len = text_end - ((dp->db_index[idx]) & DB_INDEX_MASK); size += len; if (offset != 0 && size >= offset) { --- 5377,5396 ---- idx++; } } ! #ifdef FEAT_TEXT_PROP ! if (buf->b_has_textprop) ! { ! int i; ! ! // cannot use the db_index pointer, need to get the actual text ! // lengths. ! len = 0; ! for (i = start_idx; i <= idx; ++i) ! len += STRLEN((char_u *)dp + ((dp->db_index[idx]) & DB_INDEX_MASK)) + 1; ! } ! else ! #endif ! len = text_end - ((dp->db_index[idx]) & DB_INDEX_MASK); size += len; if (offset != 0 && size >= offset) { *** ../vim-8.1.0635/src/testdir/test_textprop.vim 2018-12-24 23:05:08.546418665 +0100 --- src/testdir/test_textprop.vim 2018-12-25 22:43:20.588109002 +0100 *************** *** 226,230 **** --- 226,242 ---- call prop_type_delete('comment') endfunc + func Test_prop_byteoff() + call prop_type_add('comment', {'highlight': 'Directory'}) + new + call setline(1, ['line1', 'line2', '']) + call assert_equal(13, line2byte(3)) + call prop_add(1, 1, {'end_col': 3, 'type': 'comment'}) + call assert_equal(13, line2byte(3)) + + bwipe! + call prop_type_delete('comment') + endfunc + " TODO: screenshot test with highlighting *** ../vim-8.1.0635/src/version.c 2018-12-24 23:35:09.119234692 +0100 --- src/version.c 2018-12-25 23:14:27.288571042 +0100 *************** *** 801,802 **** --- 801,804 ---- { /* Add new patch number below this line */ + /**/ + 636, /**/ -- hundred-and-one symptoms of being an internet addict: 44. Your friends no longer send you e-mail...they just log on to your IRC channel. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///