diff --git a/src/terminal/tab.c b/src/terminal/tab.c index 123d2af4e..e914b5d25 100644 --- a/src/terminal/tab.c +++ b/src/terminal/tab.c @@ -30,6 +30,7 @@ struct window * init_tab(struct terminal *term, void *data, window_handler_T handler) { struct window *win = mem_calloc(1, sizeof(*win)); + struct window *pos; if (!win) return NULL; @@ -39,7 +40,21 @@ init_tab(struct terminal *term, void *data, window_handler_T handler) win->type = WINDOW_TAB; win->resize = 1; - add_to_list(term->windows, win); + /* Insert the new tab immediately above all existing tabs in + * the stack of windows. */ + foreach_tab (pos, term->windows) { + pos = pos->prev; + goto found_pos; + } + /* This is a new terminal and there are no tabs yet. If there + * were a main menu already, then we'd have to place the tab + * above it if it were inactive, or below if it were active. */ + assert(term->main_menu == NULL); + pos = (struct window *) term->windows.prev; + found_pos: + add_at_pos(pos, win); + + assert_window_stacking(term); return win; } diff --git a/src/terminal/terminal.h b/src/terminal/terminal.h index f02707bf4..32d148f43 100644 --- a/src/terminal/terminal.h +++ b/src/terminal/terminal.h @@ -69,13 +69,26 @@ struct terminal { * are sure what are you doing) to make sure that you don't distribute * events etc to inactive tabs. * - * The stack is top-down, thus .next is the stack's top, the current - * window. .prev is the first tab. + * The stack is top-down, thus .next is the stack's top, the + * 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. + * - If the main menu is inactive, then it is at the very bottom, + * hidden under the tabs. + * Call assert_window_stacking to verify this. * * FIXME: Tabs violate the stack nature of this list, they appear there * randomly but always in the order in which they were inserted there. * Eventually, they should all live at the stack bottom, with the - * actual tab living on the VERY bottom. --pasky */ + * actual tab living on the VERY bottom. --pasky + * + * Keeping the current tab at the very bottom would require storing + * tab numbers explicitly, rather than computing them from the + * stack order as is done now. Also, what should be done with the + * inactive main menu? --KON */ struct list_head windows; /* {struct window} */ /* The specification of terminal in terms of terminal options. */ diff --git a/src/terminal/window.c b/src/terminal/window.c index 9a3fe9b57..1099aabb5 100644 --- a/src/terminal/window.c +++ b/src/terminal/window.c @@ -6,6 +6,7 @@ #include "elinks.h" +#include "bfu/menu.h" #include "terminal/event.h" #include "terminal/tab.h" #include "terminal/terminal.h" @@ -171,3 +172,25 @@ add_empty_window(struct terminal *term, void (*fn)(void *), void *data) ewd->called_once = 0; add_window(term, empty_window_handler, ewd); } + +#if CONFIG_DEBUG +/* Check that term->windows are in the documented order. */ +void +assert_window_stacking(struct terminal *term) +{ + int prev_type = WINDOW_NORMAL; + const struct window *win; + const struct window *main_menu_win; + + /* The main menu can be either above or below the tabs. */ + 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) + assert(win->type == WINDOW_TAB); + prev_type = win->type; + } + } +} +#endif /* CONFIG_DEBUG */ diff --git a/src/terminal/window.h b/src/terminal/window.h index f3a3c6a74..a75e7cbba 100644 --- a/src/terminal/window.h +++ b/src/terminal/window.h @@ -56,4 +56,10 @@ void get_parent_ptr(struct window *, int *, int *); void add_empty_window(struct terminal *, void (*)(void *), void *); +#if CONFIG_DEBUG +void assert_window_stacking(struct terminal *); +#else +#define assert_window_stacking(t) ((void) (t)) +#endif + #endif