patch 9.1.0047: issues with temp curwin/buf while cmdwin is open

Problem:  Things that temporarily change/restore curwin/buf (e.g:
          win_execute, some autocmds) may break assumptions that
          curwin/buf is the cmdwin when "cmdwin_type != 0", causing
          issues.

Solution: Expose the cmdwin's real win/buf and check that instead. Also
          try to ensure these variables are NULL if "cmdwin_type == 0",
          allowing them to be used directly in most cases without
          checking cmdwin_type. (Sean Dewar)

Alternatively, we could ban win_execute in the cmdwin and audit all places that
temporarily change/restore curwin/buf, but I didn't notice any problems arising
from allowing this (standard cmdwin restrictions still apply, so things that may
actually break the cmdwin are still forbidden).

closes: #12819

Signed-off-by: Sean Dewar <seandewar@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/testdir/test_cmdwin.vim b/src/testdir/test_cmdwin.vim
index 5ba16db..0c7d297 100644
--- a/src/testdir/test_cmdwin.vim
+++ b/src/testdir/test_cmdwin.vim
@@ -470,4 +470,37 @@
   set cmdheight& showtabline& laststatus&
 endfunc
 
+func Test_cmdwin_temp_curwin()
+  func CheckWraps(expect_wrap)
+    setlocal textwidth=0 wrapmargin=1
+
+    call deletebufline('', 1, '$')
+    let as = repeat('a', winwidth(0) - 2 - &wrapmargin)
+    call setline(1, as .. ' b')
+    normal! gww
+
+    setlocal textwidth& wrapmargin&
+    call assert_equal(a:expect_wrap ? [as, 'b'] : [as .. ' b'], getline(1, '$'))
+  endfunc
+
+  func CheckCmdWin()
+    call assert_equal('command', win_gettype())
+    " textoff and &wrapmargin formatting considers the cmdwin_type char.
+    call assert_equal(1, getwininfo(win_getid())[0].textoff)
+    call CheckWraps(1)
+  endfunc
+
+  func CheckOtherWin()
+    call assert_equal('', win_gettype())
+    call assert_equal(0, getwininfo(win_getid())[0].textoff)
+    call CheckWraps(0)
+  endfunc
+
+  call feedkeys("q::call CheckCmdWin()\<CR>:call win_execute(win_getid(winnr('#')), 'call CheckOtherWin()')\<CR>:q<CR>", 'ntx')
+
+  delfunc CheckWraps
+  delfunc CheckCmdWin
+  delfunc CheckOtherWin
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab