Mercurial > vim
comparison src/quickfix.c @ 15770:77e97f159554 v8.1.0892
patch 8.1.0892: failure when closing a window when location list is in use
commit https://github.com/vim/vim/commit/eeb1b9c7ed33c152e041a286d79bf3ed00d80e40
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Feb 10 22:59:04 2019 +0100
patch 8.1.0892: failure when closing a window when location list is in use
Problem: Failure when closing a window when location list is in use.
Solution: Handle the situation gracefully. Make sure memory for 'switchbuf'
is not freed at the wrong time. (Yegappan Lakshmanan,
closes #3928)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 10 Feb 2019 23:00:05 +0100 |
parents | 2fe4a503c5ad |
children | f376cd250b07 |
comparison
equal
deleted
inserted
replaced
15769:86912a1ebf3d | 15770:77e97f159554 |
---|---|
1897 qi = *pqi; | 1897 qi = *pqi; |
1898 if (qi == NULL) | 1898 if (qi == NULL) |
1899 return; | 1899 return; |
1900 *pqi = NULL; // Remove reference to this list | 1900 *pqi = NULL; // Remove reference to this list |
1901 | 1901 |
1902 // If the location list is still in use, then queue the delete request | |
1903 // to be processed later. | |
1904 if (quickfix_busy > 0) | |
1905 { | |
1906 locstack_queue_delreq(qi); | |
1907 return; | |
1908 } | |
1909 | |
1902 qi->qf_refcount--; | 1910 qi->qf_refcount--; |
1903 if (qi->qf_refcount < 1) | 1911 if (qi->qf_refcount < 1) |
1904 { | 1912 { |
1905 // No references to this location list. | 1913 // No references to this location list. |
1906 // If the location list is still in use, then queue the delete request | 1914 // If the quickfix window buffer is loaded, then wipe it |
1907 // to be processed later. | 1915 wipe_qf_buffer(qi); |
1908 if (quickfix_busy > 0) | 1916 |
1909 locstack_queue_delreq(qi); | 1917 for (i = 0; i < qi->qf_listcount; ++i) |
1910 else | 1918 qf_free(&qi->qf_lists[i]); |
1911 { | 1919 vim_free(qi); |
1912 // If the quickfix window buffer is loaded, then wipe it | |
1913 wipe_qf_buffer(qi); | |
1914 | |
1915 for (i = 0; i < qi->qf_listcount; ++i) | |
1916 qf_free(&qi->qf_lists[i]); | |
1917 vim_free(qi); | |
1918 } | |
1919 } | 1920 } |
1920 } | 1921 } |
1921 | 1922 |
1922 /* | 1923 /* |
1923 * Free all the quickfix/location lists in the stack. | 1924 * Free all the quickfix/location lists in the stack. |
3016 static int | 3017 static int |
3017 qf_jump_edit_buffer( | 3018 qf_jump_edit_buffer( |
3018 qf_info_T *qi, | 3019 qf_info_T *qi, |
3019 qfline_T *qf_ptr, | 3020 qfline_T *qf_ptr, |
3020 int forceit, | 3021 int forceit, |
3021 win_T *oldwin, | 3022 int prev_winid, |
3022 int *opened_window) | 3023 int *opened_window) |
3023 { | 3024 { |
3024 qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist]; | 3025 qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist]; |
3025 qfltype_T qfl_type = qfl->qfl_type; | 3026 qfltype_T qfl_type = qfl->qfl_type; |
3026 int retval = OK; | 3027 int retval = OK; |
3037 return FAIL; | 3038 return FAIL; |
3038 } | 3039 } |
3039 | 3040 |
3040 retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1, | 3041 retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1, |
3041 ECMD_HIDE + ECMD_SET_HELP, | 3042 ECMD_HIDE + ECMD_SET_HELP, |
3042 oldwin == curwin ? curwin : NULL); | 3043 prev_winid == curwin->w_id ? curwin : NULL); |
3043 } | 3044 } |
3044 else | 3045 else |
3045 retval = buflist_getfile(qf_ptr->qf_fnum, | 3046 retval = buflist_getfile(qf_ptr->qf_fnum, |
3046 (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); | 3047 (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); |
3047 | 3048 |
3048 // If a location list, check whether the associated window is still | 3049 // If a location list, check whether the associated window is still |
3049 // present. | 3050 // present. |
3050 if (qfl_type == QFLT_LOCATION && !win_valid_any_tab(oldwin)) | 3051 if (qfl_type == QFLT_LOCATION) |
3051 { | 3052 { |
3052 emsg(_("E924: Current window was closed")); | 3053 win_T *wp = win_id2wp(prev_winid); |
3053 *opened_window = FALSE; | 3054 if (wp == NULL && curwin->w_llist != qi) |
3054 return NOTDONE; | 3055 { |
3056 emsg(_("E924: Current window was closed")); | |
3057 *opened_window = FALSE; | |
3058 return NOTDONE; | |
3059 } | |
3055 } | 3060 } |
3056 | 3061 |
3057 if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid)) | 3062 if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid)) |
3058 { | 3063 { |
3059 emsg(_("E925: Current quickfix was changed")); | 3064 emsg(_("E925: Current quickfix was changed")); |
3209 qf_jump_to_buffer( | 3214 qf_jump_to_buffer( |
3210 qf_info_T *qi, | 3215 qf_info_T *qi, |
3211 int qf_index, | 3216 int qf_index, |
3212 qfline_T *qf_ptr, | 3217 qfline_T *qf_ptr, |
3213 int forceit, | 3218 int forceit, |
3214 win_T *oldwin, | 3219 int prev_winid, |
3215 int *opened_window, | 3220 int *opened_window, |
3216 int openfold, | 3221 int openfold, |
3217 int print_message) | 3222 int print_message) |
3218 { | 3223 { |
3219 buf_T *old_curbuf; | 3224 buf_T *old_curbuf; |
3225 old_curbuf = curbuf; | 3230 old_curbuf = curbuf; |
3226 old_lnum = curwin->w_cursor.lnum; | 3231 old_lnum = curwin->w_cursor.lnum; |
3227 | 3232 |
3228 if (qf_ptr->qf_fnum != 0) | 3233 if (qf_ptr->qf_fnum != 0) |
3229 { | 3234 { |
3230 retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin, | 3235 retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, prev_winid, |
3231 opened_window); | 3236 opened_window); |
3232 if (retval != OK) | 3237 if (retval != OK) |
3233 return retval; | 3238 return retval; |
3234 } | 3239 } |
3235 | 3240 |
3285 qfline_T *old_qf_ptr; | 3290 qfline_T *old_qf_ptr; |
3286 int qf_index; | 3291 int qf_index; |
3287 int old_qf_index; | 3292 int old_qf_index; |
3288 char_u *old_swb = p_swb; | 3293 char_u *old_swb = p_swb; |
3289 unsigned old_swb_flags = swb_flags; | 3294 unsigned old_swb_flags = swb_flags; |
3295 int prev_winid; | |
3290 int opened_window = FALSE; | 3296 int opened_window = FALSE; |
3291 win_T *oldwin = curwin; | |
3292 int print_message = TRUE; | 3297 int print_message = TRUE; |
3293 #ifdef FEAT_FOLDING | 3298 #ifdef FEAT_FOLDING |
3294 int old_KeyTyped = KeyTyped; // getting file may reset it | 3299 int old_KeyTyped = KeyTyped; // getting file may reset it |
3295 #endif | 3300 #endif |
3296 int retval = OK; | 3301 int retval = OK; |
3302 { | 3307 { |
3303 emsg(_(e_quickfix)); | 3308 emsg(_(e_quickfix)); |
3304 return; | 3309 return; |
3305 } | 3310 } |
3306 | 3311 |
3312 incr_quickfix_busy(); | |
3313 | |
3307 qfl = &qi->qf_lists[qi->qf_curlist]; | 3314 qfl = &qi->qf_lists[qi->qf_curlist]; |
3308 | 3315 |
3309 qf_ptr = qfl->qf_ptr; | 3316 qf_ptr = qfl->qf_ptr; |
3310 old_qf_ptr = qf_ptr; | 3317 old_qf_ptr = qf_ptr; |
3311 qf_index = qfl->qf_index; | 3318 qf_index = qfl->qf_index; |
3323 if (qf_win_pos_update(qi, old_qf_index)) | 3330 if (qf_win_pos_update(qi, old_qf_index)) |
3324 // No need to print the error message if it's visible in the error | 3331 // No need to print the error message if it's visible in the error |
3325 // window | 3332 // window |
3326 print_message = FALSE; | 3333 print_message = FALSE; |
3327 | 3334 |
3335 prev_winid = curwin->w_id; | |
3336 | |
3328 retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window); | 3337 retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window); |
3329 if (retval == FAIL) | 3338 if (retval == FAIL) |
3330 goto failed; | 3339 goto failed; |
3331 if (retval == NOTDONE) | 3340 if (retval == NOTDONE) |
3332 goto theend; | 3341 goto theend; |
3333 | 3342 |
3334 retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, oldwin, | 3343 retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, prev_winid, |
3335 &opened_window, old_KeyTyped, print_message); | 3344 &opened_window, old_KeyTyped, print_message); |
3336 if (retval == NOTDONE) | 3345 if (retval == NOTDONE) |
3337 { | 3346 { |
3338 // Quickfix/location list is freed by an autocmd | 3347 // Quickfix/location list is freed by an autocmd |
3339 qi = NULL; | 3348 qi = NULL; |
3357 if (qi != NULL) | 3366 if (qi != NULL) |
3358 { | 3367 { |
3359 qfl->qf_ptr = qf_ptr; | 3368 qfl->qf_ptr = qf_ptr; |
3360 qfl->qf_index = qf_index; | 3369 qfl->qf_index = qf_index; |
3361 } | 3370 } |
3362 if (p_swb != old_swb && opened_window) | 3371 if (p_swb != old_swb) |
3363 { | 3372 { |
3364 // Restore old 'switchbuf' value, but not when an autocommand or | 3373 // Restore old 'switchbuf' value, but not when an autocommand or |
3365 // modeline has changed the value. | 3374 // modeline has changed the value. |
3366 if (p_swb == empty_option) | 3375 if (p_swb == empty_option) |
3367 { | 3376 { |
3369 swb_flags = old_swb_flags; | 3378 swb_flags = old_swb_flags; |
3370 } | 3379 } |
3371 else | 3380 else |
3372 free_string_option(old_swb); | 3381 free_string_option(old_swb); |
3373 } | 3382 } |
3383 decr_quickfix_busy(); | |
3374 } | 3384 } |
3375 | 3385 |
3376 // Highlight attributes used for displaying entries from the quickfix list. | 3386 // Highlight attributes used for displaying entries from the quickfix list. |
3377 static int qfFileAttr; | 3387 static int qfFileAttr; |
3378 static int qfSepAttr; | 3388 static int qfSepAttr; |
4002 RESET_BINDING(curwin); | 4012 RESET_BINDING(curwin); |
4003 | 4013 |
4004 if (IS_LL_STACK(qi)) | 4014 if (IS_LL_STACK(qi)) |
4005 { | 4015 { |
4006 // For the location list window, create a reference to the | 4016 // For the location list window, create a reference to the |
4007 // location list from the window 'win'. | 4017 // location list stack from the window 'win'. |
4008 curwin->w_llist_ref = win->w_llist; | 4018 curwin->w_llist_ref = qi; |
4009 win->w_llist->qf_refcount++; | 4019 qi->qf_refcount++; |
4010 } | 4020 } |
4011 | 4021 |
4012 if (oldwin != curwin) | 4022 if (oldwin != curwin) |
4013 oldwin = NULL; // don't store info when in another window | 4023 oldwin = NULL; // don't store info when in another window |
4014 if (qf_buf != NULL) | 4024 if (qf_buf != NULL) |