1 /* Tab-style (those containing real documents) windows infrastructure. */
9 #include "bfu/dialog.h"
10 #include "config/options.h"
11 #include "dialogs/menu.h"
12 #include "document/document.h"
13 #include "document/view.h"
14 #include "intl/gettext/libintl.h"
15 #include "main/select.h"
16 #include "protocol/uri.h"
17 #include "session/session.h"
18 #include "terminal/screen.h"
19 #include "terminal/tab.h"
20 #include "terminal/terminal.h"
21 #include "terminal/window.h"
22 #include "util/error.h"
23 #include "util/memory.h"
24 #include "util/lists.h"
25 #include "viewer/text/link.h"
26 #include "viewer/text/view.h"
30 init_tab(struct terminal
*term
, void *data
, window_handler_T handler
)
32 struct window
*win
= mem_calloc(1, sizeof(*win
));
34 if (!win
) return NULL
;
36 win
->handler
= handler
;
39 win
->type
= WINDOW_TAB
;
42 add_to_list(term
->windows
, win
);
47 /* Number of tabs at the terminal (in term->windows) */
49 number_of_tabs(struct terminal
*term
)
54 foreach_tab (win
, term
->windows
)
62 get_tab_number(struct window
*window
)
64 struct terminal
*term
= window
->term
;
69 foreachback_tab (win
, term
->windows
) {
80 /* Get tab of an according index */
82 get_tab_by_number(struct terminal
*term
, int num
)
84 struct window
*win
= NULL
;
86 foreachback_tab (win
, term
->windows
) {
94 /* Returns number of the tab at @xpos, or -1 if none. */
96 get_tab_number_by_xpos(struct terminal
*term
, int xpos
)
99 struct window
*win
= NULL
;
101 foreachback_tab (win
, term
->windows
) {
102 if (xpos
>= win
->xpos
103 && xpos
< win
->xpos
+ win
->width
)
111 /* if @tabs > 0, then it is taken as the result of a recent
112 * call to number_of_tabs() so it just uses this value. */
114 switch_to_tab(struct terminal
*term
, int tab
, int tabs
)
116 if (tabs
< 0) tabs
= number_of_tabs(term
);
120 if (get_opt_bool("ui.tabs.wraparound"))
127 if (get_opt_bool("ui.tabs.wraparound"))
134 if (tab
!= term
->current_tab
) {
135 term
->current_tab
= tab
;
136 set_screen_dirty(term
->screen
, 0, term
->height
);
137 redraw_terminal(term
);
142 switch_current_tab(struct session
*ses
, int direction
)
144 struct terminal
*term
= ses
->tab
->term
;
145 int num_tabs
= number_of_tabs(term
);
151 count
= eat_kbd_repeat_count(ses
);
152 if (count
) direction
*= count
;
154 switch_to_tab(term
, term
->current_tab
+ direction
, num_tabs
);
158 really_close_tab(struct session
*ses
)
160 struct terminal
*term
= ses
->tab
->term
;
161 struct window
*current_tab
= get_current_tab(term
);
163 if (ses
->tab
== current_tab
) {
164 int num_tabs
= number_of_tabs(term
);
166 switch_to_tab(term
, term
->current_tab
- 1, num_tabs
- 1);
169 delete_window(ses
->tab
);
173 close_tab(struct terminal
*term
, struct session
*ses
)
175 int num_tabs
= number_of_tabs(term
);
182 if (!get_opt_bool("ui.tabs.confirm_close")) {
183 really_close_tab(ses
);
187 msg_box(term
, NULL
, 0,
188 N_("Close tab"), ALIGN_CENTER
,
189 N_("Do you really want to close the current tab?"),
191 N_("~Yes"), (void (*)(void *)) really_close_tab
, B_ENTER
,
192 N_("~No"), NULL
, B_ESC
);
196 really_close_tabs(struct session
*ses
)
198 struct terminal
*term
= ses
->tab
->term
;
199 struct window
*current
= get_current_tab(term
);
202 foreach_tab (tab
, term
->windows
) {
203 if (tab
== current
) continue;
205 delete_window(tab
->next
);
208 term
->current_tab
= 0;
209 redraw_terminal(term
);
213 close_all_tabs_but_current(struct session
*ses
)
216 if_assert_failed
return;
218 if (!get_opt_bool("ui.tabs.confirm_close")) {
219 really_close_tabs(ses
);
223 msg_box(ses
->tab
->term
, NULL
, 0,
224 N_("Close tab"), ALIGN_CENTER
,
225 N_("Do you really want to close all except the current tab?"),
227 N_("~Yes"), (void (*)(void *)) really_close_tabs
, B_ENTER
,
228 N_("~No"), NULL
, B_ESC
);
233 open_uri_in_new_tab(struct session
*ses
, struct uri
*uri
, int in_background
,
237 /* @based means whether the current @ses location will be preloaded
239 init_session(based
? ses
: NULL
, ses
->tab
->term
, uri
, in_background
);
243 open_current_link_in_new_tab(struct session
*ses
, int in_background
)
245 struct document_view
*doc_view
= current_frame(ses
);
246 struct uri
*uri
= NULL
;
249 if (doc_view
) assert(doc_view
->vs
&& doc_view
->document
);
250 if_assert_failed
return;
252 link
= get_current_link(doc_view
);
253 if (link
) uri
= get_link_uri(ses
, doc_view
, link
);
255 open_uri_in_new_tab(ses
, uri
, in_background
, 1);
256 if (uri
) done_uri(uri
);
260 move_current_tab(struct session
*ses
, int direction
)
262 struct terminal
*term
= ses
->tab
->term
;
263 int tabs
= number_of_tabs(term
);
264 struct window
*current_tab
= get_current_tab(term
);
269 assert(ses
&& direction
);
271 count
= eat_kbd_repeat_count(ses
);
272 if (count
) direction
*= count
;
274 new_pos
= term
->current_tab
+ direction
;
276 while (new_pos
< 1 || new_pos
> tabs
)
277 new_pos
+= new_pos
< 1 ? tabs
: -tabs
;
279 assert(0 < new_pos
&& new_pos
<= tabs
);
281 if (new_pos
== term
->current_tab
) return;
283 tab
= get_tab_by_number(term
, new_pos
);
285 del_from_list(current_tab
);
287 if (new_pos
< term
->current_tab
) {
288 add_at_pos(tab
, current_tab
);
290 add_to_list_end(*tab
, current_tab
);
293 switch_to_tab(term
, new_pos
, tabs
);