📄 charset.c
字号:
*
* No check for (c < 0x100) to make it a bit faster.
* This is the most often used function, keep it fast!
*/
int
safe_vim_isprintc(c)
int c;
{
return (chartab[c] & CHAR_IP);
}
/*
* like chartabsize(), but also check for line breaks on the screen
*/
int
lbr_chartabsize(s, col)
unsigned char *s;
colnr_t col;
{
if (!curwin->w_p_lbr && *p_sbr == NUL)
{
RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, *s, col)
}
return win_lbr_chartabsize(curwin, s, col, NULL);
}
/*
* This function is used very often, keep it fast!!!!
* Warning: *head is only set if it's a non-zero value, init to 0 before
* calling.
*/
int
win_lbr_chartabsize(wp, s, col, head)
WIN *wp;
unsigned char *s;
colnr_t col;
int *head;
{
int c = *s;
int size;
colnr_t col2;
colnr_t colmax;
int added;
int numberextra;
/*
* No 'linebreak' and 'showbreak': return quickly.
*/
if (!wp->w_p_lbr && *p_sbr == NUL)
{
RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, c, col)
}
/*
* First get normal size, without 'linebreak'
*/
size = win_chartabsize(wp, c, col);
/*
* If 'linebreak' set check at a blank before a non-blank if the line needs a
* break here
*/
if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(s[1]) &&
!wp->w_p_list && wp->w_p_wrap)
{
numberextra = wp->w_p_nu? 8: 0;
/* count all characters from first non-blank after a blank up to next
* non-blank after a blank */
col2 = col;
colmax = (((col + numberextra) / Columns) + 1) * Columns;
while ((c = *++s) != NUL && (vim_isbreak(c)
|| (!vim_isbreak(c) && (col2 == col || !vim_isbreak(s[-1])))))
{
col2 += win_chartabsize(wp, c, col2);
if (col2 + numberextra >= colmax) /* doesn't fit */
{
size = Columns - ((col + numberextra) % Columns);
break;
}
}
}
/*
* May have to add something for 'showbreak' string at start of line
* Set *head to the size of what we add.
*/
added = 0;
if (*p_sbr != NUL && wp->w_p_wrap && col)
{
numberextra = wp->w_p_nu? 8: 0;
col = (col + numberextra) % Columns;
if (col == 0 || col + size > (colnr_t)Columns)
{
added = STRLEN(p_sbr);
size += added;
if (col != 0)
added = 0;
}
}
if (head != NULL)
*head = added;
return size;
}
/*
* 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!
*/
void
getvcol(wp, pos, start, cursor, end)
WIN *wp;
FPOS *pos;
colnr_t *start;
colnr_t *cursor;
colnr_t *end;
{
int col;
colnr_t vcol;
char_u *ptr;
int incr;
int head;
int ts = wp->w_buffer->b_p_ts;
int c;
vcol = 0;
ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
/*
* This function is used very often, do some speed optimizations.
* When 'list', 'linebreak' and 'showbreak' are not set use a simple loop.
*/
if ((!wp->w_p_list || lcs_tab1) && !wp->w_p_lbr && *p_sbr == NUL)
{
head = 0;
for (col = pos->col; ; --col, ++ptr)
{
c = *ptr;
/* make sure we don't go past the end of the line */
if (c == NUL)
{
incr = 1; /* NUL at end of line only takes one column */
break;
}
/* A tab gets expanded, depending on the current column */
if (c == TAB)
incr = ts - (vcol % ts);
else
incr = CHARSIZE(c);
if (col == 0) /* character at pos.col */
break;
vcol += incr;
}
}
else
{
for (col = pos->col; ; --col, ++ptr)
{
/* A tab gets expanded, depending on the current column */
head = 0;
incr = win_lbr_chartabsize(wp, ptr, vcol, &head);
/* make sure we don't go past the end of the line */
if (*ptr == NUL)
{
incr = 1; /* NUL at end of line only takes one column */
break;
}
if (col == 0) /* character at pos.col */
break;
vcol += incr;
}
}
if (start != NULL)
*start = vcol + head;
if (end != NULL)
*end = vcol + incr - 1;
if (cursor != NULL)
{
if (*ptr == TAB && (State & NORMAL) && !wp->w_p_list
&& !(VIsual_active && *p_sel == 'e'))
*cursor = vcol + incr - 1; /* cursor at end */
else
*cursor = vcol + head; /* cursor at start */
}
}
/*
* Get the most left and most right virtual column of pos1 and pos2.
* Used for Visual block mode.
*/
void
getvcols(pos1, pos2, left, right)
FPOS *pos1, *pos2;
colnr_t *left, *right;
{
colnr_t l1, l2, r1, r2;
getvcol(curwin, pos1, &l1, NULL, &r1);
getvcol(curwin, pos2, &l2, NULL, &r2);
if (l1 < l2)
*left = l1;
else
*left = l2;
if (r1 > r2)
*right = r1;
else
*right = r2;
}
/*
* skipwhite: skip over ' ' and '\t'.
*/
char_u *
skipwhite(p)
char_u *p;
{
while (vim_iswhite(*p)) /* skip to next non-white */
++p;
return p;
}
/*
* skipdigits: skip over digits;
*/
char_u *
skipdigits(p)
char_u *p;
{
while (isdigit(*p)) /* skip to next non-digit */
++p;
return p;
}
/*
* vim_isdigit: version of isdigit() that can handle characters > 0x100.
*/
int
vim_isdigit(c)
int c;
{
return (c > 0 && c < 0x100 && isdigit(c));
}
/*
* skiptowhite: skip over text until ' ' or '\t' or NUL.
*/
char_u *
skiptowhite(p)
char_u *p;
{
while (*p != ' ' && *p != '\t' && *p != NUL)
++p;
return p;
}
/*
* skiptowhite_esc: Like skiptowhite(), but also skip escaped chars
*/
char_u *
skiptowhite_esc(p)
char_u *p;
{
while (*p != ' ' && *p != '\t' && *p != NUL)
{
if ((*p == '\\' || *p == Ctrl('V')) && *(p + 1) != NUL)
++p;
++p;
}
return p;
}
/*
* Getdigits: Get a number from a string and skip over it.
*
* Note: the argument is a pointer to a char_u pointer!
*/
long
getdigits(pp)
char_u **pp;
{
char_u *p;
long retval;
p = *pp;
retval = atol((char *)p);
p = skipdigits(p); /* skip to next non-digit */
*pp = p;
return retval;
}
/*
* Return TRUE if "lbuf" is empty or only contains blanks.
*/
int
vim_isblankline(lbuf)
char_u *lbuf;
{
char_u *p;
p = skipwhite(lbuf);
return (*p == NUL || *p == '\r' || *p == '\n');
}
/*
* Convert a string into a long and/or unsigned long, taking care of
* hexadecimal and octal numbers.
* If "hexp" is not NULL, returns a flag to indicate the type of the number:
* 0 decimal
* '0' octal
* 'X' hex
* 'x' hex
* If "len" is not NULL, the length of the number in characters is returned.
* If "nptr" is not NULL, the signed result is returned in it.
* If "unptr" is not NULL, the unsigned result is returned in it.
*/
void
vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr)
char_u *start;
int *hexp; /* return: type of number 0 = decimal, 'x'
or 'X' is hex, '0' = octal */
int *len; /* return: detected length of number */
int dooct; /* recognize octal number */
int dohex; /* recognize hex number */
long *nptr; /* return: signed result */
unsigned long *unptr; /* return: unsigned result */
{
char_u *ptr = start;
int hex = 0; /* default is decimal */
int negative = FALSE;
long n = 0;
unsigned long un = 0;
if (ptr[0] == '-')
{
negative = TRUE;
++ptr;
}
if (ptr[0] == '0') /* could be hex or octal */
{
hex = ptr[1];
if (dohex && (hex == 'X' || hex == 'x') && isxdigit(ptr[2]))
ptr += 2; /* hexadecimal */
else
{
if (dooct && isdigit(hex))
hex = '0'; /* octal */
else
hex = 0; /* 0 by itself is decimal */
}
}
/*
* Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
*/
if (hex)
{
if (hex == '0')
{
/* octal */
while ('0' <= *ptr && *ptr <= '7')
{
n = 8 * n + (long)(*ptr - '0');
un = 8 * un + (unsigned long)(*ptr - '0');
++ptr;
}
}
else
{
/* hex */
while (isxdigit(*ptr))
{
n = 16 * n + (long)hex2nr(*ptr);
un = 16 * un + (unsigned long)hex2nr(*ptr);
++ptr;
}
}
}
else
{
/* decimal */
while (isdigit(*ptr))
{
n = 10 * n + (long)(*ptr - '0');
un = 10 * un + (unsigned long)(*ptr - '0');
++ptr;
}
}
if (!hex && negative) /* account for leading '-' for decimal numbers */
n = -n;
if (hexp != NULL)
*hexp = hex;
if (len != NULL)
*len = ptr - start;
if (nptr != NULL)
*nptr = n;
if (unptr != NULL)
*unptr = un;
}
/*
* Return the value of a single hex character.
* Only valid when the argument is '0' - '9', 'A' - 'F' or 'a' - 'f'.
*/
int
hex2nr(c)
int c;
{
if (c >= 'a')
return c - 'a' + 10;
if (c >= 'A')
return c - 'A' + 10;
return c - '0';
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -