mirror of
https://github.com/zoriya/vim.git
synced 2025-12-19 13:45:18 +00:00
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.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
*gui.txt* For Vim version 8.0. Last change: 2017 Aug 27
|
||||
*gui.txt* For Vim version 8.0. Last change: 2017 Sep 16
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -784,10 +784,31 @@ In the Win32 and GTK+ GUI, starting a menu name with ']' excludes that menu
|
||||
from the main menu bar. You must then use the |:popup| or |:tearoff| command
|
||||
to display it.
|
||||
|
||||
*window-toolbar*
|
||||
Each window can have a local toolbar. This uses the first line of the window,
|
||||
thus reduces the space for the text by one line.
|
||||
|
||||
Only text can be used. When using Unicode special characters can be used to
|
||||
make the items look like icons.
|
||||
|
||||
If the items do not fit then the last ones cannot be used. The toolbar does
|
||||
not wrap.
|
||||
|
||||
Example for debugger tools: >
|
||||
amenu 1.10 WinBar.Step :Step<CR>
|
||||
amenu 1.20 WinBar.Next :Next<CR>
|
||||
amenu 1.30 WinBar.Finish :Finish<CR>
|
||||
amenu 1.40 WinBar.Cont :Continue<CR>
|
||||
<
|
||||
The window toolbar uses the ToolbarLine and ToolbarButton highlight groups.
|
||||
|
||||
*popup-menu*
|
||||
In the Win32, GTK+, Motif, Athena and Photon GUI, you can define the
|
||||
special menu "PopUp". This is the menu that is displayed when the right mouse
|
||||
button is pressed, if 'mousemodel' is set to popup or popup_setpos.
|
||||
Example: >
|
||||
nnoremenu 1.40 PopUp.&Paste "+gP
|
||||
menu PopUp
|
||||
|
||||
|
||||
5.3 Showing What Menus Are Mapped To *showing-menus*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*terminal.txt* For Vim version 8.0. Last change: 2017 Sep 14
|
||||
*terminal.txt* For Vim version 8.0. Last change: 2017 Sep 17
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -226,7 +226,7 @@ Use CTRL-W N (or 'termkey' N) to switch to Terminal-Normal mode. Now the
|
||||
contents of the terminal window is under control of Vim, the job output is
|
||||
suspended. CTRL-\ CTRL-N does the same.
|
||||
|
||||
Terminal-Job mode is where |tmap| mappings are applied. Keys sent by
|
||||
Terminal-Job mode is where |:tmap| mappings are applied. Keys sent by
|
||||
|term_sendkeys()| are not subject to tmap, but keys from |feedkeys()| are.
|
||||
|
||||
*E946*
|
||||
@@ -234,7 +234,7 @@ In Terminal-Normal mode you can move the cursor around with the usual Vim
|
||||
commands, Visually mark text, yank text, etc. But you cannot change the
|
||||
contents of the buffer. The commands that would start insert mode, such as
|
||||
'i' and 'a', return to Terminal-Job mode. The window will be updated to show
|
||||
the contents of the terminal.
|
||||
the contents of the terminal. |:startinsert| is ineffective.
|
||||
|
||||
In Terminal-Normal mode the statusline and window title show "(Terminal)". If
|
||||
the job ends while in Terminal-Normal mode this changes to
|
||||
@@ -372,6 +372,14 @@ In the window showing the source code some commands can used to control gdb:
|
||||
:Finish execute the gdb "finish" command
|
||||
:Continue execute the gdb "continue" command
|
||||
|
||||
The plugin adds a window toolbar with these entries:
|
||||
Step :Step
|
||||
Next :Over
|
||||
Finish :Finish
|
||||
Cont :Continue
|
||||
Eval :Evaluate
|
||||
This way you can use the mouse to perform the most common commands.
|
||||
|
||||
|
||||
Inspecting variables ~
|
||||
|
||||
|
||||
@@ -104,6 +104,11 @@ func s:StartDebug(cmd)
|
||||
call win_gotoid(s:gdbwin)
|
||||
|
||||
let s:breakpoints = {}
|
||||
|
||||
augroup TermDebug
|
||||
au BufRead * call s:BufRead()
|
||||
au BufUnload * call s:BufUnloaded()
|
||||
augroup END
|
||||
endfunc
|
||||
|
||||
func s:EndDebug(job, status)
|
||||
@@ -120,6 +125,8 @@ func s:EndDebug(job, status)
|
||||
if s:save_columns > 0
|
||||
let &columns = s:save_columns
|
||||
endif
|
||||
|
||||
au! TermDebug
|
||||
endfunc
|
||||
|
||||
" Handle a message received from gdb on the GDB/MI interface.
|
||||
@@ -132,7 +139,7 @@ func s:CommOutput(chan, msg)
|
||||
let msg = msg[1:]
|
||||
endif
|
||||
if msg != ''
|
||||
if msg =~ '^\*\(stopped\|running\)'
|
||||
if msg =~ '^\(\*stopped\|\*running\|=thread-selected\)'
|
||||
call s:HandleCursor(msg)
|
||||
elseif msg =~ '^\^done,bkpt=' || msg =~ '^=breakpoint-created,'
|
||||
call s:HandleNewBreakpoint(msg)
|
||||
@@ -161,6 +168,14 @@ func s:InstallCommands()
|
||||
|
||||
" TODO: can the K mapping be restored?
|
||||
nnoremap K :Evaluate<CR>
|
||||
|
||||
if has('menu')
|
||||
amenu WinBar.Step :Step<CR>
|
||||
amenu WinBar.Next :Over<CR>
|
||||
amenu WinBar.Finish :Finish<CR>
|
||||
amenu WinBar.Cont :Continue<CR>
|
||||
amenu WinBar.Eval :Evaluate<CR>
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Delete installed debugger commands in the current window.
|
||||
@@ -176,6 +191,15 @@ func s:DeleteCommands()
|
||||
delcommand Program
|
||||
|
||||
nunmap K
|
||||
|
||||
if has('menu')
|
||||
aunmenu WinBar.Step
|
||||
aunmenu WinBar.Next
|
||||
aunmenu WinBar.Finish
|
||||
aunmenu WinBar.Cont
|
||||
aunmenu WinBar.Eval
|
||||
endif
|
||||
|
||||
exe 'sign unplace ' . s:pc_id
|
||||
for key in keys(s:breakpoints)
|
||||
exe 'sign unplace ' . (s:break_id + key)
|
||||
@@ -232,7 +256,15 @@ endfunc
|
||||
|
||||
" Handle the result of data-evaluate-expression
|
||||
func s:HandleEvaluate(msg)
|
||||
echomsg '"' . s:evalexpr . '": ' . substitute(a:msg, '.*value="\(.*\)"', '\1', '')
|
||||
let value = substitute(a:msg, '.*value="\(.*\)"', '\1', '')
|
||||
let value = substitute(value, '\\"', '"', 'g')
|
||||
echomsg '"' . s:evalexpr . '": ' . value
|
||||
|
||||
if s:evalexpr[0] != '*' && value =~ '^0x' && value !~ '"$'
|
||||
" Looks like a pointer, also display what it points to.
|
||||
let s:evalexpr = '*' . s:evalexpr
|
||||
call term_sendkeys(s:commbuf, '-data-evaluate-expression "' . s:evalexpr . "\"\r")
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Handle an error.
|
||||
@@ -247,10 +279,10 @@ func s:HandleCursor(msg)
|
||||
|
||||
if win_gotoid(s:startwin)
|
||||
let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '')
|
||||
if a:msg =~ '^\*stopped' && filereadable(fname)
|
||||
if a:msg =~ '^\(\*stopped\|=thread-selected\)' && filereadable(fname)
|
||||
let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
|
||||
if lnum =~ '^[0-9]*$'
|
||||
if expand('%:h') != fname
|
||||
if expand('%:p') != fnamemodify(fname, ':p')
|
||||
if &modified
|
||||
" TODO: find existing window
|
||||
exe 'split ' . fnameescape(fname)
|
||||
@@ -260,7 +292,7 @@ func s:HandleCursor(msg)
|
||||
endif
|
||||
endif
|
||||
exe lnum
|
||||
exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fnameescape(fname)
|
||||
exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fname
|
||||
setlocal signcolumn=yes
|
||||
endif
|
||||
else
|
||||
@@ -288,11 +320,17 @@ func s:HandleNewBreakpoint(msg)
|
||||
|
||||
let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '')
|
||||
let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
|
||||
|
||||
exe 'sign place ' . (s:break_id + nr) . ' line=' . lnum . ' name=debugBreakpoint file=' . fnameescape(fname)
|
||||
|
||||
let entry['fname'] = fname
|
||||
let entry['lnum'] = lnum
|
||||
|
||||
if bufloaded(fname)
|
||||
call s:PlaceSign(nr, entry)
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func s:PlaceSign(nr, entry)
|
||||
exe 'sign place ' . (s:break_id + a:nr) . ' line=' . a:entry['lnum'] . ' name=debugBreakpoint file=' . a:entry['fname']
|
||||
let a:entry['placed'] = 1
|
||||
endfunc
|
||||
|
||||
" Handle deleting a breakpoint
|
||||
@@ -302,6 +340,33 @@ func s:HandleBreakpointDelete(msg)
|
||||
if nr == 0
|
||||
return
|
||||
endif
|
||||
if has_key(s:breakpoints, nr)
|
||||
let entry = s:breakpoints[nr]
|
||||
if has_key(entry, 'placed')
|
||||
exe 'sign unplace ' . (s:break_id + nr)
|
||||
unlet entry['placed']
|
||||
endif
|
||||
unlet s:breakpoints[nr]
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Handle a BufRead autocommand event: place any signs.
|
||||
func s:BufRead()
|
||||
let fname = expand('<afile>:p')
|
||||
for [nr, entry] in items(s:breakpoints)
|
||||
if entry['fname'] == fname
|
||||
call s:PlaceSign(nr, entry)
|
||||
endif
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
" Handle a BufUnloaded autocommand event: unplace any signs.
|
||||
func s:BufUnloaded()
|
||||
let fname = expand('<afile>:p')
|
||||
for [nr, entry] in items(s:breakpoints)
|
||||
if entry['fname'] == fname
|
||||
let entry['placed'] = 0
|
||||
endif
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
|
||||
@@ -2278,6 +2278,7 @@ test_arglist \
|
||||
test_vimscript \
|
||||
test_virtualedit \
|
||||
test_visual \
|
||||
test_winbar \
|
||||
test_window_cmd \
|
||||
test_window_id \
|
||||
test_windows_home \
|
||||
|
||||
@@ -8252,13 +8252,7 @@ ex_echo(exarg_T *eap)
|
||||
void
|
||||
ex_echohl(exarg_T *eap)
|
||||
{
|
||||
int id;
|
||||
|
||||
id = syn_name2id(eap->arg);
|
||||
if (id == 0)
|
||||
echo_attr = 0;
|
||||
else
|
||||
echo_attr = syn_id2attr(id);
|
||||
echo_attr = syn_name2attr(eap->arg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -5229,6 +5229,9 @@ get_win_info(win_T *wp, short tpnr, short winnr)
|
||||
dict_add_nr_str(dict, "winnr", winnr, NULL);
|
||||
dict_add_nr_str(dict, "winid", wp->w_id, NULL);
|
||||
dict_add_nr_str(dict, "height", wp->w_height, NULL);
|
||||
#ifdef FEAT_MENU
|
||||
dict_add_nr_str(dict, "winbar", wp->w_winbar_height, NULL);
|
||||
#endif
|
||||
dict_add_nr_str(dict, "width", wp->w_width, NULL);
|
||||
dict_add_nr_str(dict, "bufnr", wp->w_buffer->b_fnum, NULL);
|
||||
|
||||
|
||||
@@ -1387,11 +1387,8 @@ PerlIOVim_pushed(pTHX_ PerlIO *f, const char *mode,
|
||||
{
|
||||
PerlIOVim *s = PerlIOSelf(f, PerlIOVim);
|
||||
s->attr = 0;
|
||||
if (arg && SvPOK(arg)) {
|
||||
int id = syn_name2id((char_u *)SvPV_nolen(arg));
|
||||
if (id != 0)
|
||||
s->attr = syn_id2attr(id);
|
||||
}
|
||||
if (arg && SvPOK(arg))
|
||||
s->attr = syn_name2attr((char_u *)SvPV_nolen(arg));
|
||||
return PerlIOBase_pushed(aTHX_ f, mode, (SV *)NULL, tab);
|
||||
}
|
||||
|
||||
@@ -1482,11 +1479,7 @@ Msg(text, hl=NULL)
|
||||
{
|
||||
attr = 0;
|
||||
if (hl != NULL)
|
||||
{
|
||||
id = syn_name2id((char_u *)hl);
|
||||
if (id != 0)
|
||||
attr = syn_id2attr(id);
|
||||
}
|
||||
attr = syn_name2attr((char_u *)hl);
|
||||
msg_split((char_u *)text, attr);
|
||||
}
|
||||
|
||||
|
||||
290
src/menu.c
290
src/menu.c
@@ -82,6 +82,31 @@ static const char *toolbar_names[] =
|
||||
# define TOOLBAR_NAME_COUNT (sizeof(toolbar_names) / sizeof(char *))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return TRUE if "name" is a window toolbar menu name.
|
||||
*/
|
||||
static int
|
||||
menu_is_winbar(char_u *name)
|
||||
{
|
||||
return (STRNCMP(name, "WinBar", 5) == 0);
|
||||
}
|
||||
|
||||
int
|
||||
winbar_height(win_T *wp)
|
||||
{
|
||||
if (wp->w_winbar != NULL && wp->w_winbar->children != NULL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vimmenu_T **
|
||||
get_root_menu(char_u *name)
|
||||
{
|
||||
if (menu_is_winbar(name))
|
||||
return &curwin->w_winbar;
|
||||
return &root_menu;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the :menu command and relatives.
|
||||
*/
|
||||
@@ -113,6 +138,7 @@ ex_menu(
|
||||
char_u *icon = NULL;
|
||||
#endif
|
||||
vimmenu_T menuarg;
|
||||
vimmenu_T **root_menu_ptr;
|
||||
|
||||
modes = get_menu_cmd_modes(eap->cmd, eap->forceit, &noremap, &unmenu);
|
||||
arg = eap->arg;
|
||||
@@ -279,6 +305,11 @@ ex_menu(
|
||||
# endif
|
||||
#endif
|
||||
|
||||
root_menu_ptr = get_root_menu(menu_path);
|
||||
if (root_menu_ptr == &curwin->w_winbar)
|
||||
/* Assume the window toolbar menu will change. */
|
||||
redraw_later(NOT_VALID);
|
||||
|
||||
if (enable != MAYBE)
|
||||
{
|
||||
/*
|
||||
@@ -297,13 +328,13 @@ ex_menu(
|
||||
p = popup_mode_name(menu_path, i);
|
||||
if (p != NULL)
|
||||
{
|
||||
menu_nable_recurse(root_menu, p, MENU_ALL_MODES,
|
||||
menu_nable_recurse(*root_menu_ptr, p, MENU_ALL_MODES,
|
||||
enable);
|
||||
vim_free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
menu_nable_recurse(root_menu, menu_path, modes, enable);
|
||||
menu_nable_recurse(*root_menu_ptr, menu_path, modes, enable);
|
||||
}
|
||||
else if (unmenu)
|
||||
{
|
||||
@@ -324,14 +355,14 @@ ex_menu(
|
||||
p = popup_mode_name(menu_path, i);
|
||||
if (p != NULL)
|
||||
{
|
||||
remove_menu(&root_menu, p, MENU_ALL_MODES, TRUE);
|
||||
remove_menu(root_menu_ptr, p, MENU_ALL_MODES, TRUE);
|
||||
vim_free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Careful: remove_menu() changes menu_path */
|
||||
remove_menu(&root_menu, menu_path, modes, FALSE);
|
||||
remove_menu(root_menu_ptr, menu_path, modes, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -401,6 +432,19 @@ ex_menu(
|
||||
))
|
||||
gui_set_shellsize(FALSE, FALSE, RESIZE_VERT);
|
||||
#endif
|
||||
if (root_menu_ptr == &curwin->w_winbar)
|
||||
{
|
||||
int h = winbar_height(curwin);
|
||||
|
||||
if (h != curwin->w_winbar_height)
|
||||
{
|
||||
if (h == 0)
|
||||
++curwin->w_height;
|
||||
else if (curwin->w_height > 0)
|
||||
--curwin->w_height;
|
||||
curwin->w_winbar_height = h;
|
||||
}
|
||||
}
|
||||
|
||||
theend:
|
||||
;
|
||||
@@ -445,12 +489,14 @@ add_menu_path(
|
||||
char_u *en_name;
|
||||
char_u *map_to = NULL;
|
||||
#endif
|
||||
vimmenu_T **root_menu_ptr;
|
||||
|
||||
/* Make a copy so we can stuff around with it, since it could be const */
|
||||
path_name = vim_strsave(menu_path);
|
||||
if (path_name == NULL)
|
||||
return FAIL;
|
||||
menup = &root_menu;
|
||||
root_menu_ptr = get_root_menu(menu_path);
|
||||
menup = root_menu_ptr;
|
||||
parent = NULL;
|
||||
name = path_name;
|
||||
while (*name)
|
||||
@@ -786,7 +832,7 @@ erret:
|
||||
while (parent != NULL && parent->children == NULL)
|
||||
{
|
||||
if (parent->parent == NULL)
|
||||
menup = &root_menu;
|
||||
menup = root_menu_ptr;
|
||||
else
|
||||
menup = &parent->parent->children;
|
||||
for ( ; *menup != NULL && *menup != parent; menup = &((*menup)->next))
|
||||
@@ -985,6 +1031,16 @@ remove_menu(
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the WinBar menu from window "wp".
|
||||
*/
|
||||
void
|
||||
remove_winbar(win_T *wp)
|
||||
{
|
||||
remove_menu(&wp->w_winbar, (char_u *)"", MENU_ALL_MODES, TRUE);
|
||||
vim_free(wp->w_winbar_items);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the given menu structure and remove it from the linked list.
|
||||
*/
|
||||
@@ -1057,10 +1113,10 @@ show_menus(char_u *path_name, int modes)
|
||||
vimmenu_T *menu;
|
||||
vimmenu_T *parent = NULL;
|
||||
|
||||
menu = root_menu;
|
||||
name = path_name = vim_strsave(path_name);
|
||||
if (path_name == NULL)
|
||||
return FAIL;
|
||||
menu = *get_root_menu(path_name);
|
||||
|
||||
/* First, find the (sub)menu with the given name */
|
||||
while (*name)
|
||||
@@ -1190,6 +1246,7 @@ show_menus_recursive(vimmenu_T *menu, int modes, int depth)
|
||||
* Used when expanding menu names.
|
||||
*/
|
||||
static vimmenu_T *expand_menu = NULL;
|
||||
static vimmenu_T *expand_menu_alt = NULL;
|
||||
static int expand_modes = 0x0;
|
||||
static int expand_emenu; /* TRUE for ":emenu" command */
|
||||
|
||||
@@ -1251,6 +1308,8 @@ set_context_in_menu_cmd(
|
||||
return NULL; /* TODO: check for next command? */
|
||||
if (*p == NUL) /* Complete the menu name */
|
||||
{
|
||||
int try_alt_menu = TRUE;
|
||||
|
||||
/*
|
||||
* With :unmenu, you only want to match menus for the appropriate mode.
|
||||
* With :menu though you might want to add a menu with the same name as
|
||||
@@ -1290,6 +1349,11 @@ set_context_in_menu_cmd(
|
||||
break;
|
||||
}
|
||||
menu = menu->next;
|
||||
if (menu == NULL && try_alt_menu)
|
||||
{
|
||||
menu = curwin->w_winbar;
|
||||
try_alt_menu = FALSE;
|
||||
}
|
||||
}
|
||||
if (menu == NULL)
|
||||
{
|
||||
@@ -1299,12 +1363,17 @@ set_context_in_menu_cmd(
|
||||
}
|
||||
name = p;
|
||||
menu = menu->children;
|
||||
try_alt_menu = FALSE;
|
||||
}
|
||||
vim_free(path_name);
|
||||
|
||||
xp->xp_context = expand_menus ? EXPAND_MENUNAMES : EXPAND_MENUS;
|
||||
xp->xp_pattern = after_dot;
|
||||
expand_menu = menu;
|
||||
if (expand_menu == root_menu)
|
||||
expand_menu_alt = curwin->w_winbar;
|
||||
else
|
||||
expand_menu_alt = NULL;
|
||||
}
|
||||
else /* We're in the mapping part */
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
@@ -1319,6 +1388,7 @@ set_context_in_menu_cmd(
|
||||
get_menu_name(expand_T *xp UNUSED, int idx)
|
||||
{
|
||||
static vimmenu_T *menu = NULL;
|
||||
static int did_alt_menu = FALSE;
|
||||
char_u *str;
|
||||
#ifdef FEAT_MULTI_LANG
|
||||
static int should_advance = FALSE;
|
||||
@@ -1327,6 +1397,7 @@ get_menu_name(expand_T *xp UNUSED, int idx)
|
||||
if (idx == 0) /* first call: start at first item */
|
||||
{
|
||||
menu = expand_menu;
|
||||
did_alt_menu = FALSE;
|
||||
#ifdef FEAT_MULTI_LANG
|
||||
should_advance = FALSE;
|
||||
#endif
|
||||
@@ -1337,7 +1408,14 @@ get_menu_name(expand_T *xp UNUSED, int idx)
|
||||
|| menu_is_separator(menu->dname)
|
||||
|| menu_is_tearoff(menu->dname)
|
||||
|| menu->children == NULL))
|
||||
{
|
||||
menu = menu->next;
|
||||
if (menu == NULL && !did_alt_menu)
|
||||
{
|
||||
menu = expand_menu_alt;
|
||||
did_alt_menu = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (menu == NULL) /* at end of linked list */
|
||||
return NULL;
|
||||
@@ -1361,8 +1439,15 @@ get_menu_name(expand_T *xp UNUSED, int idx)
|
||||
#ifdef FEAT_MULTI_LANG
|
||||
if (should_advance)
|
||||
#endif
|
||||
{
|
||||
/* Advance to next menu entry. */
|
||||
menu = menu->next;
|
||||
if (menu == NULL && !did_alt_menu)
|
||||
{
|
||||
menu = expand_menu_alt;
|
||||
did_alt_menu = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FEAT_MULTI_LANG
|
||||
should_advance = !should_advance;
|
||||
@@ -1379,6 +1464,7 @@ get_menu_name(expand_T *xp UNUSED, int idx)
|
||||
get_menu_names(expand_T *xp UNUSED, int idx)
|
||||
{
|
||||
static vimmenu_T *menu = NULL;
|
||||
static int did_alt_menu = FALSE;
|
||||
#define TBUFFER_LEN 256
|
||||
static char_u tbuffer[TBUFFER_LEN]; /*hack*/
|
||||
char_u *str;
|
||||
@@ -1389,6 +1475,7 @@ get_menu_names(expand_T *xp UNUSED, int idx)
|
||||
if (idx == 0) /* first call: start at first item */
|
||||
{
|
||||
menu = expand_menu;
|
||||
did_alt_menu = FALSE;
|
||||
#ifdef FEAT_MULTI_LANG
|
||||
should_advance = FALSE;
|
||||
#endif
|
||||
@@ -1403,7 +1490,14 @@ get_menu_names(expand_T *xp UNUSED, int idx)
|
||||
|| menu->dname[STRLEN(menu->dname) - 1] == '.'
|
||||
#endif
|
||||
))
|
||||
{
|
||||
menu = menu->next;
|
||||
if (menu == NULL && !did_alt_menu)
|
||||
{
|
||||
menu = expand_menu_alt;
|
||||
did_alt_menu = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (menu == NULL) /* at end of linked list */
|
||||
return NULL;
|
||||
@@ -1451,8 +1545,15 @@ get_menu_names(expand_T *xp UNUSED, int idx)
|
||||
#ifdef FEAT_MULTI_LANG
|
||||
if (should_advance)
|
||||
#endif
|
||||
{
|
||||
/* Advance to next menu entry. */
|
||||
menu = menu->next;
|
||||
if (menu == NULL && !did_alt_menu)
|
||||
{
|
||||
menu = expand_menu_alt;
|
||||
did_alt_menu = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FEAT_MULTI_LANG
|
||||
should_advance = !should_advance;
|
||||
@@ -2134,62 +2235,16 @@ gui_destroy_tearoffs_recurse(vimmenu_T *menu)
|
||||
#endif /* FEAT_GUI_W32 && FEAT_TEAROFF */
|
||||
|
||||
/*
|
||||
* Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy and
|
||||
* execute it.
|
||||
* Execute "menu". Use by ":emenu" and the window toolbar.
|
||||
* "eap" is NULL for the window toolbar.
|
||||
*/
|
||||
void
|
||||
ex_emenu(exarg_T *eap)
|
||||
static void
|
||||
execute_menu(exarg_T *eap, vimmenu_T *menu)
|
||||
{
|
||||
vimmenu_T *menu;
|
||||
char_u *name;
|
||||
char_u *saved_name;
|
||||
char_u *p;
|
||||
int idx;
|
||||
char_u *mode;
|
||||
int idx;
|
||||
|
||||
saved_name = vim_strsave(eap->arg);
|
||||
if (saved_name == NULL)
|
||||
return;
|
||||
|
||||
menu = root_menu;
|
||||
name = saved_name;
|
||||
while (*name)
|
||||
{
|
||||
/* Find in the menu hierarchy */
|
||||
p = menu_name_skip(name);
|
||||
|
||||
while (menu != NULL)
|
||||
{
|
||||
if (menu_name_equal(name, menu))
|
||||
{
|
||||
if (*p == NUL && menu->children != NULL)
|
||||
{
|
||||
EMSG(_("E333: Menu path must lead to a menu item"));
|
||||
menu = NULL;
|
||||
}
|
||||
else if (*p != NUL && menu->children == NULL)
|
||||
{
|
||||
EMSG(_(e_notsubmenu));
|
||||
menu = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
menu = menu->next;
|
||||
}
|
||||
if (menu == NULL || *p == NUL)
|
||||
break;
|
||||
menu = menu->children;
|
||||
name = p;
|
||||
}
|
||||
vim_free(saved_name);
|
||||
if (menu == NULL)
|
||||
{
|
||||
EMSG2(_("E334: Menu not found: %s"), eap->arg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Found the menu, so execute.
|
||||
* Use the Insert mode entry when returning to Insert mode. */
|
||||
/* Use the Insert mode entry when returning to Insert mode. */
|
||||
if (restart_edit
|
||||
#ifdef FEAT_EVAL
|
||||
&& !current_SID
|
||||
@@ -2199,7 +2254,12 @@ ex_emenu(exarg_T *eap)
|
||||
mode = (char_u *)"Insert";
|
||||
idx = MENU_INDEX_INSERT;
|
||||
}
|
||||
else if (eap->addr_count)
|
||||
else if (VIsual_active)
|
||||
{
|
||||
mode = (char_u *)"Visual";
|
||||
idx = MENU_INDEX_VISUAL;
|
||||
}
|
||||
else if (eap != NULL && eap->addr_count)
|
||||
{
|
||||
pos_T tpos;
|
||||
|
||||
@@ -2255,22 +2315,120 @@ ex_emenu(exarg_T *eap)
|
||||
if (idx != MENU_INDEX_INVALID && menu->strings[idx] != NULL)
|
||||
{
|
||||
/* When executing a script or function execute the commands right now.
|
||||
* Also for the window toolbar.
|
||||
* Otherwise put them in the typeahead buffer. */
|
||||
if (eap == NULL
|
||||
#ifdef FEAT_EVAL
|
||||
if (current_SID != 0)
|
||||
|| current_SID != 0
|
||||
#endif
|
||||
)
|
||||
exec_normal_cmd(menu->strings[idx], menu->noremap[idx],
|
||||
menu->silent[idx]);
|
||||
else
|
||||
#endif
|
||||
ins_typebuf(menu->strings[idx], menu->noremap[idx], 0,
|
||||
TRUE, menu->silent[idx]);
|
||||
}
|
||||
else
|
||||
else if (eap != NULL)
|
||||
EMSG2(_("E335: Menu not defined for %s mode"), mode);
|
||||
}
|
||||
|
||||
#if defined(FEAT_GUI_MSWIN) \
|
||||
|| (defined(FEAT_GUI_GTK) && defined(FEAT_MENU)) \
|
||||
/*
|
||||
* Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy and
|
||||
* execute it.
|
||||
*/
|
||||
void
|
||||
ex_emenu(exarg_T *eap)
|
||||
{
|
||||
vimmenu_T *menu;
|
||||
char_u *name;
|
||||
char_u *saved_name;
|
||||
char_u *p;
|
||||
|
||||
saved_name = vim_strsave(eap->arg);
|
||||
if (saved_name == NULL)
|
||||
return;
|
||||
|
||||
menu = *get_root_menu(saved_name);
|
||||
name = saved_name;
|
||||
while (*name)
|
||||
{
|
||||
/* Find in the menu hierarchy */
|
||||
p = menu_name_skip(name);
|
||||
|
||||
while (menu != NULL)
|
||||
{
|
||||
if (menu_name_equal(name, menu))
|
||||
{
|
||||
if (*p == NUL && menu->children != NULL)
|
||||
{
|
||||
EMSG(_("E333: Menu path must lead to a menu item"));
|
||||
menu = NULL;
|
||||
}
|
||||
else if (*p != NUL && menu->children == NULL)
|
||||
{
|
||||
EMSG(_(e_notsubmenu));
|
||||
menu = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
menu = menu->next;
|
||||
}
|
||||
if (menu == NULL || *p == NUL)
|
||||
break;
|
||||
menu = menu->children;
|
||||
name = p;
|
||||
}
|
||||
vim_free(saved_name);
|
||||
if (menu == NULL)
|
||||
{
|
||||
EMSG2(_("E334: Menu not found: %s"), eap->arg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Found the menu, so execute. */
|
||||
execute_menu(eap, menu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a click in the window toolbar of "wp" at column "col".
|
||||
*/
|
||||
void
|
||||
winbar_click(win_T *wp, int col)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (wp->w_winbar_items == NULL)
|
||||
return;
|
||||
for (idx = 0; wp->w_winbar_items[idx].wb_menu != NULL; ++idx)
|
||||
{
|
||||
winbar_item_T *item = &wp->w_winbar_items[idx];
|
||||
|
||||
if (col >= item->wb_startcol && col <= item->wb_endcol)
|
||||
{
|
||||
win_T *save_curwin = NULL;
|
||||
|
||||
if (wp != curwin)
|
||||
{
|
||||
/* Clicking in the window toolbar of a not-current window.
|
||||
* Make that window the current one and go to Normal mode. */
|
||||
save_curwin = curwin;
|
||||
curwin = wp;
|
||||
curbuf = curwin->w_buffer;
|
||||
check_cursor();
|
||||
}
|
||||
|
||||
execute_menu(NULL, item->wb_menu);
|
||||
|
||||
if (save_curwin != NULL)
|
||||
{
|
||||
curwin = save_curwin;
|
||||
curbuf = curwin->w_buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) \
|
||||
|| defined(FEAT_BEVAL_TIP) || defined(PROTO)
|
||||
/*
|
||||
* Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy.
|
||||
@@ -2283,7 +2441,7 @@ gui_find_menu(char_u *path_name)
|
||||
char_u *saved_name;
|
||||
char_u *p;
|
||||
|
||||
menu = root_menu;
|
||||
menu = *get_root_menu(path_name);
|
||||
|
||||
saved_name = vim_strsave(path_name);
|
||||
if (saved_name == NULL)
|
||||
|
||||
@@ -2679,9 +2679,9 @@ do_mouse(
|
||||
* selection or the current window (might have false
|
||||
* negative here)
|
||||
*/
|
||||
if (mouse_row < W_WINROW(curwin)
|
||||
if (mouse_row < curwin->w_winrow
|
||||
|| mouse_row
|
||||
> (W_WINROW(curwin) + curwin->w_height))
|
||||
> (curwin->w_winrow + curwin->w_height))
|
||||
jump_flags = MOUSE_MAY_STOP_VIS;
|
||||
else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER)
|
||||
jump_flags = MOUSE_MAY_STOP_VIS;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/* menu.c */
|
||||
int winbar_height(win_T *wp);
|
||||
void ex_menu(exarg_T *eap);
|
||||
void remove_winbar(win_T *wp);
|
||||
char_u *set_context_in_menu_cmd(expand_T *xp, char_u *cmd, char_u *arg, int forceit);
|
||||
char_u *get_menu_name(expand_T *xp, int idx);
|
||||
char_u *get_menu_names(expand_T *xp, int idx);
|
||||
@@ -17,6 +19,7 @@ int gui_is_menu_shortcut(int key);
|
||||
void gui_show_popupmenu(void);
|
||||
void gui_mch_toggle_tearoffs(int enable);
|
||||
void ex_emenu(exarg_T *eap);
|
||||
void winbar_click(win_T *wp, int col);
|
||||
vimmenu_T *gui_find_menu(char_u *path_name);
|
||||
void ex_menutranslate(exarg_T *eap);
|
||||
/* vim: set ft=c : */
|
||||
|
||||
@@ -46,6 +46,7 @@ char_u *highlight_has_attr(int id, int flag, int modec);
|
||||
char_u *highlight_color(int id, char_u *what, int modec);
|
||||
long_u highlight_gui_color_rgb(int id, int fg);
|
||||
int syn_name2id(char_u *name);
|
||||
int syn_name2attr(char_u *name);
|
||||
int highlight_exists(char_u *name);
|
||||
char_u *syn_id2name(int id);
|
||||
int syn_namen2id(char_u *linep, int len);
|
||||
|
||||
362
src/screen.c
362
src/screen.c
@@ -107,6 +107,9 @@ static int screen_cur_row, screen_cur_col; /* last known cursor position */
|
||||
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_screen)
|
||||
* 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_cols)
|
||||
}
|
||||
#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.
|
||||
|
||||
@@ -70,6 +70,10 @@ typedef int scid_T; /* script ID */
|
||||
typedef struct file_buffer buf_T; /* forward declaration */
|
||||
typedef struct terminal_S term_T;
|
||||
|
||||
#ifdef FEAT_MENU
|
||||
typedef struct VimMenu vimmenu_T;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reference to a buffer that stores the value of buf_free_count.
|
||||
* bufref_valid() only needs to check "buf" when the count differs.
|
||||
@@ -2611,6 +2615,14 @@ struct matchitem
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef FEAT_MENU
|
||||
typedef struct {
|
||||
int wb_startcol;
|
||||
int wb_endcol;
|
||||
vimmenu_T *wb_menu;
|
||||
} winbar_item_T;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Structure which contains all information that belongs to a window
|
||||
*
|
||||
@@ -2686,7 +2698,7 @@ struct window_S
|
||||
*/
|
||||
int w_winrow; /* first row of window in screen */
|
||||
int w_height; /* number of rows in window, excluding
|
||||
status/command line(s) */
|
||||
status/command/winbar line(s) */
|
||||
int w_status_height; /* number of status lines (0 or 1) */
|
||||
int w_wincol; /* Leftmost column of window in screen.
|
||||
use W_WINCOL() */
|
||||
@@ -2798,6 +2810,12 @@ struct window_S
|
||||
|
||||
char_u *w_localdir; /* absolute path of local directory or
|
||||
NULL */
|
||||
#ifdef FEAT_MENU
|
||||
vimmenu_T *w_winbar; /* The root of the WinBar menu hierarchy. */
|
||||
winbar_item_T *w_winbar_items; /* list of items in the WinBar */
|
||||
int w_winbar_height; /* 1 if there is a window toolbar */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Options local to a window.
|
||||
* They are local because they influence the layout of the window or
|
||||
@@ -3064,8 +3082,6 @@ typedef struct cursor_entry
|
||||
/* Start a menu name with this to not include it on the main menu bar */
|
||||
#define MNU_HIDDEN_CHAR ']'
|
||||
|
||||
typedef struct VimMenu vimmenu_T;
|
||||
|
||||
struct VimMenu
|
||||
{
|
||||
int modes; /* Which modes is this menu visible for? */
|
||||
|
||||
26
src/syntax.c
26
src/syntax.c
@@ -7001,6 +7001,12 @@ static char *(highlight_init_light[]) = {
|
||||
"StatusLineTerm term=reverse,bold cterm=bold ctermfg=White ctermbg=DarkGreen gui=bold guifg=bg guibg=DarkGreen"),
|
||||
CENT("StatusLineTermNC term=reverse ctermfg=White ctermbg=DarkGreen",
|
||||
"StatusLineTermNC term=reverse ctermfg=White ctermbg=DarkGreen guifg=bg guibg=DarkGreen"),
|
||||
#endif
|
||||
#ifdef FEAT_MENU
|
||||
CENT("ToolbarLine term=underline ctermbg=LightGrey",
|
||||
"ToolbarLine term=underline ctermbg=LightGrey guibg=LightGrey"),
|
||||
CENT("ToolbarButton cterm=bold ctermfg=White ctermbg=DarkGrey",
|
||||
"ToolbarButton cterm=bold ctermfg=White ctermbg=DarkGrey gui=bold guifg=White guibg=DarkGrey"),
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@@ -7093,6 +7099,12 @@ static char *(highlight_init_dark[]) = {
|
||||
"StatusLineTerm term=reverse,bold cterm=bold ctermfg=Black ctermbg=LightGreen gui=bold guifg=bg guibg=LightGreen"),
|
||||
CENT("StatusLineTermNC term=reverse ctermfg=Black ctermbg=LightGreen",
|
||||
"StatusLineTermNC term=reverse ctermfg=Black ctermbg=LightGreen guifg=bg guibg=LightGreen"),
|
||||
#endif
|
||||
#ifdef FEAT_MENU
|
||||
CENT("ToolbarLine term=underline ctermbg=DarkGrey",
|
||||
"ToolbarLine term=underline ctermbg=DarkGrey guibg=DarkGrey"),
|
||||
CENT("ToolbarButton cterm=bold ctermfg=Black ctermbg=LightGrey",
|
||||
"ToolbarButton cterm=bold ctermfg=Black ctermbg=LightGrey gui=bold guifg=Black guibg=LightGrey"),
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@@ -9525,6 +9537,20 @@ syn_name2id(char_u *name)
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a highlight group name and return its attributes.
|
||||
* Return zero if not found.
|
||||
*/
|
||||
int
|
||||
syn_name2attr(char_u *name)
|
||||
{
|
||||
int id = syn_name2id(name);
|
||||
|
||||
if (id != 0)
|
||||
return syn_id2attr(syn_get_final_id(id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||
/*
|
||||
* Return TRUE if highlight group "name" exists.
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
* in tl_scrollback are no longer used.
|
||||
*
|
||||
* TODO:
|
||||
* - test_terminal_no_cmd hangs (Christian)
|
||||
* - Shift-Tab does not work.
|
||||
* - click in Window toolbar of other window: save/restore Insert and Visual
|
||||
* - Redirecting output does not work on MS-Windows, Test_terminal_redir_file()
|
||||
* is disabled.
|
||||
* - implement term_setsize()
|
||||
@@ -703,7 +704,7 @@ write_to_term(buf_T *buffer, char_u *msg, channel_T *channel)
|
||||
update_screen(0);
|
||||
update_cursor(term, TRUE);
|
||||
}
|
||||
else if (buffer->b_nwindows > 0)
|
||||
else
|
||||
redraw_after_callback(TRUE);
|
||||
}
|
||||
}
|
||||
@@ -1545,7 +1546,7 @@ terminal_loop(int blocking)
|
||||
{
|
||||
/* TODO: skip screen update when handling a sequence of keys. */
|
||||
/* Repeat redrawing in case a message is received while redrawing. */
|
||||
while (curwin->w_redr_type != 0)
|
||||
while (must_redraw != 0)
|
||||
if (update_screen(0) == FAIL)
|
||||
break;
|
||||
update_cursor(curbuf->b_term, FALSE);
|
||||
|
||||
@@ -201,12 +201,13 @@ NEW_TESTS = test_arabic.res \
|
||||
test_viminfo.res \
|
||||
test_vimscript.res \
|
||||
test_visual.res \
|
||||
test_winbar.res \
|
||||
test_window_id.res \
|
||||
test_windows_home.res \
|
||||
test_writefile.res \
|
||||
test_alot_latin.res \
|
||||
test_alot_utf8.res \
|
||||
test_alot.res \
|
||||
test_windows_home.res
|
||||
test_alot.res
|
||||
|
||||
|
||||
# Explicit dependencies.
|
||||
|
||||
23
src/testdir/test_winbar.vim
Normal file
23
src/testdir/test_winbar.vim
Normal file
@@ -0,0 +1,23 @@
|
||||
" Test WinBar
|
||||
|
||||
if !has('menu')
|
||||
finish
|
||||
endif
|
||||
|
||||
func Test_add_remove_menu()
|
||||
new
|
||||
amenu 1.10 WinBar.Next :let g:did_next = 11<CR>
|
||||
amenu 1.20 WinBar.Cont :let g:did_cont = 12<CR>
|
||||
emenu WinBar.Next
|
||||
call assert_equal(11, g:did_next)
|
||||
emenu WinBar.Cont
|
||||
call assert_equal(12, g:did_cont)
|
||||
|
||||
wincmd w
|
||||
call assert_fails('emenu WinBar.Next', 'E334')
|
||||
wincmd p
|
||||
|
||||
aunmenu WinBar.Next
|
||||
aunmenu WinBar.Cont
|
||||
close
|
||||
endfunc
|
||||
20
src/ui.c
20
src/ui.c
@@ -2657,7 +2657,7 @@ retnomove:
|
||||
}
|
||||
#if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
|
||||
/* Continue a modeless selection in another window. */
|
||||
if (cmdwin_type != 0 && row < W_WINROW(curwin))
|
||||
if (cmdwin_type != 0 && row < curwin->w_winrow)
|
||||
return IN_OTHER_WIN;
|
||||
#endif
|
||||
return IN_BUFFER;
|
||||
@@ -2692,6 +2692,17 @@ retnomove:
|
||||
if (wp == NULL)
|
||||
return IN_UNKNOWN;
|
||||
dragwin = NULL;
|
||||
|
||||
#ifdef FEAT_MENU
|
||||
if (row == -1)
|
||||
{
|
||||
/* A click in the window toolbar does not enter another window or
|
||||
* change Visual highlighting. */
|
||||
winbar_click(wp, col);
|
||||
return IN_OTHER_WIN;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* winpos and height may change in win_enter()!
|
||||
*/
|
||||
@@ -2829,7 +2840,7 @@ retnomove:
|
||||
|
||||
#if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
|
||||
/* Continue a modeless selection in another window. */
|
||||
if (cmdwin_type != 0 && row < W_WINROW(curwin))
|
||||
if (cmdwin_type != 0 && row < curwin->w_winrow)
|
||||
return IN_OTHER_WIN;
|
||||
#endif
|
||||
|
||||
@@ -3117,7 +3128,12 @@ mouse_find_win(int *rowp, int *colp UNUSED)
|
||||
* exist. */
|
||||
FOR_ALL_WINDOWS(wp)
|
||||
if (wp == fp->fr_win)
|
||||
{
|
||||
#ifdef FEAT_MENU
|
||||
*rowp -= wp->w_winbar_height;
|
||||
#endif
|
||||
return wp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -761,6 +761,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1123,
|
||||
/**/
|
||||
1122,
|
||||
/**/
|
||||
|
||||
@@ -4692,6 +4692,10 @@ win_free(
|
||||
}
|
||||
#endif /* FEAT_GUI */
|
||||
|
||||
#ifdef FEAT_MENU
|
||||
remove_winbar(wp);
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_SYN_HL
|
||||
vim_free(wp->w_p_cc_cols);
|
||||
#endif
|
||||
@@ -5667,6 +5671,7 @@ set_fraction(win_T *wp)
|
||||
|
||||
/*
|
||||
* Set the height of a window.
|
||||
* "height" excludes any window toolbar.
|
||||
* This takes care of the things inside the window, not what happens to the
|
||||
* window position, the frame or to other windows.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user