Compare commits

...

3 Commits

Author SHA1 Message Date
f16c71b669 patch 8.0.1124: use of MZSCHEME_VER is unclear
Problem:    Use of MZSCHEME_VER is unclear.
Solution:   Add a comment. (Ken Takata)
2017-09-18 20:01:02 +02:00
1b9645de3c 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.
2017-09-17 23:03:31 +02:00
dde403c2d8 patch 8.0.1122: vimtutor.bat doesn't work well with vim.bat
Problem:    vimtutor.bat doesn't work well with vim.bat.
Solution:   Use "call vim". (Ken Takata, closes #2105)
2017-09-17 21:43:00 +02:00
23 changed files with 690 additions and 241 deletions

View File

@ -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 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 from the main menu bar. You must then use the |:popup| or |:tearoff| command
to display it. 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* *popup-menu*
In the Win32, GTK+, Motif, Athena and Photon GUI, you can define the 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 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. 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* 5.3 Showing What Menus Are Mapped To *showing-menus*

View File

@ -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 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 contents of the terminal window is under control of Vim, the job output is
suspended. CTRL-\ CTRL-N does the same. 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. |term_sendkeys()| are not subject to tmap, but keys from |feedkeys()| are.
*E946* *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 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 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 '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 In Terminal-Normal mode the statusline and window title show "(Terminal)". If
the job ends while in Terminal-Normal mode this changes to 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 :Finish execute the gdb "finish" command
:Continue execute the gdb "continue" 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 ~ Inspecting variables ~

View File

@ -104,6 +104,11 @@ func s:StartDebug(cmd)
call win_gotoid(s:gdbwin) call win_gotoid(s:gdbwin)
let s:breakpoints = {} let s:breakpoints = {}
augroup TermDebug
au BufRead * call s:BufRead()
au BufUnload * call s:BufUnloaded()
augroup END
endfunc endfunc
func s:EndDebug(job, status) func s:EndDebug(job, status)
@ -120,6 +125,8 @@ func s:EndDebug(job, status)
if s:save_columns > 0 if s:save_columns > 0
let &columns = s:save_columns let &columns = s:save_columns
endif endif
au! TermDebug
endfunc endfunc
" Handle a message received from gdb on the GDB/MI interface. " Handle a message received from gdb on the GDB/MI interface.
@ -132,7 +139,7 @@ func s:CommOutput(chan, msg)
let msg = msg[1:] let msg = msg[1:]
endif endif
if msg != '' if msg != ''
if msg =~ '^\*\(stopped\|running\)' if msg =~ '^\(\*stopped\|\*running\|=thread-selected\)'
call s:HandleCursor(msg) call s:HandleCursor(msg)
elseif msg =~ '^\^done,bkpt=' || msg =~ '^=breakpoint-created,' elseif msg =~ '^\^done,bkpt=' || msg =~ '^=breakpoint-created,'
call s:HandleNewBreakpoint(msg) call s:HandleNewBreakpoint(msg)
@ -161,6 +168,14 @@ func s:InstallCommands()
" TODO: can the K mapping be restored? " TODO: can the K mapping be restored?
nnoremap K :Evaluate<CR> 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 endfunc
" Delete installed debugger commands in the current window. " Delete installed debugger commands in the current window.
@ -176,6 +191,15 @@ func s:DeleteCommands()
delcommand Program delcommand Program
nunmap K 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 exe 'sign unplace ' . s:pc_id
for key in keys(s:breakpoints) for key in keys(s:breakpoints)
exe 'sign unplace ' . (s:break_id + key) exe 'sign unplace ' . (s:break_id + key)
@ -232,7 +256,15 @@ endfunc
" Handle the result of data-evaluate-expression " Handle the result of data-evaluate-expression
func s:HandleEvaluate(msg) 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 endfunc
" Handle an error. " Handle an error.
@ -247,10 +279,10 @@ func s:HandleCursor(msg)
if win_gotoid(s:startwin) if win_gotoid(s:startwin)
let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '') 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', '') let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
if lnum =~ '^[0-9]*$' if lnum =~ '^[0-9]*$'
if expand('%:h') != fname if expand('%:p') != fnamemodify(fname, ':p')
if &modified if &modified
" TODO: find existing window " TODO: find existing window
exe 'split ' . fnameescape(fname) exe 'split ' . fnameescape(fname)
@ -260,7 +292,7 @@ func s:HandleCursor(msg)
endif endif
endif endif
exe lnum 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 setlocal signcolumn=yes
endif endif
else else
@ -288,11 +320,17 @@ func s:HandleNewBreakpoint(msg)
let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '') let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '')
let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\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['fname'] = fname
let entry['lnum'] = lnum 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 endfunc
" Handle deleting a breakpoint " Handle deleting a breakpoint
@ -302,6 +340,33 @@ func s:HandleBreakpointDelete(msg)
if nr == 0 if nr == 0
return return
endif endif
exe 'sign unplace ' . (s:break_id + nr) if has_key(s:breakpoints, nr)
unlet 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 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

View File

@ -221,6 +221,8 @@ endif
# MZSCHEME=[Path to MzScheme directory] (Set inside Make_cyg.mak or Make_ming.mak) # MZSCHEME=[Path to MzScheme directory] (Set inside Make_cyg.mak or Make_ming.mak)
# DYNAMIC_MZSCHEME=yes (to load the MzScheme DLL dynamically) # DYNAMIC_MZSCHEME=yes (to load the MzScheme DLL dynamically)
# MZSCHEME_VER=[MzScheme version] (default is 3m_a0solc (6.6)) # MZSCHEME_VER=[MzScheme version] (default is 3m_a0solc (6.6))
# Used for the DLL file name. E.g.:
# C:\Program Files (x86)\Racket\lib\libracket3m_XXXXXX.dll
# MZSCHEME_DEBUG=no # MZSCHEME_DEBUG=no
ifdef MZSCHEME ifdef MZSCHEME
ifndef DYNAMIC_MZSCHEME ifndef DYNAMIC_MZSCHEME

View File

@ -47,7 +47,9 @@
# MzScheme interface: # MzScheme interface:
# MZSCHEME=[Path to MzScheme directory] # MZSCHEME=[Path to MzScheme directory]
# DYNAMIC_MZSCHEME=yes (to load the MzScheme DLLs dynamically) # DYNAMIC_MZSCHEME=yes (to load the MzScheme DLLs dynamically)
# MZSCHEME_VER=[version, 205_000, ...] (default is 3m_a0solc (6.6)) # MZSCHEME_VER=[MzScheme version] (default is 3m_a0solc (6.6))
# Used for the DLL file name. E.g.:
# C:\Program Files (x86)\Racket\lib\libracket3m_XXXXXX.dll
# MZSCHEME_DEBUG=no # MZSCHEME_DEBUG=no
# #
# Perl interface: # Perl interface:

View File

@ -2278,6 +2278,7 @@ test_arglist \
test_vimscript \ test_vimscript \
test_virtualedit \ test_virtualedit \
test_visual \ test_visual \
test_winbar \
test_window_cmd \ test_window_cmd \
test_window_id \ test_window_id \
test_windows_home \ test_windows_home \

View File

@ -8252,13 +8252,7 @@ ex_echo(exarg_T *eap)
void void
ex_echohl(exarg_T *eap) ex_echohl(exarg_T *eap)
{ {
int id; echo_attr = syn_name2attr(eap->arg);
id = syn_name2id(eap->arg);
if (id == 0)
echo_attr = 0;
else
echo_attr = syn_id2attr(id);
} }
/* /*

View File

@ -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, "winnr", winnr, NULL);
dict_add_nr_str(dict, "winid", wp->w_id, NULL); dict_add_nr_str(dict, "winid", wp->w_id, NULL);
dict_add_nr_str(dict, "height", wp->w_height, 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, "width", wp->w_width, NULL);
dict_add_nr_str(dict, "bufnr", wp->w_buffer->b_fnum, NULL); dict_add_nr_str(dict, "bufnr", wp->w_buffer->b_fnum, NULL);

View File

@ -1387,11 +1387,8 @@ PerlIOVim_pushed(pTHX_ PerlIO *f, const char *mode,
{ {
PerlIOVim *s = PerlIOSelf(f, PerlIOVim); PerlIOVim *s = PerlIOSelf(f, PerlIOVim);
s->attr = 0; s->attr = 0;
if (arg && SvPOK(arg)) { if (arg && SvPOK(arg))
int id = syn_name2id((char_u *)SvPV_nolen(arg)); s->attr = syn_name2attr((char_u *)SvPV_nolen(arg));
if (id != 0)
s->attr = syn_id2attr(id);
}
return PerlIOBase_pushed(aTHX_ f, mode, (SV *)NULL, tab); return PerlIOBase_pushed(aTHX_ f, mode, (SV *)NULL, tab);
} }
@ -1482,11 +1479,7 @@ Msg(text, hl=NULL)
{ {
attr = 0; attr = 0;
if (hl != NULL) if (hl != NULL)
{ attr = syn_name2attr((char_u *)hl);
id = syn_name2id((char_u *)hl);
if (id != 0)
attr = syn_id2attr(id);
}
msg_split((char_u *)text, attr); msg_split((char_u *)text, attr);
} }

View File

@ -82,6 +82,31 @@ static const char *toolbar_names[] =
# define TOOLBAR_NAME_COUNT (sizeof(toolbar_names) / sizeof(char *)) # define TOOLBAR_NAME_COUNT (sizeof(toolbar_names) / sizeof(char *))
#endif #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. * Do the :menu command and relatives.
*/ */
@ -113,6 +138,7 @@ ex_menu(
char_u *icon = NULL; char_u *icon = NULL;
#endif #endif
vimmenu_T menuarg; vimmenu_T menuarg;
vimmenu_T **root_menu_ptr;
modes = get_menu_cmd_modes(eap->cmd, eap->forceit, &noremap, &unmenu); modes = get_menu_cmd_modes(eap->cmd, eap->forceit, &noremap, &unmenu);
arg = eap->arg; arg = eap->arg;
@ -279,6 +305,11 @@ ex_menu(
# endif # endif
#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) if (enable != MAYBE)
{ {
/* /*
@ -297,13 +328,13 @@ ex_menu(
p = popup_mode_name(menu_path, i); p = popup_mode_name(menu_path, i);
if (p != NULL) if (p != NULL)
{ {
menu_nable_recurse(root_menu, p, MENU_ALL_MODES, menu_nable_recurse(*root_menu_ptr, p, MENU_ALL_MODES,
enable); enable);
vim_free(p); 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) else if (unmenu)
{ {
@ -324,14 +355,14 @@ ex_menu(
p = popup_mode_name(menu_path, i); p = popup_mode_name(menu_path, i);
if (p != NULL) 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); vim_free(p);
} }
} }
} }
/* Careful: remove_menu() changes menu_path */ /* Careful: remove_menu() changes menu_path */
remove_menu(&root_menu, menu_path, modes, FALSE); remove_menu(root_menu_ptr, menu_path, modes, FALSE);
} }
else else
{ {
@ -401,6 +432,19 @@ ex_menu(
)) ))
gui_set_shellsize(FALSE, FALSE, RESIZE_VERT); gui_set_shellsize(FALSE, FALSE, RESIZE_VERT);
#endif #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: theend:
; ;
@ -445,12 +489,14 @@ add_menu_path(
char_u *en_name; char_u *en_name;
char_u *map_to = NULL; char_u *map_to = NULL;
#endif #endif
vimmenu_T **root_menu_ptr;
/* Make a copy so we can stuff around with it, since it could be const */ /* Make a copy so we can stuff around with it, since it could be const */
path_name = vim_strsave(menu_path); path_name = vim_strsave(menu_path);
if (path_name == NULL) if (path_name == NULL)
return FAIL; return FAIL;
menup = &root_menu; root_menu_ptr = get_root_menu(menu_path);
menup = root_menu_ptr;
parent = NULL; parent = NULL;
name = path_name; name = path_name;
while (*name) while (*name)
@ -786,7 +832,7 @@ erret:
while (parent != NULL && parent->children == NULL) while (parent != NULL && parent->children == NULL)
{ {
if (parent->parent == NULL) if (parent->parent == NULL)
menup = &root_menu; menup = root_menu_ptr;
else else
menup = &parent->parent->children; menup = &parent->parent->children;
for ( ; *menup != NULL && *menup != parent; menup = &((*menup)->next)) for ( ; *menup != NULL && *menup != parent; menup = &((*menup)->next))
@ -985,6 +1031,16 @@ remove_menu(
return OK; 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. * 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 *menu;
vimmenu_T *parent = NULL; vimmenu_T *parent = NULL;
menu = root_menu;
name = path_name = vim_strsave(path_name); name = path_name = vim_strsave(path_name);
if (path_name == NULL) if (path_name == NULL)
return FAIL; return FAIL;
menu = *get_root_menu(path_name);
/* First, find the (sub)menu with the given name */ /* First, find the (sub)menu with the given name */
while (*name) while (*name)
@ -1190,6 +1246,7 @@ show_menus_recursive(vimmenu_T *menu, int modes, int depth)
* Used when expanding menu names. * Used when expanding menu names.
*/ */
static vimmenu_T *expand_menu = NULL; static vimmenu_T *expand_menu = NULL;
static vimmenu_T *expand_menu_alt = NULL;
static int expand_modes = 0x0; static int expand_modes = 0x0;
static int expand_emenu; /* TRUE for ":emenu" command */ static int expand_emenu; /* TRUE for ":emenu" command */
@ -1251,6 +1308,8 @@ set_context_in_menu_cmd(
return NULL; /* TODO: check for next command? */ return NULL; /* TODO: check for next command? */
if (*p == NUL) /* Complete the menu name */ 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 :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 * 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; break;
} }
menu = menu->next; menu = menu->next;
if (menu == NULL && try_alt_menu)
{
menu = curwin->w_winbar;
try_alt_menu = FALSE;
}
} }
if (menu == NULL) if (menu == NULL)
{ {
@ -1299,12 +1363,17 @@ set_context_in_menu_cmd(
} }
name = p; name = p;
menu = menu->children; menu = menu->children;
try_alt_menu = FALSE;
} }
vim_free(path_name); vim_free(path_name);
xp->xp_context = expand_menus ? EXPAND_MENUNAMES : EXPAND_MENUS; xp->xp_context = expand_menus ? EXPAND_MENUNAMES : EXPAND_MENUS;
xp->xp_pattern = after_dot; xp->xp_pattern = after_dot;
expand_menu = menu; 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 */ else /* We're in the mapping part */
xp->xp_context = EXPAND_NOTHING; xp->xp_context = EXPAND_NOTHING;
@ -1319,6 +1388,7 @@ set_context_in_menu_cmd(
get_menu_name(expand_T *xp UNUSED, int idx) get_menu_name(expand_T *xp UNUSED, int idx)
{ {
static vimmenu_T *menu = NULL; static vimmenu_T *menu = NULL;
static int did_alt_menu = FALSE;
char_u *str; char_u *str;
#ifdef FEAT_MULTI_LANG #ifdef FEAT_MULTI_LANG
static int should_advance = FALSE; 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 */ if (idx == 0) /* first call: start at first item */
{ {
menu = expand_menu; menu = expand_menu;
did_alt_menu = FALSE;
#ifdef FEAT_MULTI_LANG #ifdef FEAT_MULTI_LANG
should_advance = FALSE; should_advance = FALSE;
#endif #endif
@ -1337,7 +1408,14 @@ get_menu_name(expand_T *xp UNUSED, int idx)
|| menu_is_separator(menu->dname) || menu_is_separator(menu->dname)
|| menu_is_tearoff(menu->dname) || menu_is_tearoff(menu->dname)
|| menu->children == NULL)) || menu->children == NULL))
{
menu = menu->next; 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 */ if (menu == NULL) /* at end of linked list */
return NULL; return NULL;
@ -1361,8 +1439,15 @@ get_menu_name(expand_T *xp UNUSED, int idx)
#ifdef FEAT_MULTI_LANG #ifdef FEAT_MULTI_LANG
if (should_advance) if (should_advance)
#endif #endif
{
/* Advance to next menu entry. */ /* Advance to next menu entry. */
menu = menu->next; menu = menu->next;
if (menu == NULL && !did_alt_menu)
{
menu = expand_menu_alt;
did_alt_menu = TRUE;
}
}
#ifdef FEAT_MULTI_LANG #ifdef FEAT_MULTI_LANG
should_advance = !should_advance; 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) get_menu_names(expand_T *xp UNUSED, int idx)
{ {
static vimmenu_T *menu = NULL; static vimmenu_T *menu = NULL;
static int did_alt_menu = FALSE;
#define TBUFFER_LEN 256 #define TBUFFER_LEN 256
static char_u tbuffer[TBUFFER_LEN]; /*hack*/ static char_u tbuffer[TBUFFER_LEN]; /*hack*/
char_u *str; 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 */ if (idx == 0) /* first call: start at first item */
{ {
menu = expand_menu; menu = expand_menu;
did_alt_menu = FALSE;
#ifdef FEAT_MULTI_LANG #ifdef FEAT_MULTI_LANG
should_advance = FALSE; should_advance = FALSE;
#endif #endif
@ -1403,7 +1490,14 @@ get_menu_names(expand_T *xp UNUSED, int idx)
|| menu->dname[STRLEN(menu->dname) - 1] == '.' || menu->dname[STRLEN(menu->dname) - 1] == '.'
#endif #endif
)) ))
{
menu = menu->next; 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 */ if (menu == NULL) /* at end of linked list */
return NULL; return NULL;
@ -1451,8 +1545,15 @@ get_menu_names(expand_T *xp UNUSED, int idx)
#ifdef FEAT_MULTI_LANG #ifdef FEAT_MULTI_LANG
if (should_advance) if (should_advance)
#endif #endif
{
/* Advance to next menu entry. */ /* Advance to next menu entry. */
menu = menu->next; menu = menu->next;
if (menu == NULL && !did_alt_menu)
{
menu = expand_menu_alt;
did_alt_menu = TRUE;
}
}
#ifdef FEAT_MULTI_LANG #ifdef FEAT_MULTI_LANG
should_advance = !should_advance; should_advance = !should_advance;
@ -2134,62 +2235,16 @@ gui_destroy_tearoffs_recurse(vimmenu_T *menu)
#endif /* FEAT_GUI_W32 && FEAT_TEAROFF */ #endif /* FEAT_GUI_W32 && FEAT_TEAROFF */
/* /*
* Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy and * Execute "menu". Use by ":emenu" and the window toolbar.
* execute it. * "eap" is NULL for the window toolbar.
*/ */
void static void
ex_emenu(exarg_T *eap) 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; char_u *mode;
int idx;
saved_name = vim_strsave(eap->arg); /* Use the Insert mode entry when returning to Insert mode. */
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. */
if (restart_edit if (restart_edit
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
&& !current_SID && !current_SID
@ -2199,7 +2254,12 @@ ex_emenu(exarg_T *eap)
mode = (char_u *)"Insert"; mode = (char_u *)"Insert";
idx = MENU_INDEX_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; pos_T tpos;
@ -2255,22 +2315,120 @@ ex_emenu(exarg_T *eap)
if (idx != MENU_INDEX_INVALID && menu->strings[idx] != NULL) if (idx != MENU_INDEX_INVALID && menu->strings[idx] != NULL)
{ {
/* When executing a script or function execute the commands right now. /* When executing a script or function execute the commands right now.
* Also for the window toolbar.
* Otherwise put them in the typeahead buffer. */ * Otherwise put them in the typeahead buffer. */
if (eap == NULL
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
if (current_SID != 0) || current_SID != 0
#endif
)
exec_normal_cmd(menu->strings[idx], menu->noremap[idx], exec_normal_cmd(menu->strings[idx], menu->noremap[idx],
menu->silent[idx]); menu->silent[idx]);
else else
#endif
ins_typebuf(menu->strings[idx], menu->noremap[idx], 0, ins_typebuf(menu->strings[idx], menu->noremap[idx], 0,
TRUE, menu->silent[idx]); TRUE, menu->silent[idx]);
} }
else else if (eap != NULL)
EMSG2(_("E335: Menu not defined for %s mode"), mode); 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) || defined(FEAT_BEVAL_TIP) || defined(PROTO)
/* /*
* Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy. * 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 *saved_name;
char_u *p; char_u *p;
menu = root_menu; menu = *get_root_menu(path_name);
saved_name = vim_strsave(path_name); saved_name = vim_strsave(path_name);
if (saved_name == NULL) if (saved_name == NULL)

View File

@ -2679,9 +2679,9 @@ do_mouse(
* selection or the current window (might have false * selection or the current window (might have false
* negative here) * negative here)
*/ */
if (mouse_row < W_WINROW(curwin) if (mouse_row < curwin->w_winrow
|| mouse_row || mouse_row
> (W_WINROW(curwin) + curwin->w_height)) > (curwin->w_winrow + curwin->w_height))
jump_flags = MOUSE_MAY_STOP_VIS; jump_flags = MOUSE_MAY_STOP_VIS;
else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER) else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER)
jump_flags = MOUSE_MAY_STOP_VIS; jump_flags = MOUSE_MAY_STOP_VIS;

View File

@ -1,5 +1,7 @@
/* menu.c */ /* menu.c */
int winbar_height(win_T *wp);
void ex_menu(exarg_T *eap); 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 *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_name(expand_T *xp, int idx);
char_u *get_menu_names(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_show_popupmenu(void);
void gui_mch_toggle_tearoffs(int enable); void gui_mch_toggle_tearoffs(int enable);
void ex_emenu(exarg_T *eap); void ex_emenu(exarg_T *eap);
void winbar_click(win_T *wp, int col);
vimmenu_T *gui_find_menu(char_u *path_name); vimmenu_T *gui_find_menu(char_u *path_name);
void ex_menutranslate(exarg_T *eap); void ex_menutranslate(exarg_T *eap);
/* vim: set ft=c : */ /* vim: set ft=c : */

View File

@ -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); char_u *highlight_color(int id, char_u *what, int modec);
long_u highlight_gui_color_rgb(int id, int fg); long_u highlight_gui_color_rgb(int id, int fg);
int syn_name2id(char_u *name); int syn_name2id(char_u *name);
int syn_name2attr(char_u *name);
int highlight_exists(char_u *name); int highlight_exists(char_u *name);
char_u *syn_id2name(int id); char_u *syn_id2name(int id);
int syn_namen2id(char_u *linep, int len); int syn_namen2id(char_u *linep, int len);

View File

@ -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 */ static match_T search_hl; /* used for 'hlsearch' highlight matching */
#endif #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 #ifdef FEAT_FOLDING
static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */ static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */
static int compute_foldcolumn(win_T *wp, int col); 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 void draw_tabline(void);
static int fillchar_status(int *attr, win_T *wp); static int fillchar_status(int *attr, win_T *wp);
static int fillchar_vsep(int *attr); static int fillchar_vsep(int *attr);
#ifdef FEAT_MENU
static void redraw_win_toolbar(win_T *wp);
#endif
#ifdef FEAT_STL_OPT #ifdef FEAT_STL_OPT
static void win_redr_custom(win_T *wp, int draw_ruler); static void win_redr_custom(win_T *wp, int draw_ruler);
#endif #endif
@ -455,7 +461,7 @@ redraw_after_callback(int call_update_screen)
* editing the command. */ * editing the command. */
redrawcmdline_ex(FALSE); redrawcmdline_ex(FALSE);
} }
else if (State & (NORMAL | INSERT)) else if (State & (NORMAL | INSERT | TERMINAL))
{ {
/* keep the command line if possible */ /* keep the command line if possible */
update_screen(VALID_NO_UPDATE); update_screen(VALID_NO_UPDATE);
@ -1804,6 +1810,15 @@ win_update(win_T *wp)
win_foldinfo.fi_level = 0; win_foldinfo.fi_level = 0;
#endif #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. * Update all the window rows.
*/ */
@ -2433,6 +2448,143 @@ advance_color_col(int vcol, int **color_cols)
} }
#endif #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 #ifdef FEAT_FOLDING
/* /*
* Compute the width of the foldcolumn. Based on 'foldcolumn' and how much * 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 * Right-left text is put in columns 0 - number-col, normal text is put
* in columns number-col - window-width. * in columns number-col - window-width.
*/ */
#ifdef FEAT_MBYTE col = text_to_screenline(wp, text, col);
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;
}
}
/* Fill the rest of the line with the fold filler */ /* Fill the rest of the line with the fold filler */
#ifdef FEAT_RIGHTLEFT #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); 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' * 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. * with character 'c1' in first column followed by 'c2' in the other columns.
@ -8502,12 +8544,7 @@ screen_fill(
col = end_col - col; col = end_col - col;
while (col--) /* clear chars in ScreenLines */ while (col--) /* clear chars in ScreenLines */
{ {
ScreenLines[off] = ' '; space_to_screenline(off, 0);
#ifdef FEAT_MBYTE
if (enc_utf8)
ScreenLinesUC[off] = 0;
#endif
ScreenAttrs[off] = 0;
++off; ++off;
} }
} }
@ -10671,6 +10708,73 @@ messaging(void)
return (!(p_lz && char_avail() && !KeyTyped)); 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 * Show current status info in ruler and various other places
* If always is FALSE, only show ruler if position has changed. * If always is FALSE, only show ruler if position has changed.

View File

@ -70,6 +70,10 @@ typedef int scid_T; /* script ID */
typedef struct file_buffer buf_T; /* forward declaration */ typedef struct file_buffer buf_T; /* forward declaration */
typedef struct terminal_S term_T; 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. * Reference to a buffer that stores the value of buf_free_count.
* bufref_valid() only needs to check "buf" when the count differs. * bufref_valid() only needs to check "buf" when the count differs.
@ -2611,6 +2615,14 @@ struct matchitem
#endif #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 * 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_winrow; /* first row of window in screen */
int w_height; /* number of rows in window, excluding 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_status_height; /* number of status lines (0 or 1) */
int w_wincol; /* Leftmost column of window in screen. int w_wincol; /* Leftmost column of window in screen.
use W_WINCOL() */ use W_WINCOL() */
@ -2798,6 +2810,12 @@ struct window_S
char_u *w_localdir; /* absolute path of local directory or char_u *w_localdir; /* absolute path of local directory or
NULL */ 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. * Options local to a window.
* They are local because they influence the layout of the window or * 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 */ /* Start a menu name with this to not include it on the main menu bar */
#define MNU_HIDDEN_CHAR ']' #define MNU_HIDDEN_CHAR ']'
typedef struct VimMenu vimmenu_T;
struct VimMenu struct VimMenu
{ {
int modes; /* Which modes is this menu visible for? */ int modes; /* Which modes is this menu visible for? */

View File

@ -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"), "StatusLineTerm term=reverse,bold cterm=bold ctermfg=White ctermbg=DarkGreen gui=bold guifg=bg guibg=DarkGreen"),
CENT("StatusLineTermNC term=reverse ctermfg=White ctermbg=DarkGreen", CENT("StatusLineTermNC term=reverse ctermfg=White ctermbg=DarkGreen",
"StatusLineTermNC term=reverse ctermfg=White ctermbg=DarkGreen guifg=bg guibg=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 #endif
NULL 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"), "StatusLineTerm term=reverse,bold cterm=bold ctermfg=Black ctermbg=LightGreen gui=bold guifg=bg guibg=LightGreen"),
CENT("StatusLineTermNC term=reverse ctermfg=Black ctermbg=LightGreen", CENT("StatusLineTermNC term=reverse ctermfg=Black ctermbg=LightGreen",
"StatusLineTermNC term=reverse ctermfg=Black ctermbg=LightGreen guifg=bg guibg=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 #endif
NULL NULL
}; };
@ -9525,6 +9537,20 @@ syn_name2id(char_u *name)
return i + 1; 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) #if defined(FEAT_EVAL) || defined(PROTO)
/* /*
* Return TRUE if highlight group "name" exists. * Return TRUE if highlight group "name" exists.

View File

@ -38,7 +38,8 @@
* in tl_scrollback are no longer used. * in tl_scrollback are no longer used.
* *
* TODO: * 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() * - Redirecting output does not work on MS-Windows, Test_terminal_redir_file()
* is disabled. * is disabled.
* - implement term_setsize() * - implement term_setsize()
@ -703,7 +704,7 @@ write_to_term(buf_T *buffer, char_u *msg, channel_T *channel)
update_screen(0); update_screen(0);
update_cursor(term, TRUE); update_cursor(term, TRUE);
} }
else if (buffer->b_nwindows > 0) else
redraw_after_callback(TRUE); redraw_after_callback(TRUE);
} }
} }
@ -1545,7 +1546,7 @@ terminal_loop(int blocking)
{ {
/* TODO: skip screen update when handling a sequence of keys. */ /* TODO: skip screen update when handling a sequence of keys. */
/* Repeat redrawing in case a message is received while redrawing. */ /* 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) if (update_screen(0) == FAIL)
break; break;
update_cursor(curbuf->b_term, FALSE); update_cursor(curbuf->b_term, FALSE);

View File

@ -201,12 +201,13 @@ NEW_TESTS = test_arabic.res \
test_viminfo.res \ test_viminfo.res \
test_vimscript.res \ test_vimscript.res \
test_visual.res \ test_visual.res \
test_winbar.res \
test_window_id.res \ test_window_id.res \
test_windows_home.res \
test_writefile.res \ test_writefile.res \
test_alot_latin.res \ test_alot_latin.res \
test_alot_utf8.res \ test_alot_utf8.res \
test_alot.res \ test_alot.res
test_windows_home.res
# Explicit dependencies. # Explicit dependencies.

View 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

View File

@ -2657,7 +2657,7 @@ retnomove:
} }
#if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD) #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
/* Continue a modeless selection in another window. */ /* 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; return IN_OTHER_WIN;
#endif #endif
return IN_BUFFER; return IN_BUFFER;
@ -2692,6 +2692,17 @@ retnomove:
if (wp == NULL) if (wp == NULL)
return IN_UNKNOWN; return IN_UNKNOWN;
dragwin = NULL; 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()! * winpos and height may change in win_enter()!
*/ */
@ -2829,7 +2840,7 @@ retnomove:
#if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD) #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
/* Continue a modeless selection in another window. */ /* 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; return IN_OTHER_WIN;
#endif #endif
@ -3117,7 +3128,12 @@ mouse_find_win(int *rowp, int *colp UNUSED)
* exist. */ * exist. */
FOR_ALL_WINDOWS(wp) FOR_ALL_WINDOWS(wp)
if (wp == fp->fr_win) if (wp == fp->fr_win)
{
#ifdef FEAT_MENU
*rowp -= wp->w_winbar_height;
#endif
return wp; return wp;
}
return NULL; return NULL;
} }

View File

@ -761,6 +761,12 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1124,
/**/
1123,
/**/
1122,
/**/ /**/
1121, 1121,
/**/ /**/

View File

@ -4692,6 +4692,10 @@ win_free(
} }
#endif /* FEAT_GUI */ #endif /* FEAT_GUI */
#ifdef FEAT_MENU
remove_winbar(wp);
#endif
#ifdef FEAT_SYN_HL #ifdef FEAT_SYN_HL
vim_free(wp->w_p_cc_cols); vim_free(wp->w_p_cc_cols);
#endif #endif
@ -5667,6 +5671,7 @@ set_fraction(win_T *wp)
/* /*
* Set the height of a window. * 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 * This takes care of the things inside the window, not what happens to the
* window position, the frame or to other windows. * window position, the frame or to other windows.
*/ */

View File

@ -47,11 +47,11 @@ GOTO end
:use_vim :use_vim
:: The script tutor.vim tells Vim which file to copy :: The script tutor.vim tells Vim which file to copy
vim -u NONE -c "so $VIMRUNTIME/tutor/tutor.vim" call vim -u NONE -c "so $VIMRUNTIME/tutor/tutor.vim"
IF ERRORLEVEL 1 GOTO no_executable IF ERRORLEVEL 1 GOTO no_executable
:: Start vim without any .vimrc, set 'nocompatible' :: Start vim without any .vimrc, set 'nocompatible'
vim -u NONE -c "set nocp" %TUTORCOPY% call vim -u NONE -c "set nocp" %TUTORCOPY%
GOTO end GOTO end