aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/charset.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
commit1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch)
treecd08258054db80bb9a11b1061bb091c70b76926a /src/nvim/charset.c
parenteaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-aucmd_textputpost.tar.gz
rneovim-aucmd_textputpost.tar.bz2
rneovim-aucmd_textputpost.zip
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'src/nvim/charset.c')
-rw-r--r--src/nvim/charset.c492
1 files changed, 106 insertions, 386 deletions
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 5aec9ccf9d..48a9808b31 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -1,6 +1,3 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
/// @file charset.c
///
/// Code related to character sets.
@@ -11,33 +8,26 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include "auto/config.h"
#include "klib/kvec.h"
-#include "nvim/ascii.h"
+#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/garray.h"
#include "nvim/globals.h"
-#include "nvim/grid_defs.h"
-#include "nvim/indent.h"
#include "nvim/keycodes.h"
-#include "nvim/macros.h"
-#include "nvim/mark.h"
+#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
-#include "nvim/memline.h"
#include "nvim/memory.h"
-#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/path.h"
-#include "nvim/plines.h"
-#include "nvim/pos.h"
-#include "nvim/state.h"
+#include "nvim/pos_defs.h"
#include "nvim/strings.h"
-#include "nvim/vim.h"
+#include "nvim/vim_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "charset.c.generated.h"
@@ -55,7 +45,7 @@ static bool chartab_initialized = false;
((chartab)[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f)))
// Table used below, see init_chartab() for an explanation
-static char_u g_chartab[256];
+static uint8_t g_chartab[256];
// Flags for g_chartab[].
#define CT_CELL_MASK 0x07 ///< mask: nr of display cells (1, 2 or 4)
@@ -97,10 +87,6 @@ int init_chartab(void)
int buf_init_chartab(buf_T *buf, int global)
{
int c;
- int c2;
- int i;
- bool tilde;
- bool do_isalpha;
if (global) {
// Set the default size for printable characters:
@@ -119,19 +105,13 @@ int buf_init_chartab(buf_T *buf, int global)
while (c < 256) {
if (c >= 0xa0) {
// UTF-8: bytes 0xa0 - 0xff are printable (latin1)
- g_chartab[c++] = CT_PRINT_CHAR + 1;
+ // Also assume that every multi-byte char is a filename character.
+ g_chartab[c++] = (CT_PRINT_CHAR | CT_FNAME_CHAR) + 1;
} else {
// the rest is unprintable by default
g_chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;
}
}
-
- // Assume that every multi-byte char is a filename character.
- for (c = 1; c < 256; c++) {
- if (c >= 0xa0) {
- g_chartab[c] |= CT_FNAME_CHAR;
- }
- }
}
// Init word char flags all to false
@@ -145,7 +125,7 @@ int buf_init_chartab(buf_T *buf, int global)
// Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
// options Each option is a list of characters, character numbers or
// ranges, separated by commas, e.g.: "200-210,x,#-178,-"
- for (i = global ? 0 : 3; i <= 3; i++) {
+ for (int i = global ? 0 : 3; i <= 3; i++) {
const char *p;
if (i == 0) {
// first round: 'isident'
@@ -162,8 +142,8 @@ int buf_init_chartab(buf_T *buf, int global)
}
while (*p) {
- tilde = false;
- do_isalpha = false;
+ bool tilde = false;
+ bool do_isalpha = false;
if ((*p == '^') && (p[1] != NUL)) {
tilde = true;
@@ -175,7 +155,7 @@ int buf_init_chartab(buf_T *buf, int global)
} else {
c = mb_ptr2char_adv(&p);
}
- c2 = -1;
+ int c2 = -1;
if ((*p == '-') && (p[1] != NUL)) {
p++;
@@ -286,7 +266,7 @@ void trans_characters(char *buf, int bufsize)
if ((trs_len = utfc_ptr2len(buf)) > 1) {
len -= trs_len;
} else {
- trs = (char *)transchar_byte((uint8_t)(*buf));
+ trs = transchar_byte((uint8_t)(*buf));
trs_len = (int)strlen(trs);
if (trs_len > 1) {
@@ -321,15 +301,13 @@ size_t transstr_len(const char *const s, bool untab)
while (*p) {
const size_t l = (size_t)utfc_ptr2len(p);
if (l > 1) {
- int pcc[MAX_MCO + 1];
- pcc[0] = utfc_ptr2char(p, &pcc[1]);
-
- if (vim_isprintc(pcc[0])) {
+ if (vim_isprintc(utf_ptr2char(p))) {
len += l;
} else {
- for (size_t i = 0; i < ARRAY_SIZE(pcc) && pcc[i]; i++) {
+ for (size_t off = 0; off < l; off += (size_t)utf_ptr2len(p + off)) {
+ int c = utf_ptr2char(p + off);
char hexbuf[9];
- len += transchar_hex(hexbuf, pcc[i]);
+ len += transchar_hex(hexbuf, c);
}
}
p += l;
@@ -354,29 +332,29 @@ size_t transstr_len(const char *const s, bool untab)
/// @param[in] untab remove tab characters
///
/// @return length of the resulting string, without the NUL byte.
-size_t transstr_buf(const char *const s, char *const buf, const size_t len, bool untab)
+size_t transstr_buf(const char *const s, const ssize_t slen, char *const buf, const size_t buflen,
+ bool untab)
FUNC_ATTR_NONNULL_ALL
{
const char *p = s;
char *buf_p = buf;
- char *const buf_e = buf_p + len - 1;
+ char *const buf_e = buf_p + buflen - 1;
- while (*p != NUL && buf_p < buf_e) {
+ while ((slen < 0 || (p - s) < slen) && *p != NUL && buf_p < buf_e) {
const size_t l = (size_t)utfc_ptr2len(p);
if (l > 1) {
if (buf_p + l > buf_e) {
break; // Exceeded `buf` size.
}
- int pcc[MAX_MCO + 1];
- pcc[0] = utfc_ptr2char(p, &pcc[1]);
- if (vim_isprintc(pcc[0])) {
+ if (vim_isprintc(utf_ptr2char(p))) {
memmove(buf_p, p, l);
buf_p += l;
} else {
- for (size_t i = 0; i < ARRAY_SIZE(pcc) && pcc[i]; i++) {
+ for (size_t off = 0; off < l; off += (size_t)utf_ptr2len(p + off)) {
+ int c = utf_ptr2char(p + off);
char hexbuf[9]; // <up to 6 bytes>NUL
- const size_t hexlen = transchar_hex(hexbuf, pcc[i]);
+ const size_t hexlen = transchar_hex(hexbuf, c);
if (buf_p + hexlen > buf_e) {
break;
}
@@ -388,7 +366,7 @@ size_t transstr_buf(const char *const s, char *const buf, const size_t len, bool
} else if (*p == TAB && !untab) {
*buf_p++ = *p++;
} else {
- const char *const tb = (const char *)transchar_byte((uint8_t)(*p++));
+ const char *const tb = transchar_byte((uint8_t)(*p++));
const size_t tb_len = strlen(tb);
if (buf_p + tb_len > buf_e) {
break; // Exceeded `buf` size.
@@ -416,7 +394,7 @@ char *transstr(const char *const s, bool untab)
// multi-byte characters.
const size_t len = transstr_len(s, untab) + 1;
char *const buf = xmalloc(len);
- transstr_buf(s, buf, len, untab);
+ transstr_buf(s, -1, buf, len, untab);
return buf;
}
@@ -431,7 +409,7 @@ size_t kv_transstr(StringBuilder *str, const char *const s, bool untab)
// multi-byte characters.
const size_t len = transstr_len(s, untab);
kv_ensure_space(*str, len + 1);
- transstr_buf(s, str->items + str->size, len + 1, untab);
+ transstr_buf(s, -1, str->items + str->size, len + 1, untab);
str->size += len; // do not include NUL byte
return len;
}
@@ -445,7 +423,6 @@ char *str_foldcase(char *str, int orglen, char *buf, int buflen)
FUNC_ATTR_NONNULL_RET
{
garray_T ga;
- int i;
int len = orglen;
#define GA_CHAR(i) ((char *)ga.ga_data)[i]
@@ -475,7 +452,7 @@ char *str_foldcase(char *str, int orglen, char *buf, int buflen)
}
// Make each character lower case.
- i = 0;
+ int i = 0;
while (STR_CHAR(i) != NUL) {
int c = utf_ptr2char(STR_PTR(i));
int olen = utf_ptr2len(STR_PTR(i));
@@ -531,7 +508,7 @@ char *str_foldcase(char *str, int orglen, char *buf, int buflen)
// Does NOT work for multi-byte characters, c must be <= 255.
// Also doesn't work for the first byte of a multi-byte, "c" must be a
// character!
-static char_u transchar_charbuf[11];
+static uint8_t transchar_charbuf[11];
/// Translate a character into a printable one, leaving printable ASCII intact
///
@@ -542,11 +519,10 @@ static char_u transchar_charbuf[11];
/// @return translated character into a static buffer.
char *transchar(int c)
{
- return (char *)transchar_buf(curbuf, c);
+ return transchar_buf(curbuf, c);
}
-char_u *transchar_buf(const buf_T *buf, int c)
- FUNC_ATTR_NONNULL_ALL
+char *transchar_buf(const buf_T *buf, int c)
{
int i = 0;
if (IS_SPECIAL(c)) {
@@ -558,33 +534,46 @@ char_u *transchar_buf(const buf_T *buf, int c)
}
if ((!chartab_initialized && (c >= ' ' && c <= '~'))
- || ((c <= 0xFF) && vim_isprintc_strict(c))) {
+ || ((c <= 0xFF) && vim_isprintc(c))) {
// printable character
- transchar_charbuf[i] = (char_u)c;
+ transchar_charbuf[i] = (uint8_t)c;
transchar_charbuf[i + 1] = NUL;
} else if (c <= 0xFF) {
- transchar_nonprint(buf, transchar_charbuf + i, c);
+ transchar_nonprint(buf, (char *)transchar_charbuf + i, c);
} else {
transchar_hex((char *)transchar_charbuf + i, c);
}
- return transchar_charbuf;
+ return (char *)transchar_charbuf;
+}
+
+/// Like transchar(), but called with a byte instead of a character.
+///
+/// Checks for an illegal UTF-8 byte. Uses 'fileformat' of the current buffer.
+///
+/// @param[in] c Byte to translate.
+///
+/// @return pointer to translated character in transchar_charbuf.
+char *transchar_byte(const int c)
+ FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return transchar_byte_buf(curbuf, c);
}
-/// Like transchar(), but called with a byte instead of a character
+/// Like transchar_buf(), but called with a byte instead of a character.
///
-/// Checks for an illegal UTF-8 byte.
+/// Checks for an illegal UTF-8 byte. Uses 'fileformat' of "buf", unless it is NULL.
///
/// @param[in] c Byte to translate.
///
/// @return pointer to translated character in transchar_charbuf.
-char_u *transchar_byte(const int c)
+char *transchar_byte_buf(const buf_T *buf, const int c)
FUNC_ATTR_WARN_UNUSED_RESULT
{
if (c >= 0x80) {
- transchar_nonprint(curbuf, transchar_charbuf, c);
- return transchar_charbuf;
+ transchar_nonprint(buf, (char *)transchar_charbuf, c);
+ return (char *)transchar_charbuf;
}
- return (char_u *)transchar(c);
+ return transchar_buf(buf, c);
}
/// Convert non-printable characters to 2..4 printable ones
@@ -596,13 +585,12 @@ char_u *transchar_byte(const int c)
/// at least 5 bytes (conversion result + NUL).
/// @param[in] c Character to convert. NUL is assumed to be NL according to
/// `:h NL-used-for-NUL`.
-void transchar_nonprint(const buf_T *buf, char_u *charbuf, int c)
- FUNC_ATTR_NONNULL_ALL
+void transchar_nonprint(const buf_T *buf, char *charbuf, int c)
{
if (c == NL) {
// we use newline in place of a NUL
c = NUL;
- } else if ((c == CAR) && (get_fileformat(buf) == EOL_MAC)) {
+ } else if (buf != NULL && c == CAR && get_fileformat(buf) == EOL_MAC) {
// we use CR in place of NL in this case
c = NL;
}
@@ -610,12 +598,12 @@ void transchar_nonprint(const buf_T *buf, char_u *charbuf, int c)
if (dy_flags & DY_UHEX || c > 0x7f) {
// 'display' has "uhex"
- transchar_hex((char *)charbuf, c);
+ transchar_hex(charbuf, c);
} else {
// 0x00 - 0x1f and 0x7f
charbuf[0] = '^';
// DEL displayed as ^?
- charbuf[1] = (char_u)(c ^ 0x40);
+ charbuf[1] = (char)(uint8_t)(c ^ 0x40);
charbuf[2] = NUL;
}
@@ -633,8 +621,8 @@ size_t transchar_hex(char *const buf, const int c)
size_t i = 0;
buf[i++] = '<';
- if (c > 255) {
- if (c > 255 * 256) {
+ if (c > 0xFF) {
+ if (c > 0xFFFF) {
buf[i++] = (char)nr2hex((unsigned)c >> 20);
buf[i++] = (char)nr2hex((unsigned)c >> 16);
}
@@ -648,6 +636,17 @@ size_t transchar_hex(char *const buf, const int c)
return i;
}
+/// Mirror text "str" for right-left displaying.
+/// Only works for single-byte characters (e.g., numbers).
+void rl_mirror_ascii(char *str, char *end)
+{
+ for (char *p1 = str, *p2 = (end ? end : str + strlen(str)) - 1; p1 < p2; p1++, p2--) {
+ char t = *p1;
+ *p1 = *p2;
+ *p2 = t;
+ }
+}
+
/// Convert the lower 4 bits of byte "c" to its hex character
///
/// Lower case letters are used to avoid the confusion of <F1> being 0xf1 or
@@ -732,7 +731,7 @@ int ptr2cells(const char *p_in)
/// @param s
///
/// @return number of character cells.
-int vim_strsize(char *s)
+int vim_strsize(const char *s)
{
return vim_strnsize(s, MAXCOL);
}
@@ -746,7 +745,7 @@ int vim_strsize(char *s)
/// @param len
///
/// @return Number of character cells.
-int vim_strnsize(char *s, int len)
+int vim_strnsize(const char *s, int len)
{
assert(s != NULL);
int size = 0;
@@ -835,8 +834,10 @@ bool vim_iswordp_buf(const char *const p, buf_T *const buf)
return vim_iswordc_buf(c, buf);
}
-/// Check that "c" is a valid file-name character.
+/// Check that "c" is a valid file-name character as specified with the
+/// 'isfname' option.
/// Assume characters above 0x100 are valid (multi-byte).
+/// To be used for commands like "gf".
///
/// @param c character to check
bool vim_isfilec(int c)
@@ -845,6 +846,14 @@ bool vim_isfilec(int c)
return c >= 0x100 || (c > 0 && (g_chartab[c] & CT_FNAME_CHAR));
}
+/// Check if "c" is a valid file-name character, including characters left
+/// out of 'isfname' to make "gf" work, such as comma, space, '@', etc.
+bool vim_is_fname_char(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return vim_isfilec(c) || c == ',' || c == ' ' || c == '@';
+}
+
/// Check that "c" is a valid file-name character or a wildcard character
/// Assume characters above 0x100 are valid (multi-byte).
/// Explicitly interpret ']' as a wildcard character as path_has_wildcard("]")
@@ -861,7 +870,6 @@ bool vim_isfilec_or_wc(int c)
}
/// Check that "c" is a printable character.
-/// Assume characters above 0x100 are printable for double-byte encodings.
///
/// @param c character to check
bool vim_isprintc(int c)
@@ -873,316 +881,19 @@ bool vim_isprintc(int c)
return c > 0 && (g_chartab[c] & CT_PRINT_CHAR);
}
-/// Strict version of vim_isprintc(c), don't return true if "c" is the head
-/// byte of a double-byte character.
-///
-/// @param c character to check
-///
-/// @return true if "c" is a printable character.
-bool vim_isprintc_strict(int c)
- FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
-{
- if (c >= 0x100) {
- return utf_printable(c);
- }
- return c > 0 && (g_chartab[c] & CT_PRINT_CHAR);
-}
-
-/// Check that virtual column "vcol" is in the rightmost column of window "wp".
-///
-/// @param wp window
-/// @param vcol column number
-bool in_win_border(win_T *wp, colnr_T vcol)
- FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
-{
- if (wp->w_width_inner == 0) {
- // there is no border
- return false;
- }
- int width1 = wp->w_width_inner - win_col_off(wp); // width of first line (after line number)
-
- if ((int)vcol < width1 - 1) {
- return false;
- }
-
- if ((int)vcol == width1 - 1) {
- return true;
- }
- int width2 = width1 + win_col_off2(wp); // width of further lines
-
- if (width2 <= 0) {
- return false;
- }
- return (vcol - width1) % width2 == width2 - 1;
-}
-
-/// Get virtual column number of pos.
-/// start: on the first position of this character (TAB, ctrl)
-/// cursor: where the cursor is on this character (first char, except for TAB)
-/// end: on the last position of this character (TAB, ctrl)
-///
-/// This is used very often, keep it fast!
-///
-/// @param wp
-/// @param pos
-/// @param start
-/// @param cursor
-/// @param end
-void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end)
-{
- char *ptr; // points to current char
- char *posptr; // points to char at pos->col
- int incr;
- int head;
- long *vts = wp->w_buffer->b_p_vts_array;
- int ts = (int)wp->w_buffer->b_p_ts;
-
- colnr_T vcol = 0;
- char *line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, false); // start of the line
-
- if (pos->col == MAXCOL) {
- // continue until the NUL
- posptr = NULL;
- } else {
- // In a few cases the position can be beyond the end of the line.
- for (colnr_T i = 0; i < pos->col; i++) {
- if (ptr[i] == NUL) {
- pos->col = i;
- break;
- }
- }
- posptr = ptr + pos->col;
- posptr -= utf_head_off(line, posptr);
- }
-
- chartabsize_T cts;
- init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
-
- // This function is used very often, do some speed optimizations.
- // When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
- // and there are no virtual text use a simple loop.
- // Also use this when 'list' is set but tabs take their normal size.
- if ((!wp->w_p_list || (wp->w_p_lcs_chars.tab1 != NUL))
- && !wp->w_p_lbr
- && *get_showbreak_value(wp) == NUL
- && !wp->w_p_bri
- && !cts.cts_has_virt_text) {
- for (;;) {
- head = 0;
- int c = (uint8_t)(*ptr);
-
- // make sure we don't go past the end of the line
- if (c == NUL) {
- // NUL at end of line only takes one column
- incr = 1;
- break;
- }
-
- // A tab gets expanded, depending on the current column
- if (c == TAB) {
- incr = tabstop_padding(vcol, ts, vts);
- } else {
- // For utf-8, if the byte is >= 0x80, need to look at
- // further bytes to find the cell width.
- if (c >= 0x80) {
- incr = utf_ptr2cells(ptr);
- } else {
- incr = g_chartab[c] & CT_CELL_MASK;
- }
-
- // If a double-cell char doesn't fit at the end of a line
- // it wraps to the next line, it's like this char is three
- // cells wide.
- if ((incr == 2)
- && wp->w_p_wrap
- && (MB_BYTE2LEN((uint8_t)(*ptr)) > 1)
- && in_win_border(wp, vcol)) {
- incr++;
- head = 1;
- }
- }
-
- if ((posptr != NULL) && (ptr >= posptr)) {
- // character at pos->col
- break;
- }
-
- vcol += incr;
- MB_PTR_ADV(ptr);
- }
- } else {
- for (;;) {
- // A tab gets expanded, depending on the current column
- // Other things also take up space.
- head = 0;
- incr = win_lbr_chartabsize(&cts, &head);
-
- // make sure we don't go past the end of the line
- if (*cts.cts_ptr == NUL) {
- // NUL at end of line only takes one column
- incr = 1;
- break;
- }
-
- if ((posptr != NULL) && (cts.cts_ptr >= posptr)) {
- // character at pos->col
- break;
- }
-
- cts.cts_vcol += incr;
- MB_PTR_ADV(cts.cts_ptr);
- }
- vcol = cts.cts_vcol;
- ptr = cts.cts_ptr;
- }
- clear_chartabsize_arg(&cts);
-
- if (start != NULL) {
- *start = vcol + head;
- }
-
- if (end != NULL) {
- *end = vcol + incr - 1;
- }
-
- if (cursor != NULL) {
- // cursor is after inserted text
- vcol += cts.cts_cur_text_width;
- if ((*ptr == TAB)
- && (State & MODE_NORMAL)
- && !wp->w_p_list
- && !virtual_active()
- && !(VIsual_active && ((*p_sel == 'e') || ltoreq(*pos, VIsual)))) {
- // cursor at end
- *cursor = vcol + incr - 1;
- } else {
- // cursor at start
- *cursor = vcol + head;
- }
- }
-}
-
-/// Get virtual cursor column in the current window, pretending 'list' is off.
-///
-/// @param posp
-///
-/// @retujrn The virtual cursor column.
-colnr_T getvcol_nolist(pos_T *posp)
-{
- int list_save = curwin->w_p_list;
- colnr_T vcol;
-
- curwin->w_p_list = false;
- if (posp->coladd) {
- getvvcol(curwin, posp, NULL, &vcol, NULL);
- } else {
- getvcol(curwin, posp, NULL, &vcol, NULL);
- }
- curwin->w_p_list = list_save;
- return vcol;
-}
-
-/// Get virtual column in virtual mode.
-///
-/// @param wp
-/// @param pos
-/// @param start
-/// @param cursor
-/// @param end
-void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end)
-{
- colnr_T col;
-
- if (virtual_active()) {
- // For virtual mode, only want one value
- getvcol(wp, pos, &col, NULL, NULL);
-
- colnr_T coladd = pos->coladd;
- colnr_T endadd = 0;
-
- // Cannot put the cursor on part of a wide character.
- char *ptr = ml_get_buf(wp->w_buffer, pos->lnum, false);
-
- if (pos->col < (colnr_T)strlen(ptr)) {
- int c = utf_ptr2char(ptr + pos->col);
- if ((c != TAB) && vim_isprintc(c)) {
- endadd = (colnr_T)(char2cells(c) - 1);
- if (coladd > endadd) {
- // past end of line
- endadd = 0;
- } else {
- coladd = 0;
- }
- }
- }
- col += coladd;
-
- if (start != NULL) {
- *start = col;
- }
-
- if (cursor != NULL) {
- *cursor = col;
- }
-
- if (end != NULL) {
- *end = col + endadd;
- }
- } else {
- getvcol(wp, pos, start, cursor, end);
- }
-}
-
-/// Get the leftmost and rightmost virtual column of pos1 and pos2.
-/// Used for Visual block mode.
-///
-/// @param wp
-/// @param pos1
-/// @param pos2
-/// @param left
-/// @param right
-void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right)
-{
- colnr_T from1;
- colnr_T from2;
- colnr_T to1;
- colnr_T to2;
-
- if (lt(*pos1, *pos2)) {
- getvvcol(wp, pos1, &from1, NULL, &to1);
- getvvcol(wp, pos2, &from2, NULL, &to2);
- } else {
- getvvcol(wp, pos2, &from1, NULL, &to1);
- getvvcol(wp, pos1, &from2, NULL, &to2);
- }
-
- if (from2 < from1) {
- *left = from2;
- } else {
- *left = from1;
- }
-
- if (to2 > to1) {
- if ((*p_sel == 'e') && (from2 - 1 >= to1)) {
- *right = from2 - 1;
- } else {
- *right = to2;
- }
- } else {
- *right = to1;
- }
-}
-
/// skipwhite: skip over ' ' and '\t'.
///
/// @param[in] p String to skip in.
///
/// @return Pointer to character after the skipped whitespace.
-char *skipwhite(const char *const p)
+char *skipwhite(const char *p)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_NONNULL_RET
{
- return skipwhite_len(p, strlen(p));
+ while (ascii_iswhite(*p)) {
+ p++;
+ }
+ return (char *)p;
}
/// Like `skipwhite`, but skip up to `len` characters.
@@ -1337,7 +1048,7 @@ char *skiptowhite(const char *p)
/// @param p
///
/// @return Pointer to the next whitespace character.
-char *skiptowhite_esc(char *p)
+char *skiptowhite_esc(const char *p)
FUNC_ATTR_PURE
{
while (*p != ' ' && *p != '\t' && *p != NUL) {
@@ -1346,7 +1057,7 @@ char *skiptowhite_esc(char *p)
}
p++;
}
- return p;
+ return (char *)p;
}
/// Skip over text until '\n' or NUL.
@@ -1431,14 +1142,14 @@ long getdigits_long(char **pp, bool strict, long def)
/// Gets a int32_t number from a string.
///
/// @see getdigits
-int32_t getdigits_int32(char **pp, bool strict, long def)
+int32_t getdigits_int32(char **pp, bool strict, int32_t def)
{
intmax_t number = getdigits(pp, strict, def);
-#if SIZEOF_INTMAX_T > SIZEOF_INT32_T
+#if SIZEOF_INTMAX_T > 4
if (strict) {
assert(number >= INT32_MIN && number <= INT32_MAX);
} else if (!(number >= INT32_MIN && number <= INT32_MAX)) {
- return (int32_t)def;
+ return def;
}
#endif
return (int32_t)number;
@@ -1488,9 +1199,10 @@ bool vim_isblankline(char *lbuf)
/// @param strict If true, fail if the number has unexpected trailing
/// alphanumeric chars: *len is set to 0 and nothing else is
/// returned.
+/// @param overflow When not NULL, set to true for overflow.
void vim_str2nr(const char *const start, int *const prep, int *const len, const int what,
varnumber_T *const nptr, uvarnumber_T *const unptr, const int maxlen,
- const bool strict)
+ const bool strict, bool *const overflow)
FUNC_ATTR_NONNULL_ARG(1)
{
const char *ptr = start;
@@ -1591,7 +1303,6 @@ void vim_str2nr(const char *const start, int *const prep, int *const len, const
// Do the conversion manually to avoid sscanf() quirks.
abort(); // Should’ve used goto earlier.
- // -V:PARSE_NUMBER:560
#define PARSE_NUMBER(base, cond, conv) \
do { \
const char *const after_prefix = ptr; \
@@ -1614,6 +1325,9 @@ void vim_str2nr(const char *const start, int *const prep, int *const len, const
un = (base) * un + digit; \
} else { \
un = UVARNUMBER_MAX; \
+ if (overflow != NULL) { \
+ *overflow = true; \
+ } \
} \
ptr++; \
} \
@@ -1652,12 +1366,18 @@ vim_str2nr_proceed:
// avoid ubsan error for overflow
if (un > VARNUMBER_MAX) {
*nptr = VARNUMBER_MIN;
+ if (overflow != NULL) {
+ *overflow = true;
+ }
} else {
*nptr = -(varnumber_T)un;
}
} else {
if (un > VARNUMBER_MAX) {
un = VARNUMBER_MAX;
+ if (overflow != NULL) {
+ *overflow = true;
+ }
}
*nptr = (varnumber_T)un;
}