summaryrefslogtreecommitdiffstats
path: root/src/ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ops.c')
-rw-r--r--src/ops.c431
1 files changed, 244 insertions, 187 deletions
diff --git a/src/ops.c b/src/ops.c
index 32461a8da6..94ef72fb5e 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -5375,9 +5375,10 @@ reverse_line(s)
* return FAIL for failure, OK otherwise
*/
int
-do_addsub(command, Prenum1)
+do_addsub(command, Prenum1, g_cmd)
int command;
linenr_T Prenum1;
+ int g_cmd; /* was g<c-a>/g<c-x> */
{
int col;
char_u *buf1;
@@ -5385,6 +5386,7 @@ do_addsub(command, Prenum1)
int hex; /* 'X' or 'x': hex; '0': octal */
static int hexupper = FALSE; /* 0xABC */
unsigned long n;
+ long offset = 0; /* line offset for Ctrl_V mode */
long_u oldn;
char_u *ptr;
int c;
@@ -5394,247 +5396,302 @@ do_addsub(command, Prenum1)
int dooct;
int doalp;
int firstdigit;
- int negative;
int subtract;
+ int negative = FALSE;
+ int visual = VIsual_active;
+ int i;
+ int lnum = curwin->w_cursor.lnum;
+ int lnume = curwin->w_cursor.lnum;
dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); /* "heX" */
dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); /* "Octal" */
doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); /* "alPha" */
- ptr = ml_get_curline();
- RLADDSUBFIX(ptr);
-
/*
* First check if we are on a hexadecimal number, after the "0x".
*/
col = curwin->w_cursor.col;
- if (dohex)
- while (col > 0 && vim_isxdigit(ptr[col]))
- --col;
- if ( dohex
- && col > 0
- && (ptr[col] == 'X'
- || ptr[col] == 'x')
- && ptr[col - 1] == '0'
- && vim_isxdigit(ptr[col + 1]))
+ if (VIsual_active)
{
- /*
- * Found hexadecimal number, move to its start.
- */
- --col;
+ if (lt(curwin->w_cursor, VIsual))
+ {
+ pos_T t;
+ t = curwin->w_cursor;
+ curwin->w_cursor = VIsual;
+ VIsual = t;
+ }
+ if (VIsual_mode == 'V')
+ VIsual.col = 0;
+
+ ptr = ml_get(VIsual.lnum);
+ RLADDSUBFIX(ptr);
+
+ /* store visual area for 'gv' */
+ curbuf->b_visual.vi_start = VIsual;
+ curbuf->b_visual.vi_end = curwin->w_cursor;
+ curbuf->b_visual.vi_mode = VIsual_mode;
+
+ col = VIsual.col;
+ lnum = VIsual.lnum;
+ lnume = curwin->w_cursor.lnum;
+ if (ptr[col] == '-')
+ {
+ negative = TRUE;
+ col++;
+ }
}
else
{
- /*
- * Search forward and then backward to find the start of number.
- */
- col = curwin->w_cursor.col;
-
- while (ptr[col] != NUL
- && !vim_isdigit(ptr[col])
- && !(doalp && ASCII_ISALPHA(ptr[col])))
- ++col;
+ ptr = ml_get_curline();
+ RLADDSUBFIX(ptr);
- while (col > 0
- && vim_isdigit(ptr[col - 1])
- && !(doalp && ASCII_ISALPHA(ptr[col])))
+ if (dohex)
+ while (col > 0 && vim_isxdigit(ptr[col]))
+ --col;
+ if ( dohex
+ && col > 0
+ && (ptr[col] == 'X'
+ || ptr[col] == 'x')
+ && ptr[col - 1] == '0'
+ && vim_isxdigit(ptr[col + 1]))
+ {
+ /* Found hexadecimal number, move to its start. */
--col;
+ }
+ else
+ {
+ /*
+ * Search forward and then backward to find the start of number.
+ */
+ col = curwin->w_cursor.col;
+
+ while (ptr[col] != NUL
+ && !vim_isdigit(ptr[col])
+ && !(doalp && ASCII_ISALPHA(ptr[col])))
+ ++col;
+
+ while (col > 0
+ && vim_isdigit(ptr[col - 1])
+ && !(doalp && ASCII_ISALPHA(ptr[col])))
+ --col;
+ }
}
- /*
- * If a number was found, and saving for undo works, replace the number.
- */
- firstdigit = ptr[col];
- RLADDSUBFIX(ptr);
- if ((!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit)))
- || u_save_cursor() != OK)
+ for (i = lnum; i <= lnume; i++)
{
- beep_flush();
- return FAIL;
- }
+ curwin->w_cursor.lnum = i;
+ ptr = ml_get_curline();
+ RLADDSUBFIX(ptr);
+ if ((int)STRLEN(ptr) <= col)
+ col = 0;
+ /*
+ * If a number was found, and saving for undo works, replace the number.
+ */
+ firstdigit = ptr[col];
+ RLADDSUBFIX(ptr);
+ if ((!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit)))
+ || u_save_cursor() != OK)
+ {
+ if (lnum < lnume)
+ /* Try again on next line */
+ continue;
+ beep_flush();
+ return FAIL;
+ }
- /* get ptr again, because u_save() may have changed it */
- ptr = ml_get_curline();
- RLADDSUBFIX(ptr);
+ ptr = ml_get_curline();
+ RLADDSUBFIX(ptr);
- if (doalp && ASCII_ISALPHA(firstdigit))
- {
- /* decrement or increment alphabetic character */
- if (command == Ctrl_X)
+ if (doalp && ASCII_ISALPHA(firstdigit))
{
- if (CharOrd(firstdigit) < Prenum1)
+ /* decrement or increment alphabetic character */
+ if (command == Ctrl_X)
{
- if (isupper(firstdigit))
- firstdigit = 'A';
+ if (CharOrd(firstdigit) < Prenum1)
+ {
+ if (isupper(firstdigit))
+ firstdigit = 'A';
+ else
+ firstdigit = 'a';
+ }
else
- firstdigit = 'a';
- }
- else
#ifdef EBCDIC
- firstdigit = EBCDIC_CHAR_ADD(firstdigit, -Prenum1);
+ firstdigit = EBCDIC_CHAR_ADD(firstdigit, -Prenum1);
#else
- firstdigit -= Prenum1;
+ firstdigit -= Prenum1;
#endif
- }
- else
- {
- if (26 - CharOrd(firstdigit) - 1 < Prenum1)
- {
- if (isupper(firstdigit))
- firstdigit = 'Z';
- else
- firstdigit = 'z';
}
else
+ {
+ if (26 - CharOrd(firstdigit) - 1 < Prenum1)
+ {
+ if (isupper(firstdigit))
+ firstdigit = 'Z';
+ else
+ firstdigit = 'z';
+ }
+ else
#ifdef EBCDIC
- firstdigit = EBCDIC_CHAR_ADD(firstdigit, Prenum1);
+ firstdigit = EBCDIC_CHAR_ADD(firstdigit, Prenum1);
#else
- firstdigit += Prenum1;
+ firstdigit += Prenum1;
#endif
+ }
+ curwin->w_cursor.col = col;
+ (void)del_char(FALSE);
+ ins_char(firstdigit);
}
- curwin->w_cursor.col = col;
- (void)del_char(FALSE);
- ins_char(firstdigit);
- }
- else
- {
- negative = FALSE;
- if (col > 0 && ptr[col - 1] == '-') /* negative number */
+ else
{
- --col;
- negative = TRUE;
- }
-
- /* get the number value (unsigned) */
- vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n);
+ if (col > 0 && ptr[col - 1] == '-' && !visual)
+ {
+ /* negative number */
+ --col;
+ negative = TRUE;
+ }
- /* ignore leading '-' for hex and octal numbers */
- if (hex && negative)
- {
- ++col;
- --length;
- negative = FALSE;
- }
+ /* get the number value (unsigned) */
+ vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n);
- /* add or subtract */
- subtract = FALSE;
- if (command == Ctrl_X)
- subtract ^= TRUE;
- if (negative)
- subtract ^= TRUE;
+ /* ignore leading '-' for hex and octal numbers */
+ if (hex && negative)
+ {
+ ++col;
+ --length;
+ negative = FALSE;
+ }
- oldn = n;
- if (subtract)
- n -= (unsigned long)Prenum1;
- else
- n += (unsigned long)Prenum1;
+ /* add or subtract */
+ subtract = FALSE;
+ if (command == Ctrl_X)
+ subtract ^= TRUE;
+ if (negative)
+ subtract ^= TRUE;
- /* handle wraparound for decimal numbers */
- if (!hex)
- {
+ oldn = n;
if (subtract)
+ n -= (unsigned long)Prenum1;
+ else
+ n += (unsigned long)Prenum1;
+
+ /* handle wraparound for decimal numbers */
+ if (!hex)
{
- if (n > oldn)
+ if (subtract)
{
- n = 1 + (n ^ (unsigned long)-1);
- negative ^= TRUE;
+ if (n > oldn)
+ {
+ n = 1 + (n ^ (unsigned long)-1);
+ negative ^= TRUE;
+ }
}
+ else
+ {
+ /* add */
+ if (n < oldn)
+ {
+ n = (n ^ (unsigned long)-1);
+ negative ^= TRUE;
+ }
+ }
+ if (n == 0)
+ negative = FALSE;
}
- else /* add */
+
+ /*
+ * Delete the old number.
+ */
+ curwin->w_cursor.col = col;
+ todel = length;
+ c = gchar_cursor();
+
+ /*
+ * Don't include the '-' in the length, only the length of the
+ * part after it is kept the same.
+ */
+ if (c == '-')
+ --length;
+ while (todel-- > 0)
{
- if (n < oldn)
+ if (c < 0x100 && isalpha(c))
{
- n = (n ^ (unsigned long)-1);
- negative ^= TRUE;
+ if (isupper(c))
+ hexupper = TRUE;
+ else
+ hexupper = FALSE;
}
+ /* del_char() will mark line needing displaying */
+ (void)del_char(FALSE);
+ c = gchar_cursor();
}
- if (n == 0)
- negative = FALSE;
- }
- /*
- * Delete the old number.
- */
- curwin->w_cursor.col = col;
- todel = length;
- c = gchar_cursor();
- /*
- * Don't include the '-' in the length, only the length of the part
- * after it is kept the same.
- */
- if (c == '-')
- --length;
- while (todel-- > 0)
- {
- if (c < 0x100 && isalpha(c))
+ /*
+ * Prepare the leading characters in buf1[].
+ * When there are many leading zeros it could be very long.
+ * Allocate a bit too much.
+ */
+ buf1 = alloc((unsigned)length + NUMBUFLEN);
+ if (buf1 == NULL)
+ return FAIL;
+ ptr = buf1;
+ /* do not add leading '-' for visual mode */
+ if (negative && !visual)
{
- if (isupper(c))
- hexupper = TRUE;
- else
- hexupper = FALSE;
+ *ptr++ = '-';
+ }
+ if (hex)
+ {
+ *ptr++ = '0';
+ --length;
+ }
+ if (hex == 'x' || hex == 'X')
+ {
+ *ptr++ = hex;
+ --length;
}
- /* del_char() will mark line needing displaying */
- (void)del_char(FALSE);
- c = gchar_cursor();
- }
- /*
- * Prepare the leading characters in buf1[].
- * When there are many leading zeros it could be very long. Allocate
- * a bit too much.
- */
- buf1 = alloc((unsigned)length + NUMBUFLEN);
- if (buf1 == NULL)
- return FAIL;
- ptr = buf1;
- if (negative)
- {
- *ptr++ = '-';
- }
- if (hex)
- {
- *ptr++ = '0';
- --length;
- }
- if (hex == 'x' || hex == 'X')
- {
- *ptr++ = hex;
- --length;
- }
+ /*
+ * Put the number characters in buf2[].
+ */
+ if (hex == 0)
+ sprintf((char *)buf2, "%lu", n + offset);
+ else if (hex == '0')
+ sprintf((char *)buf2, "%lo", n + offset);
+ else if (hex && hexupper)
+ sprintf((char *)buf2, "%lX", n + offset);
+ else
+ sprintf((char *)buf2, "%lx", n + offset);
+ length -= (int)STRLEN(buf2);
- /*
- * Put the number characters in buf2[].
- */
- if (hex == 0)
- sprintf((char *)buf2, "%lu", n);
- else if (hex == '0')
- sprintf((char *)buf2, "%lo", n);
- else if (hex && hexupper)
- sprintf((char *)buf2, "%lX", n);
- else
- sprintf((char *)buf2, "%lx", n);
- length -= (int)STRLEN(buf2);
+ if (g_cmd)
+ {
+ if (subtract)
+ offset -= (unsigned long)Prenum1;
+ else
+ offset += (unsigned long)Prenum1;
+ }
- /*
- * Adjust number of zeros to the new number of digits, so the
- * total length of the number remains the same.
- * Don't do this when
- * the result may look like an octal number.
- */
- if (firstdigit == '0' && !(dooct && hex == 0))
- while (length-- > 0)
- *ptr++ = '0';
- *ptr = NUL;
- STRCAT(buf1, buf2);
- ins_str(buf1); /* insert the new number */
- vim_free(buf1);
- }
- --curwin->w_cursor.col;
- curwin->w_set_curswant = TRUE;
+ /*
+ * Adjust number of zeros to the new number of digits, so the
+ * total length of the number remains the same.
+ * Don't do this when
+ * the result may look like an octal number.
+ */
+ if (firstdigit == '0' && !(dooct && hex == 0))
+ while (length-- > 0)
+ *ptr++ = '0';
+ *ptr = NUL;
+ STRCAT(buf1, buf2);
+ ins_str(buf1); /* insert the new number */
+ vim_free(buf1);
+ }
+ --curwin->w_cursor.col;
+ curwin->w_set_curswant = TRUE;
#ifdef FEAT_RIGHTLEFT
- ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE);
- RLADDSUBFIX(ptr);
+ ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE);
+ RLADDSUBFIX(ptr);
#endif
+ }
return OK;
}