To: vim-dev@vim.org Subject: Patch 6.1.276 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 6.1.276 Problem: "gvim --remote file" doesn't prompt for an encryption key. Solution: The further characters the client sends to the server are used. Added inputsave() and inputrestore() to allow prompting the user directly and not using typeahead. Also fix possible memory leak for ":normal". Files: src/eval.c, src/ex_cmds2.c, src/ex_docmd.c, src/getchar.c, src/main.c, src/proto/getchar.pro, src/proto/ui.pro, src/runtime/doc/eval.txt, src/structs.h, src/ui.c, src/vim.h *** ../vim61.275/src/eval.c Mon Dec 23 22:54:36 2002 --- src/eval.c Sun Jan 5 22:07:26 2003 *************** *** 212,218 **** static void f_cscope_connection __ARGS((VAR argvars, VAR retvar)); static void f_cursor __ARGS((VAR argsvars, VAR retvar)); static void f_delete __ARGS((VAR argvars, VAR retvar)); - static void f_inputdialog __ARGS((VAR argvars, VAR retvar)); static void f_did_filetype __ARGS((VAR argvars, VAR retvar)); static void f_escape __ARGS((VAR argvars, VAR retvar)); static void f_eventhandler __ARGS((VAR argvars, VAR retvar)); --- 212,217 ---- *************** *** 253,258 **** --- 252,260 ---- static void f_indent __ARGS((VAR argvars, VAR retvar)); static void f_isdirectory __ARGS((VAR argvars, VAR retvar)); static void f_input __ARGS((VAR argvars, VAR retvar)); + static void f_inputdialog __ARGS((VAR argvars, VAR retvar)); + static void f_inputrestore __ARGS((VAR argvars, VAR retvar)); + static void f_inputsave __ARGS((VAR argvars, VAR retvar)); static void f_inputsecret __ARGS((VAR argvars, VAR retvar)); static void f_last_buffer_nr __ARGS((VAR argvars, VAR retvar)); static void f_libcall __ARGS((VAR argvars, VAR retvar)); *************** *** 2450,2455 **** --- 2467,2474 ---- {"indent", 1, 1, f_indent}, {"input", 1, 2, f_input}, {"inputdialog", 1, 2, f_inputdialog}, + {"inputrestore", 0, 0, f_inputrestore}, + {"inputsave", 0, 0, f_inputsave}, {"inputsecret", 1, 2, f_inputsecret}, {"isdirectory", 1, 1, f_isdirectory}, {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */ *************** *** 4916,4921 **** --- 4935,4988 ---- else #endif f_input(argvars, retvar); + } + + static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL}; + + /* + * "inputrestore()" function + */ + /*ARGSUSED*/ + static void + f_inputrestore(argvars, retvar) + VAR argvars; + VAR retvar; + { + if (ga_userinput.ga_len > 0) + { + --ga_userinput.ga_len; + ++ga_userinput.ga_room; + restore_typeahead((tasave_T *)(ga_userinput.ga_data) + + ga_userinput.ga_len); + retvar->var_val.var_number = 0; /* OK */ + } + else if (p_verbose > 1) + { + msg((char_u *)_("called inputrestore() more often than inputsave()")); + retvar->var_val.var_number = 1; /* Failed */ + } + } + + /* + * "inputsave()" function + */ + /*ARGSUSED*/ + static void + f_inputsave(argvars, retvar) + VAR argvars; + VAR retvar; + { + /* Add an entry to the stack of typehead storage. */ + if (ga_grow(&ga_userinput, 1) == OK) + { + save_typeahead((tasave_T *)(ga_userinput.ga_data) + + ga_userinput.ga_len); + ++ga_userinput.ga_len; + --ga_userinput.ga_room; + retvar->var_val.var_number = 0; /* OK */ + } + else + retvar->var_val.var_number = 1; /* Failed */ } /* *** ../vim61.275/src/ex_cmds2.c Fri Jan 3 22:48:00 2003 --- src/ex_cmds2.c Sun Jan 5 17:45:51 2003 *************** *** 30,38 **** int save_State = State; int save_did_emsg = did_emsg; int save_cmd_silent = cmd_silent; ! typebuf_T saved_typebuf; ! int new_typebuf; ! struct buffheader save_stuffbuff; # ifdef FEAT_EX_EXTRA int save_ex_normal_busy; # endif --- 30,36 ---- int save_State = State; int save_did_emsg = did_emsg; int save_cmd_silent = cmd_silent; ! tasave_T typeaheadbuf; # ifdef FEAT_EX_EXTRA int save_ex_normal_busy; # endif *************** *** 96,122 **** * with the commands being executed. Reset "ex_normal_busy" to avoid * the side effects of using ":normal". Save the stuff buffer and make * it empty. */ - saved_typebuf = typebuf; - new_typebuf = (alloc_typebuf() == OK); # ifdef FEAT_EX_EXTRA save_ex_normal_busy = ex_normal_busy; ex_normal_busy = 0; # endif ! save_stuffbuff = stuffbuff; ! stuffbuff.bh_first.b_next = NULL; cmdline = getcmdline_prompt('>', NULL, 0); ! if (new_typebuf) ! { ! free_typebuf(); ! typebuf = saved_typebuf; ! } # ifdef FEAT_EX_EXTRA ex_normal_busy = save_ex_normal_busy; # endif - free_buff(&stuffbuff); - stuffbuff = save_stuffbuff; cmdline_row = msg_row; if (cmdline != NULL) --- 94,111 ---- * with the commands being executed. Reset "ex_normal_busy" to avoid * the side effects of using ":normal". Save the stuff buffer and make * it empty. */ # ifdef FEAT_EX_EXTRA save_ex_normal_busy = ex_normal_busy; ex_normal_busy = 0; # endif ! save_typeahead(&typeaheadbuf); cmdline = getcmdline_prompt('>', NULL, 0); ! restore_typeahead(&typeaheadbuf); # ifdef FEAT_EX_EXTRA ex_normal_busy = save_ex_normal_busy; # endif cmdline_row = msg_row; if (cmdline != NULL) *** ../vim61.275/src/ex_docmd.c Mon Nov 11 21:42:40 2002 --- src/ex_docmd.c Sun Jan 5 17:54:22 2003 *************** *** 6879,6888 **** int save_restart_edit = restart_edit; int save_msg_didout = msg_didout; int save_State = State; ! typebuf_T saved_typebuf; int save_insertmode = p_im; int save_finish_op = finish_op; - struct buffheader save_stuffbuff; #ifdef FEAT_MBYTE char_u *arg = NULL; int l; --- 6879,6887 ---- int save_restart_edit = restart_edit; int save_msg_didout = msg_didout; int save_State = State; ! tasave_T tabuf; int save_insertmode = p_im; int save_finish_op = finish_op; #ifdef FEAT_MBYTE char_u *arg = NULL; int l; *************** *** 6969,6981 **** * from an event handler and makes sure we don't hang when the argument * ends with half a command. */ ! saved_typebuf = typebuf; ! if (alloc_typebuf() == OK) { - /* Also save the stuff buffer and make it empty. */ - save_stuffbuff = stuffbuff; - stuffbuff.bh_first.b_next = NULL; - /* * Repeat the :normal command for each line in the range. When no * range given, execute it just once, without positioning the cursor --- 6968,6976 ---- * from an event handler and makes sure we don't hang when the argument * ends with half a command. */ ! save_typeahead(&tabuf); ! if (tabuf.typebuf_valid) { /* * Repeat the :normal command for each line in the range. When no * range given, execute it just once, without positioning the cursor *************** *** 7009,7024 **** } } while (eap->addr_count > 0 && eap->line1 <= eap->line2 && !got_int); - - stuffbuff = save_stuffbuff; } /* Might not return to the main loop when in an event handler. */ update_topline_cursor(); /* Restore the previous typeahead. */ ! free_typebuf(); ! typebuf = saved_typebuf; --ex_normal_busy; msg_scroll = save_msg_scroll; --- 7004,7016 ---- } } while (eap->addr_count > 0 && eap->line1 <= eap->line2 && !got_int); } /* Might not return to the main loop when in an event handler. */ update_topline_cursor(); /* Restore the previous typeahead. */ ! restore_typeahead(&tabuf); --ex_normal_busy; msg_scroll = save_msg_scroll; *** ../vim61.275/src/getchar.c Thu Jan 2 21:07:23 2003 --- src/getchar.c Sun Jan 5 18:00:25 2003 *************** *** 1200,1205 **** --- 1200,1247 ---- } return OK; } + + #if defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) || defined(PROTO) + + /* + * Save all three kinds of typeahead, so that the user must type at a prompt. + */ + void + save_typeahead(tp) + tasave_T *tp; + { + tp->save_typebuf = typebuf; + tp->typebuf_valid = (alloc_typebuf() == OK); + if (!tp->typebuf_valid) + typebuf = tp->save_typebuf; + + tp->save_stuffbuff = stuffbuff; + stuffbuff.bh_first.b_next = NULL; + # ifdef USE_INPUT_BUF + tp->save_inputbuf = get_input_buf(); + # endif + } + + /* + * Restore the typeahead to what it was before calling save_typeahead(). + */ + void + restore_typeahead(tp) + tasave_T *tp; + { + if (tp->typebuf_valid) + { + free_typebuf(); + typebuf = tp->save_typebuf; + } + + free_buff(&stuffbuff); + stuffbuff = tp->save_stuffbuff; + # ifdef USE_INPUT_BUF + set_input_buf(tp->save_inputbuf); + # endif + } + #endif /* * Open a new script file for the ":source!" command. *** ../vim61.275/src/main.c Mon Nov 11 21:34:16 2002 --- src/main.c Sun Jan 5 22:06:11 2003 *************** *** 2835,2841 **** ga_init2(&ga, 1, 100); ga_concat(&ga, (char_u *)":cd "); ga_concat(&ga, p); ! ga_concat(&ga, (char_u *)":drop"); vim_free(p); for (i = 0; i < filec; i++) { --- 2835,2842 ---- ga_init2(&ga, 1, 100); ga_concat(&ga, (char_u *)":cd "); ga_concat(&ga, p); ! /* Call inputsave() so that a prompt for an encryption key works. */ ! ga_concat(&ga, (char_u *)":if exists('*inputsave')|call inputsave()|endif|drop"); vim_free(p); for (i = 0; i < filec; i++) { *************** *** 2860,2866 **** } /* The :drop commands goes to Insert mode when 'insertmode' is set, use * CTRL-\ CTRL-N again. */ ! ga_concat(&ga, (char_u *)":cd -"); if (sendReply) ga_concat(&ga, (char_u *)":call SetupRemoteReplies()"); if (inicmd != NULL) --- 2861,2867 ---- } /* The :drop commands goes to Insert mode when 'insertmode' is set, use * CTRL-\ CTRL-N again. */ ! ga_concat(&ga, (char_u *)":if exists('*inputrestore')|call inputrestore()|endif|cd -"); if (sendReply) ga_concat(&ga, (char_u *)":call SetupRemoteReplies()"); if (inicmd != NULL) *** ../vim61.275/src/proto/getchar.pro Mon Oct 14 21:18:12 2002 --- src/proto/getchar.pro Sun Jan 5 17:47:42 2003 *************** *** 27,32 **** --- 27,34 ---- int alloc_typebuf __ARGS((void)); void free_typebuf __ARGS((void)); int save_typebuf __ARGS((void)); + void save_typeahead __ARGS((tasave_T *tp)); + void restore_typeahead __ARGS((tasave_T *tp)); void openscript __ARGS((char_u *name, int directly)); int using_script __ARGS((void)); void updatescript __ARGS((int c)); *** ../vim61.275/src/proto/ui.pro Fri Mar 22 21:41:23 2002 --- src/proto/ui.pro Sun Jan 5 17:47:34 2003 *************** *** 33,38 **** --- 33,40 ---- int vim_is_input_buf_empty __ARGS((void)); int vim_free_in_input_buf __ARGS((void)); int vim_used_in_input_buf __ARGS((void)); + char_u *get_input_buf __ARGS((void)); + void set_input_buf __ARGS((char_u *p)); void add_to_input_buf __ARGS((char_u *s, int len)); void add_to_input_buf_csi __ARGS((char_u *str, int len)); void push_raw_key __ARGS((char_u *s, int len)); *** ../vim61.275/runtime/doc/eval.txt Sat Sep 7 22:20:49 2002 --- runtime/doc/eval.txt Sun Jan 5 22:04:53 2003 *************** *** 1,4 **** ! *eval.txt* For Vim version 6.1. Last change: 2002 Sep 07 VIM REFERENCE MANUAL by Bram Moolenaar --- 1,4 ---- ! *eval.txt* For Vim version 6.1. Last change: 2003 Jan 05 VIM REFERENCE MANUAL by Bram Moolenaar *************** *** 804,809 **** --- 808,815 ---- indent( {lnum}) Number indent of line {lnum} input( {prompt} [, {text}]) String get input from the user inputdialog( {prompt} [, {text}]) String like input() but in a GUI dialog + inputrestore() Number restore typeahead + inputsave() Number save and clear typeahead inputsecret( {prompt} [, {text}]) String like input() but hiding the text isdirectory( {directory}) Number TRUE if {directory} is a directory libcall( {lib}, {func}, {arg}) String call {func} in library {lib} with {arg} *************** *** 1647,1652 **** --- 1672,1684 ---- default reply, as if the user typed this. NOTE: This must not be used in a startup file, for the versions that only run in GUI mode (e.g., the Win32 GUI). + Note: When input() is called from within a mapping it will + consume remaining characters from that mapping, because a + mapping is handled like the characters were typed. + Use |inputsave()| before input() and |inputrestore()| + after input() to avoid that. Another solution is to avoid + that further characters follow in the mapping, e.g., by using + |:execute| or |:normal|. Example: > :if input("Coffee or beer? ") == "beer" *************** *** 1654,1659 **** --- 1686,1698 ---- :endif < Example with default text: > :let color = input("Color? ", "white") + < Example with a mapping: > + :nmap \x :call GetFoo():exe "/" . Foo + :function GetFoo() + : call inputsave() + : let g:Foo = input("enter search pattern: ") + : call inputrestore() + :endfunction inputdialog({prompt} [, {text}) *inputdialog()* Like input(), but when the GUI is running and text dialogs are *************** *** 1666,1671 **** --- 1705,1724 ---- < Hitting works like pressing the OK button. Hitting works like pressing the Cancel button. + inputrestore() *inputrestore()* + Restore typeahead that was saved with a previous inputsave(). + Should be called the same number of times inputsave() is + called. Calling it more often is harmless though. + Returns 1 when there is nothing to restore, 0 otherwise. + + inputsave() *inputsave()* + Preserve typeahead (also from mappings) and clear it, so that + a following prompt gets input from the user. Should be + followed by a matching inputrestore() after the prompt. Can + be used several times, in which case there must be just as + many inputrestore() calls. + Returns 1 when out of memory, 0 otherwise. + inputsecret({prompt} [, {text}]) *inputsecret()* This function acts much like the |input()| function with but two exceptions: *** ../vim61.275/src/structs.h Mon Sep 23 21:32:08 2002 --- src/structs.h Sun Jan 5 18:00:36 2003 *************** *** 668,673 **** --- 668,684 ---- int tb_no_abbr_cnt; /* nr of chars without abbrev. in tb_buf[] */ } typebuf_T; + /* Struct to hold the saved typeahead for save_typeahead(). */ + typedef struct + { + typebuf_T save_typebuf; + int typebuf_valid; /* TRUE when save_typebuf valid */ + struct buffheader save_stuffbuff; + #ifdef USE_INPUT_BUF + char_u *save_inputbuf; + #endif + } tasave_T; + /* * Used for conversion of terminal I/O and script files. */ *** ../vim61.275/src/ui.c Sat Sep 14 16:56:33 2002 --- src/ui.c Sun Jan 5 18:15:36 2003 *************** *** 1455,1462 **** * input buffer. */ ! #if defined(UNIX) || defined(FEAT_GUI) || defined(OS2) || defined(VMS) \ ! || defined(FEAT_CLIENTSERVER) || defined(PROTO) /* * Internal typeahead buffer. Includes extra space for long key code --- 1455,1461 ---- * input buffer. */ ! #if defined(USE_INPUT_BUF) || defined(PROTO) /* * Internal typeahead buffer. Includes extra space for long key code *************** *** 1512,1517 **** --- 1511,1557 ---- vim_used_in_input_buf() { return inbufcount; + } + #endif + + #if defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) || defined(PROTO) + /* + * Return the current contents of the input buffer and make it empty. + * The returned pointer must be passed to set_input_buf() later. + */ + char_u * + get_input_buf() + { + garray_T *gap; + + /* We use a growarray to store the data pointer and the length. */ + gap = (garray_T *)alloc((unsigned)sizeof(garray_T)); + if (gap != NULL) + { + /* Add one to avoid a zero size. */ + gap->ga_data = alloc((unsigned)inbufcount + 1); + if (gap->ga_data != NULL) + mch_memmove(gap->ga_data, inbuf, (size_t)inbufcount); + gap->ga_len = inbufcount; + } + trash_input_buf(); + return (char_u *)gap; + } + + /* + * Restore the input buffer with a pointer returned from get_input_buf(). + */ + void + set_input_buf(p) + char_u *p; + { + garray_T *gap = (garray_T *)p; + + if (gap != NULL && gap->ga_data != NULL) + { + mch_memmove(inbuf, gap->ga_data, gap->ga_len); + inbufcount = gap->ga_len; + } } #endif *** ../vim61.275/src/vim.h Sun Oct 27 21:46:46 2002 --- src/vim.h Sun Jan 5 17:59:28 2003 *************** *** 1302,1307 **** --- 1302,1312 ---- # endif #endif + #if defined(UNIX) || defined(FEAT_GUI) || defined(OS2) || defined(VMS) \ + || defined(FEAT_CLIENTSERVER) + # define USE_INPUT_BUF + #endif + #ifdef MSWIN /* On MS-Windows the third argument isn't size_t. This matters for Win64, * where sizeof(size_t)==8, not 4 */ *** ../vim61.275/src/version.c Sun Jan 5 14:14:45 2003 --- src/version.c Sun Jan 5 22:08:45 2003 *************** *** 608,609 **** --- 608,611 ---- { /* Add new patch number below this line */ + /**/ + 276, /**/ -- What the word 'politics' means: 'Poli' in Latin meaning 'many' and 'tics' meaning 'bloodsucking creatures'. /// Bram Moolenaar -- Bram@moolenaar.net -- http://www.moolenaar.net \\\ /// Creator of Vim - Vi IMproved -- http://www.vim.org \\\ \\\ Project leader for A-A-P -- http://www.a-a-p.org /// \\\ Lord Of The Rings helps Uganda - http://iccf-holland.org/lotr.html ///