📄 session.c
字号:
/* session.c * (c) 2002 Mikulas Patocka * This file is a part of the Links program, released under GPL. */#include "links.h"struct list_head downloads = {&downloads, &downloads};/* prototypes */void add_xnum_to_str(unsigned char **, int *, off_t);void add_time_to_str(unsigned char **, int *, ttime);unsigned char *get_stat_msg(struct status *, struct terminal *);void x_print_screen_status(struct terminal *, struct session *);struct session *get_download_ses(struct download *);void delete_download_file(struct download *down);void close_download_file(struct download *down);void abort_download(struct download *);void abort_and_delete_download(struct download *);void kill_downloads_to_file(unsigned char *, unsigned char *);void undisplay_download(struct download *);int dlg_abort_download(struct dialog_data *, struct dialog_item_data *);int dlg_abort_and_delete_download(struct dialog_data *, struct dialog_item_data *);int dlg_undisplay_download(struct dialog_data *, struct dialog_item_data *);void download_abort_function(struct dialog_data *);void download_data(struct status *, struct download *);void increase_download_file(unsigned char **f);unsigned char *get_temp_name(unsigned char *, unsigned char *);int f_is_cacheable(struct f_data *);int f_need_reparse(struct f_data *);struct f_data *format_html(struct f_data_c *, struct object_request *, unsigned char *, struct document_options *, int *);void count_frames(struct f_data_c *, int *);void f_data_attach(struct f_data_c *, struct f_data *);void detach_f_data(struct f_data **);int shrink_format_cache(int);void create_new_frames(struct f_data_c *, struct frameset_desc *, struct document_options *);void image_timer(struct f_data_c *);int plain_type(struct session *, struct object_request *, unsigned char **);int get_file_by_term(struct terminal *term, struct cache_entry *ce, unsigned char **start, unsigned char **end, int *err);void refresh_timer(struct f_data_c *);void subst_location(struct f_data_c *, struct location *, struct location *);struct location *copy_sublocations(struct session *, struct location *, struct location *, struct location *);struct location *copy_location(struct session *, struct location *);struct f_data_c *new_main_location(struct session *);struct f_data_c *copy_location_and_replace_frame(struct session *, struct f_data_c *);void ses_go_forward(struct session *, int, int);void ses_go_backward(struct session *);void tp_cancel(struct session *);void continue_download(struct session *, unsigned char *);void tp_save(struct session *);void tp_open(struct session *);int ses_abort_1st_state_loading(struct session *);void tp_display(struct session *);int direct_download_possible(struct object_request *rq, struct assoc *a);int prog_sel_save(struct dialog_data *, struct dialog_item_data*);int prog_sel_display(struct dialog_data *, struct dialog_item_data*);int prog_sel_cancel(struct dialog_data *, struct dialog_item_data*);int prog_sel_open(struct dialog_data *, struct dialog_item_data*);void vysad_dvere(struct dialog_data *);void vysad_okno(struct session *, unsigned char *, struct assoc *, int);void type_query(struct session *, unsigned char *, struct assoc *, int);void ses_go_to_2nd_state(struct session *);void ses_go_back_to_2nd_state(struct session *);void ses_finished_1st_state(struct object_request *, struct session *);void ses_imgmap(struct session *);void reload_frame(struct f_data_c *, int);void set_doc_view(struct session *);struct session *create_session(struct window *);int read_session_info(struct session *, void *, int);int are_there_downloads(void){ int d = 0; struct download *down; foreach(down, downloads) if (!down->prog) d = 1; return d;}struct list_head sessions = {&sessions, &sessions};struct strerror_val { struct strerror_val *next; struct strerror_val *prev; unsigned char msg[1];};struct list_head strerror_buf = { &strerror_buf, &strerror_buf };void free_strerror_buf(void){ free_list(strerror_buf);}unsigned char *get_err_msg(int state){ unsigned char *e; struct strerror_val *s; if (state <= S_OK || state >= S_WAIT) { int i; for (i = 0; msg_dsc[i].msg; i++) if (msg_dsc[i].n == state) return msg_dsc[i].msg; unk: return TEXT(T_UNKNOWN_ERROR); } if (!(e = strerror(-state)) || !*e) goto unk; foreach(s, strerror_buf) if (!strcmp(s->msg, e)) return s->msg; s = mem_alloc(sizeof(struct strerror_val) + strlen(e) + 1); strcpy(s->msg, e); add_to_list(strerror_buf, s); return s->msg;}void add_xnum_to_str(unsigned char **s, int *l, off_t n){ unsigned char suff = 0; int d = -1; if (n >= 1000000000) suff = 'G', d = (n / 100000000) % 10, n /= 1000000000; else if (n >= 1000000) suff = 'M', d = (n / 100000) % 10, n /= 1000000; else if (n >= 1000) suff = 'k', d = (n / 100) % 10, n /= 1000; add_num_to_str(s, l, n); if (n < 10 && d != -1) add_chr_to_str(s, l, '.'), add_num_to_str(s, l, d); add_chr_to_str(s, l, ' '); if (suff) add_chr_to_str(s, l, suff); add_chr_to_str(s, l, 'B');}void add_time_to_str(unsigned char **s, int *l, ttime t){ unsigned char q[64]; if (t < 0) t = 0; t &= 0xffffffff; if (t >= 86400) sprintf(q, "%dd ", (int)(t / 86400)), add_to_str(s, l, q); if (t >= 3600) t %= 86400, sprintf(q, "%d:%02d", (int)(t / 3600), (int)(t / 60 % 60)), add_to_str(s, l, q); else sprintf(q, "%d", (int)(t / 60)), add_to_str(s, l, q); sprintf(q, ":%02d", (int)(t % 60)), add_to_str(s, l, q);}unsigned char *get_stat_msg(struct status *stat, struct terminal *term){ if (stat->state == S_TRANS && stat->prg->elapsed / 100) { unsigned char *m = init_str(); int l = 0; add_to_str(&m, &l, _(TEXT(T_RECEIVED), term)); add_to_str(&m, &l, " "); add_xnum_to_str(&m, &l, stat->prg->pos); if (stat->prg->size >= 0) add_to_str(&m, &l, " "), add_to_str(&m, &l, _(TEXT(T_OF), term)), add_to_str(&m, &l, " "), add_xnum_to_str(&m, &l, stat->prg->size); add_to_str(&m, &l, ", "); if (stat->prg->elapsed >= CURRENT_SPD_AFTER * SPD_DISP_TIME) add_to_str(&m, &l, _(TEXT(T_AVG), term)), add_to_str(&m, &l, " "); add_xnum_to_str(&m, &l, stat->prg->loaded * 10 / (stat->prg->elapsed / 100)); add_to_str(&m, &l, "/s"); if (stat->prg->elapsed >= CURRENT_SPD_AFTER * SPD_DISP_TIME) add_to_str(&m, &l, ", "), add_to_str(&m, &l, _(TEXT(T_CUR), term)), add_to_str(&m, &l, " "), add_xnum_to_str(&m, &l, stat->prg->cur_loaded / (CURRENT_SPD_SEC * SPD_DISP_TIME / 1000)), add_to_str(&m, &l, "/s"); return m; } return stracpy(_(get_err_msg(stat->state), term));}void change_screen_status(struct session *ses){ struct status *stat = NULL; if (ses->rq) { stat = &ses->rq->stat; } else { struct f_data_c *fd = current_frame(ses); if (fd->rq) stat = &fd->rq->stat; if (stat && stat->state == S_OK && fd->af) { struct additional_file *af; foreach(af, fd->af->af) { if (af->rq && af->rq->stat.state >= 0) stat = &af->rq->stat; } } } if (ses->st) mem_free(ses->st); /* default status se ukazuje, kdyz * a) by se jinak ukazovalo prazdno * b) neni NULL a ukazovalo by se OK */ ses->st = NULL; if (stat) { if (stat->state == S_OK) ses->st = print_current_link(ses); if (!ses->st) ses->st = ses->default_status ? stracpy(ses->default_status) : get_stat_msg(stat, ses->term); } else { ses->st = stracpy(ses->default_status); }}void x_print_screen_status(struct terminal *term, struct session *ses){ unsigned char *m; if (!F) { fill_area(term, 0, term->y - 1, term->x, 1, COLOR_STATUS_BG); if (ses->st) print_text(term, 0, term->y - 1, strlen(ses->st), ses->st, COLOR_STATUS); fill_area(term, 0, 0, term->x, 1, COLOR_TITLE_BG); if ((m = print_current_title(ses))) { int p = term->x - 1 - strlen(m); if (p < 0) p = 0; if (term->spec->braille) p = 0; print_text(term, p, 0, strlen(m), m, COLOR_TITLE); mem_free(m); }#ifdef G } else { int l = 0; if (ses->st) g_print_text(drv, term->dev, 0, term->y - G_BFU_FONT_SIZE, bfu_style_wb_mono, ses->st, &l); drv->fill_area(term->dev, l, term->y - G_BFU_FONT_SIZE, term->x, term->y, bfu_bg_color);#endif }}void print_screen_status(struct session *ses){ unsigned char *m;#ifdef G if (F) { /*debug("%s - %s", ses->st_old, ses->st); debug("clip: %d.%d , %d.%d", ses->term->dev->clip.x1, ses->term->dev->clip.y1, ses->term->dev->clip.x2, ses->term->dev->clip.y2); debug("size: %d.%d , %d.%d", ses->term->dev->size.x1, ses->term->dev->size.y1, ses->term->dev->size.x2, ses->term->dev->size.y2);*/ if (ses->st_old) { if (ses->st && !strcmp(ses->st, ses->st_old)) goto skip_status; mem_free(ses->st_old); ses->st_old = NULL; } if (!memcmp(&ses->term->dev->clip, &ses->term->dev->size, sizeof(struct rect))) ses->st_old = stracpy(ses->st); }#endif draw_to_window(ses->win, (void (*)(struct terminal *, void *))x_print_screen_status, ses);#ifdef G skip_status:#endif if ((m = stracpy("Links"))) { if (ses->screen && ses->screen->f_data && ses->screen->f_data->title && ses->screen->f_data->title[0]) add_to_strn(&m, " - "), add_to_strn(&m, ses->screen->f_data->title); set_terminal_title(ses->term, m); /*mem_free(m); -- set_terminal_title frees it */ } if (!F && ses->brl_cursor_mode) { if (ses->brl_cursor_mode == 1) set_cursor(ses->term, 0, 0, 0, 0); if (ses->brl_cursor_mode == 2) set_cursor(ses->term, 0, ses->term->y - 1, 0, ses->term->y - 1); }}void print_error_dialog(struct session *ses, struct status *stat, unsigned char *title){ unsigned char *t = get_err_msg(stat->state); unsigned char *u = stracpy(title); if (strchr(u, POST_CHAR)) *strchr(u, POST_CHAR) = 0; if (!t) return; msg_box(ses->term, getml(u, NULL), TEXT(T_ERROR), AL_CENTER | AL_EXTD_TEXT, TEXT(T_ERROR_LOADING), " ", u, ":\n\n", t, NULL, ses, 1, TEXT(T_CANCEL), NULL, B_ENTER | B_ESC/*, _("Retry"), NULL, 0 !!! FIXME: retry */);}static inline unsigned char hx(int a){ return a >= 10 ? a + 'A' - 10 : a + '0';}static inline int unhx(unsigned char a){ if (a >= '0' && a <= '9') return a - '0'; if (a >= 'A' && a <= 'F') return a - 'A' + 10; if (a >= 'a' && a <= 'f') return a - 'a' + 10; return -1;}unsigned char *encode_url(unsigned char *url){ unsigned char *u = init_str(); int l = 0; add_to_str(&u, &l, "+++"); for (; *url; url++) { if (is_safe_in_shell(*url) && *url != '+') add_chr_to_str(&u, &l, *url); else add_chr_to_str(&u, &l, '+'), add_chr_to_str(&u, &l, hx(*url >> 4)), add_chr_to_str(&u, &l, hx(*url & 0xf)); } return u;}unsigned char *decode_url(unsigned char *url){ unsigned char *u; int l; if (casecmp(url, "+++", 3)) return stracpy(url); url += 3; u = init_str(); l = 0; for (; *url; url++) { if (*url != '+' || unhx(url[1]) == -1 || unhx(url[2]) == -1) add_chr_to_str(&u, &l, *url); else add_chr_to_str(&u, &l, (unhx(url[1]) << 4) + unhx(url[2])), url += 2; } return u;}struct session *get_download_ses(struct download *down){ struct session *ses; foreach(ses, sessions) if (ses == down->ses) return ses; if (!list_empty(sessions)) return sessions.next; return NULL;}void close_download_file(struct download *down){ if (down->handle != -1) prealloc_truncate(down->handle, down->last_pos - down->file_shift), close(down->handle), down->handle = -1;}void delete_download_file(struct download *down){ unsigned char *file = stracpy(down->orig_file); unsigned char *wd = get_cwd(); set_cwd(down->cwd); while (1) { unsigned char *f = translate_download_file(file); unlink(f); mem_free(f); if (!strcmp(file, down->file)) break; increase_download_file(&file); } mem_free(file); if (wd) set_cwd(wd), mem_free(wd);}void abort_download(struct download *down){ if (down->win) delete_window(down->win); if (down->ask) delete_window(down->ask); if (down->stat.state >= 0) change_connection(&down->stat, NULL, PRI_CANCEL); mem_free(down->url); close_download_file(down); if (down->prog) { delete_download_file(down); mem_free(down->prog); } mem_free(down->cwd); mem_free(down->orig_file); mem_free(down->file); del_from_list(down); mem_free(down);}void abort_and_delete_download(struct download *down){ if (!down->prog) down->prog = DUMMY; abort_download(down);}void kill_downloads_to_file(unsigned char *file, unsigned char *cwd){ struct download *down; foreach(down, downloads) { if (strcmp(down->cwd, cwd)) {#if defined(DOS_FS) if (file[0] && file[1] == ':' && dir_sep(file[2])) goto abs;#elif defined(SPAD) if (_is_absolute(file) == _ABS_TOTAL) goto abs;#else if (file[0] == '/') goto abs;#endif continue; } abs: if (!strcmp(down->file, file) || !strcmp(down->orig_file, file)) down = down->prev, abort_download(down->next); }}void undisplay_download(struct download *down){ if (down->win) delete_window(down->win);}int dlg_abort_download(struct dialog_data *dlg, struct dialog_item_data *di){ register_bottom_half((void (*)(void *))abort_download, dlg->dlg->udata); return 0;}int dlg_abort_and_delete_download(struct dialog_data *dlg, struct dialog_item_data *di){ register_bottom_half((void (*)(void *))abort_and_delete_download, dlg->dlg->udata); return 0;}int dlg_undisplay_download(struct dialog_data *dlg, struct dialog_item_data *di){ register_bottom_half((void (*)(void *))undisplay_download, dlg->dlg->udata); return 0;}void download_abort_function(struct dialog_data *dlg){ struct download *down = dlg->dlg->udata; down->win = NULL;}void download_window_function(struct dialog_data *dlg){ struct download *down = dlg->dlg->udata; struct terminal *term = dlg->win->term; int max = 0, min = 0; int w, x, y; int t = 0; unsigned char *m, *u; struct status *stat = &down->stat; if (!F) redraw_below_window(dlg->win); down->win = dlg->win; if (stat->state == S_TRANS && stat->prg->elapsed / 100) { int l = 0; m = init_str(); t = 1; add_to_str(&m, &l, _(TEXT(T_RECEIVED), term)); add_to_str(&m, &l, " "); add_xnum_to_str(&m, &l, stat->prg->pos); if (stat->prg->size >= 0) add_to_str(&m, &l, " "), add_to_str(&m, &l, _(TEXT(T_OF),term)), add_to_str(&m, &l, " "), add_xnum_to_str(&m, &l, stat->prg->size), add_to_str(&m, &l, " "); add_to_str(&m, &l, "\n"); if (stat->prg->elapsed >= CURRENT_SPD_AFTER * SPD_DISP_TIME) add_to_str(&m, &l, _(TEXT(T_AVERAGE_SPEED), term)); else add_to_str(&m, &l, _(TEXT(T_SPEED), term)); add_to_str(&m, &l, " "); add_xnum_to_str(&m, &l, (longlong)stat->prg->loaded * 10 / (stat->prg->elapsed / 100)); add_to_str(&m, &l, "/s");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -