comparison src/ex_docmd.c @ 14428:aab5947be7c5 v8.1.0228

patch 8.1.0228: dropping files is ignored while Vim is busy commit https://github.com/vim/vim/commit/92d147be959e689f8f58fd5d138a31835e160289 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jul 29 17:35:23 2018 +0200 patch 8.1.0228: dropping files is ignored while Vim is busy Problem: Dropping files is ignored while Vim is busy. Solution: Postpone the effect of dropping files until it's safe.
author Christian Brabandt <cb@256bit.org>
date Sun, 29 Jul 2018 17:45:05 +0200
parents 9ffce640d0d3
children 4a94173743d9
comparison
equal deleted inserted replaced
14427:a6055273c735 14428:aab5947be7c5
7857 ex_shell(exarg_T *eap UNUSED) 7857 ex_shell(exarg_T *eap UNUSED)
7858 { 7858 {
7859 do_shell(NULL, 0); 7859 do_shell(NULL, 0);
7860 } 7860 }
7861 7861
7862 #if defined(HAVE_DROP_FILE) \ 7862 #if defined(HAVE_DROP_FILE) || defined(PROTO)
7863 || (defined(FEAT_GUI_GTK) && defined(FEAT_DND)) \ 7863
7864 || defined(FEAT_GUI_MSWIN) \ 7864 static int drop_busy = FALSE;
7865 || defined(FEAT_GUI_MAC) \ 7865 static int drop_filec;
7866 || defined(PROTO) 7866 static char_u **drop_filev = NULL;
7867 7867 static int drop_split;
7868 /* 7868 static void (*drop_callback)(void *);
7869 * Handle a file drop. The code is here because a drop is *nearly* like an 7869 static void *drop_cookie;
7870 * :args command, but not quite (we have a list of exact filenames, so we 7870
7871 * don't want to (a) parse a command line, or (b) expand wildcards. So the 7871 static void
7872 * code is very similar to :args and hence needs access to a lot of the static 7872 handle_drop_internal(void)
7873 * functions in this file.
7874 *
7875 * The list should be allocated using alloc(), as should each item in the
7876 * list. This function takes over responsibility for freeing the list.
7877 *
7878 * XXX The list is made into the argument list. This is freed using
7879 * FreeWild(), which does a series of vim_free() calls.
7880 */
7881 void
7882 handle_drop(
7883 int filec, /* the number of files dropped */
7884 char_u **filev, /* the list of files dropped */
7885 int split) /* force splitting the window */
7886 { 7873 {
7887 exarg_T ea; 7874 exarg_T ea;
7888 int save_msg_scroll = msg_scroll; 7875 int save_msg_scroll = msg_scroll;
7889 7876
7890 /* Postpone this while editing the command line. */ 7877 // Setting the argument list may cause screen updates and being called
7891 if (text_locked()) 7878 // recursively. Avoid that by setting drop_busy.
7892 return; 7879 drop_busy = TRUE;
7893 if (curbuf_locked())
7894 return;
7895
7896 /* When the screen is being updated we should not change buffers and
7897 * windows structures, it may cause freed memory to be used. */
7898 if (updating_screen)
7899 return;
7900 7880
7901 /* Check whether the current buffer is changed. If so, we will need 7881 /* Check whether the current buffer is changed. If so, we will need
7902 * to split the current window or data could be lost. 7882 * to split the current window or data could be lost.
7903 * We don't need to check if the 'hidden' option is set, as in this 7883 * We don't need to check if the 'hidden' option is set, as in this
7904 * case the buffer won't be lost. 7884 * case the buffer won't be lost.
7905 */ 7885 */
7906 if (!buf_hide(curbuf) && !split) 7886 if (!buf_hide(curbuf) && !drop_split)
7907 { 7887 {
7908 ++emsg_off; 7888 ++emsg_off;
7909 split = check_changed(curbuf, CCGD_AW); 7889 drop_split = check_changed(curbuf, CCGD_AW);
7910 --emsg_off; 7890 --emsg_off;
7911 } 7891 }
7912 if (split) 7892 if (drop_split)
7913 { 7893 {
7914 if (win_split(0, 0) == FAIL) 7894 if (win_split(0, 0) == FAIL)
7915 return; 7895 return;
7916 RESET_BINDING(curwin); 7896 RESET_BINDING(curwin);
7917 7897
7922 } 7902 }
7923 7903
7924 /* 7904 /*
7925 * Set up the new argument list. 7905 * Set up the new argument list.
7926 */ 7906 */
7927 alist_set(ALIST(curwin), filec, filev, FALSE, NULL, 0); 7907 alist_set(ALIST(curwin), drop_filec, drop_filev, FALSE, NULL, 0);
7928 7908
7929 /* 7909 /*
7930 * Move to the first file. 7910 * Move to the first file.
7931 */ 7911 */
7932 /* Fake up a minimal "next" command for do_argfile() */ 7912 /* Fake up a minimal "next" command for do_argfile() */
7940 7920
7941 /* Restore msg_scroll, otherwise a following command may cause scrolling 7921 /* Restore msg_scroll, otherwise a following command may cause scrolling
7942 * unexpectedly. The screen will be redrawn by the caller, thus 7922 * unexpectedly. The screen will be redrawn by the caller, thus
7943 * msg_scroll being set by displaying a message is irrelevant. */ 7923 * msg_scroll being set by displaying a message is irrelevant. */
7944 msg_scroll = save_msg_scroll; 7924 msg_scroll = save_msg_scroll;
7925
7926 if (drop_callback != NULL)
7927 drop_callback(drop_cookie);
7928
7929 drop_filev = NULL;
7930 drop_busy = FALSE;
7931 }
7932
7933 /*
7934 * Handle a file drop. The code is here because a drop is *nearly* like an
7935 * :args command, but not quite (we have a list of exact filenames, so we
7936 * don't want to (a) parse a command line, or (b) expand wildcards. So the
7937 * code is very similar to :args and hence needs access to a lot of the static
7938 * functions in this file.
7939 *
7940 * The "filev" list must have been allocated using alloc(), as should each item
7941 * in the list. This function takes over responsibility for freeing the "filev"
7942 * list.
7943 */
7944 void
7945 handle_drop(
7946 int filec, // the number of files dropped
7947 char_u **filev, // the list of files dropped
7948 int split, // force splitting the window
7949 void (*callback)(void *), // to be called after setting the argument
7950 // list
7951 void *cookie) // argument for "callback" (allocated)
7952 {
7953 // Cannot handle recursive drops, finish the pending one.
7954 if (drop_busy)
7955 {
7956 FreeWild(filec, filev);
7957 vim_free(cookie);
7958 return;
7959 }
7960
7961 // When calling handle_drop() more than once in a row we only use the last
7962 // one.
7963 if (drop_filev != NULL)
7964 {
7965 FreeWild(drop_filec, drop_filev);
7966 vim_free(drop_cookie);
7967 }
7968
7969 drop_filec = filec;
7970 drop_filev = filev;
7971 drop_split = split;
7972 drop_callback = callback;
7973 drop_cookie = cookie;
7974
7975 // Postpone this when:
7976 // - editing the command line
7977 // - not possible to change the current buffer
7978 // - updating the screen
7979 // As it may change buffers and window structures that are in use and cause
7980 // freed memory to be used.
7981 if (text_locked() || curbuf_locked() || updating_screen)
7982 return;
7983
7984 handle_drop_internal();
7985 }
7986
7987 /*
7988 * To be called when text is unlocked, curbuf is unlocked or updating_screen is
7989 * reset: Handle a postponed drop.
7990 */
7991 void
7992 handle_any_postponed_drop(void)
7993 {
7994 if (!drop_busy && drop_filev != NULL
7995 && !text_locked() && !curbuf_locked() && !updating_screen)
7996 handle_drop_internal();
7945 } 7997 }
7946 #endif 7998 #endif
7947 7999
7948 /* 8000 /*
7949 * Clear an argument list: free all file names and reset it to zero entries. 8001 * Clear an argument list: free all file names and reset it to zero entries.