aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r--src/nvim/buffer.c517
1 files changed, 391 insertions, 126 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 5306602949..95a1f783eb 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -2818,7 +2818,7 @@ void free_titles(void)
* If maxwidth is not zero, the string will be filled at any middle marker
* or truncated if too long, fillchar is used for all whitespace.
*/
-int
+int
build_stl_str_hl (
win_T *wp,
char_u *out, /* buffer to write into != NameBuff */
@@ -2833,8 +2833,11 @@ build_stl_str_hl (
{
int groupitem[STL_MAX_ITEM];
struct stl_item {
+ // Where the item starts in the status line output buffer
char_u *start;
+ // The minimum width of the item (at most 50 characters)
int minwid;
+ // The maximum width of the item
int maxwid;
enum {
Normal,
@@ -2846,6 +2849,13 @@ build_stl_str_hl (
Trunc
} type;
} item[STL_MAX_ITEM];
+
+ enum number_base {
+ DECIMAL = 10,
+ OCTAL = 8,
+ HEXIDECIMAL = 16
+ };
+
#define TMPLEN 70
char_u tmp[TMPLEN];
char_u *usefmt = fmt;
@@ -2879,12 +2889,18 @@ build_stl_str_hl (
byteval = (*mb_ptr2char)(line_ptr + wp->w_cursor.col);
int groupdepth = 0;
- char_u *p = out;
+
int curitem = 0;
bool prevchar_isflag = true;
bool prevchar_isitem = false;
- char_u *s;
- for (s = usefmt; *s; ) {
+
+ // p is the current position in the output buffer
+ char_u *p = out;
+
+
+ // Proceed character by character through the statusline format string
+ // s is the current positon in the input buffer
+ for (char_u *s = usefmt; *s; ) {
if (curitem == STL_MAX_ITEM) {
/* There are too many items. Add the error code to the statusline
* to give the user a hint about what went wrong. */
@@ -2898,64 +2914,99 @@ build_stl_str_hl (
if (*s != NUL && *s != '%')
prevchar_isflag = prevchar_isitem = false;
- /*
- * Handle up to the next '%' or the end.
- */
+ // Copy the formatting verbatim until we reach the end of the string
+ // or find a formatting item (denoted by `%`)
+ // or run out of room in our output buffer.
while (*s != NUL && *s != '%' && p + 1 < out + outlen)
*p++ = *s++;
+
+ // If we have processed the entire format string or run out of
+ // room in our output buffer, exit the loop.
if (*s == NUL || p + 1 >= out + outlen)
break;
- /*
- * Handle one '%' item.
- */
+ // The rest of this loop wil handle a single `%` item.
+ // Note: We increment here to skip over the `%` character we are currently
+ // on so we can process the item's contents.
s++;
- if (*s == NUL) /* ignore trailing % */
+
+ // Ignore `%` at the end of the format string
+ if (*s == NUL) {
break;
+ }
+
+ // Two `%` in a row is the escape sequence to print a
+ // single `%` in the output buffer.
if (*s == '%') {
+ // Ignore the character if we're out of room in the output buffer.
if (p + 1 >= out + outlen)
break;
*p++ = *s++;
prevchar_isflag = prevchar_isitem = false;
continue;
}
+
+ // STL_MIDDLEMARK denotes the separation place between left and right aligned items.
if (*s == STL_MIDDLEMARK) {
s++;
- if (groupdepth > 0)
+ // Ignored when we are inside of a grouping
+ if (groupdepth > 0) {
continue;
+ }
item[curitem].type = Middle;
item[curitem++].start = p;
continue;
}
+
+ // STL_TRUNCMARK denotes where to begin truncating if the statusline is too long.
if (*s == STL_TRUNCMARK) {
s++;
item[curitem].type = Trunc;
item[curitem++].start = p;
continue;
}
+
+ // The end of a grouping
if (*s == ')') {
s++;
- if (groupdepth < 1)
+ // Ignore if we are not actually inside a group currently
+ if (groupdepth < 1) {
continue;
+ }
groupdepth--;
+ //{ Determine how long the group is.
+ // Note: We set the current output position to null so `vim_strsize` will work.
char_u *t = item[groupitem[groupdepth]].start;
*p = NUL;
long l = vim_strsize(t);
+ //}
+
+ // If the group contained internal items and the group did not have a minimum width,
+ // and if there were no normal items in the group,
+ // move the output pointer back to where the group started (erase the group).
+ // Note: This also erases any plaintext characters that were in the group.
+ // Otherwise there would be no reason to do this step.
if (curitem > groupitem[groupdepth] + 1
&& item[groupitem[groupdepth]].minwid == 0) {
- /* remove group if all items are empty */
- long n;
- for (n = groupitem[groupdepth] + 1; n < curitem; n++)
- if (item[n].type == Normal)
+ bool has_normal_items = false;
+ for (long n = groupitem[groupdepth] + 1; n < curitem; n++) {
+ if (item[n].type == Normal) {
+ has_normal_items = true;
break;
- if (n == curitem) {
+ }
+ }
+
+ if (!has_normal_items) {
p = t;
l = 0;
}
}
+
+ // If the group is longer than it is allowed to be
+ // truncate by removing bytes from the start of the group text.
if (l > item[groupitem[groupdepth]].maxwid) {
- /* truncate, remove n bytes of text at the start */
+ //{ Determine the number of bytes to remove
long n;
if (has_mbyte) {
/* Find the first character that should be included. */
@@ -2966,60 +3017,88 @@ build_stl_str_hl (
}
} else
n = (long)(p - t) - item[groupitem[groupdepth]].maxwid + 1;
+ //}
+ // Prepend the `<` to indicate that the output was truncated.
*t = '<';
+
+ //{ Move the truncated output
memmove(t + 1, t + n, (size_t)(p - (t + n)));
p = p - n + 1;
/* Fill up space left over by half a double-wide char. */
while (++l < item[groupitem[groupdepth]].minwid)
*p++ = fillchar;
+ //}
/* correct the start of the items for the truncation */
for (l = groupitem[groupdepth] + 1; l < curitem; l++) {
+ // Shift everything back by the number of removed bytes
item[l].start -= n;
+
+ // If the item was partially or completely truncated, set its
+ // start to the start of the group
if (item[l].start < t)
item[l].start = t;
}
+ // If the group is shorter than the minimum width, add padding characters.
} else if (abs(item[groupitem[groupdepth]].minwid) > l) {
- /* fill */
- long n = item[groupitem[groupdepth]].minwid;
- if (n < 0) {
- /* fill by appending characters */
- n = 0 - n;
- while (l++ < n && p + 1 < out + outlen)
+ long min_group_width = item[groupitem[groupdepth]].minwid;
+ // If the group is left-aligned, add characters to the right.
+ if (min_group_width < 0) {
+ min_group_width = 0 - min_group_width;
+ while (l++ < min_group_width && p + 1 < out + outlen)
*p++ = fillchar;
+ // If the group is right-aligned, shift everything to the right and
+ // prepend with filler characters.
} else {
- /* fill by inserting characters */
- memmove(t + n - l, t, (size_t)(p - t));
- l = n - l;
- if (p + l >= out + outlen)
+ //{ Move the group to the right
+ memmove(t + min_group_width - l, t, (size_t)(p - t));
+ l = min_group_width - l;
+ if (p + l >= out + outlen) {
l = (long)((out + outlen) - p - 1);
+ }
p += l;
- for (n = groupitem[groupdepth] + 1; n < curitem; n++)
+ //}
+
+ // Adjust item start positions
+ for (int n = groupitem[groupdepth] + 1; n < curitem; n++) {
item[n].start += l;
- for (; l > 0; l--)
+ }
+
+ // Prepend the fill characters
+ for (; l > 0; l--) {
*t++ = fillchar;
+ }
}
}
continue;
}
int minwid = 0;
int maxwid = 9999;
- bool zeropad = false;
- long l = 1;
- if (*s == '0') {
+ bool left_align = false;
+
+ // Denotes that numbers should be left-padded with zeros
+ bool zeropad = (*s == '0');
+ if (zeropad) {
s++;
- zeropad = true;
}
+
+ // Denotes that the item should be left-aligned.
+ // This is tracked by using a negative length.
if (*s == '-') {
s++;
- l = -1;
+ left_align = true;
}
+
+ // The first digit group is the item's min width
if (ascii_isdigit(*s)) {
minwid = getdigits_int(&s);
if (minwid < 0) /* overflow */
minwid = 0;
}
+
+ // User highlight groups override the min width field
+ // to denote the styling to use.
if (*s == STL_USER_HL) {
item[curitem].type = Highlight;
item[curitem].start = p;
@@ -3049,6 +3128,9 @@ build_stl_str_hl (
curitem++;
continue;
}
+
+ // Denotes the end of the minwid
+ // the maxwid may follow immediately after
if (*s == '.') {
s++;
if (ascii_isdigit(*s)) {
@@ -3057,7 +3139,12 @@ build_stl_str_hl (
maxwid = 50;
}
}
- minwid = (minwid > 50 ? 50 : minwid) * l;
+
+ // Bound the minimum width at 50.
+ // Make the number negative to denote left alignment of the item
+ minwid = (minwid > 50 ? 50 : minwid) * (left_align ? -1 : 1);
+
+ // Denotes the start of a new group
if (*s == '(') {
groupitem[groupdepth++] = curitem;
item[curitem].type = Group;
@@ -3068,14 +3155,19 @@ build_stl_str_hl (
curitem++;
continue;
}
+
+ // An invalid item was specified.
+ // Continue processing on the next character of the format string.
if (vim_strchr(STL_ALL, *s) == NULL) {
s++;
continue;
}
+
+ // The status line item type
char_u opt = *s++;
/* OK - now for the real work */
- char_u base = 'D';
+ enum number_base base = DECIMAL;
bool itemisflag = false;
bool fillable = true;
long num = -1;
@@ -3103,6 +3195,9 @@ build_stl_str_hl (
case STL_VIM_EXPR: /* '{' */
{
itemisflag = true;
+
+ // Attempt to copy the expression to evaluate into
+ // the output buffer as a null-terminated string.
char_u *t = p;
while (*s != '}' && *s != NUL && p + 1 < out + outlen)
*p++ = *s++;
@@ -3110,22 +3205,37 @@ build_stl_str_hl (
break;
s++;
*p = 0;
+
+ // Move our position in the output buffer to the beginning of the expression
p = t;
+ //{ Evaluate the expression
+
+ // Store the current buffer number as a string variable
vim_snprintf((char *)tmp, sizeof(tmp), "%d", curbuf->b_fnum);
set_internal_string_var((char_u *)"actual_curbuf", tmp);
+ // Switch the curbuf and curwin to the buffer and window we are evaluating the
+ // statusline for.
buf_T *o_curbuf = curbuf;
win_T *o_curwin = curwin;
curwin = wp;
curbuf = wp->w_buffer;
+ // Note: The result stored in `t` is unused.
str = eval_to_string_safe(p, &t, use_sandbox);
+ // Switch back to the actual current buffer and window.
curwin = o_curwin;
curbuf = o_curbuf;
+
+ // Remove the variable we just stored
do_unlet((char_u *)"g:actual_curbuf", TRUE);
+ //}
+
+ // Check if the evaluated result is a number.
+ // If so, convert the number to an int and free the string.
if (str != NULL && *str != 0) {
if (*skipdigits(str) == NUL) {
num = atoi((char *)str);
@@ -3176,15 +3286,27 @@ build_stl_str_hl (
break;
case STL_ALTPERCENT:
+ // Store the position percentage in our temporary buffer.
+ // Note: We cannot store the value in `num` because
+ // `get_rel_pos` can return a named position. Ex: "Top"
+ get_rel_pos(wp, tmp, TMPLEN);
str = tmp;
- get_rel_pos(wp, str, TMPLEN);
break;
case STL_ARGLISTSTAT:
fillable = false;
+
+ // Note: This is important because `append_arg_number` starts appending
+ // at the end of the null-terminated string.
+ // Setting the first byte to null means it will place the argument
+ // number string at the beginning of the buffer.
tmp[0] = 0;
- if (append_arg_number(wp, tmp, (int)sizeof(tmp), FALSE))
+
+ // Note: The call will only return true if it actually
+ // appended data to the `tmp` buffer.
+ if (append_arg_number(wp, tmp, (int)sizeof(tmp), FALSE)) {
str = tmp;
+ }
break;
case STL_KEYMAP:
@@ -3201,16 +3323,17 @@ build_stl_str_hl (
break;
case STL_OFFSET_X:
- base = 'X';
+ base = HEXIDECIMAL;
case STL_OFFSET:
- l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL);
+ {
+ long l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL);
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) || l < 0 ?
0L : l + 1 + (!(State & INSERT) && empty_line ?
0 : (int)wp->w_cursor.col);
break;
-
+ }
case STL_BYTEVAL_X:
- base = 'X';
+ base = HEXIDECIMAL;
case STL_BYTEVAL:
num = byteval;
if (num == NL)
@@ -3235,6 +3358,8 @@ build_stl_str_hl (
break;
case STL_FILETYPE:
+ // Copy the filetype if it is not null and the formatted string will fit
+ // in the temporary buffer (including the brackets and null terminating character)
if (*wp->w_buffer->b_p_ft != NUL
&& STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 3) {
vim_snprintf((char *)tmp, sizeof(tmp), "[%s]",
@@ -3246,12 +3371,16 @@ build_stl_str_hl (
case STL_FILETYPE_ALT:
{
itemisflag = true;
+ // Copy the filetype if it is not null and the formatted string will fit
+ // in the temporary buffer (including the comma and null terminating character)
if (*wp->w_buffer->b_p_ft != NUL
&& STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 2) {
vim_snprintf((char *)tmp, sizeof(tmp), ",%s",
wp->w_buffer->b_p_ft);
- for (char_u *t = tmp; *t != 0; t++)
+ // Uppercase the file extension
+ for (char_u *t = tmp; *t != 0; t++) {
*t = TOUPPER_LOC(*t);
+ }
str = tmp;
}
break;
@@ -3288,24 +3417,35 @@ build_stl_str_hl (
case STL_HIGHLIGHT:
{
+ //{ The name of the highlight is surrounded by `#`
char_u *t = s;
- while (*s != '#' && *s != NUL)
+ while (*s != '#' && *s != NUL) {
++s;
+ }
+ //}
+
+ // Create a highlight item based on the name
if (*s == '#') {
item[curitem].type = Highlight;
item[curitem].start = p;
item[curitem].minwid = -syn_namen2id(t, (int)(s - t));
curitem++;
+ s++;
}
- if (*s != NUL)
- ++s;
continue;
}
}
+ // If we made it this far, the item is normal and starts at
+ // our current position in the output buffer.
+ // Non-normal items would have `continued`.
item[curitem].start = p;
item[curitem].type = Normal;
+
+ // Copy the item string into the output buffer
if (str != NULL && *str) {
+ //{ Skip the leading `,` or ` ` if the item is a flag
+ // and the proper conditions are met
char_u *t = str;
if (itemisflag) {
if ((t[0] && t[1])
@@ -3314,20 +3454,35 @@ build_stl_str_hl (
t++;
prevchar_isflag = true;
}
- l = vim_strsize(t);
- if (l > 0)
+ //}
+
+ long l = vim_strsize(t);
+
+ // If this item is non-empty, record that the last thing
+ // we put in the output buffer was an item
+ if (l > 0) {
prevchar_isitem = true;
+ }
+
+ // If the item is too wide, truncate it from the beginning
if (l > maxwid) {
while (l >= maxwid)
if (has_mbyte) {
l -= ptr2cells(t);
t += (*mb_ptr2len)(t);
- } else
+ } else {
l -= byte2cells(*t++);
+ }
+
+ // Early out if there isn't enough room for the truncation marker
if (p + 1 >= out + outlen)
break;
+
+ // Add the truncation marker
*p++ = '<';
}
+
+ // If the item is right aligned and not wide enough, pad with fill characters.
if (minwid > 0) {
for (; l < minwid && p + 1 < out + outlen; l++) {
/* Don't put a "-" in front of a digit. */
@@ -3337,8 +3492,13 @@ build_stl_str_hl (
*p++ = fillchar;
}
minwid = 0;
- } else
+ } else {
+ // Note: The negative value denotes a left aligned item.
+ // Here we switch the minimum width back to a positive value.
minwid *= -1;
+ }
+
+ //{ Copy the string text into the output buffer
while (*t && p + 1 < out + outlen) {
*p++ = *t++;
/* Change a space by fillchar, unless fillchar is '-' and a
@@ -3347,150 +3507,255 @@ build_stl_str_hl (
&& (!ascii_isdigit(*t) || fillchar != '-'))
p[-1] = fillchar;
}
- for (; l < minwid && p + 1 < out + outlen; l++)
+ //}
+
+ // For left-aligned items, fill any remaining space with the fillchar
+ for (; l < minwid && p + 1 < out + outlen; l++) {
*p++ = fillchar;
- } else if (num >= 0) {
- int nbase = (base == 'D' ? 10 : (base == 'O' ? 8 : 16));
- char_u nstr[20];
+ }
+ // Otherwise if the item is a number, copy that to the output buffer.
+ } else if (num >= 0) {
if (p + 20 >= out + outlen)
break; /* not sufficient space */
prevchar_isitem = true;
+
+ //{ Build the formatting string
+ char_u nstr[20];
char_u *t = nstr;
if (opt == STL_VIRTCOL_ALT) {
*t++ = '-';
minwid--;
}
*t++ = '%';
- if (zeropad)
+ if (zeropad) {
*t++ = '0';
+ }
+
+ // Note: The `*` means we take the width as one of the arguments
*t++ = '*';
- *t++ = nbase == 16 ? base : (char_u)(nbase == 8 ? 'o' : 'd');
+ *t++ = (char_u) (base == HEXIDECIMAL ? 'X' : (base == OCTAL ? 'o' : 'd'));
*t = 0;
+ //}
- long n;
- for (n = num, l = 1; n >= nbase; n /= nbase)
+ //{ Determine how many characters the number will take up when printed
+ long l;
+ for (long n = num, l = 1; n >= base; n /= base) {
l++;
- if (opt == STL_VIRTCOL_ALT)
+ }
+
+ // VIRTCOL_ALT takes up an extra character because of the `-` we added above.
+ if (opt == STL_VIRTCOL_ALT) {
l++;
+ }
+ //}
+
+ size_t remaining_buf_len = (outlen - (p - out));
+
+ // If the number is going to take up too much room
+ // Figure out the approximate number in "scientific" type notation.
+ // Ex: 14532 with maxwid of 4 -> '14>3'
if (l > maxwid) {
+ // Add two to the width because the power piece will take two extra characters
l += 2;
- n = l - maxwid;
- while (l-- > maxwid)
- num /= nbase;
+
+ // How many extra characters there are
+ long n = l - maxwid;
+
+ //{ Reduce the number by base^n
+ while (l-- > maxwid) {
+ num /= base;
+ }
+ //}
+
+ //{ Add the format string for the exponent bit
*t++ = '>';
*t++ = '%';
+ // Use the same base as the first number
*t = t[-3];
*++t = 0;
- vim_snprintf((char *)p, outlen - (p - out), (char *)nstr,
+ //}
+
+ vim_snprintf((char *)p, remaining_buf_len, (char *)nstr,
0, num, n);
- } else
- vim_snprintf((char *)p, outlen - (p - out), (char *)nstr,
+ } else {
+ vim_snprintf((char *)p, remaining_buf_len, (char *)nstr,
minwid, num);
+ }
+
+ // Advance the output buffer position to the end of the number we just printed
p += STRLEN(p);
- } else
+
+ // Otherwise, there was nothing to print so mark the item as empty
+ } else {
item[curitem].type = Empty;
+ }
- if (opt == STL_VIM_EXPR)
+ // Free the string buffer if we allocated it.
+ // Note: This is not needed if `str` is pointing at `tmp`
+ if (opt == STL_VIM_EXPR) {
xfree(str);
+ }
if (num >= 0 || (!itemisflag && str && *str))
prevchar_isflag = false; /* Item not NULL, but not a flag */
+
+ // Item processed, move to the next
curitem++;
}
+
+ // Null terminate the output buffer
*p = NUL;
int itemcnt = curitem;
- if (usefmt != fmt)
+ // Free the format buffer if we allocated it internally
+ if (usefmt != fmt) {
xfree(usefmt);
+ }
int width = vim_strsize(out);
if (maxwidth > 0 && width > maxwidth) {
/* Result is too long, must truncate somewhere. */
- long l = 0;
- if (itemcnt == 0)
- s = out;
- else {
- for (; l < itemcnt; l++)
- if (item[l].type == Trunc) {
- /* Truncate at %< item. */
- s = item[l].start;
+ int item_idx = 0;
+ char_u *trunc_p;
+
+ // If there are no items, truncate from beginning
+ if (itemcnt == 0) {
+ trunc_p = out;
+
+ // Otherwise, look for the truncation item
+ } else {
+ // Default to truncating at the first item
+ trunc_p = item[0].start;
+ item_idx = 0;
+
+ for (int i; i < itemcnt; i++)
+ if (item[i].type == Trunc) {
+ // Truncate at %< item.
+ trunc_p = item[i].start;
+ item_idx = i;
break;
}
- if (l == itemcnt) {
- /* No %< item, truncate first item. */
- s = item[0].start;
- l = 0;
- }
}
- if (width - vim_strsize(s) >= maxwidth) {
- /* Truncation mark is beyond max length */
+ // If the truncation point we found is beyond the maximum
+ // length of the string, truncate the end of the string.
+ if (width - vim_strsize(trunc_p) >= maxwidth) {
+ // If we are using a multi-byte encoding, walk from the beginning of the
+ // string to find the last character that will fit.
if (has_mbyte) {
- s = out;
+ trunc_p = out;
width = 0;
for (;; ) {
- width += ptr2cells(s);
+ width += ptr2cells(trunc_p);
if (width >= maxwidth)
break;
- s += (*mb_ptr2len)(s);
+
+ // Note: Only advance the pointer if the next
+ // character will fit in the available output space
+ trunc_p += (*mb_ptr2len)(trunc_p);
}
/* Fill up for half a double-wide character. */
- while (++width < maxwidth)
- *s++ = fillchar;
- } else
- s = out + maxwidth - 1;
- for (l = 0; l < itemcnt; l++)
- if (item[l].start > s)
+ // XXX : This seems impossible given the exit condition above?
+ while (++width < maxwidth) {
+ *trunc_p++ = fillchar;
+ }
+
+ // Otherwise put the truncation point at the end, leaving enough room
+ // for a single-character truncation marker
+ } else {
+ trunc_p = out + maxwidth - 1;
+ }
+
+ // Ignore any items in the statusline that occur after
+ // the truncation point
+ for (int i = 0; i < itemcnt; i++) {
+ if (item[i].start > trunc_p) {
+ itemcnt = i;
break;
- itemcnt = l;
- *s++ = '>';
- *s = 0;
+ }
+ }
+
+ // Truncate the output
+ *trunc_p++ = '>';
+ *trunc_p = 0;
+
+ // Truncate at the truncation point we found
} else {
- long n;
+ //{ Determine how many bytes to remove
+ long trunc_len;
if (has_mbyte) {
- n = 0;
+ trunc_len = 0;
while (width >= maxwidth) {
- width -= ptr2cells(s + n);
- n += (*mb_ptr2len)(s + n);
+ width -= ptr2cells(trunc_p + trunc_len);
+ trunc_len += (*mb_ptr2len)(trunc_p + trunc_len);
}
- } else
- n = width - maxwidth + 1;
- p = s + n;
- STRMOVE(s + 1, p);
- *s = '<';
+ } else {
+ // Truncate an extra character so we can insert our `<`.
+ trunc_len = (width - maxwidth) + 1;
+ }
+ //}
+
+ //{ Truncate the string
+ char_u *trunc_end_p = trunc_p + trunc_len;
+ STRMOVE(trunc_p + 1, trunc_end_p);
+
+ // Put a `<` to mark where we truncated at
+ *trunc_p = '<';
+
+ // Advance the pointer to the end of the string
+ trunc_p = trunc_p + STRLEN(trunc_p);
/* Fill up for half a double-wide character. */
while (++width < maxwidth) {
- s = s + STRLEN(s);
- *s++ = fillchar;
- *s = NUL;
+ *trunc_p++ = fillchar;
+ *trunc_p = NUL;
}
+ //}
- --n; /* count the '<' */
- for (; l < itemcnt; l++) {
- if (item[l].start - n >= s)
- item[l].start -= n;
- else
- item[l].start = s;
+ //{ Change the start point for items based on
+ // their position relative to our truncation point
+
+ // Note: The offset is one less than the truncation length because
+ // the truncation marker `<` is not counted.
+ long item_offset = trunc_len - 1;
+
+ for (int i = item_idx; i < itemcnt; i++) {
+ // Items starting at or after the end of the truncated section need
+ // to be moved backwards.
+ if (item[i].start >= trunc_end_p) {
+ item[i].start -= item_offset;
+ // Anything inside the truncated area is set to start at the `<` truncation character.
+ } else {
+ item[i].start = trunc_p;
+ }
}
+ //}
}
width = maxwidth;
- } else if (width < maxwidth && STRLEN(out) + maxwidth - width + 1 <
- outlen) {
- /* Apply STL_MIDDLE if any */
- for (long l = 0; l < itemcnt; l++)
- if (item[l].type == Middle) {
- p = item[l].start + maxwidth - width;
- STRMOVE(p, item[l].start);
- for (s = item[l].start; s < p; s++)
+
+ // If there is room left in our statusline, and room left in our buffer,
+ // add characters at the middle marker (if there is one) to fill up the available space.
+ } else if (width < maxwidth
+ && STRLEN(out) + maxwidth - width + 1 < outlen) {
+ for (int item_idx = 0; item_idx < itemcnt; item_idx++) {
+ if (item[item_idx].type == Middle) {
+ // Move the statusline to make room for the middle characters
+ char_u *middle_end = item[item_idx].start + (maxwidth - width);
+ STRMOVE(middle_end, item[item_idx].start);
+
+ // Fill the middle section with our fill character
+ for (char_u *s = item[item_idx].start; s < middle_end; s++)
*s = fillchar;
- for (l++; l < itemcnt; l++)
- item[l].start += maxwidth - width;
- width = maxwidth;
+ // Adjust the offset of any items after the middle
+ for (item_idx++; item_idx < itemcnt; item_idx++)
+ item[item_idx].start += maxwidth - width;
+
+ width = maxwidth;
break;
}
+ }
}
/* Store the info about highlighting. */