Bug 880: Prevent SIGSEGV in init_python when -no-home is used.
[elinks.git] / src / viewer / action.c
blob2f2c44681f51f65be82e713497ca61f2b03a128c
1 /* Sessions action management */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdlib.h>
9 #include "elinks.h"
11 #include "bookmarks/dialogs.h"
12 #include "cache/dialogs.h"
13 #include "config/conf.h"
14 #include "config/dialogs.h"
15 #include "config/kbdbind.h"
16 #include "config/options.h"
17 #include "cookies/cookies.h"
18 #include "cookies/dialogs.h"
19 #include "dialogs/document.h"
20 #include "dialogs/download.h"
21 #include "dialogs/exmode.h"
22 #include "dialogs/info.h"
23 #include "dialogs/menu.h"
24 #include "dialogs/options.h"
25 #include "dialogs/status.h"
26 #include "document/document.h"
27 #include "document/view.h"
28 #include "formhist/dialogs.h"
29 #include "globhist/dialogs.h"
30 #include "main/main.h"
31 #include "network/connection.h"
32 #include "protocol/auth/auth.h"
33 #include "protocol/auth/dialogs.h"
34 #include "terminal/tab.h"
35 #include "terminal/terminal.h"
36 #include "terminal/window.h"
37 #include "session/history.h"
38 #include "session/session.h"
39 #include "session/task.h"
40 #include "viewer/action.h"
41 #include "viewer/text/draw.h"
42 #include "viewer/text/form.h"
43 #include "viewer/text/link.h"
44 #include "viewer/text/search.h"
45 #include "viewer/text/view.h"
48 static void
49 goto_url_action(struct session *ses,
50 unsigned char *(*get_url)(struct session *, unsigned char *, size_t))
52 unsigned char url[MAX_STR_LEN];
54 if (!get_url || !get_url(ses, url, sizeof(url)))
55 url[0] = 0;
57 dialog_goto_url(ses, url);
60 /* This could gradually become some multiplexor / switch noodle containing
61 * most if not all default handling of actions (for the main mapping) that
62 * frame_ev() and/or send_event() could use as a backend. */
63 /* Many execution paths may lead to this code so it needs to take appropriate
64 * precausions to stuff like doc_view and doc_view->vs being NULL. */
65 enum frame_event_status
66 do_action(struct session *ses, enum main_action action_id, int verbose)
68 enum frame_event_status status = FRAME_EVENT_OK;
69 struct terminal *term = ses->tab->term;
70 struct document_view *doc_view = current_frame(ses);
71 struct link *link = NULL;
73 if (action_id == -1) goto unknown_action;
75 if (doc_view && doc_view->vs) {
76 if (action_prefix_is_link_number(KEYMAP_MAIN, action_id)
77 && !try_jump_to_link_number(ses, doc_view))
78 goto ignore_action;
80 link = get_current_link(doc_view);
82 } else if (action_requires_view_state(KEYMAP_MAIN, action_id)) {
83 goto ignore_action;
86 if (action_requires_location(KEYMAP_MAIN, action_id)
87 && !have_location(ses))
88 return FRAME_EVENT_OK;
90 if (action_requires_link(KEYMAP_MAIN, action_id)
91 && !link)
92 goto ignore_action;
94 if (action_requires_form(KEYMAP_MAIN, action_id)
95 && (!link || !link_is_form(link)))
96 goto ignore_action;
98 if (!action_is_anonymous_safe(KEYMAP_MAIN, action_id)
99 && get_cmd_opt_bool("anonymous"))
100 goto ignore_action;
102 /* Please keep in alphabetical order for now. Later we can sort by most
103 * used or something. */
104 switch (action_id) {
105 case ACT_MAIN_ABORT_CONNECTION:
106 abort_loading(ses, 1);
107 print_screen_status(ses);
108 break;
110 case ACT_MAIN_ADD_BOOKMARK:
111 #ifdef CONFIG_BOOKMARKS
112 launch_bm_add_doc_dialog(term, NULL, ses);
113 #endif
114 break;
115 case ACT_MAIN_ADD_BOOKMARK_LINK:
116 #ifdef CONFIG_BOOKMARKS
117 launch_bm_add_link_dialog(term, NULL, ses);
118 #endif
119 break;
120 case ACT_MAIN_ADD_BOOKMARK_TABS:
121 #ifdef CONFIG_BOOKMARKS
122 bookmark_terminal_tabs_dialog(term);
123 #endif
124 break;
126 case ACT_MAIN_AUTH_MANAGER:
127 auth_manager(ses);
128 break;
130 case ACT_MAIN_BOOKMARK_MANAGER:
131 #ifdef CONFIG_BOOKMARKS
132 bookmark_manager(ses);
133 #endif
134 break;
136 case ACT_MAIN_CACHE_MANAGER:
137 cache_manager(ses);
138 break;
140 case ACT_MAIN_CACHE_MINIMIZE:
141 shrink_memory(1);
142 break;
144 case ACT_MAIN_COOKIES_LOAD:
145 #ifdef CONFIG_COOKIES
146 if (!get_opt_bool("cookies.save")) break;
147 load_cookies();
148 #endif
149 break;
151 case ACT_MAIN_COOKIE_MANAGER:
152 #ifdef CONFIG_COOKIES
153 cookie_manager(ses);
154 #endif
155 break;
157 case ACT_MAIN_COPY_CLIPBOARD:
158 status = copy_current_link_to_clipboard(ses, doc_view, 0);
159 break;
161 case ACT_MAIN_DOCUMENT_INFO:
162 document_info_dialog(ses);
163 break;
165 case ACT_MAIN_DOWNLOAD_MANAGER:
166 download_manager(ses);
167 break;
169 case ACT_MAIN_EXMODE:
170 #ifdef CONFIG_EXMODE
171 exmode_start(ses);
172 #endif
173 break;
175 case ACT_MAIN_FILE_MENU:
176 activate_bfu_technology(ses, 0);
177 break;
179 case ACT_MAIN_FIND_NEXT:
180 status = find_next(ses, doc_view, 1);
181 break;
183 case ACT_MAIN_FIND_NEXT_BACK:
184 status = find_next(ses, doc_view, -1);
185 break;
187 case ACT_MAIN_FORGET_CREDENTIALS:
188 free_auth();
189 shrink_memory(1); /* flush caches */
190 break;
192 case ACT_MAIN_FORMHIST_MANAGER:
193 #ifdef CONFIG_FORMHIST
194 formhist_manager(ses);
195 #endif
196 break;
198 case ACT_MAIN_FRAME_EXTERNAL_COMMAND:
199 status = pass_uri_to_command(ses, doc_view,
200 PASS_URI_FRAME);
201 break;
203 case ACT_MAIN_FRAME_NEXT:
204 next_frame(ses, 1);
205 draw_formatted(ses, 0);
206 break;
208 case ACT_MAIN_FRAME_MAXIMIZE:
209 status = set_frame(ses, doc_view, 0);
210 break;
212 case ACT_MAIN_FRAME_PREV:
213 next_frame(ses, -1);
214 draw_formatted(ses, 0);
215 break;
217 case ACT_MAIN_GOTO_URL:
218 goto_url_action(ses, NULL);
219 break;
221 case ACT_MAIN_GOTO_URL_CURRENT:
222 goto_url_action(ses, get_current_url);
223 break;
225 case ACT_MAIN_GOTO_URL_CURRENT_LINK:
226 goto_url_action(ses, get_current_link_url);
227 break;
229 case ACT_MAIN_GOTO_URL_HOME:
230 goto_url_home(ses);
231 break;
233 case ACT_MAIN_HEADER_INFO:
234 protocol_header_dialog(ses);
235 break;
237 case ACT_MAIN_HISTORY_MANAGER:
238 #ifdef CONFIG_GLOBHIST
239 history_manager(ses);
240 #endif
241 break;
243 case ACT_MAIN_HISTORY_MOVE_BACK:
245 int count = int_max(1, eat_kbd_repeat_count(ses));
247 go_history_by_n(ses, -count);
248 break;
250 case ACT_MAIN_HISTORY_MOVE_FORWARD:
252 int count = int_max(1, eat_kbd_repeat_count(ses));
254 go_history_by_n(ses, count);
255 break;
257 case ACT_MAIN_JUMP_TO_LINK:
258 break;
260 case ACT_MAIN_KEYBINDING_MANAGER:
261 keybinding_manager(ses);
262 break;
264 case ACT_MAIN_KILL_BACKGROUNDED_CONNECTIONS:
265 abort_background_connections();
266 break;
268 case ACT_MAIN_LINK_DOWNLOAD:
269 case ACT_MAIN_LINK_DOWNLOAD_IMAGE:
270 case ACT_MAIN_LINK_DOWNLOAD_RESUME:
271 status = download_link(ses, doc_view, action_id);
272 break;
274 case ACT_MAIN_LINK_EXTERNAL_COMMAND:
275 status = pass_uri_to_command(ses, doc_view,
276 PASS_URI_LINK);
277 break;
279 case ACT_MAIN_LINK_FOLLOW:
280 status = enter(ses, doc_view, 0);
281 break;
283 case ACT_MAIN_LINK_FOLLOW_RELOAD:
284 status = enter(ses, doc_view, 1);
285 break;
287 case ACT_MAIN_LINK_MENU:
288 link_menu(term, NULL, ses);
289 break;
291 case ACT_MAIN_LINK_FORM_MENU:
292 link_form_menu(ses);
293 break;
295 case ACT_MAIN_LUA_CONSOLE:
296 #ifdef CONFIG_LUA
297 trigger_event_name("dialog-lua-console", ses);
298 #endif
299 break;
301 case ACT_MAIN_MARK_SET:
302 #ifdef CONFIG_MARKS
303 ses->kbdprefix.mark = KP_MARK_SET;
304 status = FRAME_EVENT_REFRESH;
305 #endif
306 break;
308 case ACT_MAIN_MARK_GOTO:
309 #ifdef CONFIG_MARKS
310 /* TODO: Show promptly a menu (or even listbox?)
311 * with all the marks. But the next letter must
312 * still choose a mark directly! --pasky */
313 ses->kbdprefix.mark = KP_MARK_GOTO;
314 status = FRAME_EVENT_REFRESH;
315 #endif
316 break;
318 case ACT_MAIN_MENU:
319 activate_bfu_technology(ses, -1);
320 break;
322 case ACT_MAIN_MOVE_CURSOR_UP:
323 status = move_cursor_up(ses, doc_view);
324 break;
326 case ACT_MAIN_MOVE_CURSOR_DOWN:
327 status = move_cursor_down(ses, doc_view);
328 break;
330 case ACT_MAIN_MOVE_CURSOR_LEFT:
331 status = move_cursor_left(ses, doc_view);
332 break;
334 case ACT_MAIN_MOVE_CURSOR_RIGHT:
335 status = move_cursor_right(ses, doc_view);
336 break;
338 case ACT_MAIN_MOVE_LINK_DOWN:
339 status = move_link_down(ses, doc_view);
340 break;
342 case ACT_MAIN_MOVE_LINK_LEFT:
343 status = move_link_left(ses, doc_view);
344 break;
346 case ACT_MAIN_MOVE_LINK_NEXT:
347 status = move_link_next(ses, doc_view);
348 break;
350 case ACT_MAIN_MOVE_LINK_PREV:
351 status = move_link_prev(ses, doc_view);
352 break;
354 case ACT_MAIN_MOVE_LINK_RIGHT:
355 status = move_link_right(ses, doc_view);
356 break;
358 case ACT_MAIN_MOVE_LINK_UP:
359 status = move_link_up(ses, doc_view);
360 break;
362 case ACT_MAIN_MOVE_PAGE_DOWN:
363 status = move_page_down(ses, doc_view);
364 break;
366 case ACT_MAIN_MOVE_PAGE_UP:
367 status = move_page_up(ses, doc_view);
368 break;
370 case ACT_MAIN_MOVE_DOCUMENT_START:
371 status = move_document_start(ses, doc_view);
372 break;
374 case ACT_MAIN_MOVE_DOCUMENT_END:
375 status = move_document_end(ses, doc_view);
376 break;
378 case ACT_MAIN_OPEN_LINK_IN_NEW_TAB:
379 open_current_link_in_new_tab(ses, 0);
380 break;
382 case ACT_MAIN_OPEN_LINK_IN_NEW_TAB_IN_BACKGROUND:
383 open_current_link_in_new_tab(ses, 1);
384 break;
386 case ACT_MAIN_OPEN_LINK_IN_NEW_WINDOW:
387 open_in_new_window(term, send_open_in_new_window, ses);
388 break;
390 case ACT_MAIN_OPEN_NEW_TAB:
391 open_uri_in_new_tab(ses, NULL, 0, 1);
392 break;
394 case ACT_MAIN_OPEN_NEW_TAB_IN_BACKGROUND:
395 open_uri_in_new_tab(ses, NULL, 1, 1);
396 break;
398 case ACT_MAIN_OPEN_NEW_WINDOW:
399 open_in_new_window(term, send_open_new_window, ses);
400 break;
402 case ACT_MAIN_OPEN_OS_SHELL:
403 exec_shell(term);
404 break;
406 case ACT_MAIN_OPTIONS_MANAGER:
407 options_manager(ses);
408 break;
410 case ACT_MAIN_QUIT:
411 exit_prog(ses, 1);
412 break;
414 case ACT_MAIN_REALLY_QUIT:
415 exit_prog(ses, 0);
416 break;
418 case ACT_MAIN_REDRAW:
419 redraw_terminal_cls(term);
420 break;
422 case ACT_MAIN_RELOAD:
423 reload(ses, CACHE_MODE_INCREMENT);
424 break;
426 case ACT_MAIN_RERENDER:
427 draw_formatted(ses, 2);
428 break;
430 case ACT_MAIN_RESET_FORM:
431 status = reset_form(ses, doc_view, 0);
432 break;
434 case ACT_MAIN_RESOURCE_INFO:
435 resource_info(term);
436 break;
438 case ACT_MAIN_SAVE_AS:
439 status = save_as(ses, doc_view, 0);
440 break;
442 case ACT_MAIN_SAVE_FORMATTED:
443 status = save_formatted_dlg(ses, doc_view, 0);
444 break;
446 case ACT_MAIN_SAVE_OPTIONS:
447 write_config(term);
448 break;
450 case ACT_MAIN_SAVE_URL_AS:
451 save_url_as(ses);
452 break;
454 case ACT_MAIN_SCROLL_DOWN:
455 status = scroll_down(ses, doc_view);
456 break;
458 case ACT_MAIN_SCROLL_LEFT:
459 status = scroll_left(ses, doc_view);
460 break;
462 case ACT_MAIN_SCROLL_RIGHT:
463 status = scroll_right(ses, doc_view);
464 break;
466 case ACT_MAIN_SCROLL_UP:
467 status = scroll_up(ses, doc_view);
468 break;
470 case ACT_MAIN_SEARCH:
471 status = search_dlg(ses, doc_view, 1);
472 break;
474 case ACT_MAIN_SEARCH_BACK:
475 status = search_dlg(ses, doc_view, -1);
476 break;
478 case ACT_MAIN_SEARCH_TYPEAHEAD:
479 case ACT_MAIN_SEARCH_TYPEAHEAD_LINK:
480 case ACT_MAIN_SEARCH_TYPEAHEAD_TEXT:
481 case ACT_MAIN_SEARCH_TYPEAHEAD_TEXT_BACK:
482 status = search_typeahead(ses, doc_view, action_id);
483 break;
485 case ACT_MAIN_SHOW_TERM_OPTIONS:
486 terminal_options(term, NULL, ses);
487 break;
489 case ACT_MAIN_SUBMIT_FORM:
490 status = submit_form(ses, doc_view, 0);
491 break;
493 case ACT_MAIN_SUBMIT_FORM_RELOAD:
494 status = submit_form(ses, doc_view, 1);
495 break;
497 case ACT_MAIN_TAB_CLOSE:
498 close_tab(term, ses);
499 status = FRAME_EVENT_SESSION_DESTROYED;
500 break;
502 case ACT_MAIN_TAB_CLOSE_ALL_BUT_CURRENT:
503 close_all_tabs_but_current(ses);
504 break;
506 case ACT_MAIN_TAB_EXTERNAL_COMMAND:
507 status = pass_uri_to_command(ses, doc_view,
508 PASS_URI_TAB);
509 break;
511 case ACT_MAIN_TAB_MOVE_LEFT:
512 move_current_tab(ses, -1);
513 break;
515 case ACT_MAIN_TAB_MOVE_RIGHT:
516 move_current_tab(ses, 1);
517 break;
519 case ACT_MAIN_TAB_MENU:
520 assert(ses->tab == get_current_tab(term));
522 if (ses->status.show_tabs_bar)
523 tab_menu(ses, ses->tab->xpos,
524 term->height - 1
525 - ses->status.show_status_bar,
527 else
528 tab_menu(ses, 0, 0, 0);
530 break;
532 case ACT_MAIN_TAB_NEXT:
533 switch_current_tab(ses, 1);
534 break;
536 case ACT_MAIN_TAB_PREV:
537 switch_current_tab(ses, -1);
538 break;
540 case ACT_MAIN_TERMINAL_RESIZE:
541 resize_terminal_dialog(term);
542 break;
544 case ACT_MAIN_TOGGLE_CSS:
545 #ifdef CONFIG_CSS
546 toggle_document_option(ses, "document.css.enable");
547 #endif
548 break;
550 case ACT_MAIN_TOGGLE_DISPLAY_IMAGES:
551 toggle_document_option(ses, "document.browse.images.show_as_links");
552 break;
554 case ACT_MAIN_TOGGLE_DISPLAY_TABLES:
555 toggle_document_option(ses, "document.html.display_tables");
556 break;
558 case ACT_MAIN_TOGGLE_DOCUMENT_COLORS:
559 toggle_document_option(ses, "document.colors.use_document_colors");
560 break;
562 case ACT_MAIN_TOGGLE_HTML_PLAIN:
563 toggle_plain_html(ses, ses->doc_view, 0);
564 break;
566 case ACT_MAIN_TOGGLE_MOUSE:
567 #ifdef CONFIG_MOUSE
568 toggle_mouse();
569 #endif
570 break;
572 case ACT_MAIN_TOGGLE_NUMBERED_LINKS:
573 toggle_document_option(ses, "document.browse.links.numbering");
574 break;
576 case ACT_MAIN_TOGGLE_PLAIN_COMPRESS_EMPTY_LINES:
577 toggle_document_option(ses, "document.plain.compress_empty_lines");
578 break;
580 case ACT_MAIN_TOGGLE_WRAP_TEXT:
581 toggle_wrap_text(ses, ses->doc_view, 0);
582 break;
584 case ACT_MAIN_VIEW_IMAGE:
585 status = view_image(ses, doc_view, 0);
586 break;
588 case ACT_MAIN_SCRIPTING_FUNCTION:
589 case ACT_MAIN_NONE:
590 case MAIN_ACTIONS:
591 default:
592 unknown_action:
593 if (verbose) {
594 INTERNAL("No action handling defined for '%s'.",
595 get_action_name(KEYMAP_MAIN, action_id));
598 status = FRAME_EVENT_IGNORED;
601 ignore_action:
602 /* XXX: At this point the session may have been destroyed */
604 if (status != FRAME_EVENT_SESSION_DESTROYED
605 && ses->insert_mode == INSERT_MODE_ON
606 && link != get_current_link(doc_view))
607 ses->insert_mode = INSERT_MODE_OFF;
609 if (status == FRAME_EVENT_REFRESH && doc_view)
610 refresh_view(ses, doc_view, 0);
612 return status;