mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	vim-patch:8.2.1909: number of status line items is limited to 80
Problem:    Number of status line items is limited to 80.
Solution:   Dynamically allocate the arrays. (Rom Grk, closes vim/vim#7181)
8133cc6bf4
The members of stl_item_T have not been prefixed with stl_ contrary to
the vim patch because the amount of stl_ prefixes on single lines of
code in that region was hurtful to readability.
			
			
This commit is contained in:
		| @@ -5795,7 +5795,7 @@ A jump table for the options with a short description can be found at |Q_op|. | |||||||
| 	normal text.  Each status line item is of the form: | 	normal text.  Each status line item is of the form: | ||||||
| 	  %-0{minwid}.{maxwid}{item} | 	  %-0{minwid}.{maxwid}{item} | ||||||
| 	All fields except the {item} are optional.  A single percent sign can | 	All fields except the {item} are optional.  A single percent sign can | ||||||
| 	be given as "%%".  Up to 80 items can be specified.  *E541* | 	be given as "%%". | ||||||
|  |  | ||||||
| 	When the option starts with "%!" then it is used as an expression, | 	When the option starts with "%!" then it is used as an expression, | ||||||
| 	evaluated and the result is used as the option value.  Example: > | 	evaluated and the result is used as the option value.  Example: > | ||||||
|   | |||||||
| @@ -3440,31 +3440,17 @@ int build_stl_str_hl( | |||||||
|     int use_sandbox, |     int use_sandbox, | ||||||
|     char_u fillchar, |     char_u fillchar, | ||||||
|     int maxwidth, |     int maxwidth, | ||||||
|     struct stl_hlrec *hltab, |     stl_hlrec_t **hltab, | ||||||
|     StlClickRecord *tabtab |     StlClickRecord **tabtab | ||||||
| ) | ) | ||||||
| { | { | ||||||
|   int groupitems[STL_MAX_ITEM]; |   static size_t stl_items_len = 20;  // Initial value, grows as needed. | ||||||
|   struct stl_item { |   static stl_item_t *stl_items = NULL; | ||||||
|     // Where the item starts in the status line output buffer |   static int *stl_groupitems = NULL; | ||||||
|     char_u *start; |   static stl_hlrec_t *stl_hltab = NULL; | ||||||
|     // Function to run for ClickFunc items. |   static StlClickRecord *stl_tabtab = NULL; | ||||||
|     char *cmd; |   static int *stl_separator_locations = NULL; | ||||||
|     // The minimum width of the item |  | ||||||
|     int minwid; |  | ||||||
|     // The maximum width of the item |  | ||||||
|     int maxwid; |  | ||||||
|     enum { |  | ||||||
|       Normal, |  | ||||||
|       Empty, |  | ||||||
|       Group, |  | ||||||
|       Separate, |  | ||||||
|       Highlight, |  | ||||||
|       TabPage, |  | ||||||
|       ClickFunc, |  | ||||||
|       Trunc |  | ||||||
|     } type; |  | ||||||
|   } items[STL_MAX_ITEM]; |  | ||||||
| #define TMPLEN 70 | #define TMPLEN 70 | ||||||
|   char_u buf_tmp[TMPLEN]; |   char_u buf_tmp[TMPLEN]; | ||||||
|   char_u win_tmp[TMPLEN]; |   char_u win_tmp[TMPLEN]; | ||||||
| @@ -3472,6 +3458,14 @@ int build_stl_str_hl( | |||||||
|   const int save_must_redraw = must_redraw; |   const int save_must_redraw = must_redraw; | ||||||
|   const int save_redr_type = curwin->w_redr_type; |   const int save_redr_type = curwin->w_redr_type; | ||||||
|  |  | ||||||
|  |   if (stl_items == NULL) { | ||||||
|  |     stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len); | ||||||
|  |     stl_groupitems = xmalloc(sizeof(int) * stl_items_len); | ||||||
|  |     stl_hltab  = xmalloc(sizeof(stl_hlrec_t) * stl_items_len); | ||||||
|  |     stl_tabtab = xmalloc(sizeof(stl_hlrec_t) * stl_items_len); | ||||||
|  |     stl_separator_locations = xmalloc(sizeof(int) * stl_items_len); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // When the format starts with "%!" then evaluate it as an expression and |   // When the format starts with "%!" then evaluate it as an expression and | ||||||
|   // use the result as the actual format string. |   // use the result as the actual format string. | ||||||
|   if (fmt[0] == '%' && fmt[1] == '!') { |   if (fmt[0] == '%' && fmt[1] == '!') { | ||||||
| @@ -3540,14 +3534,17 @@ int build_stl_str_hl( | |||||||
|   // Proceed character by character through the statusline format string |   // Proceed character by character through the statusline format string | ||||||
|   // fmt_p is the current positon in the input buffer |   // fmt_p is the current positon in the input buffer | ||||||
|   for (char_u *fmt_p = usefmt; *fmt_p; ) { |   for (char_u *fmt_p = usefmt; *fmt_p; ) { | ||||||
|     if (curitem == STL_MAX_ITEM) { |     if (curitem == (int)stl_items_len) { | ||||||
|       // There are too many items.  Add the error code to the statusline |         size_t new_len = stl_items_len * 3 / 2; | ||||||
|       // to give the user a hint about what went wrong. |  | ||||||
|       if (out_p + 5 < out_end_p) { |         stl_items = xrealloc(stl_items, sizeof(stl_item_t) * new_len); | ||||||
|         memmove(out_p, " E541", (size_t)5); |         stl_groupitems = xrealloc(stl_groupitems, sizeof(int) * new_len); | ||||||
|         out_p += 5; |         stl_hltab = xrealloc(stl_hltab, sizeof(stl_hlrec_t) * new_len); | ||||||
|       } |         stl_tabtab = xrealloc(stl_tabtab, sizeof(StlClickRecord) * new_len); | ||||||
|       break; |         stl_separator_locations = | ||||||
|  |           xrealloc(stl_separator_locations, sizeof(int) * new_len); | ||||||
|  |  | ||||||
|  |         stl_items_len = new_len; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (*fmt_p != NUL && *fmt_p != '%') { |     if (*fmt_p != NUL && *fmt_p != '%') { | ||||||
| @@ -3591,16 +3588,16 @@ int build_stl_str_hl( | |||||||
|       if (groupdepth > 0) { |       if (groupdepth > 0) { | ||||||
|         continue; |         continue; | ||||||
|       } |       } | ||||||
|       items[curitem].type = Separate; |       stl_items[curitem].type = Separate; | ||||||
|       items[curitem++].start = out_p; |       stl_items[curitem++].start = out_p; | ||||||
|       continue; |       continue; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // STL_TRUNCMARK: Where to begin truncating if the statusline is too long. |     // STL_TRUNCMARK: Where to begin truncating if the statusline is too long. | ||||||
|     if (*fmt_p == STL_TRUNCMARK) { |     if (*fmt_p == STL_TRUNCMARK) { | ||||||
|       fmt_p++; |       fmt_p++; | ||||||
|       items[curitem].type = Trunc; |       stl_items[curitem].type = Trunc; | ||||||
|       items[curitem++].start = out_p; |       stl_items[curitem++].start = out_p; | ||||||
|       continue; |       continue; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -3616,7 +3613,7 @@ int build_stl_str_hl( | |||||||
|       // Determine how long the group is. |       // Determine how long the group is. | ||||||
|       // Note: We set the current output position to null |       // Note: We set the current output position to null | ||||||
|       //       so `vim_strsize` will work. |       //       so `vim_strsize` will work. | ||||||
|       char_u *t = items[groupitems[groupdepth]].start; |       char_u *t = stl_items[stl_groupitems[groupdepth]].start; | ||||||
|       *out_p = NUL; |       *out_p = NUL; | ||||||
|       long group_len = vim_strsize(t); |       long group_len = vim_strsize(t); | ||||||
|  |  | ||||||
| @@ -3626,40 +3623,40 @@ int build_stl_str_hl( | |||||||
|       // move the output pointer back to where the group started. |       // move the output pointer back to where the group started. | ||||||
|       // Note: This erases any non-item characters that were in the group. |       // Note: This erases any non-item characters that were in the group. | ||||||
|       //       Otherwise there would be no reason to do this step. |       //       Otherwise there would be no reason to do this step. | ||||||
|       if (curitem > groupitems[groupdepth] + 1 |       if (curitem > stl_groupitems[groupdepth] + 1 | ||||||
|           && items[groupitems[groupdepth]].minwid == 0) { |           && stl_items[stl_groupitems[groupdepth]].minwid == 0) { | ||||||
|         // remove group if all items are empty and highlight group |         // remove group if all items are empty and highlight group | ||||||
|         // doesn't change |         // doesn't change | ||||||
|         int group_start_userhl = 0; |         int group_start_userhl = 0; | ||||||
|         int group_end_userhl = 0; |         int group_end_userhl = 0; | ||||||
|         int n; |         int n; | ||||||
|         for (n = groupitems[groupdepth] - 1; n >= 0; n--) { |         for (n = stl_groupitems[groupdepth] - 1; n >= 0; n--) { | ||||||
|           if (items[n].type == Highlight) { |           if (stl_items[n].type == Highlight) { | ||||||
|             group_start_userhl = group_end_userhl = items[n].minwid; |             group_start_userhl = group_end_userhl = stl_items[n].minwid; | ||||||
|             break; |             break; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         for (n = groupitems[groupdepth] + 1; n < curitem; n++) { |         for (n = stl_groupitems[groupdepth] + 1; n < curitem; n++) { | ||||||
|           if (items[n].type == Normal) { |           if (stl_items[n].type == Normal) { | ||||||
|             break; |             break; | ||||||
|           } |           } | ||||||
|           if (items[n].type == Highlight) { |           if (stl_items[n].type == Highlight) { | ||||||
|             group_end_userhl = items[n].minwid; |             group_end_userhl = stl_items[n].minwid; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         if (n == curitem && group_start_userhl == group_end_userhl) { |         if (n == curitem && group_start_userhl == group_end_userhl) { | ||||||
|           // empty group |           // empty group | ||||||
|           out_p = t; |           out_p = t; | ||||||
|           group_len = 0; |           group_len = 0; | ||||||
|           for (n = groupitems[groupdepth] + 1; n < curitem; n++) { |           for (n = stl_groupitems[groupdepth] + 1; n < curitem; n++) { | ||||||
|             // do not use the highlighting from the removed group |             // do not use the highlighting from the removed group | ||||||
|             if (items[n].type == Highlight) { |             if (stl_items[n].type == Highlight) { | ||||||
|               items[n].type = Empty; |               stl_items[n].type = Empty; | ||||||
|             } |             } | ||||||
|             // adjust the start position of TabPage to the next |             // adjust the start position of TabPage to the next | ||||||
|             // item position |             // item position | ||||||
|             if (items[n].type == TabPage) { |             if (stl_items[n].type == TabPage) { | ||||||
|               items[n].start = out_p; |               stl_items[n].start = out_p; | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| @@ -3667,18 +3664,19 @@ int build_stl_str_hl( | |||||||
|  |  | ||||||
|       // If the group is longer than it is allowed to be |       // If the group is longer than it is allowed to be | ||||||
|       // truncate by removing bytes from the start of the group text. |       // truncate by removing bytes from the start of the group text. | ||||||
|       if (group_len > items[groupitems[groupdepth]].maxwid) { |       if (group_len > stl_items[stl_groupitems[groupdepth]].maxwid) { | ||||||
|         // { Determine the number of bytes to remove |         // { Determine the number of bytes to remove | ||||||
|         long n; |         long n; | ||||||
|         if (has_mbyte) { |         if (has_mbyte) { | ||||||
|           // Find the first character that should be included. |           // Find the first character that should be included. | ||||||
|           n = 0; |           n = 0; | ||||||
|           while (group_len >= items[groupitems[groupdepth]].maxwid) { |           while (group_len >= stl_items[stl_groupitems[groupdepth]].maxwid) { | ||||||
|             group_len -= ptr2cells(t + n); |             group_len -= ptr2cells(t + n); | ||||||
|             n += (*mb_ptr2len)(t + n); |             n += (*mb_ptr2len)(t + n); | ||||||
|           } |           } | ||||||
|         } else { |         } else { | ||||||
|           n = (long)(out_p - t) - items[groupitems[groupdepth]].maxwid + 1; |           n = (long)(out_p - t) | ||||||
|  |             - stl_items[stl_groupitems[groupdepth]].maxwid + 1; | ||||||
|         } |         } | ||||||
|         // } |         // } | ||||||
|  |  | ||||||
| @@ -3689,25 +3687,26 @@ int build_stl_str_hl( | |||||||
|         memmove(t + 1, t + n, (size_t)(out_p - (t + n))); |         memmove(t + 1, t + n, (size_t)(out_p - (t + n))); | ||||||
|         out_p = out_p - n + 1; |         out_p = out_p - n + 1; | ||||||
|         // Fill up space left over by half a double-wide char. |         // Fill up space left over by half a double-wide char. | ||||||
|         while (++group_len < items[groupitems[groupdepth]].minwid) { |         while (++group_len < stl_items[stl_groupitems[groupdepth]].minwid) { | ||||||
|           *out_p++ = fillchar; |           *out_p++ = fillchar; | ||||||
|         } |         } | ||||||
|         // } |         // } | ||||||
|  |  | ||||||
|         // correct the start of the items for the truncation |         // correct the start of the items for the truncation | ||||||
|         for (int idx = groupitems[groupdepth] + 1; idx < curitem; idx++) { |         for (int idx = stl_groupitems[groupdepth] + 1; idx < curitem; idx++) { | ||||||
|           // Shift everything back by the number of removed bytes |           // Shift everything back by the number of removed bytes | ||||||
|           items[idx].start -= n; |           stl_items[idx].start -= n; | ||||||
|  |  | ||||||
|           // If the item was partially or completely truncated, set its |           // If the item was partially or completely truncated, set its | ||||||
|           // start to the start of the group |           // start to the start of the group | ||||||
|           if (items[idx].start < t) { |           if (stl_items[idx].start < t) { | ||||||
|             items[idx].start = t; |             stl_items[idx].start = t; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       // If the group is shorter than the minimum width, add padding characters. |       // If the group is shorter than the minimum width, add padding characters. | ||||||
|       } else if (abs(items[groupitems[groupdepth]].minwid) > group_len) { |       } else if ( | ||||||
|         long min_group_width = items[groupitems[groupdepth]].minwid; |           abs(stl_items[stl_groupitems[groupdepth]].minwid) > group_len) { | ||||||
|  |         long min_group_width = stl_items[stl_groupitems[groupdepth]].minwid; | ||||||
|         // If the group is left-aligned, add characters to the right. |         // If the group is left-aligned, add characters to the right. | ||||||
|         if (min_group_width < 0) { |         if (min_group_width < 0) { | ||||||
|           min_group_width = 0 - min_group_width; |           min_group_width = 0 - min_group_width; | ||||||
| @@ -3726,8 +3725,8 @@ int build_stl_str_hl( | |||||||
|           // } |           // } | ||||||
|  |  | ||||||
|           // Adjust item start positions |           // Adjust item start positions | ||||||
|           for (int n = groupitems[groupdepth] + 1; n < curitem; n++) { |           for (int n = stl_groupitems[groupdepth] + 1; n < curitem; n++) { | ||||||
|             items[n].start += group_len; |             stl_items[n].start += group_len; | ||||||
|           } |           } | ||||||
|  |  | ||||||
|           // Prepend the fill characters |           // Prepend the fill characters | ||||||
| @@ -3763,9 +3762,9 @@ int build_stl_str_hl( | |||||||
|     // User highlight groups override the min width field |     // User highlight groups override the min width field | ||||||
|     // to denote the styling to use. |     // to denote the styling to use. | ||||||
|     if (*fmt_p == STL_USER_HL) { |     if (*fmt_p == STL_USER_HL) { | ||||||
|       items[curitem].type = Highlight; |       stl_items[curitem].type = Highlight; | ||||||
|       items[curitem].start = out_p; |       stl_items[curitem].start = out_p; | ||||||
|       items[curitem].minwid = minwid > 9 ? 1 : minwid; |       stl_items[curitem].minwid = minwid > 9 ? 1 : minwid; | ||||||
|       fmt_p++; |       fmt_p++; | ||||||
|       curitem++; |       curitem++; | ||||||
|       continue; |       continue; | ||||||
| @@ -3799,8 +3798,8 @@ int build_stl_str_hl( | |||||||
|         if (minwid == 0) { |         if (minwid == 0) { | ||||||
|           // %X ends the close label, go back to the previous tab label nr. |           // %X ends the close label, go back to the previous tab label nr. | ||||||
|           for (long n = curitem - 1; n >= 0; n--) { |           for (long n = curitem - 1; n >= 0; n--) { | ||||||
|             if (items[n].type == TabPage && items[n].minwid >= 0) { |             if (stl_items[n].type == TabPage && stl_items[n].minwid >= 0) { | ||||||
|               minwid = items[n].minwid; |               minwid = stl_items[n].minwid; | ||||||
|               break; |               break; | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
| @@ -3809,9 +3808,9 @@ int build_stl_str_hl( | |||||||
|           minwid = -minwid; |           minwid = -minwid; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       items[curitem].type = TabPage; |       stl_items[curitem].type = TabPage; | ||||||
|       items[curitem].start = out_p; |       stl_items[curitem].start = out_p; | ||||||
|       items[curitem].minwid = minwid; |       stl_items[curitem].minwid = minwid; | ||||||
|       fmt_p++; |       fmt_p++; | ||||||
|       curitem++; |       curitem++; | ||||||
|       continue; |       continue; | ||||||
| @@ -3826,10 +3825,10 @@ int build_stl_str_hl( | |||||||
|       if (*fmt_p != STL_CLICK_FUNC) { |       if (*fmt_p != STL_CLICK_FUNC) { | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|       items[curitem].type = ClickFunc; |       stl_items[curitem].type = ClickFunc; | ||||||
|       items[curitem].start = out_p; |       stl_items[curitem].start = out_p; | ||||||
|       items[curitem].cmd = xmemdupz(t, (size_t)(((char *)fmt_p - t))); |       stl_items[curitem].cmd = xmemdupz(t, (size_t)(((char *)fmt_p - t))); | ||||||
|       items[curitem].minwid = minwid; |       stl_items[curitem].minwid = minwid; | ||||||
|       fmt_p++; |       fmt_p++; | ||||||
|       curitem++; |       curitem++; | ||||||
|       continue; |       continue; | ||||||
| @@ -3850,11 +3849,11 @@ int build_stl_str_hl( | |||||||
|  |  | ||||||
|     // Denotes the start of a new group |     // Denotes the start of a new group | ||||||
|     if (*fmt_p == '(') { |     if (*fmt_p == '(') { | ||||||
|       groupitems[groupdepth++] = curitem; |       stl_groupitems[groupdepth++] = curitem; | ||||||
|       items[curitem].type = Group; |       stl_items[curitem].type = Group; | ||||||
|       items[curitem].start = out_p; |       stl_items[curitem].start = out_p; | ||||||
|       items[curitem].minwid = minwid; |       stl_items[curitem].minwid = minwid; | ||||||
|       items[curitem].maxwid = maxwid; |       stl_items[curitem].maxwid = maxwid; | ||||||
|       fmt_p++; |       fmt_p++; | ||||||
|       curitem++; |       curitem++; | ||||||
|       continue; |       continue; | ||||||
| @@ -4149,9 +4148,9 @@ int build_stl_str_hl( | |||||||
|  |  | ||||||
|       // Create a highlight item based on the name |       // Create a highlight item based on the name | ||||||
|       if (*fmt_p == '#') { |       if (*fmt_p == '#') { | ||||||
|         items[curitem].type = Highlight; |         stl_items[curitem].type = Highlight; | ||||||
|         items[curitem].start = out_p; |         stl_items[curitem].start = out_p; | ||||||
|         items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t)); |         stl_items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t)); | ||||||
|         curitem++; |         curitem++; | ||||||
|         fmt_p++; |         fmt_p++; | ||||||
|       } |       } | ||||||
| @@ -4162,8 +4161,8 @@ int build_stl_str_hl( | |||||||
|     // If we made it this far, the item is normal and starts at |     // If we made it this far, the item is normal and starts at | ||||||
|     // our current position in the output buffer. |     // our current position in the output buffer. | ||||||
|     // Non-normal items would have `continued`. |     // Non-normal items would have `continued`. | ||||||
|     items[curitem].start = out_p; |     stl_items[curitem].start = out_p; | ||||||
|     items[curitem].type = Normal; |     stl_items[curitem].type = Normal; | ||||||
|  |  | ||||||
|     // Copy the item string into the output buffer |     // Copy the item string into the output buffer | ||||||
|     if (str != NULL && *str) { |     if (str != NULL && *str) { | ||||||
| @@ -4321,7 +4320,7 @@ int build_stl_str_hl( | |||||||
|  |  | ||||||
|     // Otherwise, there was nothing to print so mark the item as empty |     // Otherwise, there was nothing to print so mark the item as empty | ||||||
|     } else { |     } else { | ||||||
|       items[curitem].type = Empty; |       stl_items[curitem].type = Empty; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Only free the string buffer if we allocated it. |     // Only free the string buffer if we allocated it. | ||||||
| @@ -4362,13 +4361,13 @@ int build_stl_str_hl( | |||||||
|     // Otherwise, look for the truncation item |     // Otherwise, look for the truncation item | ||||||
|     } else { |     } else { | ||||||
|       // Default to truncating at the first item |       // Default to truncating at the first item | ||||||
|       trunc_p = items[0].start; |       trunc_p = stl_items[0].start; | ||||||
|       item_idx = 0; |       item_idx = 0; | ||||||
|  |  | ||||||
|       for (int i = 0; i < itemcnt; i++) { |       for (int i = 0; i < itemcnt; i++) { | ||||||
|         if (items[i].type == Trunc) { |         if (stl_items[i].type == Trunc) { | ||||||
|           // Truncate at %< items. |           // Truncate at %< stl_items. | ||||||
|           trunc_p = items[i].start; |           trunc_p = stl_items[i].start; | ||||||
|           item_idx = i; |           item_idx = i; | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
| @@ -4403,7 +4402,7 @@ int build_stl_str_hl( | |||||||
|       // Ignore any items in the statusline that occur after |       // Ignore any items in the statusline that occur after | ||||||
|       // the truncation point |       // the truncation point | ||||||
|       for (int i = 0; i < itemcnt; i++) { |       for (int i = 0; i < itemcnt; i++) { | ||||||
|         if (items[i].start > trunc_p) { |         if (stl_items[i].start > trunc_p) { | ||||||
|           itemcnt = i; |           itemcnt = i; | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
| @@ -4458,12 +4457,12 @@ int build_stl_str_hl( | |||||||
|       for (int i = item_idx; i < itemcnt; i++) { |       for (int i = item_idx; i < itemcnt; i++) { | ||||||
|         // Items starting at or after the end of the truncated section need |         // Items starting at or after the end of the truncated section need | ||||||
|         // to be moved backwards. |         // to be moved backwards. | ||||||
|         if (items[i].start >= trunc_end_p) { |         if (stl_items[i].start >= trunc_end_p) { | ||||||
|           items[i].start -= item_offset; |           stl_items[i].start -= item_offset; | ||||||
|         // Anything inside the truncated area is set to start |         // Anything inside the truncated area is set to start | ||||||
|         // at the `<` truncation character. |         // at the `<` truncation character. | ||||||
|         } else { |         } else { | ||||||
|           items[i].start = trunc_p; |           stl_items[i].start = trunc_p; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       // } |       // } | ||||||
| @@ -4479,7 +4478,7 @@ int build_stl_str_hl( | |||||||
|     // figuring out how many groups there are. |     // figuring out how many groups there are. | ||||||
|     int num_separators = 0; |     int num_separators = 0; | ||||||
|     for (int i = 0; i < itemcnt; i++) { |     for (int i = 0; i < itemcnt; i++) { | ||||||
|       if (items[i].type == Separate) { |       if (stl_items[i].type == Separate) { | ||||||
|         num_separators++; |         num_separators++; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -4488,11 +4487,10 @@ int build_stl_str_hl( | |||||||
|     if (num_separators) { |     if (num_separators) { | ||||||
|       // Create an array of the start location for each |       // Create an array of the start location for each | ||||||
|       // separator mark. |       // separator mark. | ||||||
|       int separator_locations[STL_MAX_ITEM]; |  | ||||||
|       int index = 0; |       int index = 0; | ||||||
|       for (int i = 0; i < itemcnt; i++) { |       for (int i = 0; i < itemcnt; i++) { | ||||||
|         if (items[i].type == Separate) { |         if (stl_items[i].type == Separate) { | ||||||
|           separator_locations[index] = i; |           stl_separator_locations[index] = i; | ||||||
|           index++; |           index++; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| @@ -4504,16 +4502,17 @@ int build_stl_str_hl( | |||||||
|       for (int i = 0; i < num_separators; i++) { |       for (int i = 0; i < num_separators; i++) { | ||||||
|         int dislocation = (i == (num_separators - 1)) |         int dislocation = (i == (num_separators - 1)) | ||||||
|                           ? final_spaces : standard_spaces; |                           ? final_spaces : standard_spaces; | ||||||
|         char_u *seploc = items[separator_locations[i]].start + dislocation; |         char_u *start = stl_items[stl_separator_locations[i]].start; | ||||||
|         STRMOVE(seploc, items[separator_locations[i]].start); |         char_u *seploc = start + dislocation; | ||||||
|         for (char_u *s = items[separator_locations[i]].start; s < seploc; s++) { |         STRMOVE(seploc, start); | ||||||
|  |         for (char_u *s = start; s < seploc; s++) { | ||||||
|           *s = fillchar; |           *s = fillchar; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         for (int item_idx = separator_locations[i] + 1; |         for (int item_idx = stl_separator_locations[i] + 1; | ||||||
|              item_idx < itemcnt; |              item_idx < itemcnt; | ||||||
|              item_idx++) { |              item_idx++) { | ||||||
|           items[item_idx].start += dislocation; |           stl_items[item_idx].start += dislocation; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -4523,11 +4522,12 @@ int build_stl_str_hl( | |||||||
|  |  | ||||||
|   // Store the info about highlighting. |   // Store the info about highlighting. | ||||||
|   if (hltab != NULL) { |   if (hltab != NULL) { | ||||||
|     struct stl_hlrec *sp = hltab; |     *hltab = stl_hltab; | ||||||
|  |     stl_hlrec_t *sp = stl_hltab; | ||||||
|     for (long l = 0; l < itemcnt; l++) { |     for (long l = 0; l < itemcnt; l++) { | ||||||
|       if (items[l].type == Highlight) { |       if (stl_items[l].type == Highlight) { | ||||||
|         sp->start = items[l].start; |         sp->start = stl_items[l].start; | ||||||
|         sp->userhl = items[l].minwid; |         sp->userhl = stl_items[l].minwid; | ||||||
|         sp++; |         sp++; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -4537,16 +4537,17 @@ int build_stl_str_hl( | |||||||
|  |  | ||||||
|   // Store the info about tab pages labels. |   // Store the info about tab pages labels. | ||||||
|   if (tabtab != NULL) { |   if (tabtab != NULL) { | ||||||
|     StlClickRecord *cur_tab_rec = tabtab; |     *tabtab = stl_tabtab; | ||||||
|  |     StlClickRecord *cur_tab_rec = stl_tabtab; | ||||||
|     for (long l = 0; l < itemcnt; l++) { |     for (long l = 0; l < itemcnt; l++) { | ||||||
|       if (items[l].type == TabPage) { |       if (stl_items[l].type == TabPage) { | ||||||
|         cur_tab_rec->start = (char *)items[l].start; |         cur_tab_rec->start = (char *)stl_items[l].start; | ||||||
|         if (items[l].minwid == 0) { |         if (stl_items[l].minwid == 0) { | ||||||
|           cur_tab_rec->def.type = kStlClickDisabled; |           cur_tab_rec->def.type = kStlClickDisabled; | ||||||
|           cur_tab_rec->def.tabnr = 0; |           cur_tab_rec->def.tabnr = 0; | ||||||
|         } else { |         } else { | ||||||
|           int tabnr = items[l].minwid; |           int tabnr = stl_items[l].minwid; | ||||||
|           if (items[l].minwid > 0) { |           if (stl_items[l].minwid > 0) { | ||||||
|             cur_tab_rec->def.type = kStlClickTabSwitch; |             cur_tab_rec->def.type = kStlClickTabSwitch; | ||||||
|           } else { |           } else { | ||||||
|             cur_tab_rec->def.type = kStlClickTabClose; |             cur_tab_rec->def.type = kStlClickTabClose; | ||||||
| @@ -4556,11 +4557,11 @@ int build_stl_str_hl( | |||||||
|         } |         } | ||||||
|         cur_tab_rec->def.func = NULL; |         cur_tab_rec->def.func = NULL; | ||||||
|         cur_tab_rec++; |         cur_tab_rec++; | ||||||
|       } else if (items[l].type == ClickFunc) { |       } else if (stl_items[l].type == ClickFunc) { | ||||||
|         cur_tab_rec->start = (char *)items[l].start; |         cur_tab_rec->start = (char *)stl_items[l].start; | ||||||
|         cur_tab_rec->def.type = kStlClickFuncRun; |         cur_tab_rec->def.type = kStlClickFuncRun; | ||||||
|         cur_tab_rec->def.tabnr = items[l].minwid; |         cur_tab_rec->def.tabnr = stl_items[l].minwid; | ||||||
|         cur_tab_rec->def.func = items[l].cmd; |         cur_tab_rec->def.func = stl_items[l].cmd; | ||||||
|         cur_tab_rec++; |         cur_tab_rec++; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -361,14 +361,36 @@ struct mapblock { | |||||||
|   sctx_T m_script_ctx;          // SCTX where map was defined |   sctx_T m_script_ctx;          // SCTX where map was defined | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* | /// Used for highlighting in the status line. | ||||||
|  * Used for highlighting in the status line. | typedef struct stl_hlrec stl_hlrec_t; | ||||||
|  */ |  | ||||||
| struct stl_hlrec { | struct stl_hlrec { | ||||||
|   char_u      *start; |   char_u      *start; | ||||||
|   int userhl;                   // 0: no HL, 1-9: User HL, < 0 for syn ID |   int userhl;                   // 0: no HL, 1-9: User HL, < 0 for syn ID | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /// Used for building the status line. | ||||||
|  | typedef struct stl_item stl_item_t; | ||||||
|  | struct stl_item { | ||||||
|  |   // Where the item starts in the status line output buffer | ||||||
|  |   char_u *start; | ||||||
|  |   // Function to run for ClickFunc items. | ||||||
|  |   char *cmd; | ||||||
|  |   // The minimum width of the item | ||||||
|  |   int minwid; | ||||||
|  |   // The maximum width of the item | ||||||
|  |   int maxwid; | ||||||
|  |   enum { | ||||||
|  |     Normal, | ||||||
|  |     Empty, | ||||||
|  |     Group, | ||||||
|  |     Separate, | ||||||
|  |     Highlight, | ||||||
|  |     TabPage, | ||||||
|  |     ClickFunc, | ||||||
|  |     Trunc | ||||||
|  |   } type; | ||||||
|  | }; | ||||||
|  |  | ||||||
| // values for b_syn_spell: what to do with toplevel text | // values for b_syn_spell: what to do with toplevel text | ||||||
| #define SYNSPL_DEFAULT  0       // spell check if @Spell not defined | #define SYNSPL_DEFAULT  0       // spell check if @Spell not defined | ||||||
| #define SYNSPL_TOP      1       // spell check toplevel text | #define SYNSPL_TOP      1       // spell check toplevel text | ||||||
|   | |||||||
| @@ -3751,11 +3751,10 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set) | |||||||
| /// Return error message or NULL. | /// Return error message or NULL. | ||||||
| char_u *check_stl_option(char_u *s) | char_u *check_stl_option(char_u *s) | ||||||
| { | { | ||||||
|   int itemcnt = 0; |  | ||||||
|   int groupdepth = 0; |   int groupdepth = 0; | ||||||
|   static char_u errbuf[80]; |   static char_u errbuf[80]; | ||||||
|  |  | ||||||
|   while (*s && itemcnt < STL_MAX_ITEM) { |   while (*s) { | ||||||
|     // Check for valid keys after % sequences |     // Check for valid keys after % sequences | ||||||
|     while (*s && *s != '%') { |     while (*s && *s != '%') { | ||||||
|       s++; |       s++; | ||||||
| @@ -3764,9 +3763,6 @@ char_u *check_stl_option(char_u *s) | |||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|     s++; |     s++; | ||||||
|     if (*s != '%' && *s != ')') { |  | ||||||
|       itemcnt++; |  | ||||||
|     } |  | ||||||
|     if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_SEPARATE) { |     if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_SEPARATE) { | ||||||
|       s++; |       s++; | ||||||
|       continue; |       continue; | ||||||
| @@ -3808,9 +3804,6 @@ char_u *check_stl_option(char_u *s) | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (itemcnt >= STL_MAX_ITEM) { |  | ||||||
|     return (char_u *)N_("E541: too many items"); |  | ||||||
|   } |  | ||||||
|   if (groupdepth != 0) { |   if (groupdepth != 0) { | ||||||
|     return (char_u *)N_("E542: unbalanced groups"); |     return (char_u *)N_("E542: unbalanced groups"); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -5191,8 +5191,8 @@ win_redr_custom ( | |||||||
|   char_u buf[MAXPATHL]; |   char_u buf[MAXPATHL]; | ||||||
|   char_u      *stl; |   char_u      *stl; | ||||||
|   char_u      *p; |   char_u      *p; | ||||||
|   struct      stl_hlrec hltab[STL_MAX_ITEM]; |   stl_hlrec_t *hltab; | ||||||
|   StlClickRecord tabtab[STL_MAX_ITEM]; |   StlClickRecord *tabtab; | ||||||
|   int use_sandbox = false; |   int use_sandbox = false; | ||||||
|   win_T       *ewp; |   win_T       *ewp; | ||||||
|   int p_crb_save; |   int p_crb_save; | ||||||
| @@ -5270,9 +5270,9 @@ win_redr_custom ( | |||||||
|   /* Make a copy, because the statusline may include a function call that |   /* Make a copy, because the statusline may include a function call that | ||||||
|    * might change the option value and free the memory. */ |    * might change the option value and free the memory. */ | ||||||
|   stl = vim_strsave(stl); |   stl = vim_strsave(stl); | ||||||
|   width = build_stl_str_hl(ewp, buf, sizeof(buf), |   width = | ||||||
|       stl, use_sandbox, |     build_stl_str_hl(ewp, buf, sizeof(buf), stl, use_sandbox, | ||||||
|       fillchar, maxwidth, hltab, tabtab); |                      fillchar, maxwidth, &hltab, &tabtab); | ||||||
|   xfree(stl); |   xfree(stl); | ||||||
|   ewp->w_p_crb = p_crb_save; |   ewp->w_p_crb = p_crb_save; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -267,7 +267,6 @@ func Test_set_errors() | |||||||
|   call assert_fails('set commentstring=x', 'E537:') |   call assert_fails('set commentstring=x', 'E537:') | ||||||
|   call assert_fails('set complete=x', 'E539:') |   call assert_fails('set complete=x', 'E539:') | ||||||
|   call assert_fails('set statusline=%{', 'E540:') |   call assert_fails('set statusline=%{', 'E540:') | ||||||
|   call assert_fails('set statusline=' . repeat("%p", 81), 'E541:') |  | ||||||
|   call assert_fails('set statusline=%(', 'E542:') |   call assert_fails('set statusline=%(', 'E542:') | ||||||
|   if has('cursorshape') |   if has('cursorshape') | ||||||
|     " This invalid value for 'guicursor' used to cause Vim to crash. |     " This invalid value for 'guicursor' used to cause Vim to crash. | ||||||
|   | |||||||
| @@ -354,6 +354,21 @@ func Test_statusline() | |||||||
|   delfunc GetNested |   delfunc GetNested | ||||||
|   delfunc GetStatusLine |   delfunc GetStatusLine | ||||||
|  |  | ||||||
|  |   " Test statusline works with 80+ items | ||||||
|  |   function! StatusLabel() | ||||||
|  |     redrawstatus | ||||||
|  |     return '[label]'	 | ||||||
|  |   endfunc | ||||||
|  |   let statusline = '%{StatusLabel()}' | ||||||
|  |   for i in range(150) | ||||||
|  |     let statusline .= '%#TabLine' . (i % 2 == 0 ? 'Fill' : 'Sel') . '#' . string(i)[0] | ||||||
|  |   endfor | ||||||
|  |   let &statusline = statusline | ||||||
|  |   redrawstatus | ||||||
|  |   set statusline& | ||||||
|  |   delfunc StatusLabel | ||||||
|  |  | ||||||
|  |  | ||||||
|   " Check statusline in current and non-current window |   " Check statusline in current and non-current window | ||||||
|   " with the 'fillchars' option. |   " with the 'fillchars' option. | ||||||
|   set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:- |   set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:- | ||||||
|   | |||||||
| @@ -259,7 +259,6 @@ enum { FOLD_TEXT_LEN = 51 };  //!< buffer size for get_foldtext() | |||||||
| #define PERROR(msg) (void) emsgf("%s: %s", msg, strerror(errno)) | #define PERROR(msg) (void) emsgf("%s: %s", msg, strerror(errno)) | ||||||
|  |  | ||||||
| #define SHOWCMD_COLS 10                 // columns needed by shown command | #define SHOWCMD_COLS 10                 // columns needed by shown command | ||||||
| #define STL_MAX_ITEM 80                 // max nr of %<flag> in statusline |  | ||||||
|  |  | ||||||
| #include "nvim/path.h" | #include "nvim/path.h" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -212,7 +212,7 @@ describe('buffer functions', function() | |||||||
|  |  | ||||||
|   describe('build_stl_str_hl', function() |   describe('build_stl_str_hl', function() | ||||||
|     local buffer_byte_size = 100 |     local buffer_byte_size = 100 | ||||||
|     local STL_MAX_ITEM = 80 |     local STL_INITIAL_ITEMS = 20 | ||||||
|     local output_buffer = '' |     local output_buffer = '' | ||||||
|  |  | ||||||
|     -- This function builds the statusline |     -- This function builds the statusline | ||||||
| @@ -431,31 +431,23 @@ describe('buffer functions', function() | |||||||
|       'aaaa%=b%=c%=d%=e%=fg%=hi%=jk%=lmnop%=qrstuv%=wxyz', |       'aaaa%=b%=c%=d%=e%=fg%=hi%=jk%=lmnop%=qrstuv%=wxyz', | ||||||
|       'aaaa  b  c  d  e  fg  hi  jk  lmnop  qrstuv   wxyz') |       'aaaa  b  c  d  e  fg  hi  jk  lmnop  qrstuv   wxyz') | ||||||
|  |  | ||||||
|     -- maximum stl item testing |     -- stl item testing | ||||||
|     statusline_test('should handle a much larger amount of = than buffer locations', 20, |     local tabline = '' | ||||||
|       ('%='):rep(STL_MAX_ITEM - 1), |     for i= 1, 1000 do | ||||||
|       '                    ') -- Should be fine, because within limit |       tabline = tabline .. (i % 2 == 0 and '%#TabLineSel#' or '%#TabLineFill#') .. tostring(i % 2) | ||||||
|     statusline_test('should handle a much larger amount of = than stl max item', 20, |     end | ||||||
|       ('%='):rep(STL_MAX_ITEM + 1), |     statusline_test('should handle a large amount of any items', 20, | ||||||
|       '                E541') -- Should show the VIM error |       tabline, | ||||||
|  |       '<1010101010101010101') -- Should not show any error | ||||||
|  |     statusline_test('should handle a larger amount of = than stl initial item', 20, | ||||||
|  |       ('%='):rep(STL_INITIAL_ITEMS * 5), | ||||||
|  |       '                    ') -- Should not show any error | ||||||
|     statusline_test('should handle many extra characters', 20, |     statusline_test('should handle many extra characters', 20, | ||||||
|       'a' .. ('a'):rep(STL_MAX_ITEM * 4), |       'a' .. ('a'):rep(STL_INITIAL_ITEMS * 5), | ||||||
|       '<aaaaaaaaaaaaaaaaaaa') -- Does not show the error because there are no items |       '<aaaaaaaaaaaaaaaaaaa') -- Does not show any error | ||||||
|     statusline_test('should handle almost maximum of characters and flags', 20, |  | ||||||
|       'a' .. ('%=a'):rep(STL_MAX_ITEM - 1), |  | ||||||
|       'a<aaaaaaaaaaaaaaaaaa') -- Should not show the VIM error |  | ||||||
|     statusline_test('should handle many extra characters and flags', 20, |     statusline_test('should handle many extra characters and flags', 20, | ||||||
|       'a' .. ('%=a'):rep(STL_MAX_ITEM), |       'a' .. ('%=a'):rep(STL_INITIAL_ITEMS * 2), | ||||||
|       'a<aaaaaaaaaaaaa E541') -- Should show the VIM error |       'a<aaaaaaaaaaaaaaaaaa') -- Should not show any error | ||||||
|     statusline_test('should handle many extra characters and flags', 20, |  | ||||||
|       'a' .. ('%=a'):rep(STL_MAX_ITEM * 2), |  | ||||||
|       'a<aaaaaaaaaaaaa E541') -- Should show the VIM error |  | ||||||
|     statusline_test('should handle many extra characters and flags with truncation', 20, |  | ||||||
|       'aaa%<' .. ('%=a'):rep(STL_MAX_ITEM), |  | ||||||
|       'aaa<aaaaaaaaaaa E541') -- Should show the VIM error |  | ||||||
|     statusline_test('should handle many characters and flags before and after truncation', 20, |  | ||||||
|       'a%=a%=a%<' .. ('%=a'):rep(STL_MAX_ITEM), |  | ||||||
|       'aaa<aaaaaaaaaaa E541') -- Should show the VIM error |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     -- multi-byte testing |     -- multi-byte testing | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Rom Grk
					Rom Grk