Mercurial > vim
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. |