📄 session.c
字号:
voidcheck_questions_queue(struct session *ses){ while (!list_empty(questions_queue)) { struct questions_entry *q = questions_queue.next; q->callback(ses, q->data); del_from_list(q); mem_free(q); }}voidadd_questions_entry(void (*callback)(struct session *, void *), void *data){ struct questions_entry *q = mem_alloc(sizeof(*q)); if (!q) return; q->callback = callback; q->data = data; add_to_list(questions_queue, q);}#ifdef CONFIG_SCRIPTINGstatic voidmaybe_pre_format_html(struct cache_entry *cached, struct session *ses){ struct fragment *fragment; unsigned char *src; int len; static int pre_format_html_event = EVENT_NONE; if (!cached || cached->preformatted || list_empty(cached->frag)) return; fragment = get_cache_fragment(cached); if (!fragment) return; src = fragment->data; len = fragment->length; set_event_id(pre_format_html_event, "pre-format-html"); trigger_event(pre_format_html_event, &src, &len, ses, struri(cached->uri)); if (src && src != fragment->data) { add_fragment(cached, 0, src, len); truncate_entry(cached, len, 1); cached->incomplete = 0; /* XXX */ mem_free(src); } cached->preformatted = 1;}#endifstatic intcheck_incomplete_redirects(struct cache_entry *cached){ assert(cached); cached = follow_cached_redirects(cached); if (cached && !cached->redirect) { /* XXX: This is not quite true, but does that difference * matter here? */ return cached->incomplete; } return 0;}intsession_is_loading(struct session *ses){ struct download *download = get_current_download(ses); if (!download) return 0; if (!is_in_result_state(download->state)) return 1; /* The validness of download->cached (especially the download struct in * ses->loading) is hard to maintain so check before using it. * Related to bug 559. */ if (download->cached && cache_entry_is_valid(download->cached) && check_incomplete_redirects(download->cached)) return 1; return 0;}voiddoc_loading_callback(struct download *download, struct session *ses){ int submit = 0; if (is_in_result_state(download->state)) {#ifdef CONFIG_SCRIPTING maybe_pre_format_html(download->cached, ses);#endif if (ses->display_timer != -1) { kill_timer(ses->display_timer); ses->display_timer = -1; } draw_formatted(ses, 1); if (get_cmd_opt_bool("auto-submit")) { if (!list_empty(ses->doc_view->document->forms)) { get_cmd_opt_bool("auto-submit") = 0; submit = 1; } } load_frames(ses, ses->doc_view); load_css_imports(ses, ses->doc_view); load_ecmascript_imports(ses, ses->doc_view); process_file_requests(ses); if (ses->doc_view->document->refresh && get_opt_bool("document.browse.refresh")) { start_document_refresh(ses->doc_view->document->refresh, ses); } if (download->state != S_OK) { print_error_dialog(ses, download->state, ses->doc_view->document->uri, download->pri); } } else if (is_in_transfering_state(download->state) && ses->display_timer == -1) { display_timer(ses); } check_questions_queue(ses); print_screen_status(ses);#ifdef CONFIG_GLOBHIST if (download->conn && download->pri != PRI_CSS) { unsigned char *title = ses->doc_view->document->title; struct uri *uri = download->conn->proxied_uri; add_global_history_item(struri(uri), title, time(NULL)); }#endif if (submit) auto_submit_form(ses);}static voidfile_loading_callback(struct download *download, struct file_to_load *ftl){ if (ftl->download.cached) { if (ftl->cached) object_unlock(ftl->cached); ftl->cached = ftl->download.cached; object_lock(ftl->cached); } /* FIXME: We need to do content-type check here! However, we won't * handle properly the "Choose action" dialog now :(. */ if (ftl->cached && !ftl->cached->redirect_get && download->pri != PRI_CSS) { struct session *ses = ftl->ses; struct uri *loading_uri = ses->loading_uri; unsigned char *target_frame = ses->task.target_frame; ses->loading_uri = ftl->uri; ses->task.target_frame = ftl->target_frame; ses_chktype(ses, &ftl->download, ftl->cached, 1); ses->loading_uri = loading_uri; ses->task.target_frame = target_frame; } doc_loading_callback(download, ftl->ses);}static struct file_to_load *request_additional_file(struct session *ses, unsigned char *name, struct uri *uri, int pri){ struct file_to_load *ftl; if (uri->protocol == PROTOCOL_UNKNOWN) { return NULL; } /* XXX: We cannot run the external handler here, because * request_additional_file() is called many times for a single URL * (normally the foreach() right below catches them all). Anyway, * having <frame src="mailto:foo"> would be just weird, wouldn't it? * --pasky */ if (get_protocol_external_handler(uri->protocol)) { return NULL; } foreach (ftl, ses->more_files) { if (compare_uri(ftl->uri, uri, URI_BASE)) { if (ftl->pri > pri) { ftl->pri = pri; change_connection(&ftl->download, &ftl->download, pri, 0); } return NULL; } } ftl = mem_calloc(1, sizeof(*ftl)); if (!ftl) return NULL; ftl->uri = get_uri_reference(uri); ftl->target_frame = stracpy(name); ftl->download.callback = (void (*)(struct download *, void *)) file_loading_callback; ftl->download.data = ftl; ftl->pri = pri; ftl->ses = ses; add_to_list(ses->more_files, ftl); return ftl;}static voidload_additional_file(struct file_to_load *ftl, struct document_view *doc_view, enum cache_mode cache_mode){ struct uri *referrer = doc_view && doc_view->document ? doc_view->document->uri : NULL; load_uri(ftl->uri, referrer, &ftl->download, ftl->pri, cache_mode, -1);}voidprocess_file_requests(struct session *ses){ struct file_to_load *ftl; struct document_view *doc_view = current_frame(ses); int more; if (ses->status.processing_file_requests) return; ses->status.processing_file_requests = 1; do { more = 0; foreach (ftl, ses->more_files) { if (ftl->req_sent) continue; ftl->req_sent = 1; load_additional_file(ftl, doc_view, CACHE_MODE_NORMAL); more = 1; } } while (more); ses->status.processing_file_requests = 0;}static voiddialog_goto_url_open(void *data){ dialog_goto_url((struct session *) data, NULL);}/* Returns 0 if the first session was not properly initialized and * setup_session() should be called on the session as well. */static intsetup_first_session(struct session *ses, struct uri *uri){ struct terminal *term = ses->tab->term; if (!*get_opt_str("protocol.http.user_agent")) { info_box(term, 0, N_("Warning"), ALIGN_CENTER, N_("You have empty string in protocol.http.user_agent - " "this was a default value in the past, substituted by " "default ELinks User-Agent string. However, currently " "this means that NO User-Agent HEADER " "WILL BE SENT AT ALL - if this is really what you want, " "set its value to \" \", otherwise please delete line " "with this settings from your configuration file (if you " "have no idea what I'm talking about, just do this), so " "that correct default setting will be used. Apologies for " "any inconvience caused.")); } if (!get_opt_bool("config.saving_style_w")) { get_opt_bool("config.saving_style_w") = 1; get_opt_rec(config_options, "config.saving_style_w")->flags |= OPT_TOUCHED; if (get_opt_int("config.saving_style") != 3) { info_box(term, 0, N_("Warning"), ALIGN_CENTER, N_("You have option config.saving_style set to " "a de facto obsolete value. The configuration " "saving algorithms of ELinks were changed from " "the last time you upgraded ELinks. Now, only " "those options which you actually changed are " "saved to the configuration file, instead of " "just all the options. This simplifies our " "situation greatly when we see that some option " "has inappropriate default value or we need to " "change semantic of some option in a subtle way. " "Thus, we recommend you to change the value of " "config.saving_style option to 3 in order to get " "the \"right\" behaviour. Apologies for any " "inconvience caused.")); } } if (first_use) { /* Only open the goto URL dialog if no URI was passed on the * command line. */ void *handler = uri ? NULL : dialog_goto_url_open; first_use = 0; msg_box(term, NULL, 0, N_("Welcome"), ALIGN_CENTER, N_("Welcome to ELinks!\n\n" "Press ESC for menu. Documentation is available in " "Help menu."), ses, 1, N_("~OK"), handler, B_ENTER | B_ESC); /* If there is no URI the goto dialog will pop up so there is * no need to call setup_session(). */ if (!uri) return 1;#ifdef CONFIG_BOOKMARKS } else if (!uri && get_opt_bool("ui.sessions.auto_restore")) { unsigned char *folder; folder = get_opt_str("ui.sessions.auto_save_foldername"); open_bookmark_folder(ses, folder); return 1;#endif } /* If there's a URI to load we have to call */ return 0;}/* First load the current URI of the base session. In most cases it will just * be fetched from the cache so that the new tab will not appear ``empty' while * loading the real URI or showing the goto URL dialog. */static voidsetup_session(struct session *ses, struct uri *uri, struct session *base){ if (base && have_location(base)) goto_uri(ses, cur_loc(base)->vs.uri); if (uri) { goto_uri(ses, uri); } else if (!goto_url_home(ses)) { if (get_opt_bool("ui.startup_goto_dialog")) { dialog_goto_url_open(ses); } }}struct session *init_session(struct session *base_session, struct terminal *term, struct uri *uri, int in_background){ struct session *ses = mem_calloc(1, sizeof(*ses)); if (!ses) return NULL; ses->tab = init_tab(term, ses, tabwin_func); if (!ses->tab) { mem_free(ses); return NULL; } create_history(&ses->history); init_list(ses->scrn_frames); init_list(ses->more_files); init_list(ses->type_queries); ses->task.type = TASK_NONE; ses->display_timer = -1;#ifdef CONFIG_LEDS init_led_panel(&ses->status.leds); ses->status.ssl_led = register_led(ses, 0); ses->status.insert_mode_led = register_led(ses, 1); ses->status.ecmascript_led = register_led(ses, 2); ses->status.popup_led = register_led(ses, 3);#endif ses->status.force_show_status_bar = -1; ses->status.force_show_title_bar = -1; add_to_list(sessions, ses); /* Update the status -- most importantly the info about whether to the * show the title, tab and status bar -- _before_ loading the URI so * the document cache is not filled with useless documents if the * content is already cached. * * For big document it also reduces memory usage quite a bit because * (atleast that is my interpretation --jonas) the old document will * have a chance to be released before rendering a new one. A few * numbers when opening a new tab while viewing debians package list * for unstable: * * 9307 jonas 15 0 34252 30m 5088 S 0.0 12.2 0:03.63 elinks-old * 9305 jonas 15 0 17060 13m 5088 S 0.0 5.5 0:02.07 elinks-new */ update_status(); /* Check if the newly inserted session is the only in the list and do * the special setup for the first session, */ if (!list_is_singleton(sessions) || !setup_first_session(ses, uri)) { setup_session(ses, uri, base_session); } if (!in_background) switch_to_tab(term, get_tab_number(ses->tab), -1); return ses;}static voidinit_remote_session(struct session *ses, enum remote_session_flags *remote_ptr, struct uri *uri){ enum remote_session_flags remote = *remote_ptr; if (remote & SES_REMOTE_CURRENT_TAB) { goto_uri(ses, uri); /* Mask out the current tab flag */ *remote_ptr = remote & ~SES_REMOTE_CURRENT_TAB; /* Remote session was masked out. Open all following URIs in * new tabs, */ if (!*remote_ptr) *remote_ptr = SES_REMOTE_NEW_TAB;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -