From 08e3266ac3b607522a5cf7f4132ccb2c0ae18472 Mon Sep 17 00:00:00 2001 From: basilisk0315 <basilisk@internode.on.net> Date: Mon, 28 Oct 2024 10:46:14 +1100 Subject: [PATCH] Refactor register.c to remove calls to STRLEN() --- src/clipboard.c | 8 +- src/ops.c | 4 + src/register.c | 289 +++++++++++++++++++++--------------- src/structs.h | 9 +- src/testdir/test_visual.vim | 10 +- src/viminfo.c | 52 ++++--- 6 files changed, 227 insertions(+), 145 deletions(-) diff --git a/src/clipboard.c b/src/clipboard.c index 8b9850e44e..6c8b60c2e7 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -2129,7 +2129,7 @@ clip_convert_selection(char_u **str, long_u *len, Clipboard_T *cbd) return -1; for (i = 0; i < y_ptr->y_size; i++) - *len += (long_u)STRLEN(y_ptr->y_array[i]) + eolsize; + *len += (long_u)y_ptr->y_array[i].length + eolsize; // Don't want newline character at end of last line if we're in MCHAR mode. if (y_ptr->y_type == MCHAR && *len >= eolsize) @@ -2141,9 +2141,9 @@ clip_convert_selection(char_u **str, long_u *len, Clipboard_T *cbd) lnum = 0; for (i = 0, j = 0; i < (int)*len; i++, j++) { - if (y_ptr->y_array[lnum][j] == '\n') + if (y_ptr->y_array[lnum].string[j] == '\n') p[i] = NUL; - else if (y_ptr->y_array[lnum][j] == NUL) + else if (y_ptr->y_array[lnum].string[j] == NUL) { # ifdef USE_CRNL p[i++] = '\r'; @@ -2153,7 +2153,7 @@ clip_convert_selection(char_u **str, long_u *len, Clipboard_T *cbd) j = -1; } else - p[i] = y_ptr->y_array[lnum][j]; + p[i] = y_ptr->y_array[lnum].string[j]; } return y_ptr->y_type; } diff --git a/src/ops.c b/src/ops.c index eb8f64c1fb..a544ff59ea 100644 --- a/src/ops.c +++ b/src/ops.c @@ -2504,7 +2504,11 @@ charwise_block_prep( } } if (endcol == MAXCOL) + { + // the selection ends at the end of the line endcol = ml_get_len(lnum); + inclusive = 0; // make sure we don't go over the end of the line + } if (startcol > endcol || bdp->is_oneChar) bdp->textlen = 0; else diff --git a/src/register.c b/src/register.c index 47ed218462..1986837180 100644 --- a/src/register.c +++ b/src/register.c @@ -30,8 +30,7 @@ static yankreg_T *y_previous = NULL; // ptr to last written yankreg static int stuff_yank(int, char_u *); static void put_reedit_in_typebuf(int silent); -static int put_in_typebuf(char_u *s, int esc, int colon, - int silent); +static int put_in_typebuf(char_u *s, int esc, int colon, int silent); static int yank_copy_line(struct block_def *bd, long y_idx, int exclude_trailing_space); #ifdef FEAT_CLIPBOARD static void copy_yank_reg(yankreg_T *reg); @@ -260,6 +259,7 @@ get_yank_register(int regname, int writing) y_current = &(y_regs[i]); if (writing) // remember the register we write into for do_put() y_previous = y_current; + return ret; } @@ -304,11 +304,14 @@ get_register( if (reg->y_size == 0 || y_current->y_array == NULL) reg->y_array = NULL; else - reg->y_array = ALLOC_MULT(char_u *, reg->y_size); + reg->y_array = ALLOC_MULT(string_T, reg->y_size); if (reg->y_array != NULL) { for (i = 0; i < reg->y_size; ++i) - reg->y_array[i] = vim_strsave(y_current->y_array[i]); + { + reg->y_array[i].string = vim_strnsave(y_current->y_array[i].string, y_current->y_array[i].length); + reg->y_array[i].length = y_current->y_array[i].length; + } } } else @@ -425,8 +428,7 @@ do_record(int c) static int stuff_yank(int regname, char_u *p) { - char_u *lp; - char_u **pp; + size_t plen; // check for read-only register if (regname != 0 && !valid_yank_reg(regname, TRUE)) @@ -439,31 +441,40 @@ stuff_yank(int regname, char_u *p) vim_free(p); return OK; } + + plen = STRLEN(p); get_yank_register(regname, TRUE); if (y_append && y_current->y_array != NULL) { + string_T *pp; + char_u *tmp; + size_t tmplen; + pp = &(y_current->y_array[y_current->y_size - 1]); - lp = alloc(STRLEN(*pp) + STRLEN(p) + 1); - if (lp == NULL) + tmplen = pp->length + plen; + tmp = alloc(tmplen + 1); + if (tmp == NULL) { vim_free(p); return FAIL; } - STRCPY(lp, *pp); - STRCAT(lp, p); + STRCPY(tmp, pp->string); + STRCPY(tmp + pp->length, p); vim_free(p); - vim_free(*pp); - *pp = lp; + vim_free(pp->string); + pp->string = tmp; + pp->length = tmplen; } else { free_yank_all(); - if ((y_current->y_array = ALLOC_ONE(char_u *)) == NULL) + if ((y_current->y_array = ALLOC_ONE(string_T)) == NULL) { vim_free(p); return FAIL; } - y_current->y_array[0] = p; + y_current->y_array[0].string = p; + y_current->y_array[0].length = plen; y_current->y_size = 1; y_current->y_type = MCHAR; // used to be MLINE, why? #ifdef FEAT_VIMINFO @@ -509,7 +520,7 @@ set_execreg_lastc(int lastc) * processed next is returned in idx. */ static char_u * -execreg_line_continuation(char_u **lines, long *idx) +execreg_line_continuation(string_T *lines, long *idx) { garray_T ga; long i = *idx; @@ -526,17 +537,17 @@ execreg_line_continuation(char_u **lines, long *idx) // command. while (--i > 0) { - p = skipwhite(lines[i]); + p = skipwhite(lines[i].string); if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' ')) break; } cmd_start = i; // join all the lines - ga_concat(&ga, lines[cmd_start]); + ga_concat(&ga, lines[cmd_start].string); for (j = cmd_start + 1; j <= cmd_end; j++) { - p = skipwhite(lines[j]); + p = skipwhite(lines[j].string); if (*p == '\\') { // Adjust the growsize to the current length to @@ -552,7 +563,7 @@ execreg_line_continuation(char_u **lines, long *idx) } } ga_append(&ga, NUL); - str = vim_strsave(ga.ga_data); + str = vim_strnsave(ga.ga_data, ga.ga_len); ga_clear(&ga); *idx = i; @@ -677,7 +688,7 @@ do_execreg( } // Handle line-continuation for :@<register> - str = y_current->y_array[i]; + str = y_current->y_array[i].string; if (colon && i > 0) { p = skipwhite(str); @@ -834,7 +845,7 @@ insert_reg( pos_T curpos; if (u_save_cursor() == FAIL) return FAIL; - del_chars((long)mb_charlen(y_current->y_array[0]), TRUE); + del_chars((long)mb_charlen(y_current->y_array[0].string), TRUE); curpos = curwin->w_cursor; if (oneright() == FAIL) // hit end of line, need to put forward (after the current position) @@ -847,7 +858,7 @@ insert_reg( do_put(regname, NULL, dir, 1L, PUT_CURSEND); } else - stuffescaped(y_current->y_array[i], literally); + stuffescaped(y_current->y_array[i].string, literally); // Insert a newline between lines and after last line if // y_type is MLINE. if (y_current->y_type == MLINE || i < y_current->y_size - 1) @@ -972,7 +983,7 @@ cmdline_paste_reg( for (i = 0; i < y_current->y_size; ++i) { - cmdline_paste_str(y_current->y_array[i], literally); + cmdline_paste_str(y_current->y_array[i].string, literally); // Insert ^M between lines and after last line if type is MLINE. // Don't do this when "remcr" is TRUE. @@ -1029,7 +1040,7 @@ yank_do_autocmd(oparg_T *oap, yankreg_T *reg) // yanked text contents for (n = 0; n < reg->y_size; n++) - list_append_string(list, reg->y_array[n], -1); + list_append_string(list, reg->y_array[n].string, -1); list->lv_lock = VAR_FIXED; (void)dict_add_list(v_event, "regcontents", list); @@ -1118,7 +1129,10 @@ free_yank(long n) long i; for (i = n; --i >= 0; ) - vim_free(y_current->y_array[i]); + { + vim_free(y_current->y_array[i].string); + y_current->y_array[i].length = 0; + } VIM_CLEAR(y_current->y_array); } @@ -1142,9 +1156,7 @@ op_yank(oparg_T *oap, int deleting, int mess) long y_idx; // index in y_array[] yankreg_T *curr; // copy of y_current yankreg_T newreg; // new yank register when appending - char_u **new_ptr; linenr_T lnum; // current line number - long j; int yanktype = oap->motion_type; long yanklines = oap->line_count; linenr_T yankendlnum = oap->end.lnum; @@ -1153,8 +1165,9 @@ op_yank(oparg_T *oap, int deleting, int mess) #if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) int did_star = FALSE; #endif + colnr_T len; + int i; - // check for read-only register if (oap->regname != 0 && !valid_yank_reg(oap->regname, TRUE)) { beep_flush(); @@ -1198,12 +1211,14 @@ op_yank(oparg_T *oap, int deleting, int mess) y_current->y_size = yanklines; y_current->y_type = yanktype; // set the yank register type y_current->y_width = 0; - y_current->y_array = lalloc_clear(sizeof(char_u *) * yanklines, TRUE); + y_current->y_array = lalloc_clear(sizeof(string_T) * yanklines, TRUE); if (y_current->y_array == NULL) { y_current = curr; return FAIL; } + for (i = 0; i < y_current->y_size; ++i) + y_current->y_array[i].length = 0; #ifdef FEAT_VIMINFO y_current->y_time_set = vim_time(); #endif @@ -1232,9 +1247,11 @@ op_yank(oparg_T *oap, int deleting, int mess) break; case MLINE: - if ((y_current->y_array[y_idx] = - vim_strsave(ml_get(lnum))) == NULL) + len = ml_get_len(lnum); + if ((y_current->y_array[y_idx].string = + vim_strnsave(ml_get(lnum), len)) == NULL) goto fail; + y_current->y_array[y_idx].length = len; break; case MCHAR: @@ -1250,7 +1267,10 @@ op_yank(oparg_T *oap, int deleting, int mess) if (curr != y_current) // append the new block to the old block { - new_ptr = ALLOC_MULT(char_u *, curr->y_size + y_current->y_size); + string_T *new_ptr; + long j; + + new_ptr = ALLOC_MULT(string_T, curr->y_size + y_current->y_size); if (new_ptr == NULL) goto fail; for (j = 0; j < curr->y_size; ++j) @@ -1268,18 +1288,22 @@ op_yank(oparg_T *oap, int deleting, int mess) // the new block, unless being Vi compatible. if (curr->y_type == MCHAR && vim_strchr(p_cpo, CPO_REGAPPEND) == NULL) { - pnew = alloc(STRLEN(curr->y_array[curr->y_size - 1]) - + STRLEN(y_current->y_array[0]) + 1); + pnew = alloc(curr->y_array[curr->y_size - 1].length + y_current->y_array[0].length + 1); if (pnew == NULL) { y_idx = y_current->y_size - 1; goto fail; } - STRCPY(pnew, curr->y_array[--j]); - STRCAT(pnew, y_current->y_array[0]); - vim_free(curr->y_array[j]); - vim_free(y_current->y_array[0]); - curr->y_array[j++] = pnew; + + --j; + STRCPY(pnew, curr->y_array[j].string); + STRCPY(pnew + curr->y_array[j].length, y_current->y_array[0].string); + vim_free(curr->y_array[j].string); + curr->y_array[j].string = pnew; + curr->y_array[j].length = curr->y_array[j].length + y_current->y_array[0].length; + ++j; + vim_free(y_current->y_array[0].string); + y_current->y_array[0].length = 0; y_idx = 1; } else @@ -1417,7 +1441,8 @@ yank_copy_line(struct block_def *bd, long y_idx, int exclude_trailing_space) if ((pnew = alloc(bd->startspaces + bd->endspaces + bd->textlen + 1)) == NULL) return FAIL; - y_current->y_array[y_idx] = pnew; + + y_current->y_array[y_idx].string = pnew; vim_memset(pnew, ' ', (size_t)bd->startspaces); pnew += bd->startspaces; mch_memmove(pnew, bd->textstart, (size_t)bd->textlen); @@ -1431,10 +1456,13 @@ yank_copy_line(struct block_def *bd, long y_idx, int exclude_trailing_space) while (s > 0 && VIM_ISWHITE(*(bd->textstart + s - 1))) { s = s - (*mb_head_off)(bd->textstart, bd->textstart + s - 1) - 1; - pnew--; + --pnew; } } *pnew = NUL; + + y_current->y_array[y_idx].length = (size_t)(pnew - y_current->y_array[y_idx].string); + return OK; } @@ -1452,17 +1480,20 @@ copy_yank_reg(yankreg_T *reg) free_yank_all(); *y_current = *curr; y_current->y_array = lalloc_clear( - sizeof(char_u *) * y_current->y_size, TRUE); + sizeof(string_T) * y_current->y_size, TRUE); if (y_current->y_array == NULL) y_current->y_size = 0; else for (j = 0; j < y_current->y_size; ++j) - if ((y_current->y_array[j] = vim_strsave(curr->y_array[j])) == NULL) + { + if ((y_current->y_array[j].string = vim_strnsave(curr->y_array[j].string, curr->y_array[j].length)) == NULL) { free_yank(j); y_current->y_size = 0; break; } + y_current->y_array[j].length = curr->y_array[j].length; + } y_current = curr; } #endif @@ -1484,7 +1515,8 @@ do_put( int flags) { char_u *ptr; - char_u *newp, *oldp; + char_u *newp; + char_u *oldp; int yanklen; int totlen = 0; // init for gcc linenr_T lnum; @@ -1495,23 +1527,11 @@ do_put( int oldlen; long y_width = 0; colnr_T vcol; - int delcount; - int incr = 0; - long j; - struct block_def bd; - char_u **y_array = NULL; + string_T *y_array = NULL; yankreg_T *y_current_used = NULL; long nr_lines = 0; - pos_T new_cursor; - int indent; - int orig_indent = 0; // init for gcc - int indent_diff = 0; // init for gcc - int first_indent = TRUE; - int lendiff = 0; - pos_T old_pos; - char_u *insert_string = NULL; + string_T insert_string; int allocated = FALSE; - long cnt; pos_T orig_start = curbuf->b_op_start; pos_T orig_end = curbuf->b_op_end; unsigned int cur_ve_flags = get_ve_flags(); @@ -1522,9 +1542,6 @@ do_put( (void)may_get_selection(regname); #endif - if (flags & PUT_FIXINDENT) - orig_indent = get_indent(); - curbuf->b_op_start = curwin->w_cursor; // default for '[ mark curbuf->b_op_end = curwin->w_cursor; // default for '] mark @@ -1546,10 +1563,11 @@ do_put( // For special registers '%' (file name), '#' (alternate file name) and // ':' (last command line), etc. we have to create a fake yank register. // For compiled code "expr_result" holds the expression result. + insert_string.string = NULL; if (regname == '=' && expr_result != NULL) - insert_string = expr_result; - else if (get_spec_reg(regname, &insert_string, &allocated, TRUE) - && insert_string == NULL) + insert_string.string = expr_result; + else if (get_spec_reg(regname, &insert_string.string, &allocated, TRUE) + && insert_string.string == NULL) return; // Autocommands may be executed when saving lines for undo. This might @@ -1557,41 +1575,57 @@ do_put( if (u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1) == FAIL) goto end; - if (insert_string != NULL) + if (insert_string.string != NULL) { + insert_string.length = STRLEN(insert_string.string); + y_type = MCHAR; #ifdef FEAT_EVAL if (regname == '=') { + size_t ptrlen; + char_u *tmp; + // For the = register we need to split the string at NL // characters. // Loop twice: count the number of lines and save them. for (;;) { y_size = 0; - ptr = insert_string; + ptr = insert_string.string; + ptrlen = insert_string.length; while (ptr != NULL) { if (y_array != NULL) - y_array[y_size] = ptr; + y_array[y_size].string = ptr; ++y_size; - ptr = vim_strchr(ptr, '\n'); - if (ptr != NULL) + tmp = vim_strchr(ptr, '\n'); + if (tmp == NULL) { if (y_array != NULL) - *ptr = NUL; - ++ptr; + y_array[y_size - 1].length = ptrlen; + } + else + { + if (y_array != NULL) + { + *tmp = NUL; + y_array[y_size - 1].length = (size_t)(tmp - ptr); + ptrlen -= y_array[y_size - 1].length + 1; + } + ++tmp; // A trailing '\n' makes the register linewise. - if (*ptr == NUL) + if (*tmp == NUL) { y_type = MLINE; break; } } + ptr = tmp; } if (y_array != NULL) break; - y_array = ALLOC_MULT(char_u *, y_size); + y_array = ALLOC_MULT(string_T, y_size); if (y_array == NULL) goto end; } @@ -1618,16 +1652,19 @@ do_put( { if (flags & PUT_LINE_SPLIT) { + char_u *p_orig; char_u *p; + size_t plen; // "p" or "P" in Visual mode: split the lines to put the text in // between. if (u_save_cursor() == FAIL) goto end; - p = ml_get_cursor(); + p_orig = p = ml_get_cursor(); + plen = ml_get_cursor_len(); if (dir == FORWARD && *p != NUL) MB_PTR_ADV(p); - ptr = vim_strsave(p); + ptr = vim_strnsave(p, plen - (p - p_orig)); if (ptr == NULL) goto end; ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, FALSE); @@ -1700,8 +1737,6 @@ do_put( else if (u_save_cursor() == FAIL) goto end; - yanklen = (int)STRLEN(y_array[0]); - if (cur_ve_flags == VE_ALL && y_type == MCHAR) { if (gchar_cursor() == TAB) @@ -1732,6 +1767,10 @@ do_put( // Block mode if (y_type == MBLOCK) { + int delcount; + int incr = 0; + struct block_def bd; + long j; int c = gchar_cursor(); colnr_T endcol2 = 0; @@ -1830,7 +1869,7 @@ do_put( } } - yanklen = (int)STRLEN(y_array[i]); + yanklen = (int)y_array[i].length; if ((flags & PUT_BLOCK_INNER) == 0) { @@ -1838,7 +1877,7 @@ do_put( // block spaces = y_width + 1; init_chartabsize_arg(&cts, curwin, 0, 0, - y_array[i], y_array[i]); + y_array[i].string, y_array[i].string); while (*cts.cts_ptr != NUL) { @@ -1877,7 +1916,7 @@ do_put( // insert the new text for (j = 0; j < count; ++j) { - mch_memmove(ptr, y_array[i], (size_t)yanklen); + mch_memmove(ptr, y_array[i].string, (size_t)yanklen); ptr += yanklen; // insert block's trailing spaces only if there's text behind @@ -1933,6 +1972,10 @@ do_put( } else { + pos_T new_cursor; + + yanklen = (int)y_array[0].length; + // Character or Line mode if (y_type == MCHAR) { @@ -2031,10 +2074,10 @@ do_put( ptr = newp + col; for (i = 0; i < count; ++i) { - mch_memmove(ptr, y_array[0], (size_t)yanklen); + mch_memmove(ptr, y_array[0].string, (size_t)yanklen); ptr += yanklen; } - STRMOVE(ptr, oldp + col); + mch_memmove(ptr, oldp + col, (size_t)(oldlen - col) + 1); // +1 for NUL // compute the byte offset for the last character first_byte_off = mb_head_off(newp, ptr - 1); @@ -2073,7 +2116,17 @@ do_put( else { linenr_T new_lnum = new_cursor.lnum; - size_t len; + int indent; + int orig_indent; + int indent_diff = 0; // init for gcc + int first_indent = TRUE; + int lendiff = 0; + long cnt; + + if (flags & PUT_FIXINDENT) + orig_indent = get_indent(); + else + orig_indent = 0; // Insert at least one line. When y_type is MCHAR, break the first // line in two. @@ -2087,12 +2140,12 @@ do_put( // Then append y_array[0] to first line. lnum = new_cursor.lnum; ptr = ml_get(lnum) + col; - totlen = (int)STRLEN(y_array[y_size - 1]); + totlen = (int)y_array[y_size - 1].length; newp = alloc(ml_get_len(lnum) - col + totlen + 1); if (newp == NULL) goto error; - STRCPY(newp, y_array[y_size - 1]); - STRCAT(newp, ptr); + STRCPY(newp, y_array[y_size - 1].string); + STRCPY(newp + totlen, ptr); // insert second line ml_append(lnum, newp, (colnr_T)0, FALSE); ++new_lnum; @@ -2105,7 +2158,7 @@ do_put( // copy first part of line mch_memmove(newp, oldp, (size_t)col); // append to first line - mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1)); + mch_memmove(newp + col, y_array[0].string, (size_t)(yanklen + 1)); ml_replace(lnum, newp, FALSE); curwin->w_cursor.lnum = lnum; @@ -2116,16 +2169,17 @@ do_put( { if (y_type != MCHAR || i < y_size - 1) { - if (ml_append(lnum, y_array[i], (colnr_T)0, FALSE) + if (ml_append(lnum, y_array[i].string, (colnr_T)0, FALSE) == FAIL) goto error; - new_lnum++; + ++new_lnum; } - lnum++; + ++lnum; ++nr_lines; if (flags & PUT_FIXINDENT) { - old_pos = curwin->w_cursor; + pos_T old_pos = curwin->w_cursor; + curwin->w_cursor.lnum = lnum; ptr = ml_get(lnum); if (cnt == count && i == y_size - 1) @@ -2133,7 +2187,7 @@ do_put( if (*ptr == '#' && preprocs_left()) indent = 0; // Leave # lines at start else - if (*ptr == NUL) + if (*ptr == NUL) indent = 0; // Ignore empty lines else if (first_indent) { @@ -2184,14 +2238,13 @@ error: // Put the '] mark on the first byte of the last inserted character. // Correct the length for change in indent. curbuf->b_op_end.lnum = new_lnum; - len = STRLEN(y_array[y_size - 1]); - col = (colnr_T)len - lendiff; + col = (colnr_T)y_array[y_size - 1].length - lendiff; if (col > 1) { curbuf->b_op_end.col = col - 1; - if (len > 0) - curbuf->b_op_end.col -= mb_head_off(y_array[y_size - 1], - y_array[y_size - 1] + len - 1); + if (y_array[y_size - 1].length > 0) + curbuf->b_op_end.col -= mb_head_off(y_array[y_size - 1].string, + y_array[y_size - 1].string + y_array[y_size - 1].length - 1); } else curbuf->b_op_end.col = 0; @@ -2254,7 +2307,7 @@ end: curbuf->b_op_end = orig_end; } if (allocated) - vim_free(insert_string); + vim_free(insert_string.string); if (regname == '=') vim_free(y_array); @@ -2366,7 +2419,7 @@ ex_display(exarg_T *eap) int do_show = FALSE; for (j = 0; !do_show && j < yb->y_size; ++j) - do_show = !message_filtered(yb->y_array[j]); + do_show = !message_filtered(yb->y_array[j].string); if (do_show || yb->y_size == 0) { @@ -2386,7 +2439,7 @@ ex_display(exarg_T *eap) msg_puts_attr("^J", attr); n -= 2; } - for (p = yb->y_array[j]; + for (p = yb->y_array[j].string; *p != NUL && (n -= ptr2cells(p)) >= 0; ++p) { clen = (*mb_ptr2len)(p); @@ -2500,7 +2553,7 @@ dnd_yank_drag_data(char_u *str, long len) yankreg_T *curr; curr = y_current; - y_current = &y_regs[TILDE_REGISTER]; + y_current = &y_regs[TILDE_REGISTER].string; free_yank_all(); str_to_reg(y_current, MCHAR, str, len, 0L, FALSE); y_current = curr; @@ -2589,7 +2642,7 @@ getreg_wrap_one_line(char_u *s, int flags) char_u * get_reg_contents(int regname, int flags) { - long i; + linenr_T i; char_u *retval; int allocated; long len; @@ -2636,7 +2689,7 @@ get_reg_contents(int regname, int flags) if (list == NULL) return NULL; for (i = 0; i < y_current->y_size; ++i) - if (list_append_string(list, y_current->y_array[i], -1) == FAIL) + if (list_append_string(list, y_current->y_array[i].string, -1) == FAIL) error = TRUE; if (error) { @@ -2650,9 +2703,10 @@ get_reg_contents(int regname, int flags) len = 0; for (i = 0; i < y_current->y_size; ++i) { - len += (long)STRLEN(y_current->y_array[i]); - // Insert a newline between lines and after last line if - // y_type is MLINE. + len += y_current->y_array[i].length; + + // Insert a NL between lines and after the last line if y_type is + // MLINE. if (y_current->y_type == MLINE || i < y_current->y_size - 1) ++len; } @@ -2665,8 +2719,8 @@ get_reg_contents(int regname, int flags) len = 0; for (i = 0; i < y_current->y_size; ++i) { - STRCPY(retval + len, y_current->y_array[i]); - len += (long)STRLEN(retval + len); + STRCPY(retval + len, y_current->y_array[i].string); + len += y_current->y_array[i].length; // Insert a NL between lines and after the last line if y_type is // MLINE. @@ -2815,7 +2869,7 @@ write_reg_contents_ex( semsg(_(e_buffer_nr_does_not_exist), (long)num); } else - buf = buflist_findnr(buflist_findpat(str, str + STRLEN(str), + buf = buflist_findnr(buflist_findpat(str, str + len, TRUE, FALSE, FALSE)); if (buf == NULL) return; @@ -2877,7 +2931,7 @@ str_to_reg( int append = FALSE; // append to last line in register char_u *s; char_u **ss; - char_u **pp; + string_T *pp; long maxlen; if (y_ptr->y_array == NULL) // NULL means empty register @@ -2923,7 +2977,7 @@ str_to_reg( // Allocate an array to hold the pointers to the new register lines. // If the register was not empty, move the existing lines to the new array. - pp = lalloc_clear((y_ptr->y_size + newlines) * sizeof(char_u *), TRUE); + pp = lalloc_clear((y_ptr->y_size + newlines) * sizeof(string_T), TRUE); if (pp == NULL) // out of memory return; for (lnum = 0; lnum < y_ptr->y_size; ++lnum) @@ -2937,7 +2991,8 @@ str_to_reg( { for (ss = (char_u **) str; *ss != NULL; ++ss, ++lnum) { - pp[lnum] = vim_strsave(*ss); + pp[lnum].length = STRLEN(*ss); + pp[lnum].string = vim_strnsave(*ss, pp[lnum].length); if (type == MBLOCK) { int charlen = mb_string2cells(*ss, -1); @@ -2966,7 +3021,7 @@ str_to_reg( if (append) { --lnum; - extra = (int)STRLEN(y_ptr->y_array[lnum]); + extra = (int)y_ptr->y_array[lnum].length; } else extra = 0; @@ -2974,14 +3029,16 @@ str_to_reg( if (s == NULL) break; if (extra) - mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra); + mch_memmove(s, y_ptr->y_array[lnum].string, (size_t)extra); if (append) - vim_free(y_ptr->y_array[lnum]); + vim_free(y_ptr->y_array[lnum].string); if (i > 0) mch_memmove(s + extra, str + start, (size_t)i); extra += i; s[extra] = NUL; - y_ptr->y_array[lnum++] = s; + y_ptr->y_array[lnum].string = s; + y_ptr->y_array[lnum].length = extra; + lnum++; while (--extra >= 0) { if (*s == NUL) diff --git a/src/structs.h b/src/structs.h index 39e60a42ea..d11279645d 100644 --- a/src/structs.h +++ b/src/structs.h @@ -20,6 +20,13 @@ typedef int colnr_T; typedef unsigned short short_u; #endif +// structure to store a string (including it's length) +typedef struct +{ + char_u *string; // the string + size_t length; // length of the string (excluding the NUL) +} string_T; + /* * Position in file or buffer. */ @@ -4784,7 +4791,7 @@ struct block_def // Each yank register has an array of pointers to lines. typedef struct { - char_u **y_array; // pointer to array of line pointers + string_T *y_array; // pointer to array of string_T structs linenr_T y_size; // number of lines in y_array char_u y_type; // MLINE, MCHAR or MBLOCK colnr_T y_width; // only set if y_type == MBLOCK diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim index 3750ebf6b9..3000d1ae9b 100644 --- a/src/testdir/test_visual.vim +++ b/src/testdir/test_visual.vim @@ -1882,8 +1882,8 @@ func Test_visual_getregion() \ ], \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) call assert_equal([ - \ [[bufnr('%'), 1, 3, 0], [bufnr('%'), 1, 4, 0]], - \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 4, 0]], + \ [[bufnr('%'), 1, 3, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 6, 2]], \ ], \ getregionpos(getpos('v'), getpos('.'), @@ -1894,14 +1894,14 @@ func Test_visual_getregion() call assert_equal(['', 'two', 'three '], \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) call assert_equal([ - \ [[bufnr('%'), 1, 0, 0], [bufnr('%'), 1, 0, 0]], + \ [[bufnr('%'), 1, 0, 0], [bufnr('%'), 1, 3, 0]], \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 5, 0]], \ ], \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) call assert_equal([ - \ [[bufnr('%'), 1, 4, 0], [bufnr('%'), 1, 4, 0]], - \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 4, 0]], + \ [[bufnr('%'), 1, 4, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 6, 2]], \ ], \ getregionpos(getpos('v'), getpos('.'), diff --git a/src/viminfo.c b/src/viminfo.c index 2196d3c426..6736cd5fc1 100644 --- a/src/viminfo.c +++ b/src/viminfo.c @@ -1606,7 +1606,7 @@ finish_viminfo_registers(void) if (y_read_regs[i].y_array != NULL) { for (j = 0; j < y_read_regs[i].y_size; j++) - vim_free(y_read_regs[i].y_array[j]); + vim_free(y_read_regs[i].y_array[j].string); vim_free(y_read_regs[i].y_array); } VIM_CLEAR(y_read_regs); @@ -1622,7 +1622,7 @@ read_viminfo_register(vir_T *virp, int force) int i; int set_prev = FALSE; char_u *str; - char_u **array = NULL; + string_T *array = NULL; int new_type = MCHAR; // init to shut up compiler colnr_T new_width = 0; // init to shut up compiler yankreg_T *y_current_p; @@ -1665,7 +1665,7 @@ read_viminfo_register(vir_T *virp, int force) // array[] needs to be freed. if (set_prev) set_y_previous(y_current_p); - array = ALLOC_MULT(char_u *, limit); + array = ALLOC_MULT(string_T, limit); str = skipwhite(skiptowhite(str)); if (STRNCMP(str, "CHAR", 4) == 0) new_type = MCHAR; @@ -1685,8 +1685,8 @@ read_viminfo_register(vir_T *virp, int force) { if (size == limit) { - char_u **new_array = (char_u **) - alloc(limit * 2 * sizeof(char_u *)); + string_T *new_array = (string_T *) + alloc(limit * 2 * sizeof(string_T)); if (new_array == NULL) { @@ -1701,7 +1701,11 @@ read_viminfo_register(vir_T *virp, int force) } str = viminfo_readstring(virp, 1, TRUE); if (str != NULL) - array[size++] = str; + { + array[size].string = str; + array[size].length = STRLEN(str); + ++size; + } else // error, don't store the result do_it = FALSE; @@ -1712,7 +1716,7 @@ read_viminfo_register(vir_T *virp, int force) { // free y_array[] for (i = 0; i < y_current_p->y_size; i++) - vim_free(y_current_p->y_array[i]); + vim_free(y_current_p->y_array[i].string); vim_free(y_current_p->y_array); y_current_p->y_type = new_type; @@ -1726,13 +1730,19 @@ read_viminfo_register(vir_T *virp, int force) else { // Move the lines from array[] to y_array[]. - y_current_p->y_array = ALLOC_MULT(char_u *, size); + y_current_p->y_array = ALLOC_MULT(string_T, size); for (i = 0; i < size; i++) { if (y_current_p->y_array == NULL) - vim_free(array[i]); + { + vim_free(array[i].string); + array[i].length = 0; + } else - y_current_p->y_array[i] = array[i]; + { + y_current_p->y_array[i].string = array[i].string; + y_current_p->y_array[i].length = array[i].length; + } } } } @@ -1740,7 +1750,7 @@ read_viminfo_register(vir_T *virp, int force) { // Free array[] if it was filled. for (i = 0; i < size; i++) - vim_free(array[i]); + vim_free(array[i].string); } vim_free(array); @@ -1804,7 +1814,7 @@ handle_viminfo_register(garray_T *values, int force) if (y_ptr->y_array != NULL) for (i = 0; i < y_ptr->y_size; i++) - vim_free(y_ptr->y_array[i]); + vim_free(y_ptr->y_array[i].string); vim_free(y_ptr->y_array); if (y_read_regs == NULL) @@ -1823,7 +1833,7 @@ handle_viminfo_register(garray_T *values, int force) y_ptr->y_array = NULL; return; } - y_ptr->y_array = ALLOC_MULT(char_u *, linecount); + y_ptr->y_array = ALLOC_MULT(string_T, linecount); if (y_ptr->y_array == NULL) { y_ptr->y_size = 0; // ensure object state is consistent @@ -1833,7 +1843,8 @@ handle_viminfo_register(garray_T *values, int force) { if (vp[i + 6].bv_allocated) { - y_ptr->y_array[i] = vp[i + 6].bv_string; + y_ptr->y_array[i].string = vp[i + 6].bv_string; + y_ptr->y_array[i].length = vp[i + 6].bv_len; vp[i + 6].bv_string = NULL; } else if (vp[i + 6].bv_type != BVAL_STRING) @@ -1842,7 +1853,10 @@ handle_viminfo_register(garray_T *values, int force) y_ptr->y_array = NULL; } else - y_ptr->y_array[i] = vim_strsave(vp[i + 6].bv_string); + { + y_ptr->y_array[i].string = vim_strnsave(vp[i + 6].bv_string, vp[i + 6].bv_len); + y_ptr->y_array[i].length = vp[i + 6].bv_len; + } } } @@ -1899,7 +1913,7 @@ write_viminfo_registers(FILE *fp) num_lines = y_ptr->y_size; if (num_lines == 0 || (num_lines == 1 && y_ptr->y_type == MCHAR - && *y_ptr->y_array[0] == NUL)) + && *y_ptr->y_array[0].string == NUL)) continue; if (max_kbyte > 0) @@ -1907,7 +1921,7 @@ write_viminfo_registers(FILE *fp) // Skip register if there is more text than the maximum size. len = 0; for (j = 0; j < num_lines; j++) - len += (long)STRLEN(y_ptr->y_array[j]) + 1L; + len += (long)y_ptr->y_array[j].length + 1L; if (len > (long)max_kbyte * 1024L) continue; } @@ -1942,7 +1956,7 @@ write_viminfo_registers(FILE *fp) for (j = 0; j < num_lines; j++) { putc('\t', fp); - viminfo_writestring(fp, y_ptr->y_array[j]); + viminfo_writestring(fp, y_ptr->y_array[j].string); } { @@ -1967,7 +1981,7 @@ write_viminfo_registers(FILE *fp) { putc(',', fp); --remaining; - remaining = barline_writestring(fp, y_ptr->y_array[j], + remaining = barline_writestring(fp, y_ptr->y_array[j].string, remaining); } putc('\n', fp);