/* $Id: file.c,v 1.100 2002/09/11 15:08:54 ukai Exp $ */ #include "fm.h" #include #include "myctype.h" #include #include #if defined(HAVE_WAITPID) || defined(HAVE_WAIT3) #include #endif #include #include #include #include /* foo */ #include "html.h" #include "parsetagx.h" #include "local.h" #include "regex.h" #ifndef max #define max(a,b) ((a) > (b) ? (a) : (b)) #endif /* not max */ #ifndef min #define min(a,b) ((a) > (b) ? (b) : (a)) #endif /* not min */ static int frame_source = 0; static int _MoveFile(char *path1, char *path2); static void uncompress_stream(URLFile *uf); static FILE *lessopen_stream(char *path); static Buffer *loadcmdout(char *cmd, Buffer *(*loadproc) (URLFile *, Buffer *), Buffer *defaultbuf); static void close_textarea(struct html_feed_environ *h_env); static void addnewline(Buffer *buf, char *line, Lineprop *prop, #ifdef USE_ANSI_COLOR Linecolor *color, #endif int pos, int nlines); static Lineprop propBuffer[LINELEN]; #ifdef USE_ANSI_COLOR static Linecolor colorBuffer[LINELEN]; #endif static JMP_BUF AbortLoading; static struct table *tables[MAX_TABLE]; static struct table_mode table_mode[MAX_TABLE]; #ifdef USE_IMAGE static ParsedURL *cur_baseURL = NULL; #ifdef JP_CHARSET static char cur_document_code; #endif #endif static Str cur_select; static Str select_str; static int select_is_multiple; static int n_selectitem; static Str cur_option; static Str cur_option_value; static Str cur_option_label; static int cur_option_selected; static int cur_status; #ifdef MENU_SELECT /* menu based tag. */ if (v == FORM_INPUT_FILE) q = NULL; if (q) { qq = html_quote(q); qlen = strlen(q); } Strcat_charp(tmp, ""); switch (v) { case FORM_INPUT_PASSWORD: case FORM_INPUT_TEXT: case FORM_INPUT_FILE: case FORM_INPUT_CHECKBOX: Strcat_char(tmp, '['); break; case FORM_INPUT_RADIO: Strcat_char(tmp, '('); } Strcat(tmp, Sprintf("'); if (v == FORM_INPUT_HIDDEN) Strcat_charp(tmp, ""); else { switch (v) { case FORM_INPUT_PASSWORD: case FORM_INPUT_TEXT: case FORM_INPUT_FILE: Strcat_charp(tmp, ""); break; case FORM_INPUT_IMAGE: s = NULL; parsedtag_get_value(tag, ATTR_SRC, &s); if (s) { Strcat(tmp, Sprintf("\"%s\"","); Strcat_charp(tmp, ""); return tmp; } case FORM_INPUT_SUBMIT: case FORM_INPUT_BUTTON: case FORM_INPUT_RESET: Strcat_charp(tmp, "["); break; } switch (v) { case FORM_INPUT_PASSWORD: i = 0; if (q) { for (; i < qlen && i < w; i++) Strcat_char(tmp, '*'); } for (; i < w; i++) Strcat_char(tmp, ' '); break; case FORM_INPUT_TEXT: case FORM_INPUT_FILE: if (q) Strcat(tmp, textfieldrep(Strnew_charp(q), w)); else { for (i = 0; i < w; i++) Strcat_char(tmp, ' '); } break; case FORM_INPUT_SUBMIT: case FORM_INPUT_BUTTON: if (p2) Strcat_charp(tmp, html_quote(p2)); else Strcat_charp(tmp, qq); break; case FORM_INPUT_RESET: Strcat_charp(tmp, qq); break; case FORM_INPUT_RADIO: case FORM_INPUT_CHECKBOX: if (x) Strcat_char(tmp, '*'); else Strcat_char(tmp, ' '); break; } switch (v) { case FORM_INPUT_PASSWORD: case FORM_INPUT_TEXT: case FORM_INPUT_FILE: Strcat_charp(tmp, ""); break; case FORM_INPUT_IMAGE: case FORM_INPUT_SUBMIT: case FORM_INPUT_BUTTON: case FORM_INPUT_RESET: Strcat_charp(tmp, "]"); } Strcat_charp(tmp, ""); switch (v) { case FORM_INPUT_PASSWORD: case FORM_INPUT_TEXT: case FORM_INPUT_FILE: case FORM_INPUT_CHECKBOX: Strcat_char(tmp, ']'); break; case FORM_INPUT_RADIO: Strcat_char(tmp, ')'); } Strcat_charp(tmp, ""); } return tmp; } Str process_select(struct parsed_tag *tag) { Str tmp = NULL; char *p; if (cur_form_id < 0) { char *s = ""; tmp = process_form(parse_tag(&s, TRUE)); } p = ""; parsedtag_get_value(tag, ATTR_NAME, &p); cur_select = Strnew_charp(p); select_is_multiple = parsedtag_exists(tag, ATTR_MULTIPLE); #ifdef MENU_SELECT if (!select_is_multiple) { select_str = Sprintf("["); if (n_select == max_select) { max_select *= 2; select_option = New_Reuse(FormSelectOption, select_option, max_select); } select_option[n_select].first = NULL; select_option[n_select].last = NULL; cur_option_maxwidth = 0; } else #endif /* MENU_SELECT */ select_str = Strnew(); cur_option = NULL; cur_status = R_ST_NORMAL; n_selectitem = 0; return tmp; } Str process_n_select(void) { if (cur_select == NULL) return NULL; process_option(); #ifdef MENU_SELECT if (!select_is_multiple) { if (select_option[n_select].first) { FormItemList sitem; chooseSelectOption(&sitem, select_option[n_select].first); Strcat(select_str, textfieldrep(sitem.label, cur_option_maxwidth)); } Strcat_charp(select_str, "]"); n_select++; } else #endif /* MENU_SELECT */ Strcat_charp(select_str, "
"); cur_select = NULL; n_selectitem = 0; return select_str; } void feed_select(char *str) { Str tmp = Strnew(); int prev_status = cur_status; static int prev_spaces = -1; char *p; if (cur_select == NULL) return; while (read_token(tmp, &str, &cur_status, 0, 0)) { if (cur_status != R_ST_NORMAL || prev_status != R_ST_NORMAL) continue; p = tmp->ptr; if (tmp->ptr[0] == '<' && Strlastchar(tmp) == '>') { struct parsed_tag *tag; char *q; if (!(tag = parse_tag(&p, FALSE))) continue; switch (tag->tagid) { case HTML_OPTION: process_option(); cur_option = Strnew(); if (parsedtag_get_value(tag, ATTR_VALUE, &q)) cur_option_value = Strnew_charp(q); else cur_option_value = NULL; if (parsedtag_get_value(tag, ATTR_LABEL, &q)) cur_option_label = Strnew_charp(q); else cur_option_label = NULL; cur_option_selected = parsedtag_exists(tag, ATTR_SELECTED); prev_spaces = -1; break; case HTML_N_OPTION: /* do nothing */ break; default: /* never happen */ break; } } else if (cur_option) { while (*p) { if (IS_SPACE(*p) && prev_spaces != 0) { p++; if (prev_spaces > 0) prev_spaces++; } else { if (IS_SPACE(*p)) prev_spaces = 1; else prev_spaces = 0; if (*p == '&') Strcat_charp(cur_option, getescapecmd(&p)); else Strcat_char(cur_option, *(p++)); } } } } } void process_option(void) { char begin_char = '[', end_char = ']'; if (cur_select == NULL || cur_option == NULL) return; while (cur_option->length > 0 && IS_SPACE(Strlastchar(cur_option))) Strshrink(cur_option, 1); if (cur_option_value == NULL) cur_option_value = cur_option; if (cur_option_label == NULL) cur_option_label = cur_option; #ifdef MENU_SELECT if (!select_is_multiple) { if (cur_option_label->length > cur_option_maxwidth) cur_option_maxwidth = cur_option_label->length; addSelectOption(&select_option[n_select], cur_option_value, cur_option_label, cur_option_selected); return; } #endif /* MENU_SELECT */ if (!select_is_multiple) { begin_char = '('; end_char = ')'; } Strcat(select_str, Sprintf("
%cptr), html_quote(cur_option_value->ptr))); if (cur_option_selected) Strcat_charp(select_str, " checked>*"); else Strcat_charp(select_str, "> "); Strcat_char(select_str, end_char); Strcat_charp(select_str, html_quote(cur_option_label->ptr)); Strcat_charp(select_str, ""); n_selectitem++; } Str process_textarea(struct parsed_tag *tag, int width) { Str tmp = NULL; char *p; if (cur_form_id < 0) { char *s = ""; tmp = process_form(parse_tag(&s, TRUE)); } p = ""; parsedtag_get_value(tag, ATTR_NAME, &p); cur_textarea = Strnew_charp(p); cur_textarea_size = 20; if (parsedtag_get_value(tag, ATTR_COLS, &p)) { cur_textarea_size = atoi(p); if (p[strlen(p) - 1] == '%') cur_textarea_size = width * cur_textarea_size / 100 - 2; if (cur_textarea_size <= 0) cur_textarea_size = 20; } cur_textarea_rows = 1; if (parsedtag_get_value(tag, ATTR_ROWS, &p)) { cur_textarea_rows = atoi(p); if (cur_textarea_rows <= 0) cur_textarea_rows = 1; } cur_textarea_readonly = parsedtag_exists(tag, ATTR_READONLY); if (n_textarea >= max_textarea) { max_textarea *= 2; textarea_str = New_Reuse(Str, textarea_str, max_textarea); } textarea_str[n_textarea] = Strnew(); ignore_nl_textarea = TRUE; return tmp; } Str process_n_textarea(void) { Str tmp; int i; if (cur_textarea == NULL) return NULL; tmp = Strnew(); Strcat(tmp, Sprintf("[ptr), cur_textarea_size, cur_textarea_rows, cur_textarea_rows - 1, n_textarea)); if (cur_textarea_readonly) Strcat_charp(tmp, " readonly"); Strcat_charp(tmp, ">"); for (i = 0; i < cur_textarea_size; i++) Strcat_char(tmp, ' '); Strcat_charp(tmp, "]\n"); cur_hseq++; n_textarea++; cur_textarea = NULL; return tmp; } void feed_textarea(char *str) { if (cur_textarea == NULL) return; if (ignore_nl_textarea) { if (*str == '\r') str++; if (*str == '\n') str++; } ignore_nl_textarea = FALSE; while (*str) { if (*str == '&') Strcat_charp(textarea_str[n_textarea], getescapecmd(&str)); else if (*str == '\n') { Strcat_charp(textarea_str[n_textarea], "\r\n"); str++; } else if (*str != '\r') Strcat_char(textarea_str[n_textarea], *(str++)); } } Str process_hr(struct parsed_tag *tag, int width, int indent_width) { Str tmp = Strnew_charp(""); int i, w = 0; int x = ALIGN_CENTER; if (width > indent_width) width -= indent_width; if (parsedtag_get_value(tag, ATTR_WIDTH, &w)) w = REAL_WIDTH(w, width); else w = width; parsedtag_get_value(tag, ATTR_ALIGN, &x); switch (x) { case ALIGN_CENTER: Strcat_charp(tmp, "
"); break; case ALIGN_RIGHT: Strcat_charp(tmp, "
"); break; case ALIGN_LEFT: Strcat_charp(tmp, "
"); break; } #ifndef KANJI_SYMBOLS Strcat_charp(tmp, "<_RULE TYPE=10>"); #endif /* not KANJI_SYMBOLS */ w -= HR_RULE_WIDTH - 1; if (w <= 0) w = 1; for (i = 0; i < w; i += HR_RULE_WIDTH) { Strcat_charp(tmp, HR_RULE); } #ifndef KANJI_SYMBOLS Strcat_charp(tmp, ""); #endif /* not KANJI_SYMBOLS */ Strcat_charp(tmp, "
"); return tmp; } #ifdef JP_CHARSET static char check_charset(char *s) { switch (*s) { case CODE_EUC: case CODE_SJIS: case CODE_JIS_n: case CODE_JIS_m: case CODE_JIS_N: case CODE_JIS_j: case CODE_JIS_J: case CODE_INNER_EUC: return *s; } return 0; } static char check_accept_charset(char *s) { char *e; char c; while (*s) { while (*s && (IS_SPACE(*s) || *s == ',')) s++; if (!*s) break; e = s; while (*e && !(IS_SPACE(*e) || *e == ',')) e++; c = guess_charset(Strnew_charp_n(s, e - s)->ptr); if (c) return c; s = e; } return 0; } #endif /* JP_CHARSET */ static Str process_form_int(struct parsed_tag *tag, int fid) { char *p, *q, *r, *s, *tg, *n; char cs = 0; p = "get"; parsedtag_get_value(tag, ATTR_METHOD, &p); q = "!CURRENT_URL!"; parsedtag_get_value(tag, ATTR_ACTION, &q); r = NULL; #ifdef JP_CHARSET if (parsedtag_get_value(tag, ATTR_ACCEPT_CHARSET, &r)) cs = check_accept_charset(r); if (!cs && parsedtag_get_value(tag, ATTR_CHARSET, &r)) cs = check_charset(r); #endif /*JP_CHARSET */ s = NULL; parsedtag_get_value(tag, ATTR_ENCTYPE, &s); tg = NULL; parsedtag_get_value(tag, ATTR_TARGET, &tg); n = NULL; parsedtag_get_value(tag, ATTR_NAME, &n); if (fid < 0) { form_max++; form_sp++; fid = form_max; } else { /* */ if (form_max < fid) form_max = fid; form_sp = fid; } if (forms_size == 0) { forms_size = INITIAL_FORM_SIZE; forms = New_N(FormList *, forms_size); form_stack = NewAtom_N(int, forms_size); } else if (forms_size <= form_max) { forms_size += form_max; forms = New_Reuse(FormList *, forms, forms_size); form_stack = New_Reuse(int, form_stack, forms_size); } form_stack[form_sp] = fid; if (w3m_halfdump) { Str tmp = Sprintf(""); return tmp; } forms[fid] = newFormList(q, p, &cs, s, tg, n, NULL); return NULL; } Str process_form(struct parsed_tag *tag) { return process_form_int(tag, -1); } Str process_n_form(void) { if (form_sp >= 0) form_sp--; return NULL; } static void clear_ignore_p_flag(int cmd, struct readbuffer *obuf) { static int clear_flag_cmd[] = { HTML_HR, HTML_UNKNOWN }; int i; for (i = 0; clear_flag_cmd[i] != HTML_UNKNOWN; i++) { if (cmd == clear_flag_cmd[i]) { obuf->flag &= ~RB_IGNORE_P; return; } } } static void set_alignment(struct readbuffer *obuf, struct parsed_tag *tag) { long flag = -1; int align; if (parsedtag_get_value(tag, ATTR_ALIGN, &align)) { switch (align) { case ALIGN_CENTER: flag = RB_CENTER; break; case ALIGN_RIGHT: flag = RB_RIGHT; break; case ALIGN_LEFT: flag = RB_LEFT; } } RB_SAVE_FLAG(obuf); if (flag != -1) { RB_SET_ALIGN(obuf, flag); } } #ifdef ID_EXT static void process_idattr(struct readbuffer *obuf, int cmd, struct parsed_tag *tag) { char *id = NULL, *framename = NULL; Str idtag = NULL; /* * HTML_TABLE is handled by the other process. */ if (cmd == HTML_TABLE) return; parsedtag_get_value(tag, ATTR_ID, &id); parsedtag_get_value(tag, ATTR_FRAMENAME, &framename); if (id == NULL) return; if (framename) idtag = Sprintf("<_id id=\"%s\" framename=\"%s\">", html_quote(id), html_quote(framename)); else idtag = Sprintf("<_id id=\"%s\">", html_quote(id)); push_tag(obuf, idtag->ptr, HTML_NOP); } #endif /* ID_EXT */ #define CLOSE_P if (obuf->flag & RB_P) { \ flushline(h_env, obuf, envs[h_env->envc].indent,0,h_env->limit);\ RB_RESTORE_FLAG(obuf);\ close_anchor(h_env, obuf);\ obuf->flag &= ~RB_P;\ } #define CLOSE_DT \ if (obuf->flag & RB_IN_DT) { \ obuf->flag &= ~RB_IN_DT; \ HTMLlineproc1("", h_env); \ } #define PUSH_ENV(cmd) \ if (++h_env->envc_real < h_env->nenv) { \ ++h_env->envc; \ envs[h_env->envc].env = cmd; \ envs[h_env->envc].count = 0; \ if (h_env->envc <= MAX_INDENT_LEVEL) \ envs[h_env->envc].indent = envs[h_env->envc - 1].indent + INDENT_INCR; \ else \ envs[h_env->envc].indent = envs[h_env->envc - 1].indent; \ } #define POP_ENV \ if (h_env->envc_real-- < h_env->nenv) \ h_env->envc--; static int ul_type(struct parsed_tag *tag, int default_type) { char *p; if (parsedtag_get_value(tag, ATTR_TYPE, &p)) { if (!strcasecmp(p, "disc")) return (int)'d'; else if (!strcasecmp(p, "circle")) return (int)'c'; else if (!strcasecmp(p, "square")) return (int)'s'; } return default_type; } int HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) { char *p, *q, *r; int i, w, x, y, z, count, width; struct readbuffer *obuf = h_env->obuf; struct environment *envs = h_env->envs; Str tmp; int hseq; int cmd; #ifdef ID_EXT char *id = NULL; #endif /* ID_EXT */ cmd = tag->tagid; if (obuf->flag & RB_PRE) { switch (cmd) { case HTML_NOBR: case HTML_N_NOBR: case HTML_PRE_INT: case HTML_N_PRE_INT: return 1; } } switch (cmd) { case HTML_B: obuf->in_bold++; if (obuf->in_bold > 1) return 1; return 0; case HTML_N_B: if (obuf->in_bold == 1 && close_effect0(obuf, HTML_B)) obuf->in_bold = 0; if (obuf->in_bold > 0) { obuf->in_bold--; if (obuf->in_bold == 0) return 0; } return 1; case HTML_U: obuf->in_under++; if (obuf->in_under > 1) return 1; return 0; case HTML_N_U: if (obuf->in_under == 1 && close_effect0(obuf, HTML_U)) obuf->in_under = 0; if (obuf->in_under > 0) { obuf->in_under--; if (obuf->in_under == 0) return 0; } return 1; case HTML_EM: HTMLlineproc1("", h_env); return 1; case HTML_N_EM: HTMLlineproc1("", h_env); return 1; case HTML_P: case HTML_N_P: CLOSE_P; if (!(obuf->flag & RB_IGNORE_P)) { flushline(h_env, obuf, envs[h_env->envc].indent, 1, h_env->limit); do_blankline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); } obuf->flag |= RB_IGNORE_P; if (cmd == HTML_P) { set_alignment(obuf, tag); obuf->flag |= RB_P; } return 1; case HTML_BR: flushline(h_env, obuf, envs[h_env->envc].indent, 1, h_env->limit); h_env->blank_lines = 0; return 1; case HTML_EOL: if ((obuf->flag & RB_PREMODE) && obuf->pos > envs[h_env->envc].indent) flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); return 1; case HTML_H: if (!(obuf->flag & (RB_PREMODE | RB_IGNORE_P))) { flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); do_blankline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); } HTMLlineproc1("", h_env); set_alignment(obuf, tag); return 1; case HTML_N_H: HTMLlineproc1("", h_env); if (!(obuf->flag & RB_PREMODE)) { flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); } do_blankline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); RB_RESTORE_FLAG(obuf); close_anchor(h_env, obuf); obuf->flag |= RB_IGNORE_P; return 1; case HTML_UL: case HTML_OL: case HTML_BLQ: CLOSE_P; if (!(obuf->flag & RB_IGNORE_P)) { flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); if (!(obuf->flag & RB_PREMODE) && (h_env->envc == 0 || cmd == HTML_BLQ)) do_blankline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); } PUSH_ENV(cmd); if (cmd == HTML_UL || cmd == HTML_OL) { if (parsedtag_get_value(tag, ATTR_START, &count) && count > 0) { envs[h_env->envc].count = count - 1; } } if (cmd == HTML_OL) { envs[h_env->envc].type = '1'; if (parsedtag_get_value(tag, ATTR_TYPE, &p)) { envs[h_env->envc].type = (int)*p; } } if (cmd == HTML_UL) envs[h_env->envc].type = ul_type(tag, 0); flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); return 1; case HTML_N_UL: case HTML_N_OL: case HTML_N_DL: case HTML_N_BLQ: CLOSE_DT; CLOSE_P; if (h_env->envc > 0) { flushline(h_env, obuf, envs[h_env->envc - 1].indent, 0, h_env->limit); POP_ENV; if (!(obuf->flag & RB_PREMODE) && (h_env->envc == 0 || cmd == HTML_N_DL || cmd == HTML_N_BLQ)) { do_blankline(h_env, obuf, envs[h_env->envc].indent, INDENT_INCR, h_env->limit); obuf->flag |= RB_IGNORE_P; } } close_anchor(h_env, obuf); return 1; case HTML_DL: CLOSE_P; if (!(obuf->flag & RB_IGNORE_P)) { flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); if (!(obuf->flag & RB_PREMODE)) do_blankline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); } PUSH_ENV(cmd); if (parsedtag_exists(tag, ATTR_COMPACT)) envs[h_env->envc].env = HTML_DL_COMPACT; obuf->flag |= RB_IGNORE_P; return 1; case HTML_LI: CLOSE_P; CLOSE_DT; if (h_env->envc > 0) { Str num; flushline(h_env, obuf, envs[h_env->envc - 1].indent, 0, h_env->limit); envs[h_env->envc].count++; if (parsedtag_get_value(tag, ATTR_VALUE, &p)) { count = atoi(p); if (count > 0) envs[h_env->envc].count = count; } switch (envs[h_env->envc].env) { case HTML_UL: envs[h_env->envc].type = ul_type(tag, envs[h_env->envc].type); for (i = 0; i < INDENT_INCR - 3; i++) push_charp(obuf, 1, NBSP, PC_ASCII); switch (envs[h_env->envc].type) { #ifdef KANJI_SYMBOLS case 'd': push_charp(obuf, 2, "¡ü", PC_ASCII); break; case 'c': push_charp(obuf, 2, "¡û", PC_ASCII); break; case 's': push_charp(obuf, 2, "¢¢", PC_ASCII); break; #endif /* KANJI_SYMBOLS */ default: push_charp(obuf, 2, ullevel[(h_env->envc_real - 1) % MAX_UL_LEVEL], PC_ASCII); break; } push_charp(obuf, 1, NBSP, PC_ASCII); obuf->prevchar = ' '; break; case HTML_OL: if (parsedtag_get_value(tag, ATTR_TYPE, &p)) envs[h_env->envc].type = (int)*p; switch (envs[h_env->envc].type) { case 'i': num = romanNumeral(envs[h_env->envc].count); break; case 'I': num = romanNumeral(envs[h_env->envc].count); Strupper(num); break; case 'a': num = romanAlphabet(envs[h_env->envc].count); break; case 'A': num = romanAlphabet(envs[h_env->envc].count); Strupper(num); break; default: num = Sprintf("%d", envs[h_env->envc].count); break; } #if INDENT_INCR >= 4 Strcat_charp(num, ". "); #else /* INDENT_INCR < 4 */ Strcat_char(num, '.'); #endif /* INDENT_INCR < 4 */ push_spaces(obuf, 1, INDENT_INCR - num->length); push_str(obuf, num->length, num, PC_ASCII); break; default: push_spaces(obuf, 1, INDENT_INCR); break; } } else { flushline(h_env, obuf, 0, 0, h_env->limit); } obuf->flag |= RB_IGNORE_P; return 1; case HTML_DT: CLOSE_P; if (h_env->envc == 0 || (h_env->envc_real < h_env->nenv && envs[h_env->envc].env != HTML_DL && envs[h_env->envc].env != HTML_DL_COMPACT)) { PUSH_ENV(HTML_DL); } if (h_env->envc > 0) { flushline(h_env, obuf, envs[h_env->envc - 1].indent, 0, h_env->limit); } if (!(obuf->flag & RB_IN_DT)) { HTMLlineproc1("", h_env); obuf->flag |= RB_IN_DT; } obuf->flag |= RB_IGNORE_P; return 1; case HTML_DD: CLOSE_P; CLOSE_DT; if (envs[h_env->envc].env == HTML_DL_COMPACT) { if (obuf->pos > envs[h_env->envc].indent) flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); else push_spaces(obuf, 1, envs[h_env->envc].indent - obuf->pos); } else flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); /* obuf->flag |= RB_IGNORE_P; */ return 1; case HTML_TITLE: append_tags(obuf); save_line = obuf->line; save_prevchar = obuf->prevchar; set_breakpoint(obuf, 0); obuf->line = Strnew(); discardline(obuf, 0); obuf->flag |= (RB_NOBR | RB_TITLE); return 1; case HTML_N_TITLE: if (!(obuf->flag & RB_TITLE)) return 1; obuf->flag &= ~(RB_NOBR | RB_TITLE); append_tags(obuf); tmp = Strnew_charp(obuf->line->ptr); Strremovetrailingspaces(tmp); h_env->title = html_unquote(tmp->ptr); obuf->line = save_line; obuf->prevchar = save_prevchar; back_to_breakpoint(obuf); tmp = Strnew_m_charp("title), "\">", NULL); push_tag(obuf, tmp->ptr, HTML_TITLE_ALT); return 1; case HTML_FRAMESET: PUSH_ENV(cmd); push_charp(obuf, 9, "--FRAME--", PC_ASCII); flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); return 0; case HTML_N_FRAMESET: if (h_env->envc > 0) { POP_ENV; flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); } return 0; case HTML_NOFRAMES: CLOSE_P; flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); obuf->flag |= (RB_NOFRAMES | RB_IGNORE_P); /* istr = str; */ return 1; case HTML_N_NOFRAMES: CLOSE_P; flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); obuf->flag &= ~RB_NOFRAMES; return 1; case HTML_FRAME: q = r = NULL; parsedtag_get_value(tag, ATTR_SRC, &q); parsedtag_get_value(tag, ATTR_NAME, &r); if (q) { q = html_quote(q); push_tag(obuf, Sprintf("", cur_hseq++, q)->ptr, HTML_A); if (r) q = html_quote(r); push_charp(obuf, strlen(q), q, PC_ASCII); push_tag(obuf, "", HTML_N_A); } flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); return 0; case HTML_HR: tmp = process_hr(tag, h_env->limit, envs[h_env->envc].indent); HTMLlineproc1(tmp->ptr, h_env); obuf->prevchar = ' '; close_anchor(h_env, obuf); return 1; case HTML_PRE: if (!parsedtag_exists(tag, ATTR_FOR_TABLE)) CLOSE_P; if (!(obuf->flag & RB_IGNORE_P)) flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); else fillline(obuf, envs[h_env->envc].indent); obuf->flag |= (RB_PRE | RB_IGNORE_P); /* istr = str; */ return 1; case HTML_N_PRE: flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); obuf->flag &= ~RB_PRE; close_anchor(h_env, obuf); return 1; case HTML_PRE_INT: i = obuf->line->length; append_tags(obuf); if (!(obuf->flag & RB_SPECIAL)) { set_breakpoint(obuf, obuf->line->length - i); } obuf->flag |= RB_PRE_INT; return 0; case HTML_N_PRE_INT: push_tag(obuf, "", HTML_N_PRE_INT); obuf->flag &= ~RB_PRE_INT; if (!(obuf->flag & RB_SPECIAL) && obuf->pos > obuf->bp.pos) { obuf->prevchar = '\0'; obuf->prev_ctype = PC_CTRL; } return 1; case HTML_NOBR: obuf->flag |= RB_NOBR; obuf->nobr_level++; return 0; case HTML_N_NOBR: if (obuf->nobr_level > 0) obuf->nobr_level--; if (obuf->nobr_level == 0) obuf->flag &= ~RB_NOBR; return 0; case HTML_LISTING: CLOSE_P; flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); obuf->flag |= (RB_LSTMODE | RB_IGNORE_P); /* istr = str; */ return 1; case HTML_N_LISTING: CLOSE_P; flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); obuf->flag &= ~RB_LSTMODE; return 1; case HTML_XMP: CLOSE_P; flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); obuf->flag |= (RB_XMPMODE | RB_IGNORE_P); /* istr = str; */ return 1; case HTML_N_XMP: CLOSE_P; flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); obuf->flag &= ~RB_XMPMODE; return 1; case HTML_SCRIPT: obuf->flag |= RB_IGNORE; obuf->ignore_tag = Strnew_charp(""); return 1; case HTML_N_SCRIPT: /* should not be reached */ return 1; case HTML_STYLE: obuf->flag |= RB_IGNORE; obuf->ignore_tag = Strnew_charp(""); return 1; case HTML_N_STYLE: /* should not be reached */ return 1; case HTML_PLAINTEXT: flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); obuf->flag |= RB_PLAIN; /* istr = str; */ return 1; case HTML_A: if (obuf->anchor) close_anchor(h_env, obuf); hseq = 0; if (parsedtag_get_value(tag, ATTR_HREF, &p)) obuf->anchor = Strnew_charp(p); if (parsedtag_get_value(tag, ATTR_TARGET, &p)) obuf->anchor_target = Strnew_charp(p); if (parsedtag_get_value(tag, ATTR_HSEQ, &hseq)) obuf->anchor_hseq = hseq; if (hseq == 0 && obuf->anchor) { obuf->anchor_hseq = cur_hseq; tmp = process_anchor(tag, h_env->tagbuf->ptr); push_tag(obuf, tmp->ptr, HTML_A); return 1; } return 0; case HTML_N_A: close_anchor(h_env, obuf); return 1; case HTML_IMG: tmp = process_img(tag, h_env->limit); HTMLlineproc1(tmp->ptr, h_env); return 1; case HTML_IMG_ALT: if (parsedtag_get_value(tag, ATTR_SRC, &p)) obuf->img_alt = Strnew_charp(p); #ifdef USE_IMAGE i = 0; if (parsedtag_get_value(tag, ATTR_TOP_MARGIN, &i)) { if (i > obuf->top_margin) obuf->top_margin = i; } i = 0; if (parsedtag_get_value(tag, ATTR_BOTTOM_MARGIN, &i)) { if (i > obuf->bottom_margin) obuf->bottom_margin = i; } #endif return 0; case HTML_N_IMG_ALT: if (obuf->img_alt) { if (!close_effect0(obuf, HTML_IMG_ALT)) push_tag(obuf, "", HTML_N_IMG_ALT); obuf->img_alt = NULL; } return 1; case HTML_INPUT_ALT: i = 0; if (parsedtag_get_value(tag, ATTR_TOP_MARGIN, &i)) { if (i > obuf->top_margin) obuf->top_margin = i; } i = 0; if (parsedtag_get_value(tag, ATTR_BOTTOM_MARGIN, &i)) { if (i > obuf->bottom_margin) obuf->bottom_margin = i; } return 0; case HTML_TABLE: obuf->table_level++; if (obuf->table_level >= MAX_TABLE) break; w = BORDER_NONE; /* x: cellspacing, y: cellpadding */ x = 2; y = 1; z = 0; width = 0; if (parsedtag_exists(tag, ATTR_BORDER)) { if (parsedtag_get_value(tag, ATTR_BORDER, &w)) { if (w > 2) w = BORDER_THICK; else if (w < 0) { /* weird */ w = BORDER_THIN; } } else w = BORDER_THIN; } if (parsedtag_get_value(tag, ATTR_WIDTH, &i)) { if (obuf->table_level == 0) width = REAL_WIDTH(i, h_env->limit - envs[h_env->envc].indent); else width = RELATIVE_WIDTH(i); } if (parsedtag_exists(tag, ATTR_HBORDER)) w = BORDER_NOWIN; parsedtag_get_value(tag, ATTR_CELLSPACING, &x); parsedtag_get_value(tag, ATTR_CELLPADDING, &y); parsedtag_get_value(tag, ATTR_VSPACE, &z); #ifdef ID_EXT parsedtag_get_value(tag, ATTR_ID, &id); #endif /* ID_EXT */ tables[obuf->table_level] = begin_table(w, x, y, z); #ifdef ID_EXT if (id != NULL) tables[obuf->table_level]->id = Strnew_charp(id); #endif /* ID_EXT */ table_mode[obuf->table_level].pre_mode = 0; table_mode[obuf->table_level].indent_level = 0; table_mode[obuf->table_level].nobr_level = 0; table_mode[obuf->table_level].caption = 0; #ifndef TABLE_EXPAND tables[obuf->table_level]->total_width = width; #else tables[obuf->table_level]->real_width = width; tables[obuf->table_level]->total_width = 0; #endif return 1; case HTML_N_TABLE: /* should be processed in HTMLlineproc() */ return 1; case HTML_CENTER: CLOSE_P; if (!(obuf->flag & (RB_PREMODE | RB_IGNORE_P))) flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); RB_SAVE_FLAG(obuf); RB_SET_ALIGN(obuf, RB_CENTER); return 1; case HTML_N_CENTER: CLOSE_P; if (!(obuf->flag & RB_PREMODE)) flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); RB_RESTORE_FLAG(obuf); return 1; case HTML_DIV: CLOSE_P; if (!(obuf->flag & RB_IGNORE_P)) flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); set_alignment(obuf, tag); return 1; case HTML_N_DIV: CLOSE_P; flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); RB_RESTORE_FLAG(obuf); return 1; case HTML_FORM: CLOSE_P; if (!(obuf->flag & RB_IGNORE_P)) flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); tmp = process_form(tag); if (tmp) HTMLlineproc1(tmp->ptr, h_env); return 1; case HTML_N_FORM: CLOSE_P; flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); obuf->flag |= RB_IGNORE_P; process_n_form(); return 1; case HTML_INPUT: tmp = process_input(tag); if (tmp) HTMLlineproc1(tmp->ptr, h_env); return 1; case HTML_SELECT: tmp = process_select(tag); if (tmp) HTMLlineproc1(tmp->ptr, h_env); obuf->flag |= RB_INSELECT; return 1; case HTML_N_SELECT: obuf->flag &= ~RB_INSELECT; tmp = process_n_select(); if (tmp) HTMLlineproc1(tmp->ptr, h_env); return 1; case HTML_OPTION: /* nothing */ return 1; case HTML_TEXTAREA: tmp = process_textarea(tag, h_env->limit); if (tmp) HTMLlineproc1(tmp->ptr, h_env); obuf->flag |= RB_INTXTA; return 1; case HTML_N_TEXTAREA: close_textarea(h_env); return 1; case HTML_ISINDEX: p = ""; q = "!CURRENT_URL!"; parsedtag_get_value(tag, ATTR_PROMPT, &p); parsedtag_get_value(tag, ATTR_ACTION, &q); tmp = Strnew_m_charp("
", html_quote(p), "
", NULL); HTMLlineproc1(tmp->ptr, h_env); return 1; case HTML_META: p = q = NULL; parsedtag_get_value(tag, ATTR_HTTP_EQUIV, &p); parsedtag_get_value(tag, ATTR_CONTENT, &q); #ifdef JP_CHARSET if (p && q && !strcasecmp(p, "Content-Type") && (q = strcasestr(q, "charset")) != NULL) { q += 7; SKIP_BLANKS(q); if (*q == '=') { q++; SKIP_BLANKS(q); meta_charset = guess_charset(q); } } else #endif if (p && q && !strcasecmp(p, "refresh")) { int refresh_interval = atoi(q); Str s_tmp = NULL; while (*q) { if (!strncasecmp(q, "url=", 4)) { q += 4; if (*q == '\"') /* " */ q++; r = q; while (*r && !IS_SPACE(*r) && *r != ';') r++; s_tmp = Strnew_charp_n(q, r - q); if (s_tmp->ptr[s_tmp->length - 1] == '\"') { /* " */ s_tmp->length--; s_tmp->ptr[s_tmp->length] = '\0'; } q = r; } while (*q && *q != ';') q++; if (*q == ';') q++; while (*q && *q == ' ') q++; } if (s_tmp) { q = html_quote(s_tmp->ptr); tmp = Sprintf ("Refresh (%d sec) %s", refresh_interval, cur_hseq++, q, q); push_str(obuf, s_tmp->length, tmp, PC_ASCII); flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); if (!is_redisplay && refresh_interval == 0 && MetaRefresh && !((obuf->flag & RB_NOFRAMES) && RenderFrame)) { pushEvent(FUNCNAME_gorURL, s_tmp->ptr); /* pushEvent(deletePrevBuf,NULL); */ } #ifdef USE_ALARM else if (!is_redisplay && refresh_interval > 0 && MetaRefresh && !((obuf->flag & RB_NOFRAMES) && RenderFrame)) { setAlarmEvent(refresh_interval, AL_IMPLICIT, FUNCNAME_gorURL, s_tmp->ptr); } #endif } #ifdef USE_ALARM else if (!is_redisplay && refresh_interval > 0 && MetaRefresh && !((obuf->flag & RB_NOFRAMES) && RenderFrame)) { tmp = Sprintf("Refresh (%d sec)", refresh_interval); push_str(obuf, 0, tmp, PC_ASCII); flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); setAlarmEvent(refresh_interval, AL_IMPLICIT, FUNCNAME_reload, NULL); } #endif } return 1; case HTML_BASE: #ifdef USE_IMAGE p = NULL; if (parsedtag_get_value(tag, ATTR_HREF, &p)) { if (!cur_baseURL) cur_baseURL = New(ParsedURL); parseURL(p, cur_baseURL, NULL); } #endif case HTML_MAP: case HTML_N_MAP: case HTML_AREA: return 0; case HTML_DEL: HTMLlineproc1("[DEL:", h_env); return 1; case HTML_N_DEL: HTMLlineproc1(":DEL]", h_env); return 1; case HTML_INS: HTMLlineproc1("[INS:", h_env); return 1; case HTML_N_INS: HTMLlineproc1(":INS]", h_env); return 1; case HTML_FONT: case HTML_N_FONT: case HTML_NOP: return 1; case HTML_BGSOUND: if (view_unseenobject) { if (parsedtag_get_value(tag, ATTR_SRC, &p)) { Str s; q = html_quote(p); s = Sprintf("bgsound(%s)", q, q); HTMLlineproc1(s->ptr, h_env); } } return 1; case HTML_EMBED: if (view_unseenobject) { if (parsedtag_get_value(tag, ATTR_SRC, &p)) { Str s; q = html_quote(p); s = Sprintf("embed(%s)", q, q); HTMLlineproc1(s->ptr, h_env); } } return 1; case HTML_APPLET: if (view_unseenobject) { if (parsedtag_get_value(tag, ATTR_ARCHIVE, &p)) { Str s; q = html_quote(p); s = Sprintf("applet archive(%s)", q, q); HTMLlineproc1(s->ptr, h_env); } } return 1; case HTML_BODY: if (view_unseenobject) { if (parsedtag_get_value(tag, ATTR_BACKGROUND, &p)) { Str s; q = html_quote(p); s = Sprintf("\"bg
", q, q); HTMLlineproc1(s->ptr, h_env); } } case HTML_N_BODY: return 1; default: /* obuf->prevchar = '\0'; */ return 0; } /* not reached */ return 0; } #define PPUSH(p,c) {outp[pos]=(p);outc[pos]=(c);pos++;} static TextLineListItem *_tl_lp2; static Str textlist_feed() { TextLine *p; if (_tl_lp2 != NULL) { p = _tl_lp2->ptr; _tl_lp2 = _tl_lp2->next; return p->line; } return NULL; } static void HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit) { Anchor *a_href = NULL, *a_img = NULL, *a_form = NULL; char outc[LINELEN]; char *p, *q, *r, *s, *str; Lineprop outp[LINELEN], mode, effect; int pos; int nlines; FILE *debug = NULL; struct frameset *frameset_s[FRAMESTACK_SIZE]; int frameset_sp = -1; union frameset_element *idFrame = NULL; char *id = NULL; int hseq, form_id; Str line; char *endp; #ifndef KANJI_SYMBOLS char rule = 0; #endif int internal = 0; Anchor **a_textarea = NULL; #ifdef MENU_SELECT Anchor **a_select = NULL; #endif n_textarea = -1; if (!max_textarea) { /* halfload */ max_textarea = MAX_TEXTAREA; textarea_str = New_N(Str, max_textarea); a_textarea = New_N(Anchor *, max_textarea); } #ifdef MENU_SELECT n_select = -1; if (!max_select) { /* halfload */ max_select = MAX_SELECT; select_option = New_N(FormSelectOption, max_select); a_select = New_N(Anchor *, max_select); } #endif if (w3m_debug) debug = fopen("zzzerr", "a"); effect = 0; nlines = 0; while ((line = feed()) != NULL) { if (w3m_debug) { Strfputs(line, debug); fputc('\n', debug); } if (n_textarea >= 0 && *(line->ptr) != '<') { /* halfload */ Strcat(textarea_str[n_textarea], line); continue; } proc_again: if (++nlines == llimit) break; pos = 0; #ifdef ENABLE_REMOVE_TRAILINGSPACES Strremovetrailingspaces(line); #endif str = line->ptr; endp = str + line->length; while (str < endp && pos < LINELEN) { mode = get_mctype(str); #ifndef KANJI_SYMBOLS if (effect & PC_RULE && *str != '<') { PPUSH(PC_ASCII | effect, rule | 0x80); str++; } else #endif if (mode == PC_CTRL || IS_INTSPACE(*str)) { PPUSH(PC_ASCII | effect, ' '); str++; } #ifdef JP_CHARSET else if (mode == PC_KANJI) { PPUSH(PC_KANJI1 | effect, str[0]); PPUSH(PC_KANJI2 | effect, str[1]); str += 2; } #endif else if (mode == PC_ASCII && *str != '<' && *str != '&') { PPUSH(mode | effect, *(str++)); } else if (*str == '&') { /* * & escape processing */ int emode; p = getescapecmd(&str); while (*p) { emode = get_mctype(p); #ifdef JP_CHARSET if (emode == PC_KANJI) { PPUSH(PC_KANJI1 | effect, p[0]); PPUSH(PC_KANJI2 | effect, p[1]); p += 2; } else #endif { PPUSH(emode | effect, *(p++)); } } } else { /* tag processing */ struct parsed_tag *tag; if (!(tag = parse_tag(&str, TRUE))) continue; switch (tag->tagid) { case HTML_B: effect |= PE_BOLD; break; case HTML_N_B: effect &= ~PE_BOLD; break; case HTML_U: effect |= PE_UNDER; break; case HTML_N_U: effect &= ~PE_UNDER; break; case HTML_A: if (renderFrameSet && parsedtag_get_value(tag, ATTR_FRAMENAME, &p)) { p = url_quote_conv(p, buf->document_code); if (!idFrame || strcmp(idFrame->body->name, p)) { idFrame = search_frame(renderFrameSet, p); if (idFrame && idFrame->body->attr != F_BODY) idFrame = NULL; } } p = r = NULL; q = buf->baseTarget; hseq = 0; id = NULL; if (parsedtag_get_value(tag, ATTR_NAME, &id)) { id = url_quote_conv(id, buf->document_code); registerName(buf, id, currentLn(buf), pos); } if (parsedtag_get_value(tag, ATTR_HREF, &p)) { p = remove_space(p); p = url_quote_conv(p, buf->document_code); } if (parsedtag_get_value(tag, ATTR_TARGET, &q)) q = url_quote_conv(q, buf->document_code); if (parsedtag_get_value(tag, ATTR_REFERER, &r)) r = url_quote_conv(r, buf->document_code); parsedtag_get_value(tag, ATTR_HSEQ, &hseq); if (hseq > 0) buf->hmarklist = putHmarker(buf->hmarklist, currentLn(buf), pos, hseq - 1); if (id && idFrame) idFrame->body->nameList = putAnchor(idFrame->body->nameList, id, NULL, (Anchor **)NULL, NULL, currentLn(buf), pos); if (p) { effect |= PE_ANCHOR; a_href = registerHref(buf, remove_space(p), q, r, currentLn(buf), pos); a_href->hseq = ((hseq > 0) ? hseq : -hseq) - 1; } break; case HTML_N_A: effect &= ~PE_ANCHOR; if (a_href) { a_href->end.line = currentLn(buf); a_href->end.pos = pos; if (a_href->start.line == a_href->end.line && a_href->start.pos == a_href->end.pos) a_href->hseq = -1; a_href = NULL; } break; case HTML_IMG_ALT: if (parsedtag_get_value(tag, ATTR_SRC, &p)) { #ifdef USE_IMAGE int w = -1, h = -1, iseq = 0, ismap = 0; int xoffset = 0, yoffset = 0, top = 0, bottom = 0; parsedtag_get_value(tag, ATTR_HSEQ, &iseq); parsedtag_get_value(tag, ATTR_WIDTH, &w); parsedtag_get_value(tag, ATTR_HEIGHT, &h); parsedtag_get_value(tag, ATTR_XOFFSET, &xoffset); parsedtag_get_value(tag, ATTR_YOFFSET, &yoffset); parsedtag_get_value(tag, ATTR_TOP_MARGIN, &top); parsedtag_get_value(tag, ATTR_BOTTOM_MARGIN, &bottom); if (parsedtag_exists(tag, ATTR_ISMAP)) ismap = 1; q = NULL; parsedtag_get_value(tag, ATTR_USEMAP, &q); if (iseq > 0) { buf->imarklist = putHmarker(buf->imarklist, currentLn(buf), pos, iseq - 1); } #endif p = remove_space(p); p = url_quote_conv(p, buf->document_code); a_img = registerImg(buf, p, currentLn(buf), pos); #ifdef USE_IMAGE a_img->hseq = iseq; a_img->image = NULL; if (iseq > 0) { ParsedURL u; Image *image; parseURL2(a_img->url, &u, cur_baseURL); a_img->image = image = New(Image); image->url = parsedURL2Str(&u)->ptr; image->ext = filename_extension(u.file, TRUE); image->cache = NULL; image->width = w; image->height = h; image->xoffset = xoffset; image->yoffset = yoffset; image->y = currentLn(buf) - top; if (image->xoffset < 0 && pos == 0) image->xoffset = 0; if (image->yoffset < 0 && image->y == 1) image->yoffset = 0; image->rows = 1 + top + bottom; image->map = q; image->ismap = ismap; image->touch = 0; image->cache = getImage(image, cur_baseURL, IMG_FLAG_SKIP); } else if (iseq < 0) { BufferPoint *po = buf->imarklist->marks - iseq - 1; Anchor *a = retrieveAnchor(buf->img, po->line, po->pos); if (a) { a_img->url = a->url; a_img->image = a->image; } } #endif } effect |= PE_IMAGE; break; case HTML_N_IMG_ALT: effect &= ~PE_IMAGE; if (a_img) { a_img->end.line = currentLn(buf); a_img->end.pos = pos; } a_img = NULL; break; case HTML_INPUT_ALT: { FormList *form; int top = 0, bottom = 0; int textareanumber = -1; #ifdef MENU_SELECT int selectnumber = -1; #endif hseq = 0; form_id = -1; parsedtag_get_value(tag, ATTR_HSEQ, &hseq); parsedtag_get_value(tag, ATTR_FID, &form_id); parsedtag_get_value(tag, ATTR_TOP_MARGIN, &top); parsedtag_get_value(tag, ATTR_BOTTOM_MARGIN, &bottom); if (form_id < 0 || form_id > form_max || forms == NULL) break; /* outside of
..
*/ form = forms[form_id]; if (hseq > 0) { int hpos = pos; if (*str == '[') hpos++; buf->hmarklist = putHmarker(buf->hmarklist, currentLn(buf), hpos, hseq - 1); } if (!form->target) form->target = buf->baseTarget; if (a_textarea && parsedtag_get_value(tag, ATTR_TEXTAREANUMBER, &textareanumber)) { if (textareanumber >= max_textarea) { max_textarea = 2 * textareanumber; textarea_str = New_Reuse(Str, textarea_str, max_textarea); a_textarea = New_Reuse(Anchor *, a_textarea, max_textarea); } } #ifdef MENU_SELECT if (a_select && parsedtag_get_value(tag, ATTR_SELECTNUMBER, &selectnumber)) { if (selectnumber >= max_select) { max_select = 2 * selectnumber; select_option = New_Reuse(FormSelectOption, select_option, max_select); a_select = New_Reuse(Anchor *, a_select, max_select); } } #endif a_form = registerForm(buf, form, tag, currentLn(buf), pos); if (a_textarea && textareanumber >= 0) a_textarea[textareanumber] = a_form; #ifdef MENU_SELECT if (a_select && selectnumber >= 0) a_select[selectnumber] = a_form; #endif if (a_form) { a_form->hseq = hseq - 1; a_form->y = currentLn(buf) - top; a_form->rows = 1 + top + bottom; if (!parsedtag_exists(tag, ATTR_NO_EFFECT)) effect |= PE_FORM; break; } } case HTML_N_INPUT_ALT: effect &= ~PE_FORM; if (a_form) { a_form->end.line = currentLn(buf); a_form->end.pos = pos; if (a_form->start.line == a_form->end.line && a_form->start.pos == a_form->end.pos) a_form->hseq = -1; } a_form = NULL; break; case HTML_MAP: if (parsedtag_get_value(tag, ATTR_NAME, &p)) { MapList *m = New(MapList); m->name = Strnew_charp(p); m->area = newGeneralList(); m->next = buf->maplist; buf->maplist = m; } break; case HTML_N_MAP: /* nothing to do */ break; case HTML_AREA: if (buf->maplist == NULL) /* outside of .. */ break; if (parsedtag_get_value(tag, ATTR_HREF, &p)) { MapArea *a; p = remove_space(p); p = url_quote_conv(p, buf->document_code); q = ""; parsedtag_get_value(tag, ATTR_ALT, &q); r = NULL; s = NULL; #ifdef USE_IMAGE parsedtag_get_value(tag, ATTR_SHAPE, &r); parsedtag_get_value(tag, ATTR_COORDS, &s); #endif a = newMapArea(p, q, r, s); pushValue(buf->maplist->area, (void *)a); } break; case HTML_FRAMESET: frameset_sp++; if (frameset_sp >= FRAMESTACK_SIZE) break; frameset_s[frameset_sp] = newFrameSet(tag); if (frameset_s[frameset_sp] == NULL) break; if (frameset_sp == 0) { if (buf->frameset == NULL) { buf->frameset = frameset_s[frameset_sp]; } else pushFrameTree(&(buf->frameQ), frameset_s[frameset_sp], NULL); } else addFrameSetElement(frameset_s[frameset_sp - 1], *(union frameset_element *) &frameset_s[frameset_sp]); break; case HTML_N_FRAMESET: if (frameset_sp >= 0) frameset_sp--; break; case HTML_FRAME: if (frameset_sp >= 0 && frameset_sp < FRAMESTACK_SIZE) { union frameset_element element; element.body = newFrame(tag, buf); addFrameSetElement(frameset_s[frameset_sp], element); } break; case HTML_BASE: if (parsedtag_get_value(tag, ATTR_HREF, &p)) { p = remove_space(p); p = url_quote_conv(p, buf->document_code); if (!buf->baseURL) buf->baseURL = New(ParsedURL); parseURL(p, buf->baseURL, NULL); } if (parsedtag_get_value(tag, ATTR_TARGET, &p)) buf->baseTarget = url_quote_conv(p, buf->document_code); break; case HTML_INTERNAL: internal = HTML_INTERNAL; break; case HTML_N_INTERNAL: internal = HTML_N_INTERNAL; break; case HTML_FORM_INT: if (parsedtag_get_value(tag, ATTR_FID, &form_id)) process_form_int(tag, form_id); break; case HTML_TEXTAREA_INT: if (parsedtag_get_value(tag, ATTR_TEXTAREANUMBER, &n_textarea) && n_textarea < max_textarea) { textarea_str[n_textarea] = Strnew(); } else n_textarea = -1; break; case HTML_N_TEXTAREA_INT: if (n_textarea >= 0) { FormItemList *item = (FormItemList *)a_textarea[n_textarea]->url; item->init_value = item->value = textarea_str[n_textarea]; } break; #ifdef MENU_SELECT case HTML_SELECT_INT: if (parsedtag_get_value(tag, ATTR_SELECTNUMBER, &n_select) && n_select < max_select) { select_option[n_select].first = NULL; select_option[n_select].last = NULL; } else n_select = -1; break; case HTML_N_SELECT_INT: if (n_select >= 0) { FormItemList *item = (FormItemList *)a_select[n_select]->url; item->select_option = select_option[n_select].first; chooseSelectOption(item, item->select_option); item->init_selected = item->selected; item->init_value = item->value; item->init_label = item->label; } break; case HTML_OPTION_INT: if (n_select >= 0) { int selected; q = ""; parsedtag_get_value(tag, ATTR_LABEL, &q); p = q; parsedtag_get_value(tag, ATTR_VALUE, &p); selected = parsedtag_exists(tag, ATTR_SELECTED); addSelectOption(&select_option[n_select], Strnew_charp(p), Strnew_charp(q), selected); } break; #endif case HTML_TITLE_ALT: if (parsedtag_get_value(tag, ATTR_TITLE, &p)) buf->buffername = html_unquote(p); break; #ifndef KANJI_SYMBOLS case HTML_RULE: effect |= PC_RULE; if (parsedtag_get_value(tag, ATTR_TYPE, &p)) rule = (char)atoi(p); break; case HTML_N_RULE: effect &= ~PC_RULE; break; #endif /* not KANJI_SYMBOLS */ } #ifdef ID_EXT id = NULL; if (parsedtag_get_value(tag, ATTR_ID, &id)) { id = url_quote_conv(id, buf->document_code); registerName(buf, id, currentLn(buf), pos); } if (renderFrameSet && parsedtag_get_value(tag, ATTR_FRAMENAME, &p)) { p = url_quote_conv(p, buf->document_code); if (!idFrame || strcmp(idFrame->body->name, p)) { idFrame = search_frame(renderFrameSet, p); if (idFrame && idFrame->body->attr != F_BODY) idFrame = NULL; } } if (id && idFrame) idFrame->body->nameList = putAnchor(idFrame->body->nameList, id, NULL, (Anchor **)NULL, NULL, currentLn(buf), pos); #endif /* ID_EXT */ } } /* end of processing for one line */ if (!internal) addnewline(buf, outc, outp, #ifdef USE_ANSI_COLOR NULL, #endif pos, nlines); if (internal == HTML_N_INTERNAL) internal = 0; if (str != endp) { line = Strsubstr(line, str - line->ptr, endp - str); goto proc_again; } } if (w3m_debug) fclose(debug); for (form_id = 1; form_id <= form_max; form_id++) forms[form_id]->next = forms[form_id - 1]; buf->formlist = (form_max >= 0) ? forms[form_max] : NULL; if (n_textarea) addMultirowsForm(buf, buf->formitem); #ifdef USE_IMAGE addMultirowsImg(buf, buf->img); #endif } void HTMLlineproc2(Buffer *buf, TextLineList *tl) { _tl_lp2 = tl->first; HTMLlineproc2body(buf, textlist_feed, -1); } static InputStream _file_lp2; static Str file_feed() { Str s; s = StrISgets(_file_lp2); if (s->length == 0) { ISclose(_file_lp2); return NULL; } return s; } void HTMLlineproc3(Buffer *buf, InputStream stream) { _file_lp2 = stream; HTMLlineproc2body(buf, file_feed, -1); } static void proc_escape(struct readbuffer *obuf, char **str_return) { char *str = *str_return, *estr; int ech = getescapechar(str_return); int width, n_add = *str_return - str; Lineprop mode; if (ech < 0) { *str_return = str; proc_mchar(obuf, obuf->flag & RB_SPECIAL, 1, str_return, PC_ASCII); return; } mode = IS_CNTRL(ech) ? PC_CTRL : PC_ASCII; check_breakpoint(obuf, obuf->flag & RB_SPECIAL, ech); estr = conv_entity(ech); width = strlen(estr); if (width == 1 && ech == (unsigned char)*estr && ech != '&' && ech != '<' && ech != '>') push_charp(obuf, width, estr, mode); else push_nchars(obuf, width, str, n_add, mode); obuf->prevchar = ech; obuf->prev_ctype = mode; } static int need_flushline(struct html_feed_environ *h_env, struct readbuffer *obuf, Lineprop mode) { char ch; if (obuf->flag & RB_PRE_INT) { if (obuf->pos > h_env->limit) return 1; else return 0; } ch = Strlastchar(obuf->line); /* if (ch == ' ' && obuf->tag_sp > 0) */ if (ch == ' ') return 0; if (obuf->pos > h_env->limit) return 1; return 0; } static int table_width(struct html_feed_environ *h_env, int table_level) { int width; if (table_level < 0) return 0; width = tables[table_level]->total_width; if (table_level > 0 || width > 0) return width; return h_env->limit - h_env->envs[h_env->envc].indent; } /* HTML processing first pass */ void HTMLlineproc0(char *str, struct html_feed_environ *h_env, int internal) { Lineprop mode; char *q; int cmd; struct readbuffer *obuf = h_env->obuf; int indent, delta; struct parsed_tag *tag; Str tokbuf; struct table *tbl = NULL; struct table_mode *tbl_mode = NULL; int tbl_width = 0; if (w3m_debug) { FILE *f = fopen("zzzproc1", "a"); fprintf(f, "%c%c%c%c", (obuf->flag & RB_PREMODE) ? 'P' : ' ', (obuf->table_level >= 0) ? 'T' : ' ', (obuf->flag & RB_INTXTA) ? 'X' : ' ', (obuf->flag & RB_IGNORE) ? 'I' : ' '); fprintf(f, "HTMLlineproc1(\"%s\",%d,%lx)\n", str, h_env->limit, (unsigned long)h_env); fclose(f); } /* comment processing */ if (obuf->status == R_ST_CMNT || obuf->status == R_ST_NCMNT3 || obuf->status == R_ST_IRRTAG) { while (*str != '\0' && obuf->status != R_ST_NORMAL) { next_status(*str, &obuf->status); str++; } if (obuf->status != R_ST_NORMAL) return; } tokbuf = Strnew(); table_start: if (obuf->table_level >= 0) { int level = min(obuf->table_level, MAX_TABLE - 1); tbl = tables[level]; tbl_mode = &table_mode[level]; tbl_width = table_width(h_env, level); } while (*str != '\0') { int is_tag = FALSE; if (obuf->flag & RB_PLAIN) goto read_as_plain; /* don't process tag */ if (*str == '<' || ST_IS_TAG(obuf->status)) { int pre_mode = (obuf->table_level >= 0) ? tbl_mode->pre_mode & TBLM_PLAIN : obuf->flag & RB_PLAINMODE; /* * Tag processing */ if (ST_IS_TAG(obuf->status)) { /*** continuation of a tag ***/ read_token(h_env->tagbuf, &str, &obuf->status, pre_mode, 1); } else { if (!REALLY_THE_BEGINNING_OF_A_TAG(str)) { /* this is NOT a beginning of a tag */ obuf->status = R_ST_NORMAL; HTMLlineproc1("<", h_env); str++; continue; } read_token(h_env->tagbuf, &str, &obuf->status, pre_mode, 0); } if (ST_IS_COMMENT(obuf->status)) { if (obuf->flag & RB_IGNORE) /* within ignored tag, such as * * , don't process comment. */ obuf->status = R_ST_NORMAL; return; } if (h_env->tagbuf->length == 0) continue; if (obuf->status != R_ST_NORMAL) { if (!pre_mode) { if (Strlastchar(h_env->tagbuf) == '\n') Strchop(h_env->tagbuf); if (ST_IS_REAL_TAG(obuf->status)) Strcat_char(h_env->tagbuf, ' '); } if ((obuf->flag & RB_IGNORE) && !TAG_IS(h_env->tagbuf->ptr, obuf->ignore_tag->ptr, obuf->ignore_tag->length - 1)) /* within ignored tag, such as * * , don't process tag. */ obuf->status = R_ST_NORMAL; continue; } is_tag = TRUE; q = h_env->tagbuf->ptr; } if (obuf->flag & (RB_INTXTA | RB_INSELECT | RB_IGNORE)) { cmd = HTML_UNKNOWN; if (!is_tag) { read_token(tokbuf, &str, &obuf->status, (obuf->flag & RB_INTXTA) ? 1 : 0, 0); if (obuf->status != R_ST_NORMAL) continue; q = tokbuf->ptr; } else { char *p = q; cmd = gethtmlcmd(&p); } /* textarea */ if (obuf->flag & RB_INTXTA) { if (cmd == HTML_N_TEXTAREA) goto proc_normal; feed_textarea(q); } else if (obuf->flag & RB_INSELECT) { if (cmd == HTML_N_SELECT || cmd == HTML_N_FORM) goto proc_normal; feed_select(q); } /* script */ else if (obuf->flag & RB_IGNORE) { if (TAG_IS(q, obuf->ignore_tag->ptr, obuf->ignore_tag->length - 1)) { obuf->flag &= ~RB_IGNORE; } } continue; } if (obuf->table_level >= 0) { /* * within table: in ..
, all input tokens * are fed to the table renderer, and then the renderer * makes HTML output. */ if (!is_tag) { read_token(tokbuf, &str, &obuf->status, tbl_mode->pre_mode & TBLM_PREMODE, 0); if (obuf->status != R_ST_NORMAL) continue; q = tokbuf->ptr; } switch (feed_table(tbl, q, tbl_mode, tbl_width, internal)) { case 0: /* tag */ obuf->table_level--; if (obuf->table_level >= MAX_TABLE - 1) continue; end_table(tbl); if (obuf->table_level >= 0) { Str tmp; struct table *tbl0 = tables[obuf->table_level]; tmp = Sprintf("", tbl0->ntable); pushTable(tbl0, tbl); tbl = tbl0; tbl_mode = &table_mode[obuf->table_level]; tbl_width = table_width(h_env, obuf->table_level); feed_table(tbl, tmp->ptr, tbl_mode, tbl_width, TRUE); continue; /* continue to the next */ } /* all tables have been read */ if (tbl->vspace > 0 && !(obuf->flag & RB_IGNORE_P)) { int indent = h_env->envs[h_env->envc].indent; flushline(h_env, obuf, indent, 0, h_env->limit); do_blankline(h_env, obuf, indent, 0, h_env->limit); } save_fonteffect(h_env, obuf); renderTable(tbl, tbl_width, h_env); restore_fonteffect(h_env, obuf); obuf->flag &= ~RB_IGNORE_P; if (tbl->vspace > 0) { int indent = h_env->envs[h_env->envc].indent; do_blankline(h_env, obuf, indent, 0, h_env->limit); obuf->flag |= RB_IGNORE_P; } obuf->prevchar = ' '; continue; case 1: /* tag */ goto proc_normal; default: continue; } } proc_normal: if (is_tag) { /*** Beginning of a new tag ***/ if ((tag = parse_tag(&q, internal))) cmd = tag->tagid; else cmd = HTML_UNKNOWN; if (((obuf->flag & RB_XMPMODE) && cmd != HTML_N_XMP) || ((obuf->flag & RB_LSTMODE) && cmd != HTML_N_LISTING)) { Str tmp = Strdup(h_env->tagbuf); Strcat_charp(tmp, str); str = tmp->ptr; goto read_as_plain; } if (cmd == HTML_UNKNOWN) continue; /* process tags */ if (HTMLtagproc1(tag, h_env) == 0) { /* preserve the tag for second-stage processing */ if (parsedtag_need_reconstruct(tag)) h_env->tagbuf = parsedtag2str(tag); push_tag(obuf, h_env->tagbuf->ptr, cmd); } #ifdef ID_EXT else { process_idattr(obuf, cmd, tag); } #endif /* ID_EXT */ obuf->bp.init_flag = 1; clear_ignore_p_flag(cmd, obuf); if (cmd == HTML_TABLE) goto table_start; else continue; } read_as_plain: mode = get_mctype(str); delta = get_mclen(mode); if (obuf->flag & (RB_SPECIAL & ~RB_NOBR)) { char ch = *str; if (!(obuf->flag & RB_PLAINMODE) && (*str == '&')) { char *p = str; int ech = getescapechar(&p); if (ech == '\n' || ech == '\r') { ch = '\n'; str = p - 1; } else if (ech == '\t') { ch = '\t'; str = p - 1; } } if (ch != '\n') obuf->flag &= ~RB_IGNORE_P; if (ch == '\n') { str++; if (obuf->flag & RB_IGNORE_P) { obuf->flag &= ~RB_IGNORE_P; continue; } if (obuf->flag & RB_PRE_INT) PUSH(' '); else flushline(h_env, obuf, h_env->envs[h_env->envc].indent, 1, h_env->limit); } else if (ch == '\t') { do { PUSH(' '); } while (obuf->pos % Tabstop != 0); str++; } else if (obuf->flag & RB_PLAINMODE) { char *p = html_quote_char(*str); if (p) { push_charp(obuf, 1, p, PC_ASCII); str++; } else { proc_mchar(obuf, 1, delta, &str, mode); } } else { if (*str == '&') proc_escape(obuf, &str); else proc_mchar(obuf, 1, delta, &str, mode); } if (obuf->flag & (RB_SPECIAL & ~RB_PRE_INT)) continue; } else { if (!IS_SPACE(*str)) obuf->flag &= ~RB_IGNORE_P; if ((mode == PC_ASCII || mode == PC_CTRL) && IS_SPACE(*str)) { if (obuf->prevchar != ' ') { PUSH(' '); } str++; } else { #ifdef JP_CHARSET if (mode == PC_KANJI && obuf->pos > h_env->envs[h_env->envc].indent && Strlastchar(obuf->line) == ' ') { while (obuf->line->length >= 2 && !strncmp(obuf->line->ptr + obuf->line->length - 2, " ", 2) && obuf->pos >= h_env->envs[h_env->envc].indent) { Strshrink(obuf->line, 1); obuf->pos--; } if (obuf->line->length >= 3 && obuf->prev_ctype == PC_KANJI && Strlastchar(obuf->line) == ' ' && obuf->pos >= h_env->envs[h_env->envc].indent) { Strshrink(obuf->line, 1); obuf->pos--; } } #endif /* JP_CHARSET */ if (*str == '&') proc_escape(obuf, &str); else proc_mchar(obuf, obuf->flag & RB_SPECIAL, delta, &str, mode); } } if (need_flushline(h_env, obuf, mode)) { char *bp = obuf->line->ptr + obuf->bp.len; char *tp = bp - obuf->bp.tlen; int i = 0; if (tp > obuf->line->ptr && tp[-1] == ' ') i = 1; indent = h_env->envs[h_env->envc].indent; if (obuf->bp.pos - i > indent) { Str line; append_tags(obuf); line = Strnew_charp(bp); Strshrink(obuf->line, obuf->line->length - obuf->bp.len); #ifdef FORMAT_NICE if (obuf->pos - i > h_env->limit) obuf->flag |= RB_FILL; #endif /* FORMAT_NICE */ back_to_breakpoint(obuf); flushline(h_env, obuf, indent, 0, h_env->limit); #ifdef FORMAT_NICE obuf->flag &= ~RB_FILL; #endif /* FORMAT_NICE */ HTMLlineproc1(line->ptr, h_env); } } } if (!(obuf->flag & (RB_PREMODE | RB_NOBR | RB_INTXTA | RB_INSELECT | RB_PLAINMODE | RB_IGNORE))) { char *tp; int i = 0; if (obuf->bp.pos == obuf->pos) { tp = &obuf->line->ptr[obuf->bp.len - obuf->bp.tlen]; } else { tp = &obuf->line->ptr[obuf->line->length]; } if (tp > obuf->line->ptr && tp[-1] == ' ') i = 1; indent = h_env->envs[h_env->envc].indent; if (obuf->pos - i > h_env->limit) { #ifdef FORMAT_NICE obuf->flag |= RB_FILL; #endif /* FORMAT_NICE */ flushline(h_env, obuf, indent, 0, h_env->limit); #ifdef FORMAT_NICE obuf->flag &= ~RB_FILL; #endif /* FORMAT_NICE */ } } } static void close_textarea(struct html_feed_environ *h_env) { Str tmp; h_env->obuf->flag &= ~RB_INTXTA; tmp = process_n_textarea(); if (tmp != NULL) HTMLlineproc1(tmp->ptr, h_env); } extern char *NullLine; extern Lineprop NullProp[]; static void addnewline(Buffer *buf, char *line, Lineprop *prop, #ifdef USE_ANSI_COLOR Linecolor *color, #endif int pos, int nlines) { Line *l; l = New(Line); l->next = NULL; if (pos > 0) { l->lineBuf = allocStr(line, pos); l->propBuf = NewAtom_N(Lineprop, pos); bcopy((void *)prop, (void *)l->propBuf, pos * sizeof(Lineprop)); } else { l->lineBuf = NullLine; l->propBuf = NullProp; } #ifdef USE_ANSI_COLOR if (pos > 0 && color) { l->colorBuf = NewAtom_N(Linecolor, pos); bcopy((void *)color, (void *)l->colorBuf, pos * sizeof(Linecolor)); } else { l->colorBuf = NULL; } #endif l->len = pos; l->width = -1; l->prev = buf->currentLine; if (buf->currentLine) { l->next = buf->currentLine->next; buf->currentLine->next = l; } else l->next = NULL; if (buf->lastLine == NULL || buf->lastLine == buf->currentLine) buf->lastLine = l; buf->currentLine = l; if (buf->firstLine == NULL) buf->firstLine = l; l->linenumber = ++buf->allLine; if (nlines < 0) { /* l->real_linenumber = l->linenumber; */ l->real_linenumber = 0; } else { l->real_linenumber = nlines; } l = NULL; } /* * loadHTMLBuffer: read file and make new buffer */ Buffer * loadHTMLBuffer(URLFile *f, Buffer *newBuf) { FILE *src = NULL; Str tmp; if (newBuf == NULL) newBuf = newBuffer(INIT_BUFFER_WIDTH); if (newBuf->sourcefile == NULL && (f->scheme != SCM_LOCAL || newBuf->mailcap)) { tmp = tmpfname(TMPF_SRC, ".html"); pushText(fileToDelete, tmp->ptr); src = fopen(tmp->ptr, "w"); if (src) newBuf->sourcefile = tmp->ptr; } loadHTMLstream(f, newBuf, src, newBuf->bufferprop & BP_FRAME); newBuf->topLine = newBuf->firstLine; newBuf->lastLine = newBuf->currentLine; newBuf->currentLine = newBuf->firstLine; if (n_textarea) formResetBuffer(newBuf, newBuf->formitem); if (src) fclose(src); return newBuf; } static char *_size_unit[] = { "b", "kb", "Mb", "Gb", "Tb", "Pb", "Eb", "Zb", "Bb", "Yb", NULL }; char * convert_size(clen_t size, int usefloat) { float csize; int sizepos = 0; char **sizes = _size_unit; csize = (float)size; while (csize >= 999.495 && sizes[sizepos + 1]) { csize = csize / 1024.0; sizepos++; } return Sprintf(usefloat ? "%.3g%s" : "%.0f%s", floor(csize * 100.0 + 0.5) / 100.0, sizes[sizepos])->ptr; } char * convert_size2(clen_t size1, clen_t size2, int usefloat) { char **sizes = _size_unit; float csize, factor = 1; int sizepos = 0; csize = (float)((size1 > size2) ? size1 : size2); while (csize / factor >= 999.495 && sizes[sizepos + 1]) { factor *= 1024.0; sizepos++; } return Sprintf(usefloat ? "%.3g/%.3g%s" : "%.0f/%.0f%s", floor(size1 / factor * 100.0 + 0.5) / 100.0, floor(size2 / factor * 100.0 + 0.5) / 100.0, sizes[sizepos])->ptr; } void showProgress(clen_t * linelen, clen_t * trbyte) { int i, j, rate, duration, eta, pos; static time_t last_time, start_time; time_t cur_time; Str messages; char *fmtrbyte, *fmrate; if (!fmInitialized) return; if (current_content_length > 0) { double ratio; cur_time = time(0); if (cur_time == last_time) return; last_time = cur_time; if (*trbyte == 0) { move(LASTLINE, 0); clrtoeolx(); start_time = cur_time; } *trbyte += *linelen; *linelen = 0; move(LASTLINE, 0); ratio = 100.0 * (*trbyte) / current_content_length; fmtrbyte = convert_size2(*trbyte, current_content_length, 1); duration = cur_time - start_time; if (duration) { rate = *trbyte / duration; fmrate = convert_size(rate, 1); eta = rate ? (current_content_length - *trbyte) / rate : -1; messages = Sprintf("%11s %3.0f%% " "%7s/s " "eta %02d:%02d:%02d ", fmtrbyte, ratio, fmrate, eta / (60 * 60), (eta / 60) % 60, eta % 60); } else { messages = Sprintf("%11s %3.0f%% ", fmtrbyte, ratio); } addstr(messages->ptr); pos = 42; i = pos + (COLS - pos - 1) * (*trbyte) / current_content_length; move(LASTLINE, pos); #if 0 /* def KANJI_SYMBOLS */ for (j = pos; j <= i; j += 2) addstr("¢£"); #else /* not 0 */ standout(); addch(' '); for (j = pos + 1; j <= i; j++) addch('|'); standend(); #endif /* not 0 */ /* no_clrtoeol(); */ refresh(); } else if (*linelen > 1000) { cur_time = time(0); if (cur_time == last_time) return; last_time = cur_time; if (*trbyte == 0) { move(LASTLINE, 0); clrtoeolx(); start_time = cur_time; } *trbyte += *linelen; *linelen = 0; move(LASTLINE, 0); fmtrbyte = convert_size(*trbyte, 1); duration = cur_time - start_time; if (duration) { fmrate = convert_size(*trbyte / duration, 1); messages = Sprintf("%7s loaded %7s/s", fmtrbyte, fmrate); } else { messages = Sprintf("%7s loaded", fmtrbyte); } message(messages->ptr, 0, 0); refresh(); } } void init_henv(struct html_feed_environ *h_env, struct readbuffer *obuf, struct environment *envs, int nenv, TextLineList *buf, int limit, int indent) { envs[0].indent = indent; obuf->line = Strnew(); obuf->cprop = 0; obuf->pos = 0; obuf->prevchar = ' '; obuf->flag = RB_IGNORE_P; obuf->flag_sp = 0; obuf->status = R_ST_NORMAL; obuf->table_level = -1; obuf->nobr_level = 0; obuf->anchor = 0; obuf->anchor_target = 0; obuf->anchor_hseq = 0; obuf->img_alt = 0; obuf->in_bold = 0; obuf->in_under = 0; obuf->prev_ctype = PC_ASCII; obuf->tag_sp = 0; obuf->fontstat_sp = 0; obuf->top_margin = 0; obuf->bottom_margin = 0; obuf->bp.init_flag = 1; set_breakpoint(obuf, 0); h_env->buf = buf; h_env->f = NULL; h_env->obuf = obuf; h_env->tagbuf = Strnew(); h_env->limit = limit; h_env->maxlimit = 0; h_env->envs = envs; h_env->nenv = nenv; h_env->envc = 0; h_env->envc_real = 0; h_env->title = NULL; h_env->blank_lines = 0; } void completeHTMLstream(struct html_feed_environ *h_env, struct readbuffer *obuf) { close_anchor(h_env, obuf); if (obuf->img_alt) { push_tag(obuf, "", HTML_N_IMG_ALT); obuf->img_alt = NULL; } if (obuf->in_bold) { push_tag(obuf, "", HTML_N_B); obuf->in_bold = 0; } if (obuf->in_under) { push_tag(obuf, "", HTML_N_U); obuf->in_under = 0; } /* for unbalanced select tag */ if (obuf->flag & RB_INSELECT) HTMLlineproc1("", h_env); /* for unbalanced table tag */ while (obuf->table_level >= 0) { table_mode[obuf->table_level].pre_mode &= ~(TBLM_IGNORE | TBLM_XMP | TBLM_LST); HTMLlineproc1("
", h_env); } } static void print_internal_information(struct html_feed_environ *henv) { int i; Str s; TextLineList *tl = newTextLineList(); s = Strnew_charp(""); pushTextLine(tl, newTextLine(s, 0)); if (henv->title) { s = Strnew_m_charp("title), "\">", NULL); pushTextLine(tl, newTextLine(s, 0)); } #if 0 if (form_max >= 0) { FormList *fp; for (i = 0; i <= form_max; i++) { fp = forms[i]; s = Sprintf("action->ptr), (fp->method == FORM_METHOD_POST) ? "post" : ((fp->method == FORM_METHOD_INTERNAL) ? "internal" : "get")); if (fp->target) Strcat(s, Sprintf(" target=\"%s\"", html_quote(fp->target))); if (fp->enctype == FORM_ENCTYPE_MULTIPART) Strcat_charp(s, " enctype=\"multipart/form-data\""); #ifdef JP_CHARSET if (fp->charset) Strcat(s, Sprintf(" accept-charset=\"%s\"", code_to_str(fp->charset))); #endif Strcat_charp(s, ">"); pushTextLine(tl, newTextLine(s, 0)); } } #endif #ifdef MENU_SELECT if (n_select > 0) { FormSelectOptionItem *ip; for (i = 0; i < n_select; i++) { s = Sprintf("", i); pushTextLine(tl, newTextLine(s, 0)); for (ip = select_option[i].first; ip; ip = ip->next) { s = Sprintf("", html_quote(ip->value ? ip->value->ptr : ip->label->ptr), html_quote(ip->label->ptr), ip->checked ? " selected" : ""); pushTextLine(tl, newTextLine(s, 0)); } s = Strnew_charp(""); pushTextLine(tl, newTextLine(s, 0)); } } #endif /* MENU_SELECT */ if (n_textarea > 0) { for (i = 0; i < n_textarea; i++) { s = Sprintf("", i); pushTextLine(tl, newTextLine(s, 0)); s = Strnew_charp(html_quote(textarea_str[i]->ptr)); Strcat_charp(s, ""); pushTextLine(tl, newTextLine(s, 0)); } } s = Strnew_charp(""); pushTextLine(tl, newTextLine(s, 0)); if (henv->buf) appendTextLineList(henv->buf, tl); else if (henv->f) { TextLineListItem *p; for (p = tl->first; p; p = p->next) fprintf(henv->f, "%s\n", p->ptr->line->ptr); } } void loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal) { struct environment envs[MAX_ENV_LEVEL]; clen_t linelen = 0; clen_t trbyte = 0; Str lineBuf2 = Strnew(); char code; struct html_feed_environ htmlenv1; struct readbuffer obuf; #ifdef USE_IMAGE int volatile image_flag; #endif MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL; n_textarea = 0; cur_textarea = NULL; max_textarea = MAX_TEXTAREA; textarea_str = New_N(Str, max_textarea); #ifdef MENU_SELECT n_select = 0; max_select = MAX_SELECT; select_option = New_N(FormSelectOption, max_select); #endif /* MENU_SELECT */ cur_select = NULL; form_sp = -1; form_max = -1; forms_size = 0; forms = NULL; cur_hseq = 1; #ifdef USE_IMAGE cur_iseq = 1; if (newBuf->image_flag) image_flag = newBuf->image_flag; else if (activeImage && displayImage && autoImage) image_flag = IMG_FLAG_AUTO; else image_flag = IMG_FLAG_SKIP; if (newBuf->currentURL.file) cur_baseURL = baseURL(newBuf); #endif if (w3m_halfload) { newBuf->buffername = "---"; #ifdef JP_CHARSET newBuf->document_code = InnerCode; #endif /* JP_CHARSET */ max_textarea = 0; #ifdef MENU_SELECT max_select = 0; #endif HTMLlineproc3(newBuf, f->stream); w3m_halfload = FALSE; if (fmInitialized) term_raw(); signal(SIGINT, prevtrap); return; } init_henv(&htmlenv1, &obuf, envs, MAX_ENV_LEVEL, NULL, newBuf->width, 0); if (w3m_halfdump) htmlenv1.f = stdout; else htmlenv1.buf = newTextLineList(); if (SETJMP(AbortLoading) != 0) { HTMLlineproc1("
Transfer Interrupted!
", &htmlenv1); goto phase2; } prevtrap = signal(SIGINT, KeyAbort); if (fmInitialized) term_cbreak(); #ifdef JP_CHARSET if (newBuf != NULL && newBuf->document_code != '\0') code = newBuf->document_code; else if (content_charset != '\0' && UseContentCharset) code = content_charset; else code = DocumentCode; meta_charset = '\0'; #endif #if 0 do_blankline(&htmlenv1, &obuf, 0, 0, htmlenv1.limit); obuf.flag = RB_IGNORE_P; #endif if (IStype(f->stream) != IST_ENCODED) f->stream = newEncodedStream(f->stream, f->encoding); while ((lineBuf2 = StrmyUFgets(f))->length) { if (src) Strfputs(lineBuf2, src); linelen += lineBuf2->length; if (w3m_dump & DUMP_SOURCE) continue; showProgress(&linelen, &trbyte); /* * if (frame_source) * continue; */ #ifdef JP_CHARSET if (meta_charset != '\0') { /* */ if (content_charset == '\0' && UseContentCharset) { code = meta_charset; #ifdef USE_IMAGE cur_document_code = code; #endif } meta_charset = '\0'; } #endif if (!internal) { lineBuf2 = convertLine(f, lineBuf2, &code, HTML_MODE); #ifdef JP_CHARSET #ifdef USE_IMAGE cur_document_code = code; #endif #endif } #ifdef USE_NNTP if (f->scheme == SCM_NEWS) { if (Str_news_endline(lineBuf2)) { iseos(f->stream) = TRUE; break; } } #endif /* USE_NNTP */ HTMLlineproc0(lineBuf2->ptr, &htmlenv1, internal); } if (obuf.status != R_ST_NORMAL) HTMLlineproc1(correct_irrtag(obuf.status)->ptr, &htmlenv1); obuf.status = R_ST_NORMAL; completeHTMLstream(&htmlenv1, &obuf); flushline(&htmlenv1, &obuf, 0, 2, htmlenv1.limit); if (htmlenv1.title) newBuf->buffername = htmlenv1.title; if (w3m_halfdump) { if (fmInitialized) term_raw(); signal(SIGINT, prevtrap); print_internal_information(&htmlenv1); return; } if (w3m_backend) { print_internal_information(&htmlenv1); backend_halfdump_buf = htmlenv1.buf; return; } phase2: newBuf->trbyte = trbyte + linelen; if (fmInitialized) term_raw(); signal(SIGINT, prevtrap); #ifdef JP_CHARSET newBuf->document_code = code; content_charset = '\0'; #endif /* JP_CHARSET */ #ifdef USE_IMAGE newBuf->image_flag = image_flag; #endif HTMLlineproc2(newBuf, htmlenv1.buf); } /* * loadHTMLString: read string and make new buffer */ Buffer * loadHTMLString(Str page) { URLFile f; MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL; Buffer *newBuf; Str tmp; FILE *volatile src = NULL; newBuf = newBuffer(INIT_BUFFER_WIDTH); if (SETJMP(AbortLoading) != 0) { if (fmInitialized) term_raw(); signal(SIGINT, prevtrap); discardBuffer(newBuf); return NULL; } prevtrap = signal(SIGINT, KeyAbort); if (fmInitialized) term_cbreak(); init_stream(&f, SCM_LOCAL, newStrStream(page)); if (w3m_dump & DUMP_FRAME) { tmp = tmpfname(TMPF_SRC, ".html"); pushText(fileToDelete, tmp->ptr); src = fopen(tmp->ptr, "w"); if (src) newBuf->sourcefile = tmp->ptr; } loadHTMLstream(&f, newBuf, src, TRUE); if (fmInitialized) term_raw(); signal(SIGINT, prevtrap); newBuf->topLine = newBuf->firstLine; newBuf->lastLine = newBuf->currentLine; newBuf->currentLine = newBuf->firstLine; #ifdef JP_CHARSET newBuf->document_code = InnerCode; #endif /* JP_CHARSET */ newBuf->type = "text/html"; newBuf->real_type = newBuf->type; if (n_textarea) formResetBuffer(newBuf, newBuf->formitem); if (src) fclose(src); return newBuf; } #ifdef USE_GOPHER /* * loadGopherDir: get gopher directory */ Buffer * loadGopherDir(URLFile *uf, Buffer *volatile newBuf) { Str tmp, lbuf, name, file, host, port; char code = CODE_ASCII; char *p, *q; FILE *src; URLFile f; MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL; if (newBuf == NULL) newBuf = newBuffer(INIT_BUFFER_WIDTH); tmp = Strnew_charp("
\n");

    if (SETJMP(AbortLoading) != 0)
	goto gopher_end;
    prevtrap = signal(SIGINT, KeyAbort);
    if (fmInitialized)
	term_cbreak();

#ifdef JP_CHARSET
    if (newBuf->document_code != '\0')
	code = newBuf->document_code;
    else if (content_charset != '\0' && UseContentCharset)
	code = content_charset;
    else
	code = DocumentCode;
    content_charset = '\0';
#endif
    while (1) {
	if (lbuf = StrUFgets(uf), lbuf->length == 0)
	    break;
	if (lbuf->ptr[0] == '.' &&
	    (lbuf->ptr[1] == '\n' || lbuf->ptr[1] == '\r'))
	    break;
	lbuf = convertLine(uf, lbuf, &code, HTML_MODE);
	p = lbuf->ptr;
	for (q = p; *q && *q != '\t'; q++) ;
	name = Strnew_charp_n(p, q - p);
	if (!*q)
	    continue;
	p = q + 1;
	for (q = p; *q && *q != '\t'; q++) ;
	file = Strnew_charp_n(p, q - p);
	if (!*q)
	    continue;
	p = q + 1;
	for (q = p; *q && *q != '\t'; q++) ;
	host = Strnew_charp_n(p, q - p);
	if (!*q)
	    continue;
	p = q + 1;
	for (q = p; *q && *q != '\t' && *q != '\r' && *q != '\n'; q++) ;
	port = Strnew_charp_n(p, q - p);

	switch (name->ptr[0]) {
	case '0':
	    p = "[text file]  ";
	    break;
	case '1':
	    p = "[directory]  ";
	    break;
	case 'm':
	    p = "[message]    ";
	    break;
	case 's':
	    p = "[sound]      ";
	    break;
	case 'g':
	    p = "[gif]        ";
	    break;
	case 'h':
	    p = "[HTML]       ";
	    break;
	default:
	    p = "[unsupported]";
	    break;
	}
	q = Strnew_m_charp("gopher://", host->ptr, ":", port->ptr,
			   "/", file->ptr, NULL)->ptr;
	Strcat_m_charp(tmp, "", p, html_quote(name->ptr + 1), "\n", NULL);
    }

  gopher_end:
    if (fmInitialized)
	term_raw();
    signal(SIGINT, prevtrap);

    Strcat_charp(tmp, "
\n"); file = tmpfname(TMPF_SRC, ".html"); src = fopen(file->ptr, "w"); newBuf->sourcefile = file->ptr; pushText(fileToDelete, file->ptr); init_stream(&f, SCM_LOCAL, newStrStream(tmp)); loadHTMLstream(&f, newBuf, src, TRUE); if (src) fclose(src); #ifdef JP_CHARSET newBuf->document_code = code; #endif /* JP_CHARSET */ newBuf->topLine = newBuf->firstLine; newBuf->lastLine = newBuf->currentLine; newBuf->currentLine = newBuf->firstLine; return newBuf; } #endif /* USE_GOPHER */ /* * loadBuffer: read file and make new buffer */ Buffer * loadBuffer(URLFile *uf, Buffer *volatile newBuf) { FILE *volatile src = NULL; char code; Str lineBuf2; volatile char pre_lbuf = '\0'; int nlines; Str tmpf; clen_t linelen = 0, trbyte = 0; #ifdef USE_ANSI_COLOR int check_color; #endif MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL; if (newBuf == NULL) newBuf = newBuffer(INIT_BUFFER_WIDTH); lineBuf2 = Strnew(); if (SETJMP(AbortLoading) != 0) { goto _end; } prevtrap = signal(SIGINT, KeyAbort); if (fmInitialized) term_cbreak(); if (newBuf->sourcefile == NULL && (uf->scheme != SCM_LOCAL || newBuf->mailcap)) { tmpf = tmpfname(TMPF_SRC, NULL); src = fopen(tmpf->ptr, "w"); if (src) newBuf->sourcefile = tmpf->ptr; } #ifdef JP_CHARSET if (newBuf->document_code != '\0') code = newBuf->document_code; else if (content_charset != '\0' && UseContentCharset) code = content_charset; else code = DocumentCode; content_charset = '\0'; #endif nlines = 0; if (IStype(uf->stream) != IST_ENCODED) uf->stream = newEncodedStream(uf->stream, uf->encoding); while ((lineBuf2 = StrmyISgets(uf->stream))->length) { if (src) Strfputs(lineBuf2, src); linelen += lineBuf2->length; if (w3m_dump & DUMP_SOURCE) continue; showProgress(&linelen, &trbyte); if (frame_source) continue; lineBuf2 = convertLine(uf, lineBuf2, &code, PAGER_MODE); if (squeezeBlankLine) { if (lineBuf2->ptr[0] == '\n' && pre_lbuf == '\n') { ++nlines; continue; } pre_lbuf = lineBuf2->ptr[0]; } ++nlines; #ifdef USE_NNTP if (uf->scheme == SCM_NEWS) { if (Str_news_endline(lineBuf2)) { iseos(uf->stream) = TRUE; break; } } #endif /* USE_NNTP */ Strchop(lineBuf2); lineBuf2 = checkType(lineBuf2, propBuffer, #ifdef USE_ANSI_COLOR colorBuffer, &check_color, #endif LINELEN); addnewline(newBuf, lineBuf2->ptr, propBuffer, #ifdef USE_ANSI_COLOR check_color ? colorBuffer : NULL, #endif lineBuf2->length, nlines); } _end: if (fmInitialized) term_raw(); signal(SIGINT, prevtrap); newBuf->topLine = newBuf->firstLine; newBuf->lastLine = newBuf->currentLine; newBuf->currentLine = newBuf->firstLine; newBuf->trbyte = trbyte + linelen; #ifdef JP_CHARSET newBuf->document_code = code; #endif /* JP_CHARSET */ if (src) fclose(src); return newBuf; } #ifdef USE_IMAGE Buffer * loadImageBuffer(URLFile *uf, Buffer *newBuf) { Image *image; ImageCache *cache; Str tmp, tmpf; FILE *src = NULL; URLFile f; MySignalHandler(*prevtrap) (); loadImage(IMG_FLAG_STOP); image = New(Image); image->url = parsedURL2Str(cur_baseURL)->ptr; image->ext = filename_extension(cur_baseURL->file, 1); image->width = -1; image->height = -1; cache = getImage(image, cur_baseURL, IMG_FLAG_AUTO); if (!cur_baseURL->is_nocache && cache->loaded == IMG_FLAG_LOADED) goto image_buffer; prevtrap = signal(SIGINT, KeyAbort); if (fmInitialized) term_cbreak(); if (IStype(uf->stream) != IST_ENCODED) uf->stream = newEncodedStream(uf->stream, uf->encoding); if (save2tmp(*uf, cache->file) < 0) { if (fmInitialized) term_raw(); signal(SIGINT, prevtrap); return NULL; } if (fmInitialized) term_raw(); signal(SIGINT, prevtrap); cache->loaded = IMG_FLAG_LOADED; cache->index = 0; /* * getImageSize(cache); */ image_buffer: tmp = Sprintf("

", html_quote(image->url)); if (newBuf == NULL) newBuf = newBuffer(INIT_BUFFER_WIDTH); /* * if (frame_source) { */ tmpf = tmpfname(TMPF_SRC, ".html"); src = fopen(tmpf->ptr, "w"); newBuf->sourcefile = tmpf->ptr; pushText(fileToDelete, tmpf->ptr); /* * } */ init_stream(&f, SCM_LOCAL, newStrStream(tmp)); loadHTMLstream(&f, newBuf, src, TRUE); if (src) fclose(src); newBuf->topLine = newBuf->firstLine; newBuf->lastLine = newBuf->currentLine; newBuf->currentLine = newBuf->firstLine; newBuf->image_flag = IMG_FLAG_AUTO; return newBuf; } #endif #ifndef KANJI_SYMBOLS static Str conv_rule(Line *l) { Str tmp = NULL; char *p = l->lineBuf, *ep = p + l->len; Lineprop *pr = l->propBuf; for (; p < ep; p++, pr++) { if (*pr & PC_RULE) { if (tmp == NULL) { tmp = Strnew_size(l->len); Strcopy_charp_n(tmp, l->lineBuf, p - l->lineBuf); } Strcat_char(tmp, alt_rule[*p & 0xF]); } else if (tmp != NULL) Strcat_char(tmp, *p); } if (tmp) return tmp; else return Strnew_charp_n(l->lineBuf, l->len); } #endif /* * saveBuffer: write buffer to file */ void saveBuffer(Buffer *buf, FILE * f) { Line *l = buf->firstLine; Str tmp; #ifndef KANJI_SYMBOLS int is_html = FALSE; if (buf->type && !strcasecmp(buf->type, "text/html")) is_html = TRUE; #endif pager_next: for (; l != NULL; l = l->next) { #ifndef KANJI_SYMBOLS if (is_html) tmp = conv_rule(l); else #endif tmp = Strnew_charp_n(l->lineBuf, l->len); #ifdef JP_CHARSET tmp = conv_str(tmp, InnerCode, DisplayCode); #endif Strfputs(tmp, f); if (Strlastchar(tmp) != '\n') putc('\n', f); } if (buf->pagerSource && !(buf->bufferprop & BP_CLOSE)) { l = getNextPage(buf, PagerMax); goto pager_next; } } static Buffer * loadcmdout(char *cmd, Buffer *(*loadproc) (URLFile *, Buffer *), Buffer *defaultbuf) { FILE *f, *popen(const char *, const char *); Buffer *buf; URLFile uf; if (cmd == NULL || *cmd == '\0') return NULL; f = popen(cmd, "r"); if (f == NULL) return NULL; init_stream(&uf, SCM_UNKNOWN, newFileStream(f, (void (*)())pclose)); buf = loadproc(&uf, defaultbuf); UFclose(&uf); return buf; } /* * getshell: execute shell command and get the result into a buffer */ Buffer * getshell(char *cmd) { Buffer *buf; buf = loadcmdout(cmd, loadBuffer, NULL); if (buf == NULL) return NULL; buf->filename = cmd; buf->buffername = Sprintf("%s %s", SHELLBUFFERNAME, conv_from_system(cmd))->ptr; return buf; } /* * getpipe: execute shell command and connect pipe to the buffer */ Buffer * getpipe(char *cmd) { FILE *f, *popen(const char *, const char *); Buffer *buf; if (cmd == NULL || *cmd == '\0') return NULL; f = popen(cmd, "r"); if (f == NULL) return NULL; buf = newBuffer(INIT_BUFFER_WIDTH); buf->pagerSource = newFileStream(f, (void (*)())pclose); buf->filename = cmd; buf->buffername = Sprintf("%s %s", PIPEBUFFERNAME, conv_from_system(cmd))->ptr; buf->bufferprop |= BP_PIPE; return buf; } /* * Open pager buffer */ Buffer * openPagerBuffer(InputStream stream, Buffer *buf) { if (buf == NULL) buf = newBuffer(INIT_BUFFER_WIDTH); buf->pagerSource = stream; buf->buffername = getenv("MAN_PN"); if (buf->buffername == NULL) buf->buffername = PIPEBUFFERNAME; else buf->buffername = conv_from_system(buf->buffername); buf->bufferprop |= BP_PIPE; #ifdef JP_CHARSET if (content_charset != '\0' && UseContentCharset) buf->document_code = content_charset; #endif buf->currentLine = buf->firstLine; return buf; } Buffer * openGeneralPagerBuffer(InputStream stream) { Buffer *buf; char *t = "text/plain"; Buffer *t_buf = NULL; URLFile uf; init_stream(&uf, SCM_UNKNOWN, stream); #ifdef JP_CHARSET content_charset = '\0'; #endif if (SearchHeader) { t_buf = newBuffer(INIT_BUFFER_WIDTH); readHeader(&uf, t_buf, TRUE, NULL); t = checkContentType(t_buf); if (t == NULL) t = "text/plain"; if (t_buf) { t_buf->topLine = t_buf->firstLine; t_buf->currentLine = t_buf->lastLine; } SearchHeader = FALSE; } else if (DefaultType) { t = DefaultType; DefaultType = NULL; } if (!strcasecmp(t, "text/html")) { buf = loadHTMLBuffer(&uf, t_buf); buf->type = "text/html"; } else if (is_plain_text_type(t)) { if (IStype(stream) != IST_ENCODED) stream = newEncodedStream(stream, uf.encoding); buf = openPagerBuffer(stream, t_buf); buf->type = "text/plain"; } #ifdef USE_IMAGE else if (activeImage && displayImage && !useExtImageViewer && !(w3m_dump & ~DUMP_FRAME) && !strncasecmp(t, "image/", 6)) { cur_baseURL = New(ParsedURL); parseURL("-", cur_baseURL, NULL); buf = loadImageBuffer(&uf, t_buf); buf->type = "text/html"; } #endif else { if (doExternal(uf, "-", t, &buf, t_buf)) { if (buf == NULL || buf == NO_BUFFER) return buf; } else { /* unknown type is regarded as text/plain */ if (IStype(stream) != IST_ENCODED) stream = newEncodedStream(stream, uf.encoding); buf = openPagerBuffer(stream, t_buf); buf->type = "text/plain"; } } buf->real_type = t; buf->currentURL.scheme = SCM_LOCAL; buf->currentURL.file = "-"; return buf; } Line * getNextPage(Buffer *buf, int plen) { Line *l, *fl, *pl = buf->lastLine; Line *rl = NULL; int len, i, nlines = 0; clen_t linelen = buf->linelen, trbyte = buf->trbyte; Str lineBuf2; char pre_lbuf = '\0'; URLFile uf; char code; int squeeze_flag = 0; #ifdef USE_ANSI_COLOR int check_color; #endif if (buf->pagerSource == NULL) return NULL; if (fmInitialized) crmode(); if (pl != NULL) { nlines = pl->real_linenumber; pre_lbuf = *(pl->lineBuf); if (pre_lbuf == '\0') pre_lbuf = '\n'; } #ifdef JP_CHARSET if (buf->document_code) code = buf->document_code; else code = DocumentCode; #endif init_stream(&uf, SCM_UNKNOWN, NULL); for (i = 0; i < plen; i++) { lineBuf2 = StrmyISgets(buf->pagerSource); if (lineBuf2->length == 0) { /* Assume that `cmd == buf->filename' */ if (buf->filename) buf->buffername = Sprintf("%s %s", CPIPEBUFFERNAME, conv_from_system(buf->filename))-> ptr; else if (getenv("MAN_PN") == NULL) buf->buffername = CPIPEBUFFERNAME; buf->bufferprop |= BP_CLOSE; trbyte += linelen; linelen = 0; break; } linelen += lineBuf2->length; showProgress(&linelen, &trbyte); lineBuf2 = convertLine(&uf, lineBuf2, &code, PAGER_MODE); if (squeezeBlankLine) { squeeze_flag = 0; if (lineBuf2->ptr[0] == '\n' && pre_lbuf == '\n') { ++nlines; --i; squeeze_flag = 1; continue; } pre_lbuf = lineBuf2->ptr[0]; } ++nlines; Strchop(lineBuf2); lineBuf2 = checkType(lineBuf2, propBuffer, #ifdef USE_ANSI_COLOR colorBuffer, &check_color, #endif LINELEN); len = lineBuf2->length; l = New(Line); l->lineBuf = lineBuf2->ptr; l->propBuf = NewAtom_N(Lineprop, len); bcopy((void *)propBuffer, (void *)l->propBuf, len * sizeof(Lineprop)); #ifdef USE_ANSI_COLOR if (check_color) { l->colorBuf = NewAtom_N(Linecolor, len); bcopy((void *)colorBuffer, (void *)l->colorBuf, len * sizeof(Linecolor)); } else { l->colorBuf = NULL; } #endif l->len = len; l->width = -1; l->prev = pl; #if 0 if (squeezeBlankLine) { #endif l->real_linenumber = nlines; l->linenumber = (pl == NULL ? nlines : pl->linenumber + 1); #if 0 } else { l->real_linenumber = l->linenumber = nlines; } #endif if (pl == NULL) { pl = l; buf->firstLine = buf->topLine = buf->currentLine = l; } else { pl->next = l; pl = l; } if (rl == NULL) rl = l; if (nlines > PagerMax) { fl = buf->firstLine; buf->firstLine = fl->next; fl->next->prev = NULL; if (buf->topLine == fl) buf->topLine = fl->next; if (buf->currentLine == fl) buf->currentLine = fl->next; } } if (pl != NULL) pl->next = NULL; buf->lastLine = pl; if (rl == NULL && squeeze_flag) { rl = pl; } if (fmInitialized) term_raw(); buf->linelen = linelen; buf->trbyte = trbyte; #ifdef JP_CHARSET buf->document_code = code; #endif return rl; } static void FTPhalfclose(InputStream stream) { if (IStype(stream) == IST_FILE && file_of(stream)) { Ftpfclose(file_of(stream)); file_of(stream) = NULL; } } int save2tmp(URLFile uf, char *tmpf) { FILE *ff; int check; clen_t linelen = 0, trbyte = 0; MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL; static JMP_BUF env_bak; ff = fopen(tmpf, "wb"); if (ff == NULL) { /* fclose(f); */ return -1; } bcopy(AbortLoading, env_bak, sizeof(JMP_BUF)); if (SETJMP(AbortLoading) != 0) { goto _end; } prevtrap = signal(SIGINT, KeyAbort); if (fmInitialized) term_cbreak(); check = 0; current_content_length = 0; #ifdef USE_NNTP if (uf.scheme == SCM_NEWS) { char c; while (c = UFgetc(&uf), !iseos(uf.stream)) { if (c == '\n') { if (check == 0) check++; else if (check == 3) break; } else if (c == '.' && check == 1) check++; else if (c == '\r' && check == 2) check++; else check = 0; putc(c, ff); linelen += sizeof(c); showProgress(&linelen, &trbyte); } } else #endif /* USE_NNTP */ { Str buf = Strnew_size(SAVE_BUF_SIZE); while (UFread(&uf, buf, SAVE_BUF_SIZE)) { Strfputs(buf, ff); linelen += buf->length; showProgress(&linelen, &trbyte); } } _end: bcopy(env_bak, AbortLoading, sizeof(JMP_BUF)); if (fmInitialized) term_raw(); signal(SIGINT, prevtrap); fclose(ff); if (uf.scheme == SCM_FTP) FTPhalfclose(uf.stream); return 0; } int doExternal(URLFile uf, char *path, char *type, Buffer **bufp, Buffer *defaultbuf) { Str tmpf, command; struct mailcap *mcap; int mc_stat; Buffer *buf = NULL; char *header; if (!(mcap = searchExtViewer(type))) return 0; tmpf = tmpfname(TMPF_DFL, NULL); if (mcap->nametemplate) { Str tmp = unquote_mailcap(mcap->nametemplate, NULL, tmpf->ptr, NULL, NULL); if (Strncmp(tmpf, tmp, tmpf->length) == 0) { tmpf = tmp; goto _save; } } if (uf.ext && *uf.ext) { Strcat_charp(tmpf, uf.ext); } _save: if (IStype(uf.stream) != IST_ENCODED) uf.stream = newEncodedStream(uf.stream, uf.encoding); if (save2tmp(uf, tmpf->ptr) < 0) return 0; header = checkHeader(defaultbuf, "Content-Type:"); if (header) header = conv_to_system(header); command = unquote_mailcap(mcap->viewer, type, tmpf->ptr, header, &mc_stat); #ifndef __EMX__ if (!(mc_stat & MCSTAT_REPNAME)) { Str tmp = Sprintf("(%s) < %s", command->ptr, shell_quote(tmpf->ptr)); command = tmp; } #endif if (mcap->flags & (MAILCAP_HTMLOUTPUT | MAILCAP_COPIOUSOUTPUT)) { if (defaultbuf == NULL) defaultbuf = newBuffer(INIT_BUFFER_WIDTH); defaultbuf->mailcap = mcap; } if (mcap->flags & MAILCAP_HTMLOUTPUT) { buf = loadcmdout(command->ptr, loadHTMLBuffer, defaultbuf); if (buf && buf != NO_BUFFER) { buf->type = "text/html"; buf->mailcap_source = buf->sourcefile; buf->sourcefile = tmpf->ptr; } } else if (mcap->flags & MAILCAP_COPIOUSOUTPUT) { buf = loadcmdout(command->ptr, loadBuffer, defaultbuf); if (buf && buf != NO_BUFFER) { buf->type = "text/plain"; buf->mailcap_source = buf->sourcefile; buf->sourcefile = tmpf->ptr; } } else { if (mcap->flags & MAILCAP_NEEDSTERMINAL || !BackgroundExtViewer) { fmTerm(); mySystem(command->ptr, 0); fmInit(); if (Currentbuf) displayBuffer(Currentbuf, B_FORCE_REDRAW); } else { mySystem(command->ptr, 1); } buf = NO_BUFFER; } if (buf && buf != NO_BUFFER) { buf->filename = path; if (buf->buffername == NULL || buf->buffername[0] == '\0') buf->buffername = conv_from_system(lastFileName(path)); buf->edit = mcap->edit; buf->mailcap = mcap; } *bufp = buf; pushText(fileToDelete, tmpf->ptr); return 1; } static int _MoveFile(char *path1, char *path2) { InputStream f1; FILE *f2; int is_pipe; clen_t linelen = 0, trbyte = 0; Str buf; f1 = openIS(path1); if (f1 == NULL) return -1; if (*path2 == '|' && PermitSaveToPipe) { is_pipe = TRUE; f2 = popen(path2 + 1, "w"); } else { is_pipe = FALSE; f2 = fopen(path2, "wb"); } if (f2 == NULL) { ISclose(f1); return -1; } current_content_length = 0; buf = Strnew_size(SAVE_BUF_SIZE); while (ISread(f1, buf, SAVE_BUF_SIZE)) { Strfputs(buf, f2); linelen += buf->length; showProgress(&linelen, &trbyte); } ISclose(f1); if (is_pipe) pclose(f2); else fclose(f2); return 0; } void doFileCopy(char *tmpf, char *defstr) { Str msg; Str filen; char *p, *q = NULL; if (fmInitialized) { p = searchKeyData(); if (p == NULL || *p == '\0') { q = inputLineHist("(Download)Save file to: ", defstr, IN_COMMAND, SaveHist); if (q == NULL || *q == '\0') return; p = conv_to_system(q); } if (*p != '|' || !PermitSaveToPipe) { if (q) { p = unescape_spaces(Strnew_charp(q))->ptr; p = conv_to_system(q); } p = expandName(p); if (checkOverWrite(p) < 0) return; } if (checkCopyFile(tmpf, p) < 0) { msg = Sprintf("Can't copy. %s and %s are identical.", tmpf, p); disp_err_message(msg->ptr, FALSE); return; } if (_MoveFile(tmpf, p) < 0) { msg = Sprintf("Can't save to %s", p); disp_err_message(msg->ptr, FALSE); } } else { q = searchKeyData(); if (q == NULL || *q == '\0') { printf("(Download)Save file to: "); fflush(stdout); filen = Strfgets(stdin); if (filen->length == 0) return; q = filen->ptr; } for (p = q + strlen(q) - 1; IS_SPACE(*p); p--) ; *(p + 1) = '\0'; if (*q == '\0') return; p = q; if (*p != '|' || !PermitSaveToPipe) { p = expandName(p); if (checkOverWrite(p) < 0) return; } if (checkCopyFile(tmpf, p) < 0) { printf("Can't copy. %s and %s are identical.", tmpf, p); return; } if (_MoveFile(tmpf, p) < 0) { printf("Can't save to %s\n", p); } } } void doFileMove(char *tmpf, char *defstr) { doFileCopy(tmpf, defstr); unlink(tmpf); } void doFileSave(URLFile uf, char *defstr) { Str msg; Str filen; char *p, *q; if (fmInitialized) { p = searchKeyData(); if (p == NULL || *p == '\0') { p = inputLineHist("(Download)Save file to: ", defstr, IN_FILENAME, SaveHist); if (p == NULL || *p == '\0') return; p = conv_to_system(p); } if (checkOverWrite(p) < 0) return; if (checkSaveFile(uf.stream, p) < 0) { msg = Sprintf("Can't save. Load file and %s are identical.", p); disp_err_message(msg->ptr, FALSE); return; } if (save2tmp(uf, p) < 0) { msg = Sprintf("Can't save to %s", p); disp_err_message(msg->ptr, FALSE); } } else { q = searchKeyData(); if (q == NULL || *q == '\0') { printf("(Download)Save file to: "); fflush(stdout); filen = Strfgets(stdin); if (filen->length == 0) return; q = filen->ptr; } for (p = q + strlen(q) - 1; IS_SPACE(*p); p--) ; *(p + 1) = '\0'; if (*q == '\0') return; p = expandName(q); if (checkOverWrite(p) < 0) return; if (checkSaveFile(uf.stream, p) < 0) { printf("Can't save. Load file and %s are identical.", p); return; } if (save2tmp(uf, p) < 0) { printf("Can't save to %s\n", p); } } } int checkCopyFile(char *path1, char *path2) { struct stat st1, st2; if (*path2 == '|' && PermitSaveToPipe) return 0; if ((stat(path1, &st1) == 0) && (stat(path2, &st2) == 0)) if (st1.st_ino == st2.st_ino) return -1; return 0; } int checkSaveFile(InputStream stream, char *path2) { struct stat st1, st2; int des = ISfileno(stream); if (des < 0) return 0; if (*path2 == '|' && PermitSaveToPipe) return 0; if ((fstat(des, &st1) == 0) && (stat(path2, &st2) == 0)) if (st1.st_ino == st2.st_ino) return -1; return 0; } int checkOverWrite(char *path) { struct stat st; char *ans; if (stat(path, &st) < 0) return 0; ans = inputAnswer("File exists. Overwrite? (y/n)"); if (ans && tolower(*ans) == 'y') return 0; else return -1; } char * inputAnswer(char *prompt) { char *ans; if (QuietMessage) return "n"; if (fmInitialized) { term_raw(); ans = inputChar(prompt); } else { printf(prompt); fflush(stdout); ans = Strfgets(stdin)->ptr; } return ans; } static void uncompress_stream(URLFile *uf) { int pid1; int fd1[2]; char *expand_cmd = GUNZIP_CMDNAME; char *expand_name = GUNZIP_NAME; char *tmpf = NULL; struct compression_decoder *d; if (IStype(uf->stream) != IST_ENCODED) { uf->stream = newEncodedStream(uf->stream, uf->encoding); uf->encoding = ENC_7BIT; } for (d = compression_decoders; d->type != CMP_NOCOMPRESS; d++) { if (uf->compression == d->type) { if (d->libfile_p) expand_cmd = libFile(d->cmd); else expand_cmd = d->cmd; expand_name = d->name; break; } } uf->compression = CMP_NOCOMPRESS; if (pipe(fd1) < 0) { UFclose(uf); return; } if (uf->scheme != SCM_HTTP && uf->scheme != SCM_LOCAL) { tmpf = tmpfname(TMPF_DFL, NULL)->ptr; if (save2tmp(*uf, tmpf) < 0) { UFclose(uf); return; } #if 0 if (uf->scheme != SCM_FTP) #endif UFclose(uf); uf->scheme = SCM_LOCAL; pushText(fileToDelete, tmpf); } flush_tty(); /* fd1[0]: read, fd1[1]: write */ if ((pid1 = fork()) == 0) { reset_signals(); close(fd1[0]); if (tmpf) { #ifdef USE_BINMODE_STREAM int tmpfd = open(tmpf, O_RDONLY | O_BINARY); #else int tmpfd = open(tmpf, O_RDONLY); #endif if (tmpfd < 0) { close(fd1[1]); exit(1); } dup2(tmpfd, 0); } else { /* child */ int pid2; int fd2[2]; if (fmInitialized) { close_tty(); fmInitialized = FALSE; } if (pipe(fd2) < 0) { close(fd1[1]); UFclose(uf); exit(1); } if ((pid2 = fork()) == 0) { /* child */ Str buf = Strnew_size(SAVE_BUF_SIZE); close(fd2[0]); while (UFread(uf, buf, SAVE_BUF_SIZE)) { if (write(fd2[1], buf->ptr, buf->length) < 0) { close(fd2[1]); exit(0); } } close(fd2[1]); exit(0); } close(fd2[1]); dup2(fd2[0], 0); } dup2(fd1[1], 1); dup2(fd1[1], 2); execlp(expand_cmd, expand_name, NULL); exit(0); } close(fd1[1]); if (tmpf == NULL) UFclose(uf); uf->stream = newFileStream(fdopen(fd1[0], "rb"), (void (*)())pclose); } static FILE * lessopen_stream(char *path) { char *lessopen; FILE *fp; lessopen = getenv("LESSOPEN"); if (lessopen == NULL) { return NULL; } if (lessopen[0] == '\0') { return NULL; } if (lessopen[0] == '|') { /* pipe mode */ Str tmpf; int c; ++lessopen; tmpf = Sprintf(lessopen, path); fp = popen(tmpf->ptr, "r"); if (fp == NULL) { return NULL; } c = getc(fp); if (c == EOF) { fclose(fp); return NULL; } ungetc(c, fp); } else { /* filename mode */ /* not supported m(__)m */ fp = NULL; } return fp; } #if 0 void reloadBuffer(Buffer *buf) { URLFile uf; if (buf->sourcefile == NULL || buf->pagerSource != NULL) return; init_stream(&uf, SCM_UNKNOWN, NULL); examineFile(buf->mailcap_source ? buf->mailcap_source : buf->sourcefile, &uf); if (uf.stream == NULL) return; is_redisplay = TRUE; buf->allLine = 0; buf->href = NULL; buf->name = NULL; buf->img = NULL; buf->formitem = NULL; if (!strcasecmp(buf->type, "text/html")) loadHTMLBuffer(&uf, buf); else loadBuffer(&uf, buf); UFclose(&uf); is_redisplay = FALSE; } #endif #ifdef JP_CHARSET static char guess_charset(char *p) { Str c = Strnew_size(strlen(p)); if (strncasecmp(p, "x-", 2) == 0) p += 2; while (*p != '\0') { if (*p != '-' && *p != '_') Strcat_char(c, tolower(*p)); p++; } if (strncmp(c->ptr, "euc", 3) == 0) return CODE_EUC; if (strncmp(c->ptr, "shiftjis", 8) == 0 || strncmp(c->ptr, "sjis", 4) == 0) return CODE_SJIS; if (strncmp(c->ptr, "iso2022jp", 9) == 0 || strncmp(c->ptr, "jis", 3) == 0) return CODE_JIS_n; return CODE_ASCII; } #endif static char * guess_filename(char *file) { char *p = NULL, *s; if (file != NULL) p = mybasename(file); if (p == NULL || *p == '\0') return DEF_SAVE_FILE; s = p; if (*p == '#') p++; while (*p != '\0') { if ((*p == '#' && *(p + 1) != '\0') || *p == '?') { *p = '\0'; break; } p++; } return s; } char * guess_save_name(Buffer *buf, char *path) { if (buf && buf->document_header) { Str name = NULL; char *p, *q; if ((p = checkHeader(buf, "Content-Disposition:")) != NULL && (q = strcasestr(p, "filename")) != NULL && (q == p || IS_SPACE(*(q - 1)) || *(q - 1) == ';')) { if (matchattr(q, "filename", 8, &name)) return name->ptr; } if ((p = checkHeader(buf, "Content-Type:")) != NULL && (q = strcasestr(p, "name")) != NULL && (q == p || IS_SPACE(*(q - 1)) || *(q - 1) == ';')) { if (matchattr(q, "name", 4, &name)) return name->ptr; } } return guess_filename(path); } /* Local Variables: */ /* c-basic-offset: 4 */ /* tab-width: 8 */ /* End: */