comparison src/buffer.c @ 3380:07fd030f89be v7.3.456

updated for version 7.3.456 Problem: ":tab drop file" has several problems, including moving the current window and opening a new tab for a file that already has a window. Solution: Refactor ":tab drop" handling. (Hirohito Higashi)
author Bram Moolenaar <bram@vim.org>
date Wed, 22 Feb 2012 19:13:08 +0100
parents 9ccdc4a69d8f
children e61c3b09ae86
comparison
equal deleted inserted replaced
3379:4a7a394e7afe 3380:07fd030f89be
4403 int forceit; /* hide buffers in current windows */ 4403 int forceit; /* hide buffers in current windows */
4404 int keep_tabs; /* keep current tabs, for ":tab drop file" */ 4404 int keep_tabs; /* keep current tabs, for ":tab drop file" */
4405 { 4405 {
4406 int i; 4406 int i;
4407 win_T *wp, *wpnext; 4407 win_T *wp, *wpnext;
4408 char_u *opened; /* array of flags for which args are open */ 4408 char_u *opened; /* Array of weight for which args are open:
4409 * 0: not opened
4410 * 1: opened in other tab
4411 * 2: opened in curtab
4412 * 3: opened in curtab and curwin
4413 */
4409 int opened_len; /* length of opened[] */ 4414 int opened_len; /* length of opened[] */
4410 int use_firstwin = FALSE; /* use first window for arglist */ 4415 int use_firstwin = FALSE; /* use first window for arglist */
4411 int split_ret = OK; 4416 int split_ret = OK;
4412 int p_ea_save; 4417 int p_ea_save;
4413 alist_T *alist; /* argument list to be used */ 4418 alist_T *alist; /* argument list to be used */
4414 buf_T *buf; 4419 buf_T *buf;
4415 tabpage_T *tpnext; 4420 tabpage_T *tpnext;
4416 int had_tab = cmdmod.tab; 4421 int had_tab = cmdmod.tab;
4422 win_T *old_curwin, *last_curwin;
4423 tabpage_T *old_curtab, *last_curtab;
4417 win_T *new_curwin = NULL; 4424 win_T *new_curwin = NULL;
4418 tabpage_T *new_curtab = NULL; 4425 tabpage_T *new_curtab = NULL;
4419 4426
4420 if (ARGCOUNT <= 0) 4427 if (ARGCOUNT <= 0)
4421 { 4428 {
4427 4434
4428 opened_len = ARGCOUNT; 4435 opened_len = ARGCOUNT;
4429 opened = alloc_clear((unsigned)opened_len); 4436 opened = alloc_clear((unsigned)opened_len);
4430 if (opened == NULL) 4437 if (opened == NULL)
4431 return; 4438 return;
4439
4440 /* Autocommands may do anything to the argument list. Make sure it's not
4441 * freed while we are working here by "locking" it. We still have to
4442 * watch out for its size to be changed. */
4443 alist = curwin->w_alist;
4444 ++alist->al_refcount;
4445
4446 old_curwin = curwin;
4447 old_curtab = curtab;
4432 4448
4433 #ifdef FEAT_GUI 4449 #ifdef FEAT_GUI
4434 need_mouse_correct = TRUE; 4450 need_mouse_correct = TRUE;
4435 #endif 4451 #endif
4436 4452
4449 for (wp = firstwin; wp != NULL; wp = wpnext) 4465 for (wp = firstwin; wp != NULL; wp = wpnext)
4450 { 4466 {
4451 wpnext = wp->w_next; 4467 wpnext = wp->w_next;
4452 buf = wp->w_buffer; 4468 buf = wp->w_buffer;
4453 if (buf->b_ffname == NULL 4469 if (buf->b_ffname == NULL
4454 || buf->b_nwindows > 1 4470 || (!keep_tabs && buf->b_nwindows > 1)
4455 #ifdef FEAT_VERTSPLIT 4471 #ifdef FEAT_VERTSPLIT
4456 || wp->w_width != Columns 4472 || wp->w_width != Columns
4457 #endif 4473 #endif
4458 ) 4474 )
4459 i = ARGCOUNT; 4475 i = opened_len;
4460 else 4476 else
4461 { 4477 {
4462 /* check if the buffer in this window is in the arglist */ 4478 /* check if the buffer in this window is in the arglist */
4463 for (i = 0; i < ARGCOUNT; ++i) 4479 for (i = 0; i < opened_len; ++i)
4464 { 4480 {
4465 if (ARGLIST[i].ae_fnum == buf->b_fnum 4481 if (i < alist->al_ga.ga_len
4466 || fullpathcmp(alist_name(&ARGLIST[i]), 4482 && (AARGLIST(alist)[i].ae_fnum == buf->b_fnum
4467 buf->b_ffname, TRUE) & FPC_SAME) 4483 || fullpathcmp(alist_name(&AARGLIST(alist)[i]),
4484 buf->b_ffname, TRUE) & FPC_SAME))
4468 { 4485 {
4469 if (i < opened_len) 4486 int weight = 1;
4487
4488 if (old_curtab == curtab)
4470 { 4489 {
4471 opened[i] = TRUE; 4490 ++weight;
4491 if (old_curwin == wp)
4492 ++weight;
4493 }
4494
4495 if (weight > (int)opened[i])
4496 {
4497 opened[i] = (char_u)weight;
4472 if (i == 0) 4498 if (i == 0)
4473 { 4499 {
4500 if (new_curwin != NULL)
4501 new_curwin->w_arg_idx = opened_len;
4474 new_curwin = wp; 4502 new_curwin = wp;
4475 new_curtab = curtab; 4503 new_curtab = curtab;
4476 } 4504 }
4477 } 4505 }
4478 if (wp->w_alist != curwin->w_alist) 4506 else if (keep_tabs)
4507 i = opened_len;
4508
4509 if (wp->w_alist != alist)
4479 { 4510 {
4480 /* Use the current argument list for all windows 4511 /* Use the current argument list for all windows
4481 * containing a file from it. */ 4512 * containing a file from it. */
4482 alist_unlink(wp->w_alist); 4513 alist_unlink(wp->w_alist);
4483 wp->w_alist = curwin->w_alist; 4514 wp->w_alist = alist;
4484 ++wp->w_alist->al_refcount; 4515 ++wp->w_alist->al_refcount;
4485 } 4516 }
4486 break; 4517 break;
4487 } 4518 }
4488 } 4519 }
4489 } 4520 }
4490 wp->w_arg_idx = i; 4521 wp->w_arg_idx = i;
4491 4522
4492 if (i == ARGCOUNT && !keep_tabs) /* close this window */ 4523 if (i == opened_len && !keep_tabs)/* close this window */
4493 { 4524 {
4494 if (P_HID(buf) || forceit || buf->b_nwindows > 1 4525 if (P_HID(buf) || forceit || buf->b_nwindows > 1
4495 || !bufIsChanged(buf)) 4526 || !bufIsChanged(buf))
4496 { 4527 {
4497 /* If the buffer was changed, and we would like to hide it, 4528 /* If the buffer was changed, and we would like to hide it,
4509 } 4540 }
4510 #endif 4541 #endif
4511 } 4542 }
4512 #ifdef FEAT_WINDOWS 4543 #ifdef FEAT_WINDOWS
4513 /* don't close last window */ 4544 /* don't close last window */
4514 if (firstwin == lastwin && first_tabpage->tp_next == NULL) 4545 if (firstwin == lastwin
4546 && (first_tabpage->tp_next == NULL || !had_tab))
4515 #endif 4547 #endif
4516 use_firstwin = TRUE; 4548 use_firstwin = TRUE;
4517 #ifdef FEAT_WINDOWS 4549 #ifdef FEAT_WINDOWS
4518 else 4550 else
4519 { 4551 {
4543 4575
4544 /* 4576 /*
4545 * Open a window for files in the argument list that don't have one. 4577 * Open a window for files in the argument list that don't have one.
4546 * ARGCOUNT may change while doing this, because of autocommands. 4578 * ARGCOUNT may change while doing this, because of autocommands.
4547 */ 4579 */
4548 if (count > ARGCOUNT || count <= 0) 4580 if (count > opened_len || count <= 0)
4549 count = ARGCOUNT; 4581 count = opened_len;
4550
4551 /* Autocommands may do anything to the argument list. Make sure it's not
4552 * freed while we are working here by "locking" it. We still have to
4553 * watch out for its size to be changed. */
4554 alist = curwin->w_alist;
4555 ++alist->al_refcount;
4556 4582
4557 #ifdef FEAT_AUTOCMD 4583 #ifdef FEAT_AUTOCMD
4558 /* Don't execute Win/Buf Enter/Leave autocommands here. */ 4584 /* Don't execute Win/Buf Enter/Leave autocommands here. */
4559 ++autocmd_no_enter; 4585 ++autocmd_no_enter;
4560 ++autocmd_no_leave; 4586 ++autocmd_no_leave;
4561 #endif 4587 #endif
4588 last_curwin = curwin;
4589 last_curtab = curtab;
4562 win_enter(lastwin, FALSE); 4590 win_enter(lastwin, FALSE);
4563 #ifdef FEAT_WINDOWS 4591 #ifdef FEAT_WINDOWS
4564 /* ":drop all" should re-use an empty window to avoid "--remote-tab" 4592 /* ":drop all" should re-use an empty window to avoid "--remote-tab"
4565 * leaving an empty tab page when executed locally. */ 4593 * leaving an empty tab page when executed locally. */
4566 if (keep_tabs && bufempty() && curbuf->b_nwindows == 1 4594 if (keep_tabs && bufempty() && curbuf->b_nwindows == 1
4567 && curbuf->b_ffname == NULL && !curbuf->b_changed) 4595 && curbuf->b_ffname == NULL && !curbuf->b_changed)
4568 use_firstwin = TRUE; 4596 use_firstwin = TRUE;
4569 #endif 4597 #endif
4570 4598
4571 for (i = 0; i < count && i < alist->al_ga.ga_len && !got_int; ++i) 4599 for (i = 0; i < count && i < opened_len && !got_int; ++i)
4572 { 4600 {
4573 if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1) 4601 if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1)
4574 arg_had_last = TRUE; 4602 arg_had_last = TRUE;
4575 if (i < opened_len && opened[i]) 4603 if (opened[i] > 0)
4576 { 4604 {
4577 /* Move the already present window to below the current window */ 4605 /* Move the already present window to below the current window */
4578 if (curwin->w_arg_idx != i) 4606 if (curwin->w_arg_idx != i)
4579 { 4607 {
4580 for (wpnext = firstwin; wpnext != NULL; wpnext = wpnext->w_next) 4608 for (wpnext = firstwin; wpnext != NULL; wpnext = wpnext->w_next)
4581 { 4609 {
4582 if (wpnext->w_arg_idx == i) 4610 if (wpnext->w_arg_idx == i)
4583 { 4611 {
4584 win_move_after(wpnext, curwin); 4612 if (keep_tabs)
4613 {
4614 new_curwin = wpnext;
4615 new_curtab = curtab;
4616 }
4617 else
4618 win_move_after(wpnext, curwin);
4585 break; 4619 break;
4586 } 4620 }
4587 } 4621 }
4588 } 4622 }
4589 } 4623 }
4634 alist_unlink(alist); 4668 alist_unlink(alist);
4635 4669
4636 #ifdef FEAT_AUTOCMD 4670 #ifdef FEAT_AUTOCMD
4637 --autocmd_no_enter; 4671 --autocmd_no_enter;
4638 #endif 4672 #endif
4673 /* restore last referenced tabpage's curwin */
4674 if (last_curtab != new_curtab)
4675 {
4676 if (valid_tabpage(last_curtab))
4677 goto_tabpage_tp(last_curtab);
4678 if (win_valid(last_curwin))
4679 win_enter(last_curwin, FALSE);
4680 }
4639 /* to window with first arg */ 4681 /* to window with first arg */
4640 if (valid_tabpage(new_curtab)) 4682 if (valid_tabpage(new_curtab))
4641 goto_tabpage_tp(new_curtab); 4683 goto_tabpage_tp(new_curtab);
4642 if (win_valid(new_curwin)) 4684 if (win_valid(new_curwin))
4643 win_enter(new_curwin, FALSE); 4685 win_enter(new_curwin, FALSE);