diff options
Diffstat (limited to 'src/ops.c')
-rw-r--r-- | src/ops.c | 196 |
1 files changed, 139 insertions, 57 deletions
@@ -212,7 +212,7 @@ op_shift(oparg_T *oap, int curs_top, int amount) // Set "'[" and "']" marks. curbuf->b_op_start = oap->start; curbuf->b_op_end.lnum = oap->end.lnum; - curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum)); + curbuf->b_op_end.col = ml_get_len(oap->end.lnum); if (curbuf->b_op_end.col > 0) --curbuf->b_op_end.col; } @@ -476,7 +476,7 @@ shift_block(oparg_T *oap, int amount) STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white); } // replace the line - added = new_line_len - (int)STRLEN(oldp); + added = new_line_len - ml_get_curline_len(); ml_replace(curwin->w_cursor.lnum, newp, FALSE); inserted_bytes(curwin->w_cursor.lnum, bd.textcol, added); State = oldstate; @@ -554,7 +554,7 @@ block_insert( spaces = 0; // Make sure the allocated size matches what is actually copied below. - newp = alloc(STRLEN(oldp) + spaces + s_len + newp = alloc(ml_get_len(lnum) + spaces + s_len + (spaces > 0 && !bdp->is_short ? ts_val - spaces : 0) + count + 1); if (newp == NULL) @@ -800,7 +800,7 @@ op_delete(oparg_T *oap) // Thus the number of characters may increase! n = bd.textlen - bd.startspaces - bd.endspaces; oldp = ml_get(lnum); - newp = alloc(STRLEN(oldp) + 1 - n); + newp = alloc(ml_get_len(lnum) + 1 - n); if (newp == NULL) continue; // copy up to deleted part @@ -849,8 +849,8 @@ op_delete(oparg_T *oap) } else beginline(0); // cursor in column 0 - truncate_line(FALSE); // delete the rest of the line - // leave cursor past last char in line + truncate_line(FALSE); // delete the rest of the line, + // leaving cursor past last char in line if (oap->line_count > 1) u_clearline(); // "U" command not possible after "2cc" } @@ -920,8 +920,7 @@ op_delete(oparg_T *oap) { // fix up things for virtualedit-delete: // break the tabs which are going to get in our way - char_u *curline = ml_get_curline(); - int len = (int)STRLEN(curline); + int len = ml_get_curline_len(); if (oap->end.coladd != 0 && (int)oap->end.col >= len - 1 @@ -990,13 +989,20 @@ setmarks: static void mb_adjust_opend(oparg_T *oap) { - char_u *p; + char_u *line; + char_u *ptr; if (!oap->inclusive) return; - p = ml_get(oap->end.lnum); - oap->end.col += mb_tail_off(p, p + oap->end.col); + line = ml_get(oap->end.lnum); + ptr = line + oap->end.col; + if (*ptr != NUL) + { + ptr -= (*mb_head_off)(line, ptr); + ptr += (*mb_ptr2len)(ptr) - 1; + oap->end.col = ptr - line; + } } /* @@ -1109,7 +1115,7 @@ op_replace(oparg_T *oap, int c) n += numc - bd.textlen; oldp = ml_get_curline(); - oldlen = STRLEN(oldp); + oldlen = ml_get_curline_len(); newp = alloc(oldlen + 1 + n); if (newp == NULL) continue; @@ -1167,7 +1173,7 @@ op_replace(oparg_T *oap, int c) { oap->start.col = 0; curwin->w_cursor.col = 0; - oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum)); + oap->end.col = ml_get_len(oap->end.lnum); if (oap->end.col) --oap->end.col; } @@ -1313,7 +1319,7 @@ op_tilde(oparg_T *oap) { oap->start.col = 0; pos.col = 0; - oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum)); + oap->end.col = ml_get_len(oap->end.lnum); if (oap->end.col) --oap->end.col; } @@ -1327,8 +1333,8 @@ op_tilde(oparg_T *oap) for (;;) { did_change |= swapchars(oap->op_type, &pos, - pos.lnum == oap->end.lnum ? oap->end.col + 1: - (int)STRLEN(ml_get_pos(&pos))); + pos.lnum == oap->end.lnum ? oap->end.col + 1 + : ml_get_pos_len(&pos)); if (LTOREQ_POS(oap->end, pos) || inc(&pos) == -1) break; } @@ -1346,7 +1352,7 @@ op_tilde(oparg_T *oap) while (pos.lnum < oap->end.lnum) { ptr = ml_get_buf(curbuf, pos.lnum, FALSE); - count = (int)STRLEN(ptr) - pos.col; + count = ml_get_buf_len(curbuf, pos.lnum) - pos.col; netbeans_removed(curbuf, pos.lnum, pos.col, (long)count); // get the line again, it may have been flushed ptr = ml_get_buf(curbuf, pos.lnum, FALSE); @@ -1431,18 +1437,19 @@ swapchar(int op_type, pos_T *pos) if (c >= 0x80 && op_type == OP_ROT13) return FALSE; - if (op_type == OP_UPPER && c == 0xdf - && (enc_latin1like || STRCMP(p_enc, "iso-8859-2") == 0)) + // ~ is OP_NOP, g~ is OP_TILDE, gU is OP_UPPER + if ((op_type == OP_UPPER || op_type == OP_NOP || op_type == OP_TILDE) + && c == 0xdf + && (enc_latin1like || STRCMP(p_enc, "iso-8859-2") == 0)) { pos_T sp = curwin->w_cursor; - // Special handling of German sharp s: change to "SS". + // Special handling for lowercase German sharp s (ß): convert to uppercase (ẞ). curwin->w_cursor = *pos; del_char(FALSE); - ins_char('S'); - ins_char('S'); + ins_char(0x1E9E); curwin->w_cursor = sp; - inc(pos); + return TRUE; } if (enc_dbcs != 0 && c >= 0x100) // No lower/uppercase letter @@ -1487,16 +1494,13 @@ swapchar(int op_type, pos_T *pos) void op_insert(oparg_T *oap, long count1) { - long ins_len, pre_textlen = 0; - char_u *firstline, *ins_text; + long pre_textlen = 0; colnr_T ind_pre_col = 0, ind_post_col; int ind_pre_vcol = 0, ind_post_vcol = 0; struct block_def bd; int i; pos_T t1; pos_T start_insert; - // offset when cursor was moved in insert mode - int offset = 0; // edit() changes this - record it for OP_APPEND bd.is_MAX = (curwin->w_curswant == MAXCOL); @@ -1533,11 +1537,9 @@ op_insert(oparg_T *oap, long count1) // Get indent information ind_pre_col = (colnr_T)getwhitecols_curline(); ind_pre_vcol = get_indent(); - firstline = ml_get(oap->start.lnum) + bd.textcol; - + pre_textlen = ml_get_len(oap->start.lnum) - bd.textcol; if (oap->op_type == OP_APPEND) - firstline += bd.textlen; - pre_textlen = (long)STRLEN(firstline); + pre_textlen -= bd.textlen; } if (oap->op_type == OP_APPEND) @@ -1591,10 +1593,14 @@ op_insert(oparg_T *oap, long count1) if (oap->block_mode) { + long ins_len; + char_u *firstline, *ins_text; struct block_def bd2; int did_indent = FALSE; size_t len; int add; + // offset when cursor was moved in insert mode + int offset = 0; // If indent kicked in, the firstline might have changed // but only do that, if the indent actually increased. @@ -1678,7 +1684,7 @@ op_insert(oparg_T *oap, long count1) * copy of the required string. */ firstline = ml_get(oap->start.lnum); - len = STRLEN(firstline); + len = ml_get_len(oap->start.lnum); add = bd.textcol; if (oap->op_type == OP_APPEND) { @@ -1698,11 +1704,10 @@ op_insert(oparg_T *oap, long count1) } } if ((size_t)add > len) - firstline += len; // short line, point to the NUL - else - firstline += add; - if (pre_textlen >= 0 && (ins_len = - (long)STRLEN(firstline) - pre_textlen - offset) > 0) + add = len; // short line, point to the NUL + firstline += add; + len -= add; + if (pre_textlen >= 0 && (ins_len = len - pre_textlen - offset) > 0) { ins_text = vim_strnsave(firstline, ins_len); if (ins_text != NULL) @@ -1770,7 +1775,7 @@ op_change(oparg_T *oap) || gchar_cursor() == NUL)) coladvance_force(getviscol()); firstline = ml_get(oap->start.lnum); - pre_textlen = (long)STRLEN(firstline); + pre_textlen = ml_get_len(oap->start.lnum); pre_indent = (long)getwhitecols(firstline); bd.textcol = curwin->w_cursor.col; } @@ -1804,7 +1809,7 @@ op_change(oparg_T *oap) bd.textcol += new_indent - pre_indent; } - ins_len = (long)STRLEN(firstline) - pre_textlen; + ins_len = ml_get_len(oap->start.lnum) - pre_textlen; if (ins_len > 0) { // Subsequent calls to ml_get() flush the firstline data - take a @@ -1830,7 +1835,8 @@ op_change(oparg_T *oap) else vpos.coladd = 0; oldp = ml_get(linenr); - newp = alloc(STRLEN(oldp) + vpos.coladd + ins_len + 1); + newp = alloc(ml_get_len(linenr) + + vpos.coladd + ins_len + 1); if (newp == NULL) continue; // copy up to block start @@ -2414,6 +2420,84 @@ block_prep( } /* + * Get block text from "start" to "end" + */ + void +charwise_block_prep( + pos_T start, + pos_T end, + struct block_def *bdp, + linenr_T lnum, + int inclusive) +{ + colnr_T startcol = 0, endcol = MAXCOL; + int is_oneChar = FALSE; + colnr_T cs, ce; + char_u *p; + + p = ml_get(lnum); + bdp->startspaces = 0; + bdp->endspaces = 0; + + if (lnum == start.lnum) + { + startcol = start.col; + if (virtual_op) + { + getvcol(curwin, &start, &cs, NULL, &ce); + if (ce != cs && start.coladd > 0) + { + // Part of a tab selected -- but don't + // double-count it. + bdp->startspaces = (ce - cs + 1) + - start.coladd; + if (bdp->startspaces < 0) + bdp->startspaces = 0; + startcol++; + } + } + } + + if (lnum == end.lnum) + { + endcol = end.col; + if (virtual_op) + { + getvcol(curwin, &end, &cs, NULL, &ce); + if (p[endcol] == NUL || (cs + end.coladd < ce + // Don't add space for double-wide + // char; endcol will be on last byte + // of multi-byte char. + && (*mb_head_off)(p, p + endcol) == 0)) + { + if (start.lnum == end.lnum + && start.col == end.col) + { + // Special case: inside a single char + is_oneChar = TRUE; + bdp->startspaces = end.coladd + - start.coladd + inclusive; + endcol = startcol; + } + else + { + bdp->endspaces = end.coladd + + inclusive; + endcol -= inclusive; + } + } + } + } + if (endcol == MAXCOL) + endcol = ml_get_len(lnum); + if (startcol > endcol || is_oneChar) + bdp->textlen = 0; + else + bdp->textlen = endcol - startcol + inclusive; + bdp->textstart = p + startcol; +} + +/* * Handle the add/subtract operator. */ void @@ -2479,13 +2563,13 @@ op_addsub( { curwin->w_cursor.col = 0; pos.col = 0; - length = (colnr_T)STRLEN(ml_get(pos.lnum)); + length = ml_get_len(pos.lnum); } else // oap->motion_type == MCHAR { if (pos.lnum == oap->start.lnum && !oap->inclusive) dec(&(oap->end)); - length = (colnr_T)STRLEN(ml_get(pos.lnum)); + length = ml_get_len(pos.lnum); pos.col = 0; if (pos.lnum == oap->start.lnum) { @@ -2494,7 +2578,7 @@ op_addsub( } if (pos.lnum == oap->end.lnum) { - length = (int)STRLEN(ml_get(oap->end.lnum)); + length = ml_get_len(oap->end.lnum); if (oap->end.col >= length) oap->end.col = length - 1; length = oap->end.col - pos.col + 1; @@ -2566,6 +2650,7 @@ do_addsub( uvarnumber_T n; uvarnumber_T oldn; char_u *ptr; + int linelen; int c; int todel; int do_hex; @@ -2599,9 +2684,10 @@ do_addsub( curwin->w_cursor = *pos; ptr = ml_get(pos->lnum); + linelen = ml_get_len(pos->lnum); col = pos->col; - if (*ptr == NUL || col + !!save_coladd >= (int)STRLEN(ptr)) + if (col + !!save_coladd >= linelen) goto theend; /* @@ -2781,8 +2867,7 @@ do_addsub( // get the number value (unsigned) if (visual && VIsual_mode != 'V') maxlen = (curbuf->b_visual.vi_curswant == MAXCOL - ? (int)STRLEN(ptr) - col - : length); + ? linelen - col : length); int overflow = FALSE; vim_str2nr(ptr + col, &pre, &length, @@ -2962,14 +3047,12 @@ do_addsub( // del_char() will also mark line needing displaying if (todel > 0) { - int bytes_after = (int)STRLEN(ml_get_curline()) - - curwin->w_cursor.col; + int bytes_after = ml_get_curline_len() - curwin->w_cursor.col; // Delete the one character before the insert. curwin->w_cursor = save_pos; (void)del_char(FALSE); - curwin->w_cursor.col = (colnr_T)(STRLEN(ml_get_curline()) - - bytes_after); + curwin->w_cursor.col = ml_get_curline_len() - bytes_after; --todel; } while (todel-- > 0) @@ -3275,7 +3358,7 @@ cursor_pos_info(dict_T *dict) validate_virtcol(); col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); - col_print(buf2, sizeof(buf2), (int)STRLEN(p), + col_print(buf2, sizeof(buf2), ml_get_curline_len(), linetabsize_str(p)); if (char_count_cursor == byte_count_cursor @@ -3772,13 +3855,12 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank) if (LT_POS(VIsual, curwin->w_cursor)) { VIsual.col = 0; - curwin->w_cursor.col = - (colnr_T)STRLEN(ml_get(curwin->w_cursor.lnum)); + curwin->w_cursor.col = ml_get_len(curwin->w_cursor.lnum); } else { curwin->w_cursor.col = 0; - VIsual.col = (colnr_T)STRLEN(ml_get(VIsual.lnum)); + VIsual.col = ml_get_len(VIsual.lnum); } VIsual_mode = 'v'; } @@ -3809,7 +3891,7 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank) || oap->motion_type == MLINE) && hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) - curwin->w_cursor.col = (colnr_T)STRLEN(ml_get_curline()); + curwin->w_cursor.col = ml_get_curline_len(); } #endif oap->end = curwin->w_cursor; @@ -3830,7 +3912,7 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank) NULL)) curwin->w_cursor.col = 0; if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum)) - oap->start.col = (colnr_T)STRLEN(ml_get(oap->start.lnum)); + oap->start.col = ml_get_len(oap->start.lnum); } #endif oap->end = oap->start; @@ -4040,7 +4122,7 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank) oap->motion_type = MLINE; else { - oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum)); + oap->end.col = ml_get_len(oap->end.lnum); if (oap->end.col) { --oap->end.col; |