📄 session.c
字号:
/* Sessions managment - you'll find things here which you wouldn't expect *//* $Id: session.c,v 1.593.2.8 2005/06/17 14:02:07 jonas Exp $ *//* stpcpy */#ifndef _GNU_SOURCE#define _GNU_SOURCE 1#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include "elinks.h"#include "bfu/dialog.h"#include "bookmarks/bookmarks.h"#include "cache/cache.h"#include "config/options.h"#include "dialogs/menu.h"#include "dialogs/status.h"#include "document/html/frames.h"#include "document/html/parser.h"#include "document/html/renderer.h"#include "document/refresh.h"#include "document/view.h"#include "globhist/globhist.h"#include "intl/gettext/libintl.h"#include "lowlevel/home.h"#include "lowlevel/select.h"#include "osdep/newwin.h"#include "protocol/protocol.h"#include "protocol/uri.h"#include "sched/connection.h"#include "sched/download.h"#include "sched/error.h"#include "sched/event.h"#include "sched/history.h"#include "sched/location.h"#include "sched/session.h"#include "sched/task.h"#include "terminal/tab.h"#include "terminal/terminal.h"#include "terminal/window.h"#include "util/conv.h"#include "util/error.h"#include "util/memlist.h"#include "util/memory.h"#include "util/object.h"#include "util/string.h"#include "util/ttime.h"#include "viewer/text/draw.h"#include "viewer/text/form.h"#include "viewer/text/link.h"#include "viewer/text/view.h"struct file_to_load { LIST_HEAD(struct file_to_load); struct session *ses; unsigned int req_sent:1; int pri; struct cache_entry *cached; unsigned char *target_frame; struct uri *uri; struct download download;};/* This structure and related functions are used to maintain information * for instances opened in new windows. We store all related session info like * URI and base session to clone from so that when the new instance connects * we can look up this information. In case of failure the session information * has a timeout */struct session_info { LIST_HEAD(struct session_info); int id; int timer; struct session *ses; struct uri *uri;};#define file_to_load_is_active(ftl) ((ftl)->req_sent && is_in_progress_state((ftl)->download.state))INIT_LIST_HEAD(sessions);enum remote_session_flags remote_session_flags;static struct file_to_load *request_additional_file(struct session *, unsigned char *, struct uri *, int);static window_handler tabwin_func;static INIT_LIST_HEAD(session_info);static int session_info_id = 1;static struct session_info *get_session_info(int id){ struct session_info *info; foreach (info, session_info) { struct session *ses; if (info->id != id) continue; /* Make sure the info->ses session is still with us. */ foreach (ses, sessions) if (ses == info->ses) return info; info->ses = NULL; return info; } return NULL;}static voiddone_session_info(struct session_info *info){ del_from_list(info); if (info->timer != -1) kill_timer(info->timer); if (info->uri) done_uri(info->uri); mem_free(info);}voiddone_saved_session_info(void){ while (!list_empty(session_info)) done_session_info(session_info.next);}static voidsession_info_timeout(int id){ struct session_info *info = get_session_info(id); if (!info) return; info->timer = -1; done_session_info(info);}intadd_session_info(struct session *ses, struct uri *uri){ struct session_info *info = mem_calloc(1, sizeof(*info)); if (!info) return -1; info->id = session_info_id++; /* I don't know what a reasonable start up time for a new instance is * but it won't hurt to have a few seconds atleast. --jonas */ info->timer = install_timer(10000, (void (*)(void *)) session_info_timeout, (void *) (long) info->id); info->ses = ses; if (uri) info->uri = get_uri_reference(uri); add_to_list(session_info, info); return info->id;}static struct session *init_saved_session(struct terminal *term, int id){ struct session_info *info = get_session_info(id); struct session *ses; if (!info) return NULL; ses = init_session(info->ses, term, info->uri, 0); done_session_info(info); return ses;}static struct session *get_master_session(void){ struct session *ses; foreach (ses, sessions) if (ses->tab->term->master) { struct window *tab = get_current_tab(ses->tab->term); return tab ? tab->data : NULL; } return NULL;}struct download *get_current_download(struct session *ses){ struct download *download = NULL; if (!ses) return NULL; if (ses->task.type) download = &ses->loading; else if (have_location(ses)) download = &cur_loc(ses)->download; if (download && download->state == S_OK) { struct file_to_load *ftl; foreach (ftl, ses->more_files) if (file_to_load_is_active(ftl)) return &ftl->download; } /* Note that @download isn't necessarily NULL here, * if @ses->more_files is empty. -- Miciah */ return download;}voidprint_error_dialog(struct session *ses, enum connection_state state, struct uri *uri, enum connection_priority priority){ struct string msg; unsigned char *uristring; /* Don't show error dialogs for missing CSS stylesheets */ if (priority == PRI_CSS || !init_string(&msg)) return; uristring = uri ? get_uri_string(uri, URI_PUBLIC) : NULL; if (uristring) { decode_uri_for_display(uristring); add_format_to_string(&msg, _("Unable to retrieve %s", ses->tab->term), uristring); mem_free(uristring); add_to_string(&msg, ":\n\n"); } add_to_string(&msg, get_err_msg(state, ses->tab->term)); info_box(ses->tab->term, MSGBOX_FREE_TEXT, N_("Error"), ALIGN_CENTER, msg.source); /* TODO: retry */}static voidabort_files_load(struct session *ses, int interrupt){ struct file_to_load *ftl; int more; do { more = 0; foreach (ftl, ses->more_files) { if (!file_to_load_is_active(ftl)) continue; more = 1; change_connection(&ftl->download, NULL, PRI_CANCEL, interrupt); } } while (more);}voidfree_files(struct session *ses){ struct file_to_load *ftl; abort_files_load(ses, 0); foreach (ftl, ses->more_files) { if (ftl->cached) object_unlock(ftl->cached); if (ftl->uri) done_uri(ftl->uri); mem_free_if(ftl->target_frame); } free_list(ses->more_files);}static void request_frameset(struct session *, struct frameset_desc *, int);static voidrequest_frame(struct session *ses, unsigned char *name, struct uri *uri, int depth){ struct location *loc = cur_loc(ses); struct frame *frame; assertm(have_location(ses), "request_frame: no location"); if_assert_failed return; foreach (frame, loc->frames) { struct document_view *doc_view; if (strcasecmp(frame->name, name)) continue; foreach(doc_view, ses->scrn_frames) { if (doc_view->vs == &frame->vs && doc_view->document->frame_desc) { request_frameset(ses, doc_view->document->frame_desc, depth); return; } } request_additional_file(ses, name, frame->vs.uri, PRI_FRAME); return; } frame = mem_calloc(1, sizeof(*frame)); if (!frame) return; frame->name = stracpy(name); if (!frame->name) { mem_free(frame); return; } init_vs(&frame->vs, uri, -1); add_to_list(loc->frames, frame); request_additional_file(ses, name, frame->vs.uri, PRI_FRAME);}static voidrequest_frameset(struct session *ses, struct frameset_desc *frameset_desc, int depth){ int i; if (depth > HTML_MAX_FRAME_DEPTH) return; depth++; /* Inheritation counter (recursion brake ;) */ for (i = 0; i < frameset_desc->n; i++) { struct frame_desc *frame_desc = &frameset_desc->frame_desc[i]; if (frame_desc->subframe) { request_frameset(ses, frame_desc->subframe, depth); } else if (frame_desc->name && frame_desc->uri) { request_frame(ses, frame_desc->name, frame_desc->uri, depth); } }}#ifdef CONFIG_CSSstatic inline voidload_css_imports(struct session *ses, struct document_view *doc_view){ struct document *document = doc_view->document; struct uri *uri; int index; if (!document) return; foreach_uri (uri, index, &document->css_imports) { request_additional_file(ses, "", uri, PRI_CSS); }}#else#define load_css_imports(ses, doc_view)#endif#ifdef CONFIG_ECMASCRIPTstatic inline voidload_ecmascript_imports(struct session *ses, struct document_view *doc_view){ struct document *document = doc_view->document; struct uri *uri; int index; if (!document) return; foreach_uri (uri, index, &document->ecmascript_imports) { request_additional_file(ses, "", uri, /* XXX */ PRI_CSS); }}#else#define load_ecmascript_imports(ses, doc_view)#endifinline voidload_frames(struct session *ses, struct document_view *doc_view){ struct document *document = doc_view->document; if (!document || !document->frame_desc) return; request_frameset(ses, document->frame_desc, 0); foreach (doc_view, ses->scrn_frames) { load_css_imports(ses, doc_view); load_ecmascript_imports(ses, doc_view); }}voiddisplay_timer(struct session *ses){ ttime t = get_time(); draw_formatted(ses, 3); t = (get_time() - t) * DISPLAY_TIME; if (t < DISPLAY_TIME_MIN) t = DISPLAY_TIME_MIN; ses->display_timer = install_timer(t, (void (*)(void *)) display_timer, ses); load_frames(ses, ses->doc_view); load_css_imports(ses, ses->doc_view); load_ecmascript_imports(ses, ses->doc_view); process_file_requests(ses);}struct questions_entry { LIST_HEAD(struct questions_entry); void (*callback)(struct session *, void *); void *data;};INIT_LIST_HEAD(questions_queue);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -