summaryrefslogtreecommitdiffstats
path: root/src/ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ops.c')
-rw-r--r--src/ops.c196
1 files changed, 139 insertions, 57 deletions
diff --git a/src/ops.c b/src/ops.c
index f6d765b..dbdf119 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -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;