1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-15 23:35:34 +00:00
elinks/src/viewer/action.c
2023-11-25 14:13:10 +01:00

797 lines
17 KiB
C

/* Sessions action management */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include "elinks.h"
#include "bookmarks/dialogs.h"
#include "cache/dialogs.h"
#include "config/conf.h"
#include "config/dialogs.h"
#include "config/kbdbind.h"
#include "config/options.h"
#include "cookies/cookies.h"
#include "cookies/dialogs.h"
#include "dialogs/document.h"
#include "dialogs/download.h"
#include "dialogs/exmode.h"
#include "dialogs/info.h"
#include "dialogs/menu.h"
#include "dialogs/options.h"
#include "dialogs/status.h"
#include "document/document.h"
#include "document/view.h"
#ifdef CONFIG_ECMASCRIPT
#include "ecmascript/ecmascript-c.h"
#endif
#include "formhist/dialogs.h"
#include "globhist/dialogs.h"
#include "main/main.h"
#include "network/connection.h"
#include "protocol/auth/auth.h"
#include "protocol/auth/dialogs.h"
#include "terminal/tab.h"
#include "terminal/terminal.h"
#include "terminal/window.h"
#include "session/history.h"
#include "session/session.h"
#include "session/task.h"
#include "viewer/action.h"
#include "viewer/text/draw.h"
#include "viewer/text/form.h"
#include "viewer/text/link.h"
#include "viewer/text/search.h"
#include "viewer/text/view.h"
static void
goto_url_action(struct session *ses,
char *(*get_url)(struct session *, char *, size_t))
{
char url[MAX_STR_LEN];
if (!get_url || !get_url(ses, url, sizeof(url)))
url[0] = 0;
dialog_goto_url(ses, url);
}
/* This could gradually become some multiplexor / switch noodle containing
* most if not all default handling of actions (for the main mapping) that
* frame_ev() and/or send_event() could use as a backend. */
/* Many execution paths may lead to this code so it needs to take appropriate
* precausions to stuff like doc_view and doc_view->vs being NULL. */
enum frame_event_status
do_action(struct session *ses, main_action_T action_id, int verbose)
{
enum frame_event_status status = FRAME_EVENT_OK;
struct terminal *term = ses->tab->term;
struct document_view *doc_view = current_frame(ses);
struct link *link = NULL;
if (action_id == -1) goto unknown_action;
if (doc_view && doc_view->vs) {
if (action_prefix_is_link_number(KEYMAP_MAIN, action_id)
&& !try_jump_to_link_number(ses, doc_view))
goto ignore_action;
link = get_current_link(doc_view);
} else if (action_requires_view_state(KEYMAP_MAIN, action_id)) {
goto ignore_action;
}
if (action_requires_location(KEYMAP_MAIN, action_id)
&& !have_location(ses))
return FRAME_EVENT_OK;
if (action_requires_link(KEYMAP_MAIN, action_id)
&& !link)
goto ignore_action;
if (action_requires_form(KEYMAP_MAIN, action_id)
&& (!link || !link_is_form(link)))
goto ignore_action;
if (!action_is_anonymous_safe(KEYMAP_MAIN, action_id)
&& get_cmd_opt_bool("anonymous"))
goto ignore_action;
/* Please keep in alphabetical order for now. Later we can sort by most
* used or something. */
switch (action_id) {
case ACT_MAIN_ABORT_CONNECTION:
abort_loading(ses, 1);
print_screen_status(ses);
break;
case ACT_MAIN_ADD_BOOKMARK:
#ifdef CONFIG_BOOKMARKS
launch_bm_add_doc_dialog(term, NULL, ses);
#endif
break;
case ACT_MAIN_ADD_BOOKMARK_LINK:
#ifdef CONFIG_BOOKMARKS
launch_bm_add_link_dialog(term, NULL, ses);
#endif
break;
case ACT_MAIN_ADD_BOOKMARK_TABS:
#ifdef CONFIG_BOOKMARKS
bookmark_terminal_tabs_dialog(term);
#endif
break;
case ACT_MAIN_AUTH_MANAGER:
auth_manager(ses);
break;
case ACT_MAIN_BACKSPACE_PREFIX:
if (!ses->kbdprefix.repeat_count) break;
set_kbd_repeat_count(ses,
ses->kbdprefix.repeat_count / 10);
/* Keep send_event from resetting repeat_count. */
status = FRAME_EVENT_SESSION_DESTROYED;
break;
case ACT_MAIN_BOOKMARK_MANAGER:
#ifdef CONFIG_BOOKMARKS
bookmark_manager(ses);
#endif
break;
case ACT_MAIN_CACHE_MANAGER:
cache_manager(ses);
break;
case ACT_MAIN_CACHE_MINIMIZE:
shrink_memory(1);
break;
case ACT_MAIN_CLEAN_TEMPORARY_FILES:
clean_temporary_files();
break;
case ACT_MAIN_COOKIES_LOAD:
#ifdef CONFIG_COOKIES
if (!get_opt_bool("cookies.save", NULL)) break;
load_cookies();
#endif
break;
case ACT_MAIN_COOKIE_MANAGER:
#ifdef CONFIG_COOKIES
cookie_manager(ses);
#endif
break;
case ACT_MAIN_COPY_CLIPBOARD:
status = copy_to_clipboard(ses, doc_view);
break;
case ACT_MAIN_DOCUMENT_INFO:
document_info_dialog(ses);
break;
case ACT_MAIN_DOWNLOAD_MANAGER:
download_manager(ses);
break;
case ACT_MAIN_EXMODE:
#ifdef CONFIG_EXMODE
exmode_start(ses);
#endif
break;
case ACT_MAIN_FILE_MENU:
activate_bfu_technology(ses, 0);
break;
case ACT_MAIN_FIND_NEXT:
status = move_search_next(ses, doc_view);
break;
case ACT_MAIN_FIND_NEXT_BACK:
status = move_search_prev(ses, doc_view);
break;
case ACT_MAIN_FORGET_CREDENTIALS:
free_auth();
shrink_memory(1); /* flush caches */
break;
case ACT_MAIN_FORMHIST_MANAGER:
#ifdef CONFIG_FORMHIST
formhist_manager(ses);
#endif
break;
case ACT_MAIN_FRAME_EXTERNAL_COMMAND:
status = pass_uri_to_command(ses, doc_view,
PASS_URI_FRAME);
break;
case ACT_MAIN_FRAME_NEXT:
next_frame(ses, 1);
draw_formatted(ses, 0);
break;
case ACT_MAIN_FRAME_MAXIMIZE:
status = set_frame(ses, doc_view, 0);
ses->insert_mode = INSERT_MODE_OFF;
break;
case ACT_MAIN_FRAME_PREV:
next_frame(ses, -1);
draw_formatted(ses, 0);
break;
case ACT_MAIN_GOTO_URL:
goto_url_action(ses, NULL);
break;
case ACT_MAIN_GOTO_URL_CURRENT:
goto_url_action(ses, get_current_url);
break;
case ACT_MAIN_GOTO_URL_CURRENT_LINK:
goto_url_action(ses, get_current_link_url);
break;
case ACT_MAIN_GOTO_URL_HOME:
goto_url_home(ses);
break;
case ACT_MAIN_HEADER_INFO:
protocol_header_dialog(ses);
break;
case ACT_MAIN_HISTORY_MANAGER:
#ifdef CONFIG_GLOBHIST
history_manager(ses);
#endif
break;
case ACT_MAIN_HISTORY_MOVE_BACK:
{
int count = int_max(1, eat_kbd_repeat_count(ses));
if (go_history_by_n(ses, -count) &&
get_opt_bool("ui.back_to_exit", NULL))
close_tab(term, ses);
break;
}
case ACT_MAIN_HISTORY_MOVE_FORWARD:
{
int count = int_max(1, eat_kbd_repeat_count(ses));
go_history_by_n(ses, count);
break;
}
case ACT_MAIN_JUMP_TO_LINK:
break;
case ACT_MAIN_KEYBINDING_MANAGER:
keybinding_manager(ses);
break;
case ACT_MAIN_KILL_BACKGROUNDED_CONNECTIONS:
abort_background_connections();
break;
case ACT_MAIN_LINK_DIALOG:
open_link_dialog(ses);
break;
case ACT_MAIN_LINK_DOWNLOAD:
case ACT_MAIN_LINK_DOWNLOAD_IMAGE:
case ACT_MAIN_LINK_DOWNLOAD_RESUME:
status = download_link(ses, doc_view, action_id);
break;
case ACT_MAIN_LINK_EXTERNAL_COMMAND:
status = pass_uri_to_command(ses, doc_view,
PASS_URI_LINK);
break;
case ACT_MAIN_LINK_FOLLOW:
status = enter(ses, doc_view, 0);
break;
case ACT_MAIN_LINK_FOLLOW_RELOAD:
status = enter(ses, doc_view, 1);
break;
case ACT_MAIN_LINK_INFO:
link_info_dialog(ses);
break;
case ACT_MAIN_LINK_MENU:
link_menu(term, NULL, ses);
break;
case ACT_MAIN_LINK_FORM_MENU:
link_form_menu(ses);
break;
case ACT_MAIN_LUA_CONSOLE:
#ifdef CONFIG_SCRIPTING_LUA
trigger_event_name("dialog-lua-console", ses);
#endif
break;
case ACT_MAIN_MACRO_0:
#ifdef CONFIG_EXMODE
try_exmode_exec(ses, get_opt_str("macro.0", ses));
#endif
break;
case ACT_MAIN_MACRO_1:
#ifdef CONFIG_EXMODE
try_exmode_exec(ses, get_opt_str("macro.1", ses));
#endif
break;
case ACT_MAIN_MACRO_2:
#ifdef CONFIG_EXMODE
try_exmode_exec(ses, get_opt_str("macro.2", ses));
#endif
break;
case ACT_MAIN_MACRO_3:
#ifdef CONFIG_EXMODE
try_exmode_exec(ses, get_opt_str("macro.3", ses));
#endif
break;
case ACT_MAIN_MACRO_4:
#ifdef CONFIG_EXMODE
try_exmode_exec(ses, get_opt_str("macro.4", ses));
#endif
break;
case ACT_MAIN_MACRO_5:
#ifdef CONFIG_EXMODE
try_exmode_exec(ses, get_opt_str("macro.5", ses));
#endif
break;
case ACT_MAIN_MACRO_6:
#ifdef CONFIG_EXMODE
try_exmode_exec(ses, get_opt_str("macro.6", ses));
#endif
break;
case ACT_MAIN_MACRO_7:
#ifdef CONFIG_EXMODE
try_exmode_exec(ses, get_opt_str("macro.7", ses));
#endif
break;
case ACT_MAIN_MACRO_8:
#ifdef CONFIG_EXMODE
try_exmode_exec(ses, get_opt_str("macro.8", ses));
#endif
break;
case ACT_MAIN_MACRO_9:
#ifdef CONFIG_EXMODE
try_exmode_exec(ses, get_opt_str("macro.9", ses));
#endif
break;
case ACT_MAIN_MARK_CLIPBOARD:
status = mark_clipboard(ses, doc_view);
break;
case ACT_MAIN_MARK_SET:
#ifdef CONFIG_MARKS
ses->kbdprefix.mark = KP_MARK_SET;
status = FRAME_EVENT_REFRESH;
#endif
break;
case ACT_MAIN_MARK_GOTO:
#ifdef CONFIG_MARKS
/* TODO: Show promptly a menu (or even listbox?)
* with all the marks. But the next letter must
* still choose a mark directly! --pasky */
ses->kbdprefix.mark = KP_MARK_GOTO;
status = FRAME_EVENT_REFRESH;
#endif
break;
case ACT_MAIN_MENU:
activate_bfu_technology(ses, -1);
break;
case ACT_MAIN_MOVE_CURRENT_TOP:
status = move_current_top(ses, doc_view);
break;
case ACT_MAIN_MOVE_CURSOR_UP:
status = move_cursor_up(ses, doc_view);
break;
case ACT_MAIN_MOVE_CURSOR_DOWN:
status = move_cursor_down(ses, doc_view);
break;
case ACT_MAIN_MOVE_CURSOR_LEFT:
status = move_cursor_left(ses, doc_view);
break;
case ACT_MAIN_MOVE_CURSOR_RIGHT:
status = move_cursor_right(ses, doc_view);
break;
case ACT_MAIN_MOVE_CURSOR_LINE_START:
status = move_cursor_line_start(ses, doc_view);
break;
case ACT_MAIN_MOVE_HALF_PAGE_DOWN:
status = move_half_page_down(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, 1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_HALF_PAGE_UP:
status = move_half_page_up(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, -1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_LINK_DOWN:
status = move_link_down(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, 1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_LINK_DOWN_LINE:
status = move_link_down_line(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, 1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_LINK_LEFT:
status = move_link_left(ses, doc_view);
break;
case ACT_MAIN_MOVE_LINK_LEFT_LINE:
status = move_link_prev_line(ses, doc_view);
break;
case ACT_MAIN_MOVE_LINK_NEXT:
status = move_link_next(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, 1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_LINK_PREV:
status = move_link_prev(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, -1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_LINK_RIGHT:
status = move_link_right(ses, doc_view);
break;
case ACT_MAIN_MOVE_LINK_RIGHT_LINE:
status = move_link_next_line(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, 1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_LINK_UP:
status = move_link_up(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, -1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_LINK_UP_LINE:
status = move_link_up_line(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, -1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_PAGE_DOWN:
status = move_page_down(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, 1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_PAGE_UP:
status = move_page_up(ses, doc_view);
if (status != FRAME_EVENT_REFRESH) {
next_frame(ses, -1);
draw_formatted(ses, 0);
}
break;
case ACT_MAIN_MOVE_DOCUMENT_START:
status = move_document_start(ses, doc_view);
break;
case ACT_MAIN_MOVE_DOCUMENT_END:
status = move_document_end(ses, doc_view);
break;
case ACT_MAIN_OPEN_LINK_IN_NEW_TAB:
open_current_link_in_new_tab(ses, 0);
break;
case ACT_MAIN_OPEN_LINK_IN_NEW_TAB_IN_BACKGROUND:
open_current_link_in_new_tab(ses, 1);
break;
case ACT_MAIN_OPEN_LINK_IN_NEW_WINDOW:
open_in_new_window(term, (void *)send_open_in_new_window, ses);
break;
case ACT_MAIN_OPEN_NEW_TAB:
open_uri_in_new_tab(ses, NULL, 0, 1);
break;
case ACT_MAIN_OPEN_NEW_TAB_IN_BACKGROUND:
open_uri_in_new_tab(ses, NULL, 1, 1);
break;
case ACT_MAIN_OPEN_NEW_WINDOW:
open_in_new_window(term, (void *)send_open_new_window, ses);
break;
case ACT_MAIN_OPEN_OS_SHELL:
exec_shell(term);
break;
case ACT_MAIN_OPTIONS_MANAGER:
options_manager(ses);
break;
case ACT_MAIN_QUIT:
exit_prog(ses, 1);
break;
case ACT_MAIN_REALLY_QUIT:
exit_prog(ses, 0);
break;
case ACT_MAIN_REDRAW:
redraw_terminal_cls(term);
break;
case ACT_MAIN_RELOAD:
reload(ses, CACHE_MODE_INCREMENT);
break;
case ACT_MAIN_RERENDER:
draw_formatted(ses, 2);
break;
case ACT_MAIN_RESET_FORM:
status = reset_form(ses, doc_view, 0);
break;
case ACT_MAIN_RESOURCE_INFO:
resource_info(term);
break;
case ACT_MAIN_SAVE_AS:
status = save_as(ses, doc_view, 0);
break;
case ACT_MAIN_SAVE_FORMATTED:
status = save_formatted_dlg(ses, doc_view, 0);
break;
case ACT_MAIN_SAVE_OPTIONS:
write_config(term);
break;
case ACT_MAIN_SAVE_URL_AS:
save_url_as(ses);
break;
case ACT_MAIN_SCROLL_DOWN:
status = scroll_down(ses, doc_view);
break;
case ACT_MAIN_SCROLL_LEFT:
status = scroll_left(ses, doc_view);
break;
case ACT_MAIN_SCROLL_RIGHT:
status = scroll_right(ses, doc_view);
break;
case ACT_MAIN_SCROLL_UP:
status = scroll_up(ses, doc_view);
break;
case ACT_MAIN_SEARCH:
status = search_dlg(ses, doc_view, 1);
break;
case ACT_MAIN_SEARCH_BACK:
status = search_dlg(ses, doc_view, -1);
break;
case ACT_MAIN_SEARCH_TYPEAHEAD:
case ACT_MAIN_SEARCH_TYPEAHEAD_LINK:
case ACT_MAIN_SEARCH_TYPEAHEAD_TEXT:
case ACT_MAIN_SEARCH_TYPEAHEAD_TEXT_BACK:
status = search_typeahead(ses, doc_view, action_id);
break;
case ACT_MAIN_SHOW_TERM_OPTIONS:
terminal_options(term, NULL, ses);
break;
case ACT_MAIN_SUBMIT_FORM:
status = submit_form(ses, doc_view, 0);
break;
case ACT_MAIN_SUBMIT_FORM_RELOAD:
status = submit_form(ses, doc_view, 1);
break;
case ACT_MAIN_TAB_CLOSE:
close_tab(term, ses);
status = FRAME_EVENT_SESSION_DESTROYED;
break;
case ACT_MAIN_TAB_CLOSE_ALL_BUT_CURRENT:
close_all_tabs_but_current(ses);
break;
case ACT_MAIN_TAB_EXTERNAL_COMMAND:
status = pass_uri_to_command(ses, doc_view,
PASS_URI_TAB);
break;
case ACT_MAIN_TAB_MOVE_LEFT:
move_current_tab(ses, -1);
break;
case ACT_MAIN_TAB_MOVE_RIGHT:
move_current_tab(ses, 1);
break;
case ACT_MAIN_TAB_MENU:
assert(ses->tab == get_current_tab(term));
if (ses->status.show_tabs_bar)
tab_menu(ses, ses->tab->xpos,
term->height - 1
- ses->status.show_status_bar,
1);
else
tab_menu(ses, 0, 0, 0);
break;
case ACT_MAIN_TAB_NEXT:
switch_current_tab(ses, 1);
break;
case ACT_MAIN_TAB_PREV:
switch_current_tab(ses, -1);
break;
case ACT_MAIN_TERMINAL_RESIZE:
resize_terminal_dialog(term);
break;
case ACT_MAIN_TOGGLE_CSS:
#ifdef CONFIG_CSS
toggle_document_option(ses, "document.css.enable");
#endif
break;
case ACT_MAIN_TOGGLE_DISPLAY_IMAGES:
toggle_document_option(ses, "document.browse.images.show_as_links");
break;
case ACT_MAIN_TOGGLE_DISPLAY_TABLES:
toggle_document_option(ses, "document.html.display_tables");
break;
case ACT_MAIN_TOGGLE_DOCUMENT_COLORS:
toggle_document_option(ses, "document.colors.use_document_colors");
break;
case ACT_MAIN_TOGGLE_DOCUMENT_WIDTH:
toggle_document_option(ses, "document.browse.use_preferred_document_width");
redraw_terminal_cls(term);
break;
case ACT_MAIN_TOGGLE_ECMASCRIPT:
#if defined(CONFIG_ECMASCRIPT_SMJS) || defined(CONFIG_QUICKJS) || defined(CONFIG_MUJS)
toggle_ecmascript(ses);
#endif
break;
case ACT_MAIN_TOGGLE_HTML_PLAIN:
toggle_plain_html(ses, ses->doc_view, 0);
break;
case ACT_MAIN_TOGGLE_MOUSE:
#ifdef CONFIG_MOUSE
toggle_mouse(ses);
#endif
break;
case ACT_MAIN_TOGGLE_NUMBERED_LINKS:
toggle_document_option(ses, "document.browse.links.numbering");
break;
case ACT_MAIN_TOGGLE_PLAIN_COMPRESS_EMPTY_LINES:
toggle_document_option(ses, "document.plain.compress_empty_lines");
break;
case ACT_MAIN_TOGGLE_WRAP_TEXT:
toggle_wrap_text(ses, ses->doc_view, 0);
break;
case ACT_MAIN_VIEW_IMAGE:
status = view_image(ses, doc_view, 0);
break;
case ACT_MAIN_SCRIPTING_FUNCTION:
case ACT_MAIN_NONE:
case MAIN_ACTIONS:
default:
unknown_action:
if (verbose) {
INTERNAL("No action handling defined for '%s'.",
get_action_name(KEYMAP_MAIN, action_id));
}
status = FRAME_EVENT_IGNORED;
}
ignore_action:
/* XXX: At this point the session may have been destroyed */
if (status != FRAME_EVENT_SESSION_DESTROYED
&& ses->insert_mode == INSERT_MODE_ON
&& link != get_current_link(doc_view))
ses->insert_mode = INSERT_MODE_OFF;
if (status == FRAME_EVENT_REFRESH && doc_view)
refresh_view(ses, doc_view, 0);
return status;
}