diff --git a/src/terminal/tab.c b/src/terminal/tab.c index e914b5d2..709bd5db 100644 --- a/src/terminal/tab.c +++ b/src/terminal/tab.c @@ -103,6 +103,12 @@ get_tab_by_number(struct terminal *term, int num) num--; } + /* Ensure that the return value actually points to a struct + * window. */ + assertm((struct list_head *) win != &term->windows, + "tab number out of range"); + if_assert_failed return term->windows.next; + return win; } @@ -301,22 +307,27 @@ move_current_tab(struct session *ses, int direction) new_pos = term->current_tab + direction; - while (new_pos < 1 || new_pos > tabs) - new_pos += new_pos < 1 ? tabs : -tabs; - - assert(0 < new_pos && new_pos <= tabs); + if (get_opt_bool("ui.tabs.wraparound")) { + while (new_pos < 0 || new_pos >= tabs) + new_pos += new_pos < 0 ? tabs : -tabs; + } else { + if (new_pos < 0) + new_pos = 0; + else if (new_pos >= tabs) + new_pos = tabs - 1; + } + assert(0 <= new_pos && new_pos < tabs); + /* This protects against tabs==1 and optimizes an unusual case. */ if (new_pos == term->current_tab) return; - tab = get_tab_by_number(term, new_pos); - del_from_list(current_tab); - - if (new_pos < term->current_tab) { - add_at_pos(tab, current_tab); + if (new_pos == 0) { + tab = get_tab_by_number(term, 0); } else { - add_to_list_end(*tab, current_tab); + tab = get_tab_by_number(term, new_pos-1)->prev; } + add_at_pos(tab, current_tab); switch_to_tab(term, new_pos, tabs); } diff --git a/src/terminal/terminal.h b/src/terminal/terminal.h index 32d148f4..d6a46d3d 100644 --- a/src/terminal/terminal.h +++ b/src/terminal/terminal.h @@ -73,9 +73,9 @@ struct terminal { * current window; and .prev is the bottom, covered by others. * - Dialogs or active menus are at the top. * - Next come all tabs (window.type == WINDOW_TAB). The tab - * created last is at the top, and the tab created first is - * at the bottom; but current_tab controls which tab is - * actually displayed. + * listed leftmost in the tab bar is at the top, and the tab + * listed rightmost is at the bottom; but current_tab controls + * which tab is actually displayed. * - If the main menu is inactive, then it is at the very bottom, * hidden under the tabs. * Call assert_window_stacking to verify this. diff --git a/src/terminal/window.c b/src/terminal/window.c index 1099aabb..3bad556d 100644 --- a/src/terminal/window.c +++ b/src/terminal/window.c @@ -178,7 +178,7 @@ add_empty_window(struct terminal *term, void (*fn)(void *), void *data) void assert_window_stacking(struct terminal *term) { - int prev_type = WINDOW_NORMAL; + enum { WANT_ANY, WANT_TAB, WANT_NONE } want = WANT_ANY; const struct window *win; const struct window *main_menu_win; @@ -186,10 +186,20 @@ assert_window_stacking(struct terminal *term) main_menu_win = term->main_menu ? term->main_menu->win : NULL; foreach (win, term->windows) { - if (win != main_menu_win) { - if (prev_type == WINDOW_TAB) + switch (want) { + case WANT_ANY: + if (win->type == WINDOW_TAB) + want = WANT_TAB; + break; + case WANT_TAB: + if (win == main_menu_win) + want = WANT_NONE; + else assert(win->type == WINDOW_TAB); - prev_type = win->type; + break; + case WANT_NONE: + assert(0); + break; } } }