New action: move-cursor-line-start.
[elinks.git] / src / viewer / action.c
blob8e3196abe685435d756b4cbcf5007997ef520d22
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/festival.h"
43 #include "viewer/text/form.h"
44 #include "viewer/text/link.h"
45 #include "viewer/text/search.h"
46 #include "viewer/text/view.h"
49 static void
50 goto_url_action(struct session *ses,
51 unsigned char *(*get_url)(struct session *, unsigned char *, size_t))
53 unsigned char url[MAX_STR_LEN];
55 if (!get_url || !get_url(ses, url, sizeof(url)))
56 url[0] = 0;
58 dialog_goto_url(ses, url);
61 /* This could gradually become some multiplexor / switch noodle containing
62 * most if not all default handling of actions (for the main mapping) that
63 * frame_ev() and/or send_event() could use as a backend. */
64 /* Many execution paths may lead to this code so it needs to take appropriate
65 * precausions to stuff like doc_view and doc_view->vs being NULL. */
66 enum frame_event_status
67 do_action(struct session *ses, enum main_action action_id, int verbose)
69 enum frame_event_status status = FRAME_EVENT_OK;
70 struct terminal *term = ses->tab->term;
71 struct document_view *doc_view = current_frame(ses);
72 struct link *link = NULL;
74 if (action_id == -1) goto unknown_action;
76 if (doc_view && doc_view->vs) {
77 if (action_prefix_is_link_number(KEYMAP_MAIN, action_id)
78 && !try_jump_to_link_number(ses, doc_view))
79 goto ignore_action;
81 link = get_current_link(doc_view);
83 } else if (action_requires_view_state(KEYMAP_MAIN, action_id)) {
84 goto ignore_action;
87 if (action_requires_location(KEYMAP_MAIN, action_id)
88 && !have_location(ses))
89 return FRAME_EVENT_OK;
91 if (action_requires_link(KEYMAP_MAIN, action_id)
92 && !link)
93 goto ignore_action;
95 if (action_requires_form(KEYMAP_MAIN, action_id)
96 && (!link || !link_is_form(link)))
97 goto ignore_action;
99 if (!action_is_anonymous_safe(KEYMAP_MAIN, action_id)
100 && get_cmd_opt_bool("anonymous"))
101 goto ignore_action;
103 /* Please keep in alphabetical order for now. Later we can sort by most
104 * used or something. */
105 switch (action_id) {
106 case ACT_MAIN_ABORT_CONNECTION:
107 abort_loading(ses, 1);
108 print_screen_status(ses);
109 break;
111 case ACT_MAIN_ADD_BOOKMARK:
112 #ifdef CONFIG_BOOKMARKS
113 launch_bm_add_doc_dialog(term, NULL, ses);
114 #endif
115 break;
116 case ACT_MAIN_ADD_BOOKMARK_LINK:
117 #ifdef CONFIG_BOOKMARKS
118 launch_bm_add_link_dialog(term, NULL, ses);
119 #endif
120 break;
121 case ACT_MAIN_ADD_BOOKMARK_TABS:
122 #ifdef CONFIG_BOOKMARKS
123 bookmark_terminal_tabs_dialog(term);
124 #endif
125 break;
127 case ACT_MAIN_AUTH_MANAGER:
128 auth_manager(ses);
129 break;
131 case ACT_MAIN_BACKSPACE_PREFIX:
133 if (!ses->kbdprefix.repeat_count) break;
135 /* Clear the highlighting. */
136 draw_formatted(ses, 0);
138 ses->kbdprefix.repeat_count /= 10;
140 if (ses->kbdprefix.repeat_count)
141 highlight_links_with_prefixes_that_start_with_n(
142 term, doc_view,
143 ses->kbdprefix.repeat_count);
145 print_screen_status(ses);
147 /* Keep send_event from resetting repeat_count. */
148 status = FRAME_EVENT_SESSION_DESTROYED;
150 break;
152 case ACT_MAIN_BOOKMARK_MANAGER:
153 #ifdef CONFIG_BOOKMARKS
154 bookmark_manager(ses);
155 #endif
156 break;
158 case ACT_MAIN_CACHE_MANAGER:
159 cache_manager(ses);
160 break;
162 case ACT_MAIN_CACHE_MINIMIZE:
163 shrink_memory(1);
164 break;
166 case ACT_MAIN_COOKIES_LOAD:
167 #ifdef CONFIG_COOKIES
168 if (!get_opt_bool("cookies.save")) break;
169 load_cookies();
170 #endif
171 break;
173 case ACT_MAIN_COOKIE_MANAGER:
174 #ifdef CONFIG_COOKIES
175 cookie_manager(ses);
176 #endif
177 break;
179 case ACT_MAIN_COPY_CLIPBOARD:
180 status = copy_current_link_to_clipboard(ses, doc_view, 0);
181 break;
183 case ACT_MAIN_DOCUMENT_INFO:
184 document_info_dialog(ses);
185 break;
187 case ACT_MAIN_DOWNLOAD_MANAGER:
188 download_manager(ses);
189 break;
191 case ACT_MAIN_EXMODE:
192 #ifdef CONFIG_EXMODE
193 exmode_start(ses);
194 #endif
195 break;
197 case ACT_MAIN_FILE_MENU:
198 activate_bfu_technology(ses, 0);
199 break;
201 case ACT_MAIN_FIND_NEXT:
202 status = find_next(ses, doc_view, 1);
203 break;
205 case ACT_MAIN_FIND_NEXT_BACK:
206 status = find_next(ses, doc_view, -1);
207 break;
209 case ACT_MAIN_FORGET_CREDENTIALS:
210 free_auth();
211 shrink_memory(1); /* flush caches */
212 break;
214 case ACT_MAIN_FORMHIST_MANAGER:
215 #ifdef CONFIG_FORMHIST
216 formhist_manager(ses);
217 #endif
218 break;
220 case ACT_MAIN_FRAME_EXTERNAL_COMMAND:
221 status = pass_uri_to_command(ses, doc_view,
222 PASS_URI_FRAME);
223 break;
225 case ACT_MAIN_FRAME_NEXT:
226 next_frame(ses, 1);
227 draw_formatted(ses, 0);
228 break;
230 case ACT_MAIN_FRAME_MAXIMIZE:
231 status = set_frame(ses, doc_view, 0);
232 break;
234 case ACT_MAIN_FRAME_PREV:
235 next_frame(ses, -1);
236 draw_formatted(ses, 0);
237 break;
239 case ACT_MAIN_GOTO_URL:
240 goto_url_action(ses, NULL);
241 break;
243 case ACT_MAIN_GOTO_URL_CURRENT:
244 goto_url_action(ses, get_current_url);
245 break;
247 case ACT_MAIN_GOTO_URL_CURRENT_LINK:
248 goto_url_action(ses, get_current_link_url);
249 break;
251 case ACT_MAIN_GOTO_URL_HOME:
252 goto_url_home(ses);
253 break;
255 case ACT_MAIN_HEADER_INFO:
256 protocol_header_dialog(ses);
257 break;
259 case ACT_MAIN_HISTORY_MANAGER:
260 #ifdef CONFIG_GLOBHIST
261 history_manager(ses);
262 #endif
263 break;
265 case ACT_MAIN_HISTORY_MOVE_BACK:
267 int count = int_max(1, eat_kbd_repeat_count(ses));
269 go_history_by_n(ses, -count);
270 break;
272 case ACT_MAIN_HISTORY_MOVE_FORWARD:
274 int count = int_max(1, eat_kbd_repeat_count(ses));
276 go_history_by_n(ses, count);
277 break;
279 case ACT_MAIN_JUMP_TO_LINK:
280 break;
282 case ACT_MAIN_KEYBINDING_MANAGER:
283 keybinding_manager(ses);
284 break;
286 case ACT_MAIN_KILL_BACKGROUNDED_CONNECTIONS:
287 abort_background_connections();
288 break;
290 case ACT_MAIN_LINK_DOWNLOAD:
291 case ACT_MAIN_LINK_DOWNLOAD_IMAGE:
292 case ACT_MAIN_LINK_DOWNLOAD_RESUME:
293 status = download_link(ses, doc_view, action_id);
294 break;
296 case ACT_MAIN_LINK_EXTERNAL_COMMAND:
297 status = pass_uri_to_command(ses, doc_view,
298 PASS_URI_LINK);
299 break;
301 case ACT_MAIN_LINK_FOLLOW:
302 status = enter(ses, doc_view, 0);
303 break;
305 case ACT_MAIN_LINK_FOLLOW_RELOAD:
306 status = enter(ses, doc_view, 1);
307 break;
309 case ACT_MAIN_LINK_MENU:
310 link_menu(term, NULL, ses);
311 break;
313 case ACT_MAIN_LINK_FORM_MENU:
314 link_form_menu(ses);
315 break;
317 case ACT_MAIN_LUA_CONSOLE:
318 #ifdef CONFIG_SCRIPTING_LUA
319 trigger_event_name("dialog-lua-console", ses);
320 #endif
321 break;
323 case ACT_MAIN_MARK_SET:
324 #ifdef CONFIG_MARKS
325 ses->kbdprefix.mark = KP_MARK_SET;
326 status = FRAME_EVENT_REFRESH;
327 #endif
328 break;
330 case ACT_MAIN_MARK_GOTO:
331 #ifdef CONFIG_MARKS
332 /* TODO: Show promptly a menu (or even listbox?)
333 * with all the marks. But the next letter must
334 * still choose a mark directly! --pasky */
335 ses->kbdprefix.mark = KP_MARK_GOTO;
336 status = FRAME_EVENT_REFRESH;
337 #endif
338 break;
340 case ACT_MAIN_MENU:
341 activate_bfu_technology(ses, -1);
342 break;
344 case ACT_MAIN_MOVE_CURSOR_UP:
345 status = move_cursor_up(ses, doc_view);
346 break;
348 case ACT_MAIN_MOVE_CURSOR_DOWN:
349 status = move_cursor_down(ses, doc_view);
350 break;
352 case ACT_MAIN_MOVE_CURSOR_LEFT:
353 status = move_cursor_left(ses, doc_view);
354 break;
356 case ACT_MAIN_MOVE_CURSOR_RIGHT:
357 status = move_cursor_right(ses, doc_view);
358 break;
360 case ACT_MAIN_MOVE_CURSOR_LINE_START:
361 status = move_cursor_line_start(ses, doc_view);
362 break;
364 case ACT_MAIN_MOVE_LINK_DOWN:
365 status = move_link_down(ses, doc_view);
366 break;
368 case ACT_MAIN_MOVE_LINK_DOWN_LINE:
369 status = move_link_down_line(ses, doc_view);
370 break;
372 case ACT_MAIN_MOVE_LINK_LEFT:
373 status = move_link_left(ses, doc_view);
374 break;
376 case ACT_MAIN_MOVE_LINK_LEFT_LINE:
377 status = move_link_prev_line(ses, doc_view);
378 break;
380 case ACT_MAIN_MOVE_LINK_NEXT:
381 status = move_link_next(ses, doc_view);
382 break;
384 case ACT_MAIN_MOVE_LINK_PREV:
385 status = move_link_prev(ses, doc_view);
386 break;
388 case ACT_MAIN_MOVE_LINK_RIGHT:
389 status = move_link_right(ses, doc_view);
390 break;
392 case ACT_MAIN_MOVE_LINK_RIGHT_LINE:
393 status = move_link_next_line(ses, doc_view);
394 break;
396 case ACT_MAIN_MOVE_LINK_UP:
397 status = move_link_up(ses, doc_view);
398 break;
400 case ACT_MAIN_MOVE_LINK_UP_LINE:
401 status = move_link_up_line(ses, doc_view);
402 break;
404 case ACT_MAIN_MOVE_PAGE_DOWN:
405 status = move_page_down(ses, doc_view);
406 break;
408 case ACT_MAIN_MOVE_PAGE_UP:
409 status = move_page_up(ses, doc_view);
410 break;
412 case ACT_MAIN_MOVE_DOCUMENT_START:
413 status = move_document_start(ses, doc_view);
414 break;
416 case ACT_MAIN_MOVE_DOCUMENT_END:
417 status = move_document_end(ses, doc_view);
418 break;
420 case ACT_MAIN_OPEN_LINK_IN_NEW_TAB:
421 open_current_link_in_new_tab(ses, 0);
422 break;
424 case ACT_MAIN_OPEN_LINK_IN_NEW_TAB_IN_BACKGROUND:
425 open_current_link_in_new_tab(ses, 1);
426 break;
428 case ACT_MAIN_OPEN_LINK_IN_NEW_WINDOW:
429 open_in_new_window(term, send_open_in_new_window, ses);
430 break;
432 case ACT_MAIN_OPEN_NEW_TAB:
433 open_uri_in_new_tab(ses, NULL, 0, 1);
434 break;
436 case ACT_MAIN_OPEN_NEW_TAB_IN_BACKGROUND:
437 open_uri_in_new_tab(ses, NULL, 1, 1);
438 break;
440 case ACT_MAIN_OPEN_NEW_WINDOW:
441 open_in_new_window(term, send_open_new_window, ses);
442 break;
444 case ACT_MAIN_OPEN_OS_SHELL:
445 exec_shell(term);
446 break;
448 case ACT_MAIN_OPTIONS_MANAGER:
449 options_manager(ses);
450 break;
452 case ACT_MAIN_QUIT:
453 exit_prog(ses, 1);
454 break;
456 case ACT_MAIN_REALLY_QUIT:
457 exit_prog(ses, 0);
458 break;
460 case ACT_MAIN_REDRAW:
461 redraw_terminal_cls(term);
462 break;
464 case ACT_MAIN_RELOAD:
465 reload(ses, CACHE_MODE_INCREMENT);
466 break;
468 case ACT_MAIN_RERENDER:
469 draw_formatted(ses, 2);
470 break;
472 case ACT_MAIN_RESET_FORM:
473 status = reset_form(ses, doc_view, 0);
474 break;
476 case ACT_MAIN_RESOURCE_INFO:
477 resource_info(term);
478 break;
480 case ACT_MAIN_SAVE_AS:
481 status = save_as(ses, doc_view, 0);
482 break;
484 case ACT_MAIN_SAVE_FORMATTED:
485 status = save_formatted_dlg(ses, doc_view, 0);
486 break;
488 case ACT_MAIN_SAVE_OPTIONS:
489 write_config(term);
490 break;
492 case ACT_MAIN_SAVE_URL_AS:
493 save_url_as(ses);
494 break;
496 case ACT_MAIN_SAY_TEXT:
497 #ifdef HAVE_FORK
498 run_festival(ses, doc_view);
499 #endif
500 break;
502 case ACT_MAIN_SCROLL_DOWN:
503 status = scroll_down(ses, doc_view);
504 break;
506 case ACT_MAIN_SCROLL_LEFT:
507 status = scroll_left(ses, doc_view);
508 break;
510 case ACT_MAIN_SCROLL_RIGHT:
511 status = scroll_right(ses, doc_view);
512 break;
514 case ACT_MAIN_SCROLL_UP:
515 status = scroll_up(ses, doc_view);
516 break;
518 case ACT_MAIN_SEARCH:
519 status = search_dlg(ses, doc_view, 1);
520 break;
522 case ACT_MAIN_SEARCH_BACK:
523 status = search_dlg(ses, doc_view, -1);
524 break;
526 case ACT_MAIN_SEARCH_TYPEAHEAD:
527 case ACT_MAIN_SEARCH_TYPEAHEAD_LINK:
528 case ACT_MAIN_SEARCH_TYPEAHEAD_TEXT:
529 case ACT_MAIN_SEARCH_TYPEAHEAD_TEXT_BACK:
530 status = search_typeahead(ses, doc_view, action_id);
531 break;
533 case ACT_MAIN_SHOW_TERM_OPTIONS:
534 terminal_options(term, NULL, ses);
535 break;
537 case ACT_MAIN_SUBMIT_FORM:
538 status = submit_form(ses, doc_view, 0);
539 break;
541 case ACT_MAIN_SUBMIT_FORM_RELOAD:
542 status = submit_form(ses, doc_view, 1);
543 break;
545 case ACT_MAIN_TAB_CLOSE:
546 close_tab(term, ses);
547 status = FRAME_EVENT_SESSION_DESTROYED;
548 break;
550 case ACT_MAIN_TAB_CLOSE_ALL_BUT_CURRENT:
551 close_all_tabs_but_current(ses);
552 break;
554 case ACT_MAIN_TAB_EXTERNAL_COMMAND:
555 status = pass_uri_to_command(ses, doc_view,
556 PASS_URI_TAB);
557 break;
559 case ACT_MAIN_TAB_MOVE_LEFT:
560 move_current_tab(ses, -1);
561 break;
563 case ACT_MAIN_TAB_MOVE_RIGHT:
564 move_current_tab(ses, 1);
565 break;
567 case ACT_MAIN_TAB_MENU:
568 assert(ses->tab == get_current_tab(term));
570 if (ses->status.show_tabs_bar)
571 tab_menu(ses, ses->tab->xpos,
572 term->height - 1
573 - ses->status.show_status_bar,
575 else
576 tab_menu(ses, 0, 0, 0);
578 break;
580 case ACT_MAIN_TAB_NEXT:
581 switch_current_tab(ses, 1);
582 break;
584 case ACT_MAIN_TAB_PREV:
585 switch_current_tab(ses, -1);
586 break;
588 case ACT_MAIN_TERMINAL_RESIZE:
589 resize_terminal_dialog(term);
590 break;
592 case ACT_MAIN_TOGGLE_CSS:
593 #ifdef CONFIG_CSS
594 toggle_document_option(ses, "document.css.enable");
595 #endif
596 break;
598 case ACT_MAIN_TOGGLE_DISPLAY_IMAGES:
599 toggle_document_option(ses, "document.browse.images.show_as_links");
600 break;
602 case ACT_MAIN_TOGGLE_DISPLAY_TABLES:
603 toggle_document_option(ses, "document.html.display_tables");
604 break;
606 case ACT_MAIN_TOGGLE_DOCUMENT_COLORS:
607 toggle_document_option(ses, "document.colors.use_document_colors");
608 break;
610 case ACT_MAIN_TOGGLE_HTML_PLAIN:
611 toggle_plain_html(ses, ses->doc_view, 0);
612 break;
614 case ACT_MAIN_TOGGLE_MOUSE:
615 #ifdef CONFIG_MOUSE
616 toggle_mouse();
617 #endif
618 break;
620 case ACT_MAIN_TOGGLE_NUMBERED_LINKS:
621 toggle_document_option(ses, "document.browse.links.numbering");
622 break;
624 case ACT_MAIN_TOGGLE_PLAIN_COMPRESS_EMPTY_LINES:
625 toggle_document_option(ses, "document.plain.compress_empty_lines");
626 break;
628 case ACT_MAIN_TOGGLE_WRAP_TEXT:
629 toggle_wrap_text(ses, ses->doc_view, 0);
630 break;
632 case ACT_MAIN_VIEW_IMAGE:
633 status = view_image(ses, doc_view, 0);
634 break;
636 case ACT_MAIN_SCRIPTING_FUNCTION:
637 case ACT_MAIN_NONE:
638 case MAIN_ACTIONS:
639 default:
640 unknown_action:
641 if (verbose) {
642 INTERNAL("No action handling defined for '%s'.",
643 get_action_name(KEYMAP_MAIN, action_id));
646 status = FRAME_EVENT_IGNORED;
649 ignore_action:
650 /* XXX: At this point the session may have been destroyed */
652 if (status != FRAME_EVENT_SESSION_DESTROYED
653 && ses->insert_mode == INSERT_MODE_ON
654 && link != get_current_link(doc_view))
655 ses->insert_mode = INSERT_MODE_OFF;
657 if (status == FRAME_EVENT_REFRESH && doc_view)
658 refresh_view(ses, doc_view, 0);
660 return status;