patch 8.0.1660: the terminal API "drop" command doesn't support options

Problem:    The terminal API "drop" command doesn't support options.
Solution:   Implement the options.
diff --git a/src/eval.c b/src/eval.c
index 2da56a4..c965d64 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -6590,7 +6590,7 @@
 	len += 7;
 
     if (eap->force_ff != 0)
-	len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
+	len += 10; /* " ++ff=unix" */
 # ifdef FEAT_MBYTE
     if (eap->force_enc != 0)
 	len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
@@ -6614,7 +6614,9 @@
 
     if (eap->force_ff != 0)
 	sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
-						eap->cmd + eap->force_ff);
+						eap->force_ff == 'u' ? "unix"
+						: eap->force_ff == 'd' ? "dos"
+						: "mac");
 #ifdef FEAT_MBYTE
     if (eap->force_enc != 0)
 	sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 41c7c80..48b0253 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -1778,7 +1778,7 @@
     int		regname;	/* register name (NUL if none) */
     int		force_bin;	/* 0, FORCE_BIN or FORCE_NOBIN */
     int		read_edit;	/* ++edit argument */
-    int		force_ff;	/* ++ff= argument (index in cmd[]) */
+    int		force_ff;	/* ++ff= argument (first char of argument) */
 #ifdef FEAT_MBYTE
     int		force_enc;	/* ++enc= argument (index in cmd[]) */
     int		bad_char;	/* BAD_KEEP, BAD_DROP or replacement byte */
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 3a6c7cf..b013004 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -5308,6 +5308,18 @@
     return p;
 }
 
+    int
+get_bad_opt(char_u *p, exarg_T *eap)
+{
+    if (STRICMP(p, "keep") == 0)
+	eap->bad_char = BAD_KEEP;
+    else if (STRICMP(p, "drop") == 0)
+	eap->bad_char = BAD_DROP;
+    else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL)
+	eap->bad_char = *p;
+    return FAIL;
+}
+
 /*
  * Get "++opt=arg" argument.
  * Return FAIL or OK.
@@ -5387,6 +5399,7 @@
 #endif
 	if (check_ff_value(eap->cmd + eap->force_ff) == FAIL)
 	    return FAIL;
+	eap->force_ff = eap->cmd[eap->force_ff];
 #ifdef FEAT_MBYTE
     }
     else if (pp == &eap->force_enc)
@@ -5399,14 +5412,7 @@
     {
 	/* Check ++bad= argument.  Must be a single-byte character, "keep" or
 	 * "drop". */
-	p = eap->cmd + bad_char_idx;
-	if (STRICMP(p, "keep") == 0)
-	    eap->bad_char = BAD_KEEP;
-	else if (STRICMP(p, "drop") == 0)
-	    eap->bad_char = BAD_DROP;
-	else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL)
-	    eap->bad_char = *p;
-	else
+	if (get_bad_opt(eap->cmd + bad_char_idx, eap) == FAIL)
 	    return FAIL;
     }
 #endif
diff --git a/src/fileio.c b/src/fileio.c
index 05c3df5..e2fa3e2 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2779,22 +2779,22 @@
     int
 prep_exarg(exarg_T *eap, buf_T *buf)
 {
-    eap->cmd = alloc((unsigned)(STRLEN(buf->b_p_ff)
+    eap->cmd = alloc(15
 #ifdef FEAT_MBYTE
-		+ STRLEN(buf->b_p_fenc)
+		+ (unsigned)STRLEN(buf->b_p_fenc)
 #endif
-						 + 15));
+	    );
     if (eap->cmd == NULL)
 	return FAIL;
 
 #ifdef FEAT_MBYTE
-    sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc);
-    eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff);
+    sprintf((char *)eap->cmd, "e ++enc=%s", buf->b_p_fenc);
+    eap->force_enc = 8;
     eap->bad_char = buf->b_bad_char;
 #else
-    sprintf((char *)eap->cmd, "e ++ff=%s", buf->b_p_ff);
+    sprintf((char *)eap->cmd, "e");
 #endif
-    eap->force_ff = 7;
+    eap->force_ff = *buf->b_p_ff;
 
     eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
     eap->read_edit = FALSE;
diff --git a/src/misc2.c b/src/misc2.c
index cd1dcf0..9127e66 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -3161,7 +3161,7 @@
     int		c;
 
     if (eap != NULL && eap->force_ff != 0)
-	c = eap->cmd[eap->force_ff];
+	c = eap->force_ff;
     else
     {
 	if ((eap != NULL && eap->force_bin != 0)
diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro
index 3819531..0eace62 100644
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -12,6 +12,7 @@
 void ex_ni(exarg_T *eap);
 int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp);
 void separate_nextcmd(exarg_T *eap);
+int get_bad_opt(char_u *p, exarg_T *eap);
 int ends_excmd(int c);
 char_u *find_nextcmd(char_u *p);
 char_u *check_nextcmd(char_u *p);
diff --git a/src/terminal.c b/src/terminal.c
index b60799d..3268062 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -38,7 +38,6 @@
  * in tl_scrollback are no longer used.
  *
  * TODO:
- * - For the "drop" command accept another argument for options.
  * - Add a way to set the 16 ANSI colors, to be used for 'termguicolors' and in
  *   the GUI.
  * - Win32: Make terminal used for :!cmd in the GUI work better.  Allow for
@@ -3152,10 +3151,12 @@
 handle_drop_command(listitem_T *item)
 {
     char_u	*fname = get_tv_string(&item->li_tv);
+    listitem_T	*opt_item = item->li_next;
     int		bufnr;
     win_T	*wp;
     tabpage_T   *tp;
     exarg_T	ea;
+    char_u	*tofree = NULL;
 
     bufnr = buflist_add(fname, BLN_LISTED | BLN_NOOPT);
     FOR_ALL_TAB_WINDOWS(tp, wp)
@@ -3168,10 +3169,60 @@
 	}
     }
 
-    /* open in new window, like ":sbuffer N" */
     vim_memset(&ea, 0, sizeof(ea));
-    ea.cmd = (char_u *)"sbuffer";
-    goto_buffer(&ea, DOBUF_FIRST, FORWARD, bufnr);
+
+    if (opt_item != NULL && opt_item->li_tv.v_type == VAR_DICT
+					&& opt_item->li_tv.vval.v_dict != NULL)
+    {
+	dict_T *dict = opt_item->li_tv.vval.v_dict;
+	char_u *p;
+
+	p = get_dict_string(dict, (char_u *)"ff", FALSE);
+	if (p == NULL)
+	    p = get_dict_string(dict, (char_u *)"fileformat", FALSE);
+	if (p != NULL)
+	{
+	    if (check_ff_value(p) == FAIL)
+		ch_log(NULL, "Invalid ff argument to drop: %s", p);
+	    else
+		ea.force_ff = *p;
+	}
+	p = get_dict_string(dict, (char_u *)"enc", FALSE);
+	if (p == NULL)
+	    p = get_dict_string(dict, (char_u *)"encoding", FALSE);
+	if (p != NULL)
+	{
+	    ea.cmd = alloc((int)STRLEN(p) + 10);
+	    if (ea.cmd != NULL)
+	    {
+		sprintf((char *)ea.cmd, "sbuf ++enc=%s", p);
+		ea.force_enc = 11;
+		tofree = ea.cmd;
+	    }
+	}
+
+	p = get_dict_string(dict, (char_u *)"bad", FALSE);
+	if (p != NULL)
+	    get_bad_opt(p, &ea);
+
+	if (dict_find(dict, (char_u *)"bin", -1) != NULL)
+	    ea.force_bin = FORCE_BIN;
+	if (dict_find(dict, (char_u *)"binary", -1) != NULL)
+	    ea.force_bin = FORCE_BIN;
+	if (dict_find(dict, (char_u *)"nobin", -1) != NULL)
+	    ea.force_bin = FORCE_NOBIN;
+	if (dict_find(dict, (char_u *)"nobinary", -1) != NULL)
+	    ea.force_bin = FORCE_NOBIN;
+    }
+
+    /* open in new window, like ":split fname" */
+    if (ea.cmd == NULL)
+	ea.cmd = (char_u *)"split";
+    ea.arg = fname;
+    ea.cmdidx = CMD_split;
+    ex_splitview(&ea);
+
+    vim_free(tofree);
 }
 
 /*
diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim
index eac54c1..218b4ca 100644
--- a/src/testdir/test_terminal.vim
+++ b/src/testdir/test_terminal.vim
@@ -1049,17 +1049,14 @@
   set laststatus&
 endfunc
 
-func Test_terminal_api_drop_newwin()
-  if !CanRunVimInTerminal()
-    return
-  endif
+func Api_drop_common(options)
   call assert_equal(1, winnr('$'))
 
   " Use the title termcap entries to output the escape sequence.
   call writefile([
 	\ 'set title',
 	\ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"',
-	\ 'let &titlestring = ''["drop","Xtextfile"]''',
+	\ 'let &titlestring = ''["drop","Xtextfile"' . a:options . ']''',
 	\ 'redraw',
 	\ "set t_ts=",
 	\ ], 'Xscript')
@@ -1067,6 +1064,116 @@
   call WaitFor({-> bufnr('Xtextfile') > 0})
   call assert_equal('Xtextfile', expand('%:t'))
   call assert_true(winnr('$') >= 3)
+  return buf
+endfunc
+
+func Test_terminal_api_drop_newwin()
+  if !CanRunVimInTerminal()
+    return
+  endif
+  let buf = Api_drop_common('')
+  call assert_equal(0, &bin)
+  call assert_equal('', &fenc)
+
+  call StopVimInTerminal(buf)
+  call delete('Xscript')
+  bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_bin()
+  if !CanRunVimInTerminal()
+    return
+  endif
+  let buf = Api_drop_common(',{"bin":1}')
+  call assert_equal(1, &bin)
+
+  call StopVimInTerminal(buf)
+  call delete('Xscript')
+  bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_binary()
+  if !CanRunVimInTerminal()
+    return
+  endif
+  let buf = Api_drop_common(',{"binary":1}')
+  call assert_equal(1, &bin)
+
+  call StopVimInTerminal(buf)
+  call delete('Xscript')
+  bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_nobin()
+  if !CanRunVimInTerminal()
+    return
+  endif
+  set binary
+  let buf = Api_drop_common(',{"nobin":1}')
+  call assert_equal(0, &bin)
+
+  call StopVimInTerminal(buf)
+  call delete('Xscript')
+  bwipe Xtextfile
+  set nobinary
+endfunc
+
+func Test_terminal_api_drop_newwin_nobinary()
+  if !CanRunVimInTerminal()
+    return
+  endif
+  set binary
+  let buf = Api_drop_common(',{"nobinary":1}')
+  call assert_equal(0, &bin)
+
+  call StopVimInTerminal(buf)
+  call delete('Xscript')
+  bwipe Xtextfile
+  set nobinary
+endfunc
+
+func Test_terminal_api_drop_newwin_ff()
+  if !CanRunVimInTerminal()
+    return
+  endif
+  let buf = Api_drop_common(',{"ff":"dos"}')
+  call assert_equal("dos", &ff)
+
+  call StopVimInTerminal(buf)
+  call delete('Xscript')
+  bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_fileformat()
+  if !CanRunVimInTerminal()
+    return
+  endif
+  let buf = Api_drop_common(',{"fileformat":"dos"}')
+  call assert_equal("dos", &ff)
+
+  call StopVimInTerminal(buf)
+  call delete('Xscript')
+  bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_enc()
+  if !CanRunVimInTerminal()
+    return
+  endif
+  let buf = Api_drop_common(',{"enc":"utf-16"}')
+  call assert_equal("utf-16", &fenc)
+
+  call StopVimInTerminal(buf)
+  call delete('Xscript')
+  bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_encoding()
+  if !CanRunVimInTerminal()
+    return
+  endif
+  let buf = Api_drop_common(',{"encoding":"utf-16"}')
+  call assert_equal("utf-16", &fenc)
 
   call StopVimInTerminal(buf)
   call delete('Xscript')
diff --git a/src/version.c b/src/version.c
index cdd8b41..2d566ca 100644
--- a/src/version.c
+++ b/src/version.c
@@ -763,6 +763,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1660,
+/**/
     1659,
 /**/
     1658,