aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/plines.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/plines.c')
-rw-r--r--src/nvim/plines.c98
1 files changed, 66 insertions, 32 deletions
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index eca07f0144..5881d34c48 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -44,6 +44,8 @@
/// @param col
///
/// @return Number of cells.
+///
+/// @see charsize_nowrap()
int win_chartabsize(win_T *wp, char *p, colnr_T col)
{
buf_T *buf = wp->w_buffer;
@@ -55,7 +57,7 @@ int win_chartabsize(win_T *wp, char *p, colnr_T col)
/// Like linetabsize_str(), but "s" starts at virtual column "startvcol".
///
-/// @param startcol
+/// @param startvcol
/// @param s
///
/// @return Number of cells the string will take on the screen.
@@ -74,7 +76,7 @@ int linetabsize_col(int startvcol, char *s)
/// screen, taking into account the size of a tab and inline virtual text.
int linetabsize(win_T *wp, linenr_T lnum)
{
- return win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum), (colnr_T)MAXCOL);
+ return win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum), MAXCOL);
}
static const uint32_t inline_filter[4] = {[kMTMetaInline] = kMTFilterSelect };
@@ -234,7 +236,7 @@ CharSize charsize_regular(CharsizeArg *csarg, char *const cur, colnr_T const vco
wcol += col_off_prev;
}
- if (wcol + size > wp->w_width) {
+ if (wcol + size > wp->w_width_inner) {
// cells taken by 'showbreak'/'breakindent' halfway current char
int head_mid = csarg->indent_width;
if (head_mid == INT_MIN) {
@@ -247,7 +249,7 @@ CharSize charsize_regular(CharsizeArg *csarg, char *const cur, colnr_T const vco
}
csarg->indent_width = head_mid;
}
- if (head_mid > 0 && wcol + size > wp->w_width_inner) {
+ if (head_mid > 0) {
// Calculate effective window width.
int prev_rem = wp->w_width_inner - wcol;
int width = width2 - head_mid;
@@ -375,6 +377,20 @@ CharSize charsize_fast(CharsizeArg *csarg, colnr_T const vcol, int32_t const cur
return charsize_fast_impl(csarg->win, csarg->use_tabstop, vcol, cur_char);
}
+/// Get the number of cells taken up on the screen at given virtual column.
+///
+/// @see win_chartabsize()
+int charsize_nowrap(buf_T *buf, bool use_tabstop, colnr_T vcol, int32_t cur_char)
+{
+ if (cur_char == TAB && use_tabstop) {
+ return tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array);
+ } else if (cur_char < 0) {
+ return kInvalidByteCells;
+ } else {
+ return char2cells(cur_char);
+ }
+}
+
/// Check that virtual column "vcol" is in the rightmost column of window "wp".
///
/// @param wp window
@@ -405,48 +421,63 @@ static bool in_win_border(win_T *wp, colnr_T vcol)
/// Calculate virtual column until the given "len".
///
-/// @param arg Argument to charsize functions.
-/// @param vcol Starting virtual column.
-/// @param len First byte of the end character, or MAXCOL.
+/// @param csarg Argument to charsize functions.
+/// @param vcol_arg Starting virtual column.
+/// @param len First byte of the end character, or MAXCOL.
///
/// @return virtual column before the character at "len",
-/// or full size of the line if "len" is MAXCOL.
-int linesize_regular(CharsizeArg *const csarg, int vcol, colnr_T const len)
+/// or full size of the line if "len" is MAXCOL.
+int linesize_regular(CharsizeArg *const csarg, int vcol_arg, colnr_T const len)
{
char *const line = csarg->line;
+ int64_t vcol = vcol_arg;
StrCharInfo ci = utf_ptr2StrCharInfo(line);
while (ci.ptr - line < len && *ci.ptr != NUL) {
- vcol += charsize_regular(csarg, ci.ptr, vcol, ci.chr.value).width;
+ vcol += charsize_regular(csarg, ci.ptr, vcol_arg, ci.chr.value).width;
ci = utfc_next(ci);
+ if (vcol > MAXCOL) {
+ vcol_arg = MAXCOL;
+ break;
+ } else {
+ vcol_arg = (int)vcol;
+ }
}
// Check for inline virtual text after the end of the line.
- if (len == MAXCOL && csarg->virt_row >= 0) {
- (void)charsize_regular(csarg, ci.ptr, vcol, ci.chr.value);
+ if (len == MAXCOL && csarg->virt_row >= 0 && *ci.ptr == NUL) {
+ (void)charsize_regular(csarg, ci.ptr, vcol_arg, ci.chr.value);
vcol += csarg->cur_text_width_left + csarg->cur_text_width_right;
+ vcol_arg = vcol > MAXCOL ? MAXCOL : (int)vcol;
}
- return vcol;
+ return vcol_arg;
}
-/// Like linesize_regular(), but can be used when CStype is kCharsizeFast.
+/// Like linesize_regular(), but can be used when CSType is kCharsizeFast.
///
/// @see linesize_regular
-int linesize_fast(CharsizeArg const *const csarg, int vcol, colnr_T const len)
+int linesize_fast(CharsizeArg const *const csarg, int vcol_arg, colnr_T const len)
{
win_T *const wp = csarg->win;
bool const use_tabstop = csarg->use_tabstop;
char *const line = csarg->line;
+ int64_t vcol = vcol_arg;
StrCharInfo ci = utf_ptr2StrCharInfo(line);
while (ci.ptr - line < len && *ci.ptr != NUL) {
- vcol += charsize_fast_impl(wp, use_tabstop, vcol, ci.chr.value).width;
+ vcol += charsize_fast_impl(wp, use_tabstop, vcol_arg, ci.chr.value).width;
ci = utfc_next(ci);
+ if (vcol > MAXCOL) {
+ vcol_arg = MAXCOL;
+ break;
+ } else {
+ vcol_arg = (int)vcol;
+ }
}
- return vcol;
+ return vcol_arg;
}
/// Get how many virtual columns inline virtual text should offset the cursor.
@@ -540,7 +571,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
if (ci.chr.value == TAB
&& (State & MODE_NORMAL)
&& !wp->w_p_list
- && !virtual_active()
+ && !virtual_active(wp)
&& !(VIsual_active && ((*p_sel == 'e') || ltoreq(*pos, VIsual)))) {
// cursor at end
*cursor = vcol + incr - 1;
@@ -556,7 +587,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
///
/// @param posp
///
-/// @retujrn The virtual cursor column.
+/// @return The virtual cursor column.
colnr_T getvcol_nolist(pos_T *posp)
{
int list_save = curwin->w_p_list;
@@ -583,7 +614,7 @@ void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *e
{
colnr_T col;
- if (virtual_active()) {
+ if (virtual_active(wp)) {
// For virtual mode, only want one value
getvcol(wp, pos, &col, NULL, NULL);
@@ -593,7 +624,7 @@ void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *e
// Cannot put the cursor on part of a wide character.
char *ptr = ml_get_buf(wp->w_buffer, pos->lnum);
- if (pos->col < (colnr_T)strlen(ptr)) {
+ if (pos->col < ml_get_buf_len(wp->w_buffer, pos->lnum)) {
int c = utf_ptr2char(ptr + pos->col);
if ((c != TAB) && vim_isprintc(c)) {
endadd = (colnr_T)(char2cells(c) - 1);
@@ -850,26 +881,29 @@ int plines_win_full(win_T *wp, linenr_T lnum, linenr_T *const nextp, bool *const
(lnum == wp->w_topline ? wp->w_topfill : win_get_fill(wp, lnum)));
}
-/// Get the number of screen lines a range of buffer lines will take in window "wp".
-/// This takes care of both folds and topfill.
+/// Return number of window lines a physical line range will occupy in window "wp".
+/// Takes into account folding, 'wrap', topfill and filler lines beyond the end of the buffer.
///
/// XXX: Because of topfill, this only makes sense when first >= wp->w_topline.
///
-/// @param first first line number
-/// @param last last line number
-/// @param limit_winheight when true limit each line to window height
+/// @param first first line number
+/// @param last last line number
+/// @param max number of lines to limit the height to
///
/// @see win_text_height
-int plines_m_win(win_T *wp, linenr_T first, linenr_T last, bool limit_winheight)
+int plines_m_win(win_T *wp, linenr_T first, linenr_T last, int max)
{
int count = 0;
- while (first <= last) {
+ while (first <= last && count < max) {
linenr_T next = first;
- count += plines_win_full(wp, first, &next, NULL, false, limit_winheight);
+ count += plines_win_full(wp, first, &next, NULL, false, false);
first = next + 1;
}
- return count;
+ if (first == wp->w_buffer->b_ml.ml_line_count + 1) {
+ count += win_get_fill(wp, first);
+ }
+ return MIN(max, count);
}
/// Get the number of screen lines a range of text will take in window "wp".
@@ -902,7 +936,7 @@ int64_t win_text_height(win_T *const wp, const linenr_T start_lnum, const int64_
if (start_vcol >= 0) {
linenr_T lnum_next = lnum;
- const bool folded = hasFoldingWin(wp, lnum, &lnum, &lnum_next, true, NULL);
+ const bool folded = hasFolding(wp, lnum, &lnum, &lnum_next);
height_cur_nofill = folded ? 1 : plines_win_nofill(wp, lnum, false);
height_sum_nofill += height_cur_nofill;
const int64_t row_off = (start_vcol < width1 || width2 <= 0)
@@ -914,7 +948,7 @@ int64_t win_text_height(win_T *const wp, const linenr_T start_lnum, const int64_
while (lnum <= end_lnum) {
linenr_T lnum_next = lnum;
- const bool folded = hasFoldingWin(wp, lnum, &lnum, &lnum_next, true, NULL);
+ const bool folded = hasFolding(wp, lnum, &lnum, &lnum_next);
height_sum_fill += win_get_fill(wp, lnum);
height_cur_nofill = folded ? 1 : plines_win_nofill(wp, lnum, false);
height_sum_nofill += height_cur_nofill;