📄 link.c
字号:
uri = get_link_uri(ses, doc_view, link); if (!uri) return NULL; if (link->type == LINK_MAP) { /* TODO: Test reload? */ goto_imgmap(ses, uri, null_or_stracpy(link->target)); } else { enum cache_mode mode = do_reload ? CACHE_MODE_FORCE_RELOAD : CACHE_MODE_NORMAL; goto_uri_frame(ses, uri, link->target, mode); } done_uri(uri); return link;}enum frame_event_statusenter(struct session *ses, struct document_view *doc_view, int do_reload){ struct form_control *link_fc; struct link *link; assert(ses && doc_view && doc_view->vs && doc_view->document); if_assert_failed return FRAME_EVENT_REFRESH; link = get_current_link(doc_view); if (!link) return FRAME_EVENT_REFRESH; if (!current_link_evhook(doc_view, SEVHOOK_ONCLICK)) return FRAME_EVENT_REFRESH; if (!link_is_form(link) || link_is_textinput(link) || link->type == LINK_BUTTON) { if (goto_current_link(ses, doc_view, do_reload)) return FRAME_EVENT_OK; return FRAME_EVENT_REFRESH; } link_fc = get_link_form_control(link); if (form_field_is_readonly(link_fc)) return FRAME_EVENT_OK; if (link->type == LINK_CHECKBOX) { struct form_state *fs; fs = find_form_state(doc_view, link_fc); if (!fs) return FRAME_EVENT_OK; if (link_fc->type == FC_CHECKBOX) { fs->state = !fs->state; } else { struct form *form; foreach (form, doc_view->document->forms) { struct form_control *fc; if (form != link_fc->form) continue; foreach (fc, form->items) { if (fc->type == FC_RADIO && !xstrcmp(fc->name, link_fc->name)) { struct form_state *frm_st; frm_st = find_form_state(doc_view, fc); if (frm_st) frm_st->state = 0; } } } fs->state = 1; } } else if (link->type == LINK_SELECT) { object_lock(doc_view->document); add_empty_window(ses->tab->term, (void (*)(void *)) release_document, doc_view->document); do_select_submenu(ses->tab->term, link_fc->menu, ses); } else { INTERNAL("bad link type %d", link->type); } return FRAME_EVENT_REFRESH;}struct link *get_link_at_coordinates(struct document_view *doc_view, int x, int y){ struct link *l1, *l2, *link; int i, height; assert(doc_view && doc_view->vs && doc_view->document); if_assert_failed return NULL; /* If there are no links in in document, there is nothing to do. */ if (!doc_view->document->nlinks) return NULL; /* If the coordinates are outside document view, no need to go further. */ if (x < 0 || x >= doc_view->box.width) return NULL; if (y < 0 || y >= doc_view->box.height) return NULL; /* FIXME: This doesn't work. --Zas if (!check_mouse_position(ev, &doc_view->box)) return NULL; */ /* Find link candidates. */ l1 = doc_view->document->links + doc_view->document->nlinks; l2 = doc_view->document->links; height = int_min(doc_view->document->height, doc_view->vs->y + doc_view->box.height); for (i = doc_view->vs->y; i < height; i++) { if (doc_view->document->lines1[i] && doc_view->document->lines1[i] < l1) l1 = doc_view->document->lines1[i]; if (doc_view->document->lines2[i] && doc_view->document->lines2[i] > l2) l2 = doc_view->document->lines2[i]; } /* Is there a link at the given coordinates? */ x += doc_view->vs->x; y += doc_view->vs->y; for (link = l1; link <= l2; link++) { for (i = 0; i < link->npoints; i++) if (link->points[i].x == x && link->points[i].y == y) return link; } return NULL;}/* This is backend of the backend goto_link_number_do() below ;)). */voidjump_to_link_number(struct session *ses, struct document_view *doc_view, int n){ assert(ses && doc_view && doc_view->vs && doc_view->document); if_assert_failed return; if (n < 0 || n >= doc_view->document->nlinks) return; current_link_blur(doc_view); doc_view->vs->current_link = n; if (ses->navigate_mode == NAVIGATE_CURSOR_ROUTING) { struct link *link = get_current_link(doc_view); int offset = get_link_cursor_offset(doc_view, link); if (link->npoints > offset) { int x = link->points[offset].x + doc_view->box.x - doc_view->vs->x; int y = link->points[offset].y + doc_view->box.y - doc_view->vs->y; move_cursor(ses, doc_view, x, y); } } check_vs(doc_view); current_link_hover(doc_view);}/* This is common backend for goto_link_number() and try_document_key(). */static voidgoto_link_number_do(struct session *ses, struct document_view *doc_view, int n){ struct link *link; assert(ses && doc_view && doc_view->document); if_assert_failed return; if (n < 0 || n >= doc_view->document->nlinks) return; jump_to_link_number(ses, doc_view, n); link = &doc_view->document->links[n]; if (!link_is_textinput(link) && get_opt_bool("document.browse.accesskey.auto_follow")) enter(ses, doc_view, 0);}voidgoto_link_number(struct session *ses, unsigned char *num){ struct document_view *doc_view; assert(ses && num); if_assert_failed return; doc_view = current_frame(ses); assert(doc_view); if_assert_failed return; goto_link_number_do(ses, doc_view, atoi(num) - 1);}/* See if this document is interested in the key user pressed. */enum frame_event_statustry_document_key(struct session *ses, struct document_view *doc_view, struct term_event *ev){ long key; int passed = -1; int i; /* GOD I HATE C! --FF */ /* YEAH, BRAINFUCK RULEZ! --pasky */ assert(ses && doc_view && doc_view->document && doc_view->vs && ev); if_assert_failed return FRAME_EVENT_IGNORED; if (isasciialpha(get_kbd_key(ev)) && !check_kbd_modifier(ev, KBD_ALT)) { /* We accept those only in alt-combo. */ return FRAME_EVENT_IGNORED; } /* Run through all the links and see if one of them is bound to the * key we test.. */ key = toupper(get_kbd_key(ev)); for (i = 0; i < doc_view->document->nlinks; i++) { struct link *link = &doc_view->document->links[i]; if (key == link->accesskey) { if (passed != i && i <= doc_view->vs->current_link) { /* This is here in order to rotate between * links with same accesskey. */ if (passed < 0) passed = i; continue; } ses->kbdprefix.repeat_count = 0; goto_link_number_do(ses, doc_view, i); return FRAME_EVENT_REFRESH; } if (i == doc_view->document->nlinks - 1 && passed >= 0) { /* Return to the start. */ i = passed - 1; } } return FRAME_EVENT_IGNORED;}/* Open a contextual menu on a link, form or image element. *//* TODO: This should be completely configurable. */voidlink_menu(struct terminal *term, void *xxx, void *ses_){ struct session *ses = ses_; struct document_view *doc_view; struct link *link; struct menu_item *mi; struct form_control *fc; assert(term && ses); if_assert_failed return; doc_view = current_frame(ses); mi = new_menu(FREE_LIST); if (!mi) return; if (!doc_view) goto end; assert(doc_view->vs && doc_view->document); if_assert_failed return; link = get_current_link(doc_view); if (!link) goto end; if (link->where && !link_is_form(link)) { if (link->type == LINK_MAP) { add_to_menu(&mi, N_("Display ~usemap"), NULL, ACT_MAIN_LINK_FOLLOW, NULL, NULL, SUBMENU); } else { add_menu_action(&mi, N_("~Follow link"), ACT_MAIN_LINK_FOLLOW); add_menu_action(&mi, N_("Follow link and r~eload"), ACT_MAIN_LINK_FOLLOW_RELOAD); add_menu_separator(&mi); add_new_win_to_menu(&mi, N_("Open in new ~window"), term); add_menu_action(&mi, N_("Open in new ~tab"), ACT_MAIN_OPEN_LINK_IN_NEW_TAB); add_menu_action(&mi, N_("Open in new tab in ~background"), ACT_MAIN_OPEN_LINK_IN_NEW_TAB_IN_BACKGROUND); if (!get_cmd_opt_bool("anonymous")) { add_menu_separator(&mi); add_menu_action(&mi, N_("~Download link"), ACT_MAIN_LINK_DOWNLOAD);#ifdef CONFIG_BOOKMARKS add_menu_action(&mi, N_("~Add link to bookmarks"), ACT_MAIN_ADD_BOOKMARK_LINK);#endif add_uri_command_to_menu(&mi, PASS_URI_LINK); } } } fc = get_link_form_control(link); if (fc) { switch (fc->type) { case FC_RESET: add_menu_action(&mi, N_("~Reset form"), ACT_MAIN_RESET_FORM); break; case FC_TEXTAREA: if (!form_field_is_readonly(fc)) { struct string keystroke; if (init_string(&keystroke)) add_keystroke_to_string(&keystroke, ACT_EDIT_OPEN_EXTERNAL, KEYMAP_EDIT); add_to_menu(&mi, N_("Open in ~external editor"), keystroke.source, ACT_MAIN_NONE, menu_textarea_edit, NULL, FREE_RTEXT); } /* Fall through */ default: add_menu_action(&mi, N_("~Submit form"), ACT_MAIN_SUBMIT_FORM); add_menu_action(&mi, N_("Submit form and rel~oad"), ACT_MAIN_SUBMIT_FORM_RELOAD); assert(fc->form); if (fc->form->method == FORM_METHOD_GET) { add_new_win_to_menu(&mi, N_("Submit form and open in new ~window"), term); add_menu_action(&mi, N_("Submit form and open in new ~tab"), ACT_MAIN_OPEN_LINK_IN_NEW_TAB); add_menu_action(&mi, N_("Submit form and open in new tab in ~background"), ACT_MAIN_OPEN_LINK_IN_NEW_TAB_IN_BACKGROUND); } if (!get_cmd_opt_bool("anonymous")) add_menu_action(&mi, N_("Submit form and ~download"), ACT_MAIN_LINK_DOWNLOAD); add_menu_action(&mi, N_("~Reset form"), ACT_MAIN_RESET_FORM); } } if (link->where_img) { add_menu_action(&mi, N_("V~iew image"), ACT_MAIN_VIEW_IMAGE); if (!get_cmd_opt_bool("anonymous")) add_menu_action(&mi, N_("Download ima~ge"), ACT_MAIN_LINK_DOWNLOAD_IMAGE); } /* TODO: Make it possible to trigger any script event hooks associated * to the link. --pasky */end: if (!mi->text) { add_to_menu(&mi, N_("No link selected"), NULL, ACT_MAIN_NONE, NULL, NULL, NO_SELECT); } do_menu(term, mi, ses, 1);}/* Return current link's title. Pretty trivial. */unsigned char *get_current_link_title(struct document_view *doc_view){ struct link *link; assert(doc_view && doc_view->document && doc_view->vs); if_assert_failed return NULL; if (doc_view->document->frame_desc) return NULL; link = get_current_link(doc_view); return (link && link->title && *link->title) ? stracpy(link->title) : NULL;}unsigned char *get_current_link_info(struct session *ses, struct document_view *doc_view){ struct link *link; assert(ses && doc_view && doc_view->document && doc_view->vs); if_assert_failed return NULL; if (doc_view->document->frame_desc) return NULL; link = get_current_link(doc_view); if (!link) return NULL; /* TODO: Provide info about script event hooks too. --pasky */ if (link_is_form(link)) { if (!get_link_form_control(link)) return NULL; return get_form_info(ses, doc_view); } else { struct terminal *term = ses->tab->term; struct string str; unsigned char *uristring = link->where; if (!init_string(&str)) return NULL; if (!link->where && link->where_img) { add_to_string(&str, _("Image", term)); add_char_to_string(&str, ' '); uristring = link->where_img; } else if (link->type == LINK_MAP) { add_to_string(&str, _("Usemap", term)); add_char_to_string(&str, ' '); } /* Add the uri with password and post info stripped */ add_string_uri_to_string(&str, uristring, URI_PUBLIC); if (link->accesskey > 0 && get_opt_bool("document.browse.accesskey.display")) { add_to_string(&str, " ("); make_keystroke(&str, link->accesskey, 0, 0); add_char_to_string(&str, ')'); } decode_uri_string_for_display(&str); return str.source; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -