patch 8.2.0413: buffer menu does not handle special buffers properly

Problem:    Buffer menu does not handle special buffers properly.
Solution:   Keep a dictionary with buffer names to reliably keep track of
            entries.
            Also trigger BufFilePre and BufFilePost for command-line and
            terminal buffers when the name changes.
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 7193a2a..bc3cccc 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -4195,7 +4195,9 @@
 
     // Create the command-line buffer empty.
     (void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL);
+    apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
     (void)setfname(curbuf, (char_u *)"[Command Line]", NULL, TRUE);
+    apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
     set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL);
     curbuf->b_p_ma = TRUE;
 #ifdef FEAT_FOLDING
diff --git a/src/terminal.c b/src/terminal.c
index 30590b6..7f440a3 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -523,6 +523,8 @@
     term->tl_next = first_term;
     first_term = term;
 
+    apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
+
     if (opt->jo_term_name != NULL)
 	curbuf->b_ffname = vim_strsave(opt->jo_term_name);
     else if (argv != NULL)
@@ -571,6 +573,8 @@
     curbuf->b_sfname = vim_strsave(curbuf->b_ffname);
     curbuf->b_fname = curbuf->b_ffname;
 
+    apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
+
     if (opt->jo_term_opencmd != NULL)
 	term->tl_opencmd = vim_strsave(opt->jo_term_opencmd);
 
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index f4ba55d..81b780b 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -175,9 +175,9 @@
 	test_matchadd_conceal \
 	test_matchadd_conceal_utf8 \
 	test_memory_usage \
-	test_method \
 	test_menu \
 	test_messages \
+	test_method \
 	test_mksession \
 	test_mksession_utf8 \
 	test_modeline \
@@ -402,6 +402,7 @@
 	test_matchadd_conceal.res \
 	test_matchadd_conceal_utf8.res \
 	test_memory_usage.res \
+	test_menu.res \
 	test_messages.res \
 	test_method.res \
 	test_mksession.res \
diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim
index 171abde..375213c 100644
--- a/src/testdir/test_alot.vim
+++ b/src/testdir/test_alot.vim
@@ -19,7 +19,6 @@
 source test_global.vim
 source test_jumps.vim
 source test_lispwords.vim
-source test_menu.vim
 source test_move.vim
 source test_put.vim
 source test_recover.vim
diff --git a/src/testdir/test_menu.vim b/src/testdir/test_menu.vim
index 5e7a77b..f8d8081 100644
--- a/src/testdir/test_menu.vim
+++ b/src/testdir/test_menu.vim
@@ -19,6 +19,41 @@
   call assert_equal('', v:errmsg)
 endfunc
 
+func Test_buffer_menu_special_buffers()
+  " Load in runtime menus
+  try
+    source $VIMRUNTIME/menu.vim
+  catch
+    call assert_report('error while loading menus: ' . v:exception)
+  endtry
+
+  let v:errmsg = ''
+  doautocmd LoadBufferMenu VimEnter
+  call assert_equal('', v:errmsg)
+
+  let orig_buffer_menus = execute("nmenu Buffers")
+
+  " Make a new command-line window, test that it does not create a new buffer
+  " menu.
+  call feedkeys("q::let cmdline_buffer_menus=execute('nmenu Buffers')\<CR>:q\<CR>", 'ntx')
+  call assert_equal(len(split(orig_buffer_menus, "\n")), len(split(cmdline_buffer_menus, "\n")))
+  call assert_equal(orig_buffer_menus, execute("nmenu Buffers"))
+
+  if has('terminal')
+    " Open a terminal window and test that it does not create a buffer menu
+    " item.
+    terminal
+    let term_buffer_menus = execute('nmenu Buffers')
+    call assert_equal(len(split(orig_buffer_menus, "\n")), len(split(term_buffer_menus, "\n")))
+    bwipe!
+    call assert_equal(orig_buffer_menus, execute("nmenu Buffers"))
+  endif
+
+  " Remove menus to clean up
+  source $VIMRUNTIME/delmenu.vim
+  call assert_equal('', v:errmsg)
+endfunc
+
 func Test_translate_menu()
   if !has('multi_lang')
     return
@@ -121,6 +156,7 @@
 " Test for menu item completion in command line
 func Test_menu_expand()
   " Create the menu itmes for test
+  menu Dummy.Nothing lll
   for i in range(1, 4)
     let m = 'menu Xmenu.A' .. i .. '.A' .. i
     for j in range(1, 4)
@@ -146,7 +182,7 @@
   " Test for <Up> to go up a menu
   call feedkeys(":emenu Xmenu.A\<Tab>\<Down>\<Up>\<Up>\<Up>" ..
         \ "\<C-A>\<C-B>\"\<CR>", 'xt')
-  call assert_equal('"emenu Buffers. Xmenu.', @:)
+  call assert_equal('"emenu Dummy. Xmenu.', @:)
 
   " Test for expanding only submenus
   call feedkeys(":popup Xmenu.\<C-A>\<C-B>\"\<CR>", 'xt')
@@ -166,6 +202,7 @@
 
   set wildmenu&
   unmenu Xmenu
+  unmenu Dummy
 
   " Test for expanding popup menus with some hidden items
   menu Xmenu.foo.A1 a1
@@ -175,7 +212,6 @@
   call feedkeys(":popup Xmenu.\<C-A>\<C-B>\"\<CR>", 'xt')
   call assert_equal('"popup Xmenu.foo', @:)
   unmenu Xmenu
-
 endfunc
 
 " Test for the menu_info() function
diff --git a/src/version.c b/src/version.c
index 7bebf92..13c384f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -739,6 +739,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    413,
+/**/
     412,
 /**/
     411,