@@ -7513,17 +7513,17 @@ free_cd_dir(void)
75137513
75147514/*
75157515 * Deal with the side effects of changing the current directory.
7516- * When "tablocal" is TRUE then this was after an ":tcd" command.
7517- * When "winlocal" is TRUE then this was after an ":lcd" command.
7516+ * When 'scope' is CDSCOPE_TABPAGE then this was after an ":tcd" command.
7517+ * When 'scope' is CDSCOPE_WINDOW then this was after an ":lcd" command.
75187518 */
75197519 void
7520- post_chdir (int tablocal , int winlocal )
7520+ post_chdir (cdscope_T scope )
75217521{
7522- if (! winlocal )
7522+ if (scope != CDSCOPE_WINDOW )
75237523 // Clear tab local directory for both :cd and :tcd
75247524 VIM_CLEAR (curtab -> tp_localdir );
75257525 VIM_CLEAR (curwin -> w_localdir );
7526- if (winlocal || tablocal )
7526+ if (scope != CDSCOPE_GLOBAL )
75277527 {
75287528 /* If still in global directory, need to remember current
75297529 * directory as global directory. */
@@ -7532,7 +7532,7 @@ post_chdir(int tablocal, int winlocal)
75327532 /* Remember this local directory for the window. */
75337533 if (mch_dirname (NameBuff , MAXPATHL ) == OK )
75347534 {
7535- if (tablocal )
7535+ if (scope == CDSCOPE_TABPAGE )
75367536 curtab -> tp_localdir = vim_strsave (NameBuff );
75377537 else
75387538 curwin -> w_localdir = vim_strsave (NameBuff );
@@ -7548,102 +7548,126 @@ post_chdir(int tablocal, int winlocal)
75487548 shorten_fnames (TRUE);
75497549}
75507550
7551-
75527551/*
7553- * ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir".
7552+ * Change directory function used by :cd/:tcd/:lcd Ex commands and the
7553+ * chdir() function. If 'winlocaldir' is TRUE, then changes the window-local
7554+ * directory. If 'tablocaldir' is TRUE, then changes the tab-local directory.
7555+ * Otherwise changes the global directory.
7556+ * Returns TRUE if the directory is successfully changed.
75547557 */
7555- void
7556- ex_cd (exarg_T * eap )
7558+ int
7559+ changedir_func (
7560+ char_u * new_dir ,
7561+ int forceit ,
7562+ cdscope_T scope )
75577563{
7558- char_u * new_dir ;
75597564 char_u * tofree ;
75607565 int dir_differs ;
7566+ int retval = FALSE;
75617567
7562- new_dir = eap -> arg ;
7563- #if !defined(UNIX ) && !defined(VMS )
7564- /* for non-UNIX ":cd" means: print current directory */
7565- if (* new_dir == NUL )
7566- ex_pwd (NULL );
7567- else
7568- #endif
7568+ if (allbuf_locked ())
7569+ return FALSE;
7570+
7571+ if (vim_strchr (p_cpo , CPO_CHDIR ) != NULL && curbufIsChanged () && !forceit )
75697572 {
7570- if (allbuf_locked ())
7571- return ;
7572- if (vim_strchr (p_cpo , CPO_CHDIR ) != NULL && curbufIsChanged ()
7573- && !eap -> forceit )
7574- {
7575- emsg (_ ("E747: Cannot change directory, buffer is modified (add ! to override)" ));
7576- return ;
7577- }
7573+ emsg (_ ("E747: Cannot change directory, buffer is modified (add ! to override)" ));
7574+ return FALSE;
7575+ }
75787576
7579- /* ":cd -": Change to previous directory */
7580- if (STRCMP (new_dir , "-" ) == 0 )
7577+ // ":cd -": Change to previous directory
7578+ if (STRCMP (new_dir , "-" ) == 0 )
7579+ {
7580+ if (prev_dir == NULL )
75817581 {
7582- if (prev_dir == NULL )
7583- {
7584- emsg (_ ("E186: No previous directory" ));
7585- return ;
7586- }
7587- new_dir = prev_dir ;
7582+ emsg (_ ("E186: No previous directory" ));
7583+ return FALSE;
75887584 }
7585+ new_dir = prev_dir ;
7586+ }
75897587
7590- /* Save current directory for next ":cd -" */
7591- tofree = prev_dir ;
7592- if (mch_dirname (NameBuff , MAXPATHL ) == OK )
7593- prev_dir = vim_strsave (NameBuff );
7594- else
7595- prev_dir = NULL ;
7588+ // Save current directory for next ":cd -"
7589+ tofree = prev_dir ;
7590+ if (mch_dirname (NameBuff , MAXPATHL ) == OK )
7591+ prev_dir = vim_strsave (NameBuff );
7592+ else
7593+ prev_dir = NULL ;
75967594
75977595#if defined(UNIX ) || defined(VMS )
7598- /* for UNIX ":cd" means: go to home directory */
7599- if (* new_dir == NUL )
7600- {
7601- /* use NameBuff for home directory name */
7596+ // for UNIX ":cd" means: go to home directory
7597+ if (* new_dir == NUL )
7598+ {
7599+ // use NameBuff for home directory name
76027600# ifdef VMS
7603- char_u * p ;
7601+ char_u * p ;
76047602
7605- p = mch_getenv ((char_u * )"SYS$LOGIN" );
7606- if (p == NULL || * p == NUL ) /* empty is the same as not set */
7607- NameBuff [0 ] = NUL ;
7608- else
7609- vim_strncpy (NameBuff , p , MAXPATHL - 1 );
7603+ p = mch_getenv ((char_u * )"SYS$LOGIN" );
7604+ if (p == NULL || * p == NUL ) // empty is the same as not set
7605+ NameBuff [0 ] = NUL ;
7606+ else
7607+ vim_strncpy (NameBuff , p , MAXPATHL - 1 );
76107608# else
7611- expand_env ((char_u * )"$HOME" , NameBuff , MAXPATHL );
7609+ expand_env ((char_u * )"$HOME" , NameBuff , MAXPATHL );
76127610# endif
7613- new_dir = NameBuff ;
7614- }
7611+ new_dir = NameBuff ;
7612+ }
76157613#endif
7616- dir_differs = new_dir == NULL || prev_dir == NULL
7617- || pathcmp ((char * )prev_dir , (char * )new_dir , -1 ) != 0 ;
7618- if (new_dir == NULL || (dir_differs && vim_chdir (new_dir )))
7619- emsg (_ (e_failed ));
7620- else
7614+ dir_differs = new_dir == NULL || prev_dir == NULL
7615+ || pathcmp ((char * )prev_dir , (char * )new_dir , -1 ) != 0 ;
7616+ if (new_dir == NULL || (dir_differs && vim_chdir (new_dir )))
7617+ emsg (_ (e_failed ));
7618+ else
7619+ {
7620+ char_u * acmd_fname ;
7621+
7622+ post_chdir (scope );
7623+
7624+ if (dir_differs )
76217625 {
7622- char_u * acmd_fname ;
7623- int is_winlocal_chdir = eap -> cmdidx == CMD_lcd
7624- || eap -> cmdidx == CMD_lchdir ;
7625- int is_tablocal_chdir = eap -> cmdidx == CMD_tcd
7626- || eap -> cmdidx == CMD_tchdir ;
7626+ if (scope == CDSCOPE_WINDOW )
7627+ acmd_fname = (char_u * )"window" ;
7628+ else if (scope == CDSCOPE_TABPAGE )
7629+ acmd_fname = (char_u * )"tabpage" ;
7630+ else
7631+ acmd_fname = (char_u * )"global" ;
7632+ apply_autocmds (EVENT_DIRCHANGED , acmd_fname , new_dir , FALSE,
7633+ curbuf );
7634+ }
7635+ retval = TRUE;
7636+ }
7637+ vim_free (tofree );
7638+
7639+ return retval ;
7640+ }
7641+
7642+ /*
7643+ * ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir".
7644+ */
7645+ void
7646+ ex_cd (exarg_T * eap )
7647+ {
7648+ char_u * new_dir ;
76277649
7628- post_chdir (is_tablocal_chdir , is_winlocal_chdir );
7650+ new_dir = eap -> arg ;
7651+ #if !defined(UNIX ) && !defined(VMS )
7652+ // for non-UNIX ":cd" means: print current directory
7653+ if (* new_dir == NUL )
7654+ ex_pwd (NULL );
7655+ else
7656+ #endif
7657+ {
7658+ cdscope_T scope = CDSCOPE_GLOBAL ;
76297659
7630- /* Echo the new current directory if the command was typed. */
7660+ if (eap -> cmdidx == CMD_lcd || eap -> cmdidx == CMD_lchdir )
7661+ scope = CDSCOPE_WINDOW ;
7662+ else if (eap -> cmdidx == CMD_tcd || eap -> cmdidx == CMD_tchdir )
7663+ scope = CDSCOPE_TABPAGE ;
7664+
7665+ if (changedir_func (new_dir , eap -> forceit , scope ))
7666+ {
7667+ // Echo the new current directory if the command was typed.
76317668 if (KeyTyped || p_verbose >= 5 )
76327669 ex_pwd (eap );
7633-
7634- if (dir_differs )
7635- {
7636- if (is_winlocal_chdir )
7637- acmd_fname = (char_u * )"window" ;
7638- else if (is_tablocal_chdir )
7639- acmd_fname = (char_u * )"tabpage" ;
7640- else
7641- acmd_fname = (char_u * )"global" ;
7642- apply_autocmds (EVENT_DIRCHANGED , acmd_fname ,
7643- new_dir , FALSE, curbuf );
7644- }
76457670 }
7646- vim_free (tofree );
76477671 }
76487672}
76497673
0 commit comments