diff src/screen.c @ 12487:3f16cf18386c v8.0.1123

patch 8.0.1123: cannot define a toolbar for a window commit https://github.com/vim/vim/commit/1b9645de3c05f37b5c30e78f999351b0cf486ade Author: Bram Moolenaar <Bram@vim.org> Date: Sun Sep 17 23:03:31 2017 +0200 patch 8.0.1123: cannot define a toolbar for a window Problem: Cannot define a toolbar for a window. Solution: Add a window-local toolbar.
author Christian Brabandt <cb@256bit.org>
date Sun, 17 Sep 2017 23:15:04 +0200
parents 68d7bc045dbe
children 7a887dccd13a
line wrap: on
line diff
--- a/src/screen.c
+++ b/src/screen.c
@@ -107,6 +107,9 @@ static int	screen_cur_row, screen_cur_co
 static match_T search_hl;	/* used for 'hlsearch' highlight matching */
 #endif
 
+#if defined(FEAT_MENU) || defined(FEAT_FOLDING)
+static int text_to_screenline(win_T *wp, char_u *text, int col);
+#endif
 #ifdef FEAT_FOLDING
 static foldinfo_T win_foldinfo;	/* info for 'foldcolumn' */
 static int compute_foldcolumn(win_T *wp, int col);
@@ -160,6 +163,9 @@ static void recording_mode(int attr);
 static void draw_tabline(void);
 static int fillchar_status(int *attr, win_T *wp);
 static int fillchar_vsep(int *attr);
+#ifdef FEAT_MENU
+static void redraw_win_toolbar(win_T *wp);
+#endif
 #ifdef FEAT_STL_OPT
 static void win_redr_custom(win_T *wp, int draw_ruler);
 #endif
@@ -455,7 +461,7 @@ redraw_after_callback(int call_update_sc
 	 * editing the command. */
 	redrawcmdline_ex(FALSE);
     }
-    else if (State & (NORMAL | INSERT))
+    else if (State & (NORMAL | INSERT | TERMINAL))
     {
 	/* keep the command line if possible */
 	update_screen(VALID_NO_UPDATE);
@@ -1804,6 +1810,15 @@ win_update(win_T *wp)
     win_foldinfo.fi_level = 0;
 #endif
 
+#ifdef FEAT_MENU
+    /*
+     * Draw the window toolbar, if there is one.
+     * TODO: only when needed.
+     */
+    if (winbar_height(wp) > 0)
+	redraw_win_toolbar(wp);
+#endif
+
     /*
      * Update all the window rows.
      */
@@ -2433,6 +2448,143 @@ advance_color_col(int vcol, int **color_
 }
 #endif
 
+#if defined(FEAT_MENU) || defined(FEAT_FOLDING)
+/*
+ * Copy "text" to ScreenLines using "attr".
+ * Returns the next screen column.
+ */
+    static int
+text_to_screenline(win_T *wp, char_u *text, int col)
+{
+    int		off = (int)(current_ScreenLine - ScreenLines);
+
+#ifdef FEAT_MBYTE
+    if (has_mbyte)
+    {
+	int	cells;
+	int	u8c, u8cc[MAX_MCO];
+	int	i;
+	int	idx;
+	int	c_len;
+	char_u	*p;
+# ifdef FEAT_ARABIC
+	int	prev_c = 0;		/* previous Arabic character */
+	int	prev_c1 = 0;		/* first composing char for prev_c */
+# endif
+
+# ifdef FEAT_RIGHTLEFT
+	if (wp->w_p_rl)
+	    idx = off;
+	else
+# endif
+	    idx = off + col;
+
+	/* Store multibyte characters in ScreenLines[] et al. correctly. */
+	for (p = text; *p != NUL; )
+	{
+	    cells = (*mb_ptr2cells)(p);
+	    c_len = (*mb_ptr2len)(p);
+	    if (col + cells > W_WIDTH(wp)
+# ifdef FEAT_RIGHTLEFT
+		    - (wp->w_p_rl ? col : 0)
+# endif
+		    )
+		break;
+	    ScreenLines[idx] = *p;
+	    if (enc_utf8)
+	    {
+		u8c = utfc_ptr2char(p, u8cc);
+		if (*p < 0x80 && u8cc[0] == 0)
+		{
+		    ScreenLinesUC[idx] = 0;
+#ifdef FEAT_ARABIC
+		    prev_c = u8c;
+#endif
+		}
+		else
+		{
+#ifdef FEAT_ARABIC
+		    if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c))
+		    {
+			/* Do Arabic shaping. */
+			int	pc, pc1, nc;
+			int	pcc[MAX_MCO];
+			int	firstbyte = *p;
+
+			/* The idea of what is the previous and next
+			 * character depends on 'rightleft'. */
+			if (wp->w_p_rl)
+			{
+			    pc = prev_c;
+			    pc1 = prev_c1;
+			    nc = utf_ptr2char(p + c_len);
+			    prev_c1 = u8cc[0];
+			}
+			else
+			{
+			    pc = utfc_ptr2char(p + c_len, pcc);
+			    nc = prev_c;
+			    pc1 = pcc[0];
+			}
+			prev_c = u8c;
+
+			u8c = arabic_shape(u8c, &firstbyte, &u8cc[0],
+								 pc, pc1, nc);
+			ScreenLines[idx] = firstbyte;
+		    }
+		    else
+			prev_c = u8c;
+#endif
+		    /* Non-BMP character: display as ? or fullwidth ?. */
+#ifdef UNICODE16
+		    if (u8c >= 0x10000)
+			ScreenLinesUC[idx] = (cells == 2) ? 0xff1f : (int)'?';
+		    else
+#endif
+			ScreenLinesUC[idx] = u8c;
+		    for (i = 0; i < Screen_mco; ++i)
+		    {
+			ScreenLinesC[i][idx] = u8cc[i];
+			if (u8cc[i] == 0)
+			    break;
+		    }
+		}
+		if (cells > 1)
+		    ScreenLines[idx + 1] = 0;
+	    }
+	    else if (enc_dbcs == DBCS_JPNU && *p == 0x8e)
+		/* double-byte single width character */
+		ScreenLines2[idx] = p[1];
+	    else if (cells > 1)
+		/* double-width character */
+		ScreenLines[idx + 1] = p[1];
+	    col += cells;
+	    idx += cells;
+	    p += c_len;
+	}
+    }
+    else
+#endif
+    {
+	int len = (int)STRLEN(text);
+
+	if (len > W_WIDTH(wp) - col)
+	    len = W_WIDTH(wp) - col;
+	if (len > 0)
+	{
+#ifdef FEAT_RIGHTLEFT
+	    if (wp->w_p_rl)
+		STRNCPY(current_ScreenLine, text, len);
+	    else
+#endif
+		STRNCPY(current_ScreenLine + col, text, len);
+	    col += len;
+	}
+    }
+    return col;
+}
+#endif
+
 #ifdef FEAT_FOLDING
 /*
  * Compute the width of the foldcolumn.  Based on 'foldcolumn' and how much
@@ -2618,128 +2770,7 @@ fold_line(
      *    Right-left text is put in columns 0 - number-col, normal text is put
      *    in columns number-col - window-width.
      */
-#ifdef FEAT_MBYTE
-    if (has_mbyte)
-    {
-	int	cells;
-	int	u8c, u8cc[MAX_MCO];
-	int	i;
-	int	idx;
-	int	c_len;
-	char_u	*p;
-# ifdef FEAT_ARABIC
-	int	prev_c = 0;		/* previous Arabic character */
-	int	prev_c1 = 0;		/* first composing char for prev_c */
-# endif
-
-# ifdef FEAT_RIGHTLEFT
-	if (wp->w_p_rl)
-	    idx = off;
-	else
-# endif
-	    idx = off + col;
-
-	/* Store multibyte characters in ScreenLines[] et al. correctly. */
-	for (p = text; *p != NUL; )
-	{
-	    cells = (*mb_ptr2cells)(p);
-	    c_len = (*mb_ptr2len)(p);
-	    if (col + cells > W_WIDTH(wp)
-# ifdef FEAT_RIGHTLEFT
-		    - (wp->w_p_rl ? col : 0)
-# endif
-		    )
-		break;
-	    ScreenLines[idx] = *p;
-	    if (enc_utf8)
-	    {
-		u8c = utfc_ptr2char(p, u8cc);
-		if (*p < 0x80 && u8cc[0] == 0)
-		{
-		    ScreenLinesUC[idx] = 0;
-#ifdef FEAT_ARABIC
-		    prev_c = u8c;
-#endif
-		}
-		else
-		{
-#ifdef FEAT_ARABIC
-		    if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c))
-		    {
-			/* Do Arabic shaping. */
-			int	pc, pc1, nc;
-			int	pcc[MAX_MCO];
-			int	firstbyte = *p;
-
-			/* The idea of what is the previous and next
-			 * character depends on 'rightleft'. */
-			if (wp->w_p_rl)
-			{
-			    pc = prev_c;
-			    pc1 = prev_c1;
-			    nc = utf_ptr2char(p + c_len);
-			    prev_c1 = u8cc[0];
-			}
-			else
-			{
-			    pc = utfc_ptr2char(p + c_len, pcc);
-			    nc = prev_c;
-			    pc1 = pcc[0];
-			}
-			prev_c = u8c;
-
-			u8c = arabic_shape(u8c, &firstbyte, &u8cc[0],
-								 pc, pc1, nc);
-			ScreenLines[idx] = firstbyte;
-		    }
-		    else
-			prev_c = u8c;
-#endif
-		    /* Non-BMP character: display as ? or fullwidth ?. */
-#ifdef UNICODE16
-		    if (u8c >= 0x10000)
-			ScreenLinesUC[idx] = (cells == 2) ? 0xff1f : (int)'?';
-		    else
-#endif
-			ScreenLinesUC[idx] = u8c;
-		    for (i = 0; i < Screen_mco; ++i)
-		    {
-			ScreenLinesC[i][idx] = u8cc[i];
-			if (u8cc[i] == 0)
-			    break;
-		    }
-		}
-		if (cells > 1)
-		    ScreenLines[idx + 1] = 0;
-	    }
-	    else if (enc_dbcs == DBCS_JPNU && *p == 0x8e)
-		/* double-byte single width character */
-		ScreenLines2[idx] = p[1];
-	    else if (cells > 1)
-		/* double-width character */
-		ScreenLines[idx + 1] = p[1];
-	    col += cells;
-	    idx += cells;
-	    p += c_len;
-	}
-    }
-    else
-#endif
-    {
-	len = (int)STRLEN(text);
-	if (len > W_WIDTH(wp) - col)
-	    len = W_WIDTH(wp) - col;
-	if (len > 0)
-	{
-#ifdef FEAT_RIGHTLEFT
-	    if (wp->w_p_rl)
-		STRNCPY(current_ScreenLine, text, len);
-	    else
-#endif
-		STRNCPY(current_ScreenLine + col, text, len);
-	    col += len;
-	}
-    }
+    col = text_to_screenline(wp, text, col);
 
     /* Fill the rest of the line with the fold filler */
 #ifdef FEAT_RIGHTLEFT
@@ -8397,6 +8428,17 @@ redraw_block(int row, int end, win_T *wp
     screen_draw_rectangle(row, col, end - row, width, FALSE);
 }
 
+    static void
+space_to_screenline(int off, int attr)
+{
+    ScreenLines[off] = ' ';
+    ScreenAttrs[off] = attr;
+# ifdef FEAT_MBYTE
+    if (enc_utf8)
+	ScreenLinesUC[off] = 0;
+# endif
+}
+
 /*
  * Fill the screen from 'start_row' to 'end_row', from 'start_col' to 'end_col'
  * with character 'c1' in first column followed by 'c2' in the other columns.
@@ -8502,12 +8544,7 @@ screen_fill(
 		col = end_col - col;
 		while (col--)		/* clear chars in ScreenLines */
 		{
-		    ScreenLines[off] = ' ';
-#ifdef FEAT_MBYTE
-		    if (enc_utf8)
-			ScreenLinesUC[off] = 0;
-#endif
-		    ScreenAttrs[off] = 0;
+		    space_to_screenline(off, 0);
 		    ++off;
 		}
 	    }
@@ -10671,6 +10708,73 @@ messaging(void)
     return (!(p_lz && char_avail() && !KeyTyped));
 }
 
+#ifdef FEAT_MENU
+/*
+ * Draw the window toolbar.
+ */
+    static void
+redraw_win_toolbar(win_T *wp)
+{
+    vimmenu_T	*menu;
+    int		item_idx = 0;
+    int		item_count = 0;
+    int		col = 0;
+    int		next_col;
+    int		off = (int)(current_ScreenLine - ScreenLines);
+    int		fill_attr = syn_name2attr((char_u *)"ToolbarLine");
+    int		button_attr = syn_name2attr((char_u *)"ToolbarButton");
+
+    vim_free(wp->w_winbar_items);
+    for (menu = wp->w_winbar->children; menu != NULL; menu = menu->next)
+	++item_count;
+    wp->w_winbar_items = (winbar_item_T *)alloc_clear(
+			   (unsigned)sizeof(winbar_item_T) * (item_count + 1));
+
+    /* TODO: use fewer spaces if there is not enough room */
+    for (menu = wp->w_winbar->children;
+			  menu != NULL && col < W_WIDTH(wp); menu = menu->next)
+    {
+	space_to_screenline(off + col, fill_attr);
+	if (++col >= W_WIDTH(wp))
+	    break;
+	if (col > 1)
+	{
+	    space_to_screenline(off + col, fill_attr);
+	    if (++col >= W_WIDTH(wp))
+		break;
+	}
+
+	wp->w_winbar_items[item_idx].wb_startcol = col;
+	space_to_screenline(off + col, button_attr);
+	if (++col >= W_WIDTH(wp))
+	    break;
+
+	next_col = text_to_screenline(wp, menu->name, col);
+	while (col < next_col)
+	{
+	    ScreenAttrs[off + col] = button_attr;
+	    ++col;
+	}
+	wp->w_winbar_items[item_idx].wb_endcol = col;
+	wp->w_winbar_items[item_idx].wb_menu = menu;
+	++item_idx;
+
+	if (col >= W_WIDTH(wp))
+	    break;
+	space_to_screenline(off + col, button_attr);
+	++col;
+    }
+    while (col < W_WIDTH(wp))
+    {
+	space_to_screenline(off + col, fill_attr);
+	++col;
+    }
+    wp->w_winbar_items[item_idx].wb_menu = NULL; /* end marker */
+
+    screen_line(wp->w_winrow, W_WINCOL(wp), (int)W_WIDTH(wp),
+						     (int)W_WIDTH(wp), FALSE);
+}
+#endif
 /*
  * Show current status info in ruler and various other places
  * If always is FALSE, only show ruler if position has changed.