📄 view.c
字号:
#include "links.h"void init_vs(struct view_state *vs, unsigned char *url){ memset(vs, 0, sizeof(struct view_state)); vs->current_link = -1; vs->orig_link = -1; vs->plain = -1; vs->form_info = DUMMY; vs->form_info_len = 0; strcpy(vs->url, url);}void destroy_vs(struct view_state *vs){ int i; if (vs->goto_position) mem_free(vs->goto_position); if (vs->goto_position_end) mem_free(vs->goto_position_end); for (i = 0; i < vs->form_info_len; i++) if (vs->form_info[i].value) mem_free(vs->form_info[i].value); mem_free(vs->form_info);}void init_formatted(struct f_data *scr){ memset(((struct f_data **)scr) + 2, 0, SIZEOF_F_DATA - 2 * sizeof(struct f_data *)); scr->data = DUMMY; scr->nlinks = 0; scr->links = DUMMY; init_list(scr->forms); init_list(scr->tags); init_list(scr->nodes);}void destroy_fc(struct form_control *fc){ int i; if (fc->action) mem_free(fc->action); if (fc->target) mem_free(fc->target); if (fc->name) mem_free(fc->name); if (fc->alt) mem_free(fc->alt); if (fc->default_value) mem_free(fc->default_value); for (i = 0; i < fc->nvalues; i++) { if (fc->values[i]) mem_free(fc->values[i]); if (fc->labels[i]) mem_free(fc->labels[i]); } if (fc->values) mem_free(fc->values); if (fc->labels) mem_free(fc->labels); if (fc->menu) free_menu(fc->menu);}void free_frameset_desc(struct frameset_desc *fd){ int i; for (i = 0; i < fd->n; i++) { if (fd->f[i].subframe) free_frameset_desc(fd->f[i].subframe); if (fd->f[i].name) mem_free(fd->f[i].name); if (fd->f[i].url) mem_free(fd->f[i].url); } mem_free(fd);}void clear_formatted(struct f_data *scr){ int n; int y; struct cache_entry *ce; struct form_control *fc; if (!scr) return; if (find_in_cache(scr->url, &ce) || !ce) internal("no cache entry for document"); else ce->refcount--; if (scr->url) mem_free(scr->url); if (scr->title) mem_free(scr->title); if (scr->frame_desc) { free_frameset_desc(scr->frame_desc); } for (n = 0; n < scr->nlinks; n++) { struct link *l = &scr->links[n]; if (l->where) mem_free(l->where); if (l->target) mem_free(l->target); if (l->where_img) mem_free(l->where_img); if (l->pos) mem_free(l->pos); } mem_free(scr->links); for (y = 0; y < scr->y; y++) mem_free(scr->data[y].d); mem_free(scr->data); if (scr->lines1) mem_free(scr->lines1); if (scr->lines2) mem_free(scr->lines2); mem_free(scr->opt.framename); foreach(fc, scr->forms) { destroy_fc(fc); } free_list(scr->forms); free_list(scr->tags); free_list(scr->nodes); if (scr->search) mem_free(scr->search); if (scr->slines1) mem_free(scr->slines1); if (scr->slines2) mem_free(scr->slines2); init_formatted(scr);}void destroy_formatted(struct f_data *scr){ if (scr->refcount) { internal("trying to free locked formatted data"); return; } clear_formatted(scr); del_from_list(scr); mem_free(scr);}void detach_formatted(struct f_data_c *scr){ if (scr->f_data) { format_cache_reactivate(scr->f_data); if (!--scr->f_data->refcount) { format_cache_entries++; /*shrink_format_cache();*/ } if (scr->f_data->refcount < 0) { internal("format_cache refcount underflow"); scr->f_data->refcount = 0; } scr->f_data = NULL; } scr->vs = NULL; if (scr->link_bg) mem_free(scr->link_bg), scr->link_bg = NULL, scr->link_bg_n = 0; if (scr->name) mem_free(scr->name), scr->name = NULL;}void copy_vs(struct view_state *dst, struct view_state *src){ int i; memcpy(dst, src, sizeof(struct view_state)); strcpy(dst->url, src->url); dst->goto_position = stracpy(src->goto_position); dst->goto_position_end = stracpy(src->goto_position_end); if ((unsigned)src->form_info_len > MAXINT / sizeof(struct form_state)) overalloc(); dst->form_info = mem_alloc(src->form_info_len * sizeof(struct form_state)); memcpy(dst->form_info, src->form_info, src->form_info_len * sizeof(struct form_state)); for (i = 0; i < src->form_info_len; i++) if (src->form_info[i].value) dst->form_info[i].value = stracpy(src->form_info[i].value);}void copy_location(struct location *dst, struct location *src){ struct frame *f, *nf; init_list(dst->frames); foreachback(f, src->frames) { nf = mem_alloc(sizeof(struct frame) + strlen(f->vs.url) + 1); nf->name = stracpy(f->name); nf->redirect_cnt = 0; copy_vs(&nf->vs, &f->vs); add_to_list(dst->frames, nf); } copy_vs(&dst->vs, &src->vs);}static inline int c_in_view(struct f_data_c *);void set_pos_x(struct f_data_c *, struct link *);void set_pos_y(struct f_data_c *, struct link *);void find_link(struct f_data_c *, int, int);void next_frame(struct session *, int);void check_vs(struct f_data_c *f){ struct view_state *vs = f->vs; int ovx = vs->orig_view_posx, ovy = vs->orig_view_pos, ol = vs->orig_link; if (vs->current_link >= f->f_data->nlinks) vs->current_link = f->f_data->nlinks - 1; if (vs->current_link != -1 && !c_in_view(f)) { set_pos_x(f, &f->f_data->links[f->vs->current_link]); set_pos_y(f, &f->f_data->links[f->vs->current_link]); } if (vs->current_link == -1) find_link(f, 1, 0); vs->orig_view_posx = ovx, vs->orig_view_pos = ovy, vs->orig_link = ol;}void set_link(struct f_data_c *f){ if (c_in_view(f)) return; find_link(f, 1, 0);}int find_tag(struct f_data *f, unsigned char *name){ struct tag *tag; unsigned char *tt; int ll; tt = init_str(); ll = 0; add_conv_str(&tt, &ll, name, strlen(name), -2); foreach(tag, f->tags) if (!strcasecmp(tag->name, tt) || (tag->name[0] == '#' && !strcasecmp(tag->name + 1, tt))) { mem_free(tt); return tag->y; } mem_free(tt); return -1;}int comp_links(struct link *l1, struct link *l2){ return l1->num - l2->num;}void sort_links(struct f_data *f){ int i; if (f->nlinks) qsort(f->links, f->nlinks, sizeof(struct link), (void *)comp_links); if ((unsigned)f->y > MAXINT / sizeof(struct link *)) overalloc(); f->lines1 = mem_alloc(f->y * sizeof(struct link *)); f->lines2 = mem_alloc(f->y * sizeof(struct link *)); memset(f->lines1, 0, f->y * sizeof(struct link *)); memset(f->lines2, 0, f->y * sizeof(struct link *)); for (i = 0; i < f->nlinks; i++) { int p, q, j; struct link *link = &f->links[i]; if (!link->n) { if (d_opt->num_links) continue; if (link->where) mem_free(link->where); if (link->target) mem_free(link->target); if (link->where_img) mem_free(link->where_img); if (link->pos) mem_free(link->pos); memmove(link, link + 1, (f->nlinks - i - 1) * sizeof(struct link)); f->nlinks --; i--; continue; } p = f->y - 1; q = 0; for (j = 0; j < link->n; j++) { if (link->pos[j].y < p) p = link->pos[j].y; if (link->pos[j].y > q) q = link->pos[j].y; } /* p = link->pos[0].y; q = link->pos[link->n - 1].y; */ if (p > q) j = p, p = q, q = j; for (j = p; j <= q; j++) { if (j >= f->y) { internal("link out of screen"); continue; } f->lines2[j] = &f->links[i]; if (!f->lines1[j]) f->lines1[j] = &f->links[i]; } }}struct form_state *find_form_state(struct f_data_c *, struct form_control *);struct line_info { unsigned char *st; unsigned char *en;};struct line_info *format_text(unsigned char *text, int width, int wrap){ struct line_info *ln = DUMMY; int lnn = 0; unsigned char *b = text; int sk, ps = 0; while (*text) { unsigned char *s; if (*text == '\n') { sk = 1; put: if (!(lnn & (ALLOC_GR-1))) { if ((unsigned)lnn > MAXINT / sizeof(struct line_info) - ALLOC_GR) overalloc(); ln = mem_realloc(ln, (lnn + ALLOC_GR) * sizeof(struct line_info)); } ln[lnn].st = b; ln[lnn++].en = text; b = text += sk; continue; } if (!wrap || text - b < width) { text++; continue; } for (s = text; s >= b; s--) if (*s == ' ') { text = s; if (wrap == 2) { *s = '\n'; for (s++; *s; s++) if (*s == '\n') { if (s[1] != '\n') *s = ' '; break; } } sk = 1; goto put; } sk = 0; goto put; } if (ps < 2) { ps++; sk = 0; goto put; } ln[lnn - 1].st = ln[lnn - 1].en = NULL; return ln;}int _area_cursor(struct form_control *form, struct form_state *fs){ struct line_info *ln; int q = 0; if ((ln = format_text(fs->value, form->cols, form->wrap))) { int x, y; for (y = 0; ln[y].st; y++) if (fs->value + fs->state >= ln[y].st && fs->value + fs->state < ln[y].en + (ln[y+1].st != ln[y].en)) { x = fs->value + fs->state - ln[y].st; if (form->wrap && x == form->cols) x--; if (x >= form->cols + fs->vpos) fs->vpos = x - form->cols + 1; if (x < fs->vpos) fs->vpos = x; if (y >= form->rows + fs->vypos) fs->vypos = y - form->rows + 1; if (y < fs->vypos) fs->vypos = y; x -= fs->vpos; y -= fs->vypos; q = y * form->cols + x; break; } mem_free(ln); } return q;}void draw_link(struct terminal *t, struct f_data_c *scr, int l){ struct link *link = &scr->f_data->links[l]; int xp = scr->xp; int yp = scr->yp; int xw = scr->xw; int yw = scr->yw; int vx, vy; struct view_state *vs = scr->vs; int f = 0; vx = vs->view_posx; vy = vs->view_pos; if (scr->link_bg) { internal("link background not empty"); mem_free(scr->link_bg); } if (l == -1) return; switch (link->type) { int i; int q; case L_LINK: case L_CHECKBOX: case L_BUTTON: case L_SELECT: case L_FIELD: case L_AREA: q = 0; if (link->type == L_FIELD) { struct form_state *fs = find_form_state(scr, link->form); if (fs) q = fs->state - fs->vpos; /*else internal("link has no form control");*/ } else if (link->type == L_AREA) { struct form_state *fs = find_form_state(scr, link->form); if (fs) q = _area_cursor(link->form, fs); /*else internal("link has no form control");*/ } if ((unsigned)link->n > MAXINT / sizeof(struct link_bg)) overalloc(); scr->link_bg = mem_alloc(link->n * sizeof(struct link_bg)); scr->link_bg_n = link->n; for (i = 0; i < link->n; i++) { int x = link->pos[i].x + xp - vx; int y = link->pos[i].y + yp - vy; if (x >= xp && y >= yp && x < xp+xw && y < yp+yw) { unsigned co; co = get_char(t, x, y); if (scr->link_bg) scr->link_bg[i].x = x, scr->link_bg[i].y = y, scr->link_bg[i].c = co; if (!f || (link->type == L_CHECKBOX && i == 1) || (link->type == L_BUTTON && i == 2) || ((link->type == L_FIELD || link->type == L_AREA) && i == q)) { int xx = x, yy = y; if (link->type != L_FIELD && link->type != L_AREA) { if (((co >> 8) & 0x38) != (link->sel_color & 0x38)) xx = xp + xw - 1, yy = yp + yw - 1; } set_cursor(t, x, y, xx, yy); set_window_ptr(get_root_window(t), x, y); f = 1; } set_color(t, x, y, /*((link->sel_color << 3) | (co >> 11 & 7)) << 8*/ link->sel_color << 8); } else scr->link_bg[i].x = scr->link_bg[i].y = scr->link_bg[i].c = -1; } break; default: internal("bad link type"); }}void free_link(struct f_data_c *scr){ if (scr->link_bg) { mem_free(scr->link_bg); scr->link_bg = NULL; } scr->link_bg_n = 0;}void clear_link(struct terminal *t, struct f_data_c *scr){ if (scr->link_bg) { int i; for (i = scr->link_bg_n - 1; i >= 0; i--) set_char(t, scr->link_bg[i].x, scr->link_bg[i].y, scr->link_bg[i].c); free_link(scr); }}int get_range(struct f_data *f, int y, int yw, int l, struct search **s1, struct search **s2){ int i; *s1 = *s2 = NULL; for (i = y < 0 ? 0 : y; i < y + yw && i < f->y; i++) { if (f->slines1[i] && (!*s1 || f->slines1[i] < *s1)) *s1 = f->slines1[i]; if (f->slines2[i] && (!*s2 || f->slines2[i] > *s2)) *s2 = f->slines2[i]; } if (!*s1 || !*s2) return -1; *s1 -= l; if (*s1 < f->search) *s1 = f->search; if (*s2 + l > f->search + f->nsearch) *s2 = f->search + f->nsearch - l; if (*s1 > *s2) *s1 = *s2 = NULL; if (!*s1 || !*s2) return -1; return 0;}int is_in_range(struct f_data *f, int y, int yw, unsigned char *txt, int *min, int *max){ int found = 0; int l = strlen(txt); struct search *s1, *s2; if (min || max) *min = MAXINT, *max = 0; if (get_range(f, y, yw, l, &s1, &s2)) return 0; for (; s1 <= s2; s1++) { int i; if (s1->c != txt[0]) { unable_to_handle_kernel_paging_request___oops: continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -