Mercurial > vim
comparison src/quickfix.c @ 3490:8101253704f6 v7.3.509
updated for version 7.3.509
Problem: ":vimgrep" fails when 'autochdir' is set.
Solution: A more generic solution for changing directory. (Ben Fritz)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Wed, 25 Apr 2012 18:57:21 +0200 |
parents | 38a135730423 |
children | bbf1fbbe4ab4 |
comparison
equal
deleted
inserted
replaced
3489:f53d1d03019a | 3490:8101253704f6 |
---|---|
128 static void qf_update_buffer __ARGS((qf_info_T *qi)); | 128 static void qf_update_buffer __ARGS((qf_info_T *qi)); |
129 static void qf_set_title __ARGS((qf_info_T *qi)); | 129 static void qf_set_title __ARGS((qf_info_T *qi)); |
130 static void qf_fill_buffer __ARGS((qf_info_T *qi)); | 130 static void qf_fill_buffer __ARGS((qf_info_T *qi)); |
131 #endif | 131 #endif |
132 static char_u *get_mef_name __ARGS((void)); | 132 static char_u *get_mef_name __ARGS((void)); |
133 static buf_T *load_dummy_buffer __ARGS((char_u *fname)); | 133 static void restore_start_dir __ARGS((char_u *dirname_start)); |
134 static void wipe_dummy_buffer __ARGS((buf_T *buf)); | 134 static buf_T *load_dummy_buffer __ARGS((char_u *fname, char_u *dirname_start, char_u *resulting_dir)); |
135 static void unload_dummy_buffer __ARGS((buf_T *buf)); | 135 static void wipe_dummy_buffer __ARGS((buf_T *buf, char_u *dirname_start)); |
136 static void unload_dummy_buffer __ARGS((buf_T *buf, char_u *dirname_start)); | |
136 static qf_info_T *ll_get_or_alloc_list __ARGS((win_T *)); | 137 static qf_info_T *ll_get_or_alloc_list __ARGS((win_T *)); |
137 | 138 |
138 /* Quickfix window check helper macro */ | 139 /* Quickfix window check helper macro */ |
139 #define IS_QF_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref == NULL) | 140 #define IS_QF_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref == NULL) |
140 /* Location list window check helper macro */ | 141 /* Location list window check helper macro */ |
3235 save_mls = p_mls; | 3236 save_mls = p_mls; |
3236 p_mls = 0; | 3237 p_mls = 0; |
3237 | 3238 |
3238 /* Load file into a buffer, so that 'fileencoding' is detected, | 3239 /* Load file into a buffer, so that 'fileencoding' is detected, |
3239 * autocommands applied, etc. */ | 3240 * autocommands applied, etc. */ |
3240 buf = load_dummy_buffer(fname); | 3241 buf = load_dummy_buffer(fname, dirname_start, dirname_now); |
3241 | |
3242 /* When autocommands changed directory: go back. We assume it was | |
3243 * ":lcd %:p:h". */ | |
3244 mch_dirname(dirname_now, MAXPATHL); | |
3245 if (STRCMP(dirname_start, dirname_now) != 0) | |
3246 { | |
3247 exarg_T ea; | |
3248 | |
3249 ea.arg = dirname_start; | |
3250 ea.cmdidx = CMD_lcd; | |
3251 ex_cd(&ea); | |
3252 } | |
3253 | 3242 |
3254 p_mls = save_mls; | 3243 p_mls = save_mls; |
3255 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) | 3244 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) |
3256 au_event_restore(save_ei); | 3245 au_event_restore(save_ei); |
3257 #endif | 3246 #endif |
3318 first_match_buf = buf; | 3307 first_match_buf = buf; |
3319 if (duplicate_name) | 3308 if (duplicate_name) |
3320 { | 3309 { |
3321 /* Never keep a dummy buffer if there is another buffer | 3310 /* Never keep a dummy buffer if there is another buffer |
3322 * with the same name. */ | 3311 * with the same name. */ |
3323 wipe_dummy_buffer(buf); | 3312 wipe_dummy_buffer(buf, dirname_start); |
3324 buf = NULL; | 3313 buf = NULL; |
3325 } | 3314 } |
3326 else if (!cmdmod.hide | 3315 else if (!cmdmod.hide |
3327 || buf->b_p_bh[0] == 'u' /* "unload" */ | 3316 || buf->b_p_bh[0] == 'u' /* "unload" */ |
3328 || buf->b_p_bh[0] == 'w' /* "wipe" */ | 3317 || buf->b_p_bh[0] == 'w' /* "wipe" */ |
3334 * unload the buffer. | 3323 * unload the buffer. |
3335 * Ignore 'hidden' here, because it may lead to having too | 3324 * Ignore 'hidden' here, because it may lead to having too |
3336 * many swap files. */ | 3325 * many swap files. */ |
3337 if (!found_match) | 3326 if (!found_match) |
3338 { | 3327 { |
3339 wipe_dummy_buffer(buf); | 3328 wipe_dummy_buffer(buf, dirname_start); |
3340 buf = NULL; | 3329 buf = NULL; |
3341 } | 3330 } |
3342 else if (buf != first_match_buf || (flags & VGR_NOJUMP)) | 3331 else if (buf != first_match_buf || (flags & VGR_NOJUMP)) |
3343 { | 3332 { |
3344 unload_dummy_buffer(buf); | 3333 unload_dummy_buffer(buf, dirname_start); |
3345 buf = NULL; | 3334 buf = NULL; |
3346 } | 3335 } |
3347 } | 3336 } |
3348 | 3337 |
3349 if (buf != NULL) | 3338 if (buf != NULL) |
3485 } | 3474 } |
3486 return p; | 3475 return p; |
3487 } | 3476 } |
3488 | 3477 |
3489 /* | 3478 /* |
3490 * Load file "fname" into a dummy buffer and return the buffer pointer. | 3479 * Restore current working directory to "dirname_start" if they differ, taking |
3480 * into account whether it is set locally or globally. | |
3481 */ | |
3482 static void | |
3483 restore_start_dir(dirname_start) | |
3484 char_u *dirname_start; | |
3485 { | |
3486 char_u *dirname_now = alloc(MAXPATHL); | |
3487 | |
3488 if (NULL != dirname_now) | |
3489 { | |
3490 mch_dirname(dirname_now, MAXPATHL); | |
3491 if (STRCMP(dirname_start, dirname_now) != 0) | |
3492 { | |
3493 /* If the directory has changed, change it back by building up an | |
3494 * appropriate ex command and executing it. */ | |
3495 exarg_T ea; | |
3496 | |
3497 ea.arg = dirname_start; | |
3498 ea.cmdidx = (curwin->w_localdir == NULL) ? CMD_cd : CMD_lcd; | |
3499 ex_cd(&ea); | |
3500 } | |
3501 } | |
3502 } | |
3503 | |
3504 /* | |
3505 * Load file "fname" into a dummy buffer and return the buffer pointer, | |
3506 * placing the directory resulting from the buffer load into the | |
3507 * "resulting_dir" pointer. "resulting_dir" must be allocated by the caller | |
3508 * prior to calling this function. Restores directory to "dirname_start" prior | |
3509 * to returning, if autocmds or the 'autochdir' option have changed it. | |
3510 * | |
3511 * If creating the dummy buffer does not fail, must call unload_dummy_buffer() | |
3512 * or wipe_dummy_buffer() later! | |
3513 * | |
3491 * Returns NULL if it fails. | 3514 * Returns NULL if it fails. |
3492 * Must call unload_dummy_buffer() or wipe_dummy_buffer() later! | |
3493 */ | 3515 */ |
3494 static buf_T * | 3516 static buf_T * |
3495 load_dummy_buffer(fname) | 3517 load_dummy_buffer(fname, dirname_start, resulting_dir) |
3496 char_u *fname; | 3518 char_u *fname; |
3519 char_u *dirname_start; /* in: old directory */ | |
3520 char_u *resulting_dir; /* out: new directory */ | |
3497 { | 3521 { |
3498 buf_T *newbuf; | 3522 buf_T *newbuf; |
3499 buf_T *newbuf_to_wipe = NULL; | 3523 buf_T *newbuf_to_wipe = NULL; |
3500 int failed = TRUE; | 3524 int failed = TRUE; |
3501 aco_save_T aco; | 3525 aco_save_T aco; |
3546 aucmd_restbuf(&aco); | 3570 aucmd_restbuf(&aco); |
3547 if (newbuf_to_wipe != NULL && buf_valid(newbuf_to_wipe)) | 3571 if (newbuf_to_wipe != NULL && buf_valid(newbuf_to_wipe)) |
3548 wipe_buffer(newbuf_to_wipe, FALSE); | 3572 wipe_buffer(newbuf_to_wipe, FALSE); |
3549 } | 3573 } |
3550 | 3574 |
3575 /* | |
3576 * When autocommands/'autochdir' option changed directory: go back. | |
3577 * Let the caller know what the resulting dir was first, in case it is | |
3578 * important. | |
3579 */ | |
3580 mch_dirname(resulting_dir, MAXPATHL); | |
3581 restore_start_dir(dirname_start); | |
3582 | |
3551 if (!buf_valid(newbuf)) | 3583 if (!buf_valid(newbuf)) |
3552 return NULL; | 3584 return NULL; |
3553 if (failed) | 3585 if (failed) |
3554 { | 3586 { |
3555 wipe_dummy_buffer(newbuf); | 3587 wipe_dummy_buffer(newbuf, dirname_start); |
3556 return NULL; | 3588 return NULL; |
3557 } | 3589 } |
3558 return newbuf; | 3590 return newbuf; |
3559 } | 3591 } |
3560 | 3592 |
3561 /* | 3593 /* |
3562 * Wipe out the dummy buffer that load_dummy_buffer() created. | 3594 * Wipe out the dummy buffer that load_dummy_buffer() created. Restores |
3595 * directory to "dirname_start" prior to returning, if autocmds or the | |
3596 * 'autochdir' option have changed it. | |
3563 */ | 3597 */ |
3564 static void | 3598 static void |
3565 wipe_dummy_buffer(buf) | 3599 wipe_dummy_buffer(buf, dirname_start) |
3566 buf_T *buf; | 3600 buf_T *buf; |
3601 char_u *dirname_start; | |
3567 { | 3602 { |
3568 if (curbuf != buf) /* safety check */ | 3603 if (curbuf != buf) /* safety check */ |
3569 { | 3604 { |
3570 #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) | 3605 #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) |
3571 cleanup_T cs; | 3606 cleanup_T cs; |
3581 #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) | 3616 #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) |
3582 /* Restore the error/interrupt/exception state if not discarded by a | 3617 /* Restore the error/interrupt/exception state if not discarded by a |
3583 * new aborting error, interrupt, or uncaught exception. */ | 3618 * new aborting error, interrupt, or uncaught exception. */ |
3584 leave_cleanup(&cs); | 3619 leave_cleanup(&cs); |
3585 #endif | 3620 #endif |
3586 } | 3621 /* When autocommands/'autochdir' option changed directory: go back. */ |
3587 } | 3622 restore_start_dir(dirname_start); |
3588 | 3623 } |
3589 /* | 3624 } |
3590 * Unload the dummy buffer that load_dummy_buffer() created. | 3625 |
3626 /* | |
3627 * Unload the dummy buffer that load_dummy_buffer() created. Restores | |
3628 * directory to "dirname_start" prior to returning, if autocmds or the | |
3629 * 'autochdir' option have changed it. | |
3591 */ | 3630 */ |
3592 static void | 3631 static void |
3593 unload_dummy_buffer(buf) | 3632 unload_dummy_buffer(buf, dirname_start) |
3594 buf_T *buf; | 3633 buf_T *buf; |
3634 char_u *dirname_start; | |
3595 { | 3635 { |
3596 if (curbuf != buf) /* safety check */ | 3636 if (curbuf != buf) /* safety check */ |
3637 { | |
3597 close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE); | 3638 close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE); |
3639 | |
3640 /* When autocommands/'autochdir' option changed directory: go back. */ | |
3641 restore_start_dir(dirname_start); | |
3642 } | |
3598 } | 3643 } |
3599 | 3644 |
3600 #if defined(FEAT_EVAL) || defined(PROTO) | 3645 #if defined(FEAT_EVAL) || defined(PROTO) |
3601 /* | 3646 /* |
3602 * Add each quickfix error to list "list" as a dictionary. | 3647 * Add each quickfix error to list "list" as a dictionary. |