From 68a07bf03b7624c9924065cce9ffa45497225834 Mon Sep 17 00:00:00 2001 From: Akinori Ito Date: Thu, 8 Nov 2001 05:14:08 +0000 Subject: Initial revision --- file.c | 6002 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 6002 insertions(+) create mode 100644 file.c (limited to 'file.c') diff --git a/file.c b/file.c new file mode 100644 index 0000000..79c3885 --- /dev/null +++ b/file.c @@ -0,0 +1,6002 @@ +/* $Id: file.c,v 1.1 2001/11/08 05:14:50 a-ito Exp $ */ +#include "fm.h" +#include +#include "myctype.h" +#include +#include +#include +#include +#include +#ifdef __EMX__ +#include +#endif /* __EMX__ */ +#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 void gunzip_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 ANSI_COLOR + Linecolor * color, +#endif + int pos, int nlines); + +static Lineprop propBuffer[LINELEN]; +#ifdef 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]; + +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 = htmlquote_str(q); + qlen = strlen(q); + } + + tmp = Strnew_charp(""); + 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, '('); + } +#ifdef NEW_FORM + 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: + 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_IMAGE: + case FORM_INPUT_SUBMIT: + case FORM_INPUT_BUTTON: + if (p2) { + Strcat_charp(tmp, htmlquote_str(p2)); + i = strlen(p2); + } + else { + Strcat_charp(tmp, qq); + i = qlen; + } + break; + case FORM_INPUT_RESET: + Strcat_charp(tmp, qq); + i = qlen; + 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; +} + +void +process_select(struct parsed_tag * tag) +{ + char *p; + + 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 && n_select < MAX_SELECT) { +#ifdef NEW_FORM + select_str = Sprintf("["); + 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; +} + +Str +process_n_select(void) +{ + if (cur_select == NULL) + return NULL; + process_option(); +#ifdef MENU_SELECT + if (!select_is_multiple && n_select < MAX_SELECT) { + if (select_option[n_select].first) + Strcat(select_str, textfieldrep(chooseSelectOption( + select_option[n_select].first, CHOOSE_OPTION), + cur_option_maxwidth)); + Strcat_charp(select_str, "]"); + n_select++; + if (n_select == MAX_SELECT) { + disp_err_message("Too many select in one page", FALSE); + } + } 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 && n_select < MAX_SELECT) { + 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 */ +#ifdef NEW_FORM + if (!select_is_multiple) { + begin_char = '('; + end_char = ')'; + } + Strcat(select_str, Sprintf("
%cptr), + htmlquote_str(cur_option_value->ptr))); + if (cur_option_selected) + Strcat_charp(select_str, " checked>*"); + else + Strcat_charp(select_str, "> "); +#ifdef NEW_FORM + Strcat_char(select_str, end_char); +#endif /* not NEW_FORM */ + Strcat_charp(select_str, htmlquote_str(cur_option_label->ptr)); + Strcat_charp(select_str, ""); + n_selectitem++; +} + +Str +process_textarea(struct parsed_tag * tag, int width) +{ + char *p, *q, *r; + + p = "40"; + parsedtag_get_value(tag, ATTR_COLS, &p); + q = ""; + parsedtag_get_value(tag, ATTR_NAME, &q); + r = "10"; + parsedtag_get_value(tag, ATTR_ROWS, &r); + cur_textarea = Strnew_charp(q); + 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 = 40; + + cur_textarea_rows = atoi(r); + if (n_textarea < MAX_TEXTAREA) + textarea_str[n_textarea] = Strnew(); + + return NULL; +} + +Str +process_n_textarea(void) +{ + Str tmp; + + if (cur_textarea == NULL || n_textarea >= MAX_TEXTAREA) + return NULL; + +#ifdef NEW_FORM + tmp = Sprintf("[", + cur_hseq++, cur_form_id, htmlquote_str(cur_textarea->ptr), + cur_textarea_size, cur_textarea_rows, n_textarea); +#else /* not NEW_FORM */ + tmp = Sprintf("[", + cur_hseq++, htmlquote_str(cur_textarea->ptr), + cur_textarea_size, cur_textarea_rows, n_textarea); +#endif /* not NEW_FORM */ + Strcat(tmp, textfieldrep(textarea_str[n_textarea], cur_textarea_size)); + Strcat_charp(tmp, "]"); + n_textarea++; + if (n_textarea == MAX_TEXTAREA) { + disp_err_message("Too many textarea in one page", FALSE); + } + else + textarea_str[n_textarea] = Strnew(); + cur_textarea = NULL; + + return tmp; +} + +void +feed_textarea(char *str) +{ + if (n_textarea < MAX_TEXTAREA) { + 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 + 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>"); +#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 NEW_FORM +#ifdef JP_CHARSET +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; +} + +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 + +Str +process_form(struct parsed_tag *tag) +{ + char *p, *q, *r, *s, *tg; + 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 + s = NULL; + parsedtag_get_value(tag, ATTR_ENCTYPE, &s); + tg = NULL; + parsedtag_get_value(tag, ATTR_TARGET, &tg); + form_max++; + form_sp++; + if (forms_size == 0) { + forms_size = INITIAL_FORM_SIZE; + forms = New_N(FormList *, forms_size); + form_stack = New_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); + } + forms[form_max] = + newFormList(q, p, &cs, s, tg, (form_max > 0) ? forms[form_max - 1] : NULL); + form_stack[form_sp] = form_max; + + return NULL; +} + +Str +process_n_form(void) +{ + if (form_sp >= 0) + form_sp--; + return NULL; +} +#endif /* NEW_FORM */ + +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\">", + htmlquote_str(id), htmlquote_str(framename)); + else + idtag = Sprintf("<_id id=\"%s\">", htmlquote_str(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); + if (cmd == HTML_BLQ) + 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 = cleanup_str(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_FRAME: + q = r = NULL; + parsedtag_get_value(tag, ATTR_SRC, &q); + parsedtag_get_value(tag, ATTR_NAME, &r); + if (q) { + q = htmlquote_str(q); + push_tag(obuf, Sprintf("", + cur_hseq++, q)->ptr, HTML_A); + if (r) + q = htmlquote_str(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); + 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); + 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_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: +#ifdef NEW_FORM + case HTML_FORM_INT: + process_form(tag); + return 1; +#endif /* NEW_FORM */ + case HTML_N_FORM: +#ifdef NEW_FORM + case HTML_N_FORM_INT: + process_n_form(); + return 1; +#else /* not NEW_FORM */ + flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); + return 0; +#endif /* not NEW_FORM */ + case HTML_INPUT: + tmp = process_input(tag); + if (tmp) + HTMLlineproc1(tmp->ptr, h_env); + return 1; + case HTML_SELECT: + process_select(tag); + 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: + process_textarea(tag, h_env->limit); + 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("
", + htmlquote_str(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); + content_charset = guess_charset(q); + } + } + else +#endif + if (p && q && !strcasecmp(p, "refresh")) { + int refresh = 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 = htmlquote_str(s_tmp->ptr); + tmp = Sprintf("Refresh (%d sec) %s", + refresh, 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 == 0) { + pushEvent(FUNCNAME_goURL, s_tmp->ptr); + /* pushEvent(deletePrevBuf,NULL); */ + } + } + } + return 1; + case HTML_BASE: + 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; +#ifdef VIEW_UNSEENOBJECTS + case HTML_BGSOUND: + if (view_unseenobject) { + if (parsedtag_get_value(tag, ATTR_SRC, &p)) { + Str s; + q = htmlquote_str(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 = htmlquote_str(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 = htmlquote_str(p); + s = Sprintf("applet archive(%s)", q, q); + HTMLlineproc1(s->ptr, h_env); + } + } + return 1; +#endif /* VIEW_UNSEENOBJECTS */ + case HTML_BODY: +#ifdef VIEW_UNSEENOBJECTS + if (view_unseenobject) { + if (parsedtag_get_value(tag, ATTR_BACKGROUND, &p)) { + Str s; + q = htmlquote_str(p); + s = Sprintf("\"bg
", + q, q); + HTMLlineproc1(s->ptr, h_env); + } + } +#endif /* VIEW_UNSEENOBJECTS */ + case HTML_N_BODY: + obuf->flag |= RB_IGNORE_P; + 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, *str; +#ifndef NEW_FORM + char cs; +#endif + Lineprop outp[LINELEN], mode, effect; + int pos; + int nlines; + FILE *debug; + struct frameset *frameset_s[FRAMESTACK_SIZE]; + int frameset_sp = -1; + union frameset_element *idFrame = NULL; + char *id = NULL; + Str tmp; + int hseq; + Str line; + char *endp; + + if (w3m_debug) + debug = fopen("zzzerr", "a"); + + effect = 0; + nlines = 0; +#ifdef NEW_FORM + buf->formlist = (form_max >= 0) ? forms[form_max] : NULL; +#endif /* NEW_FORM */ + while ((line = feed()) != NULL) { + if (w3m_debug) { + Strfputs(line, debug); + fputc('\n', debug); + } + proc_again: + if (++nlines == llimit) + break; + pos = 0; + if (showLineNum) { + tmp = Sprintf("%4d:", nlines); + for (p = tmp->ptr; *p; p++) { + PPUSH(PC_ASCII, *p); + } + } +#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 && IS_INTSPACE(*str)) { + PPUSH(PC_ASCII | effect, *str); + 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) && + (!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)) + registerName(buf, id, currentLn(buf), pos); + parsedtag_get_value(tag, ATTR_HREF, &p); + parsedtag_get_value(tag, ATTR_TARGET, &q); + parsedtag_get_value(tag, ATTR_REFERER, &r); + 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)) { + a_img = registerImg(buf, p, + currentLn(buf), pos); + } + 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; +#ifdef NEW_FORM + int form_id = -1; +#endif /* NEW_FORM */ + +#ifndef NEW_FORM + if (form_sp < 0) + break; /* outside of
..
*/ +#endif /* not NEW_FORM */ + hseq = 0; + parsedtag_get_value(tag, ATTR_HSEQ, &hseq); +#ifdef NEW_FORM + parsedtag_get_value(tag, ATTR_FID, &form_id); +#endif +#ifdef NEW_FORM + if (form_id < 0 || form_id > form_max || forms == NULL) + break; /* outside of
..
*/ + form = forms[form_id]; +#else /* not NEW_FORM */ + if (form_sp >= FORMSTACK_SIZE) + break; + form = form_stack[form_sp]; +#endif /* not NEW_FORM */ + 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; + a_form = registerForm(buf, form, tag, currentLn(buf), pos); + if (a_form) { + a_form->hseq = hseq - 1; + 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; +#ifndef NEW_FORM + case HTML_FORM: + case HTML_FORM_INT: + form_sp++; + if (form_sp >= FORMSTACK_SIZE) + break; + p = "get"; + q = "/"; + s = NULL; + cs = 0; + parsedtag_get_value(tag, ATTR_METHOD, &p); + parsedtag_get_value(tag, ATTR_ACTION, &q); +#ifdef JP_CHARSET + if (parsedtag_get_value(tag, ATTR_CHARSET, &r)) + cs = check_charset(r); +#endif + parsedtag_get_value(tag, ATTR_ENCTYPE, &s); + buf->formlist = newFormList(q, p, &cs, s, buf->formlist); + form_stack[form_sp] = buf->formlist; + break; + case HTML_N_FORM: + case HTML_N_FORM_INT: + if (form_sp >= 0) + form_sp--; + break; +#endif /* not NEW_FORM */ + case HTML_MAP: + if (parsedtag_get_value(tag, ATTR_NAME, &p)) { + MapList *m = New(MapList); + m->name = Strnew_charp(p); + m->next = buf->maplist; + m->urls = newTextList(); + m->alts = newTextList(); + 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)) { + pushText(buf->maplist->urls, p); + if (parsedtag_get_value(tag, ATTR_ALT, &q)) + pushText(buf->maplist->alts, q); + else + pushText(buf->maplist->alts, ""); + } + 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], 0, 0); + } + 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, baseURL(buf)); + addFrameSetElement(frameset_s[frameset_sp], element); + } + break; + case HTML_BASE: + if (parsedtag_get_value(tag, ATTR_HREF, &p)) { + if (!buf->baseURL) + buf->baseURL = New(ParsedURL); + parseURL(p, buf->baseURL, NULL); + } + parsedtag_get_value(tag, ATTR_TARGET, &buf->baseTarget); + break; + case HTML_TITLE_ALT: + if (parsedtag_get_value(tag, ATTR_TITLE, &p)) + buf->buffername = cleanup_str(p); + break; +#ifndef KANJI_SYMBOLS + case HTML_RULE: + effect |= PC_RULE; + 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)) + registerName(buf, id, currentLn(buf), pos); + if (renderFrameSet && + parsedtag_get_value(tag, ATTR_FRAMENAME, &p) && + (!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 */ + addnewline(buf, outc, outp, +#ifdef ANSI_COLOR + NULL, +#endif + pos, nlines); + if (str != endp) { + line = Strsubstr(line, str - line->ptr, endp - str); + goto proc_again; + } + } + if (w3m_debug) + fclose(debug); +} + +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 = IS_CNTRL(ech) ? PC_CTRL : PC_ASCII; + + if (!ech) { + *str_return = str; + proc_mchar(obuf, obuf->flag & RB_SPECIAL, 1, str_return, PC_ASCII); + return; + } + + check_breakpoint(obuf, obuf->flag & RB_SPECIAL, ech); + estr = conv_latin1(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 = Strlastchar(obuf->line); + + if (obuf->flag & RB_PRE_INT) { + if (obuf->pos > h_env->limit) + return 1; + else + return 0; + } + + /* 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 *istr, struct html_feed_environ *h_env, int internal) +{ + Lineprop mode; + char *str = istr, *q; + int cmd; + struct readbuffer *obuf = h_env->obuf; + int indent, delta; + struct parsed_tag *tag; + Str tokbuf = Strnew(); + struct table *tbl = NULL; + struct table_mode *tbl_mode; + int tbl_width; + + 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", istr, 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; + } + + 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, ' '); + } + 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, NULL); + } + + /* 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)) { + if (*str != '\n') + obuf->flag &= ~RB_IGNORE_P; + if (*str == '\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 (*str == '\t') { + do { + PUSH(' '); + } while (obuf->pos % Tabstop != 0); + str++; + } + else if (obuf->flag & RB_PLAINMODE) { + char *p = htmlquote_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 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 = New_N(Lineprop, pos); + bcopy((void *) prop, (void *) l->propBuf, pos * sizeof(Lineprop)); + } + else { + l->lineBuf = NullLine; + l->propBuf = NullProp; + } +#ifdef ANSI_COLOR + if (pos > 0 && color) { + l->colorBuf = New_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; + } + 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) { + tmp = tmpfname(TMPF_SRC, ".html"); + 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 (src) + fclose(src); + + return newBuf; +} + +static char *_size_unit[] = +{"b", "kb", "Mb", "Gb", "Tb", + "Pb", "Eb", "Zb", "Bb", "Yb", NULL}; + +char * +convert_size(int 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(int size1, int 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(int *linelen, int *trbyte) +{ + int i, j, rate, duration, eta, pos; + static time_t last_time, start_time; + time_t cur_time = time(0); + Str messages; + char *fmtrbyte, *fmrate; + + if (!fmInitialized) + return; + + if (current_content_length > 0) { + double ratio; + 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) { + 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\n", fmtrbyte, fmrate); + } + else { + messages = Sprintf("%7s loaded\n", 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->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); + } +} + +void +loadHTMLstream(URLFile * f, Buffer * newBuf, FILE * src, int internal) +{ + struct environment envs[MAX_ENV_LEVEL]; + int linelen = 0; + int trbyte = 0; + Str lineBuf2 = Strnew(); + char code; + struct html_feed_environ htmlenv1; + struct readbuffer obuf; + MySignalHandler(*prevtrap) (); + + if (SETJMP(AbortLoading) != 0) { + HTMLlineproc1("
Transfer Interrupted!
", &htmlenv1); + goto phase2; + } + if (fmInitialized) { + prevtrap = signal(SIGINT, KeyAbort); + term_cbreak(); + } + + n_textarea = 0; + cur_textarea = NULL; +#ifdef MENU_SELECT + n_select = 0; +#endif /* MENU_SELECT */ + cur_select = NULL; + form_sp = -1; +#ifdef NEW_FORM + form_max = -1; + forms_size = 0; + forms = NULL; +#endif /* NEW_FORM */ + + cur_hseq = 1; + + if (w3m_halfload) { + newBuf->buffername = "---"; +#ifdef JP_CHARSET + newBuf->document_code = InnerCode; +#endif /* JP_CHARSET */ + 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(); + +#ifdef JP_CHARSET + if (newBuf != NULL && newBuf->document_code != '\0') + code = newBuf->document_code; + else if (content_charset != '\0') + code = content_charset; + else + code = DocumentCode; + content_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; + showProgress(&linelen, &trbyte); +#ifdef JP_CHARSET + if (content_charset != '\0') { /* */ + code = content_charset; + content_charset = '\0'; + } +#endif + if (!internal) + lineBuf2 = convertLine(f, lineBuf2, &code, HTML_MODE); +#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); + } + return; + } + phase2: + newBuf->trbyte = trbyte + linelen; + if (fmInitialized) { + term_raw(); + signal(SIGINT, prevtrap); + } + HTMLlineproc2(newBuf, htmlenv1.buf); +#ifdef JP_CHARSET + newBuf->document_code = code; +#endif /* JP_CHARSET */ +} + +/* + * loadHTMLString: read string and make new buffer + */ +Buffer * +loadHTMLString(Str page) +{ + URLFile f; + MySignalHandler(*prevtrap) (); + Buffer *newBuf; + + newBuf = newBuffer(INIT_BUFFER_WIDTH); + if (SETJMP(AbortLoading) != 0) { + discardBuffer(newBuf); + return NULL; + } + init_stream(&f, SCM_LOCAL, newStrStream(page)); + + if (fmInitialized) { + prevtrap = signal(SIGINT, KeyAbort); + term_cbreak(); + } + + loadHTMLstream(&f, newBuf, NULL, 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 */ + + return newBuf; +} + +#ifdef USE_GOPHER + +/* + * loadGopherDir: get gopher directory + */ +Buffer * +loadGopherDir(URLFile * uf, Buffer * newBuf) +{ +#ifdef JP_CHARSET + char code, ic; +#endif + Str name, file, host, port; + char type; + char *p; + TextLineList *tl = newTextLineList(); + Str lbuf; + int hseq = 1; + + if (newBuf == NULL) + newBuf = newBuffer(INIT_BUFFER_WIDTH); +#ifdef JP_CHARSET + if (newBuf->document_code != '\0') + code = newBuf->document_code; + else if (content_charset != '\0') + 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; +#ifdef JP_CHARSET + if ((ic = checkShiftCode(lbuf, code)) != '\0') + lbuf = conv_str(lbuf, (code = ic), InnerCode); +#endif /* JP_CHARSET */ + cleanup_line(lbuf, HTML_MODE); + + p = lbuf->ptr; + for (name = Strnew(); *p && *p != '\t'; p++) + Strcat_char(name, *p); + p++; + for (file = Strnew(); *p && *p != '\t'; p++) + Strcat_char(file, *p); + p++; + for (host = Strnew(); *p && *p != '\t'; p++) + Strcat_char(host, *p); + p++; + for (port = Strnew(); *p && + *p != '\t' && *p != '\r' && *p != '\n'; + p++) + Strcat_char(port, *p); + p++; + type = name->ptr[0]; + switch (type) { + 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; + } + lbuf = Sprintf(""); + Strcat_charp(lbuf, p); + Strcat_charp(lbuf, name->ptr + 1); + pushTextLine(tl, newTextLine(lbuf, visible_length(lbuf->ptr))); + } + HTMLlineproc2(newBuf, tl); + 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 * newBuf) +{ + FILE *src = NULL; + char code; + Str lineBuf2; + char pre_lbuf = '\0'; + int nlines; + Str tmpf; + int linelen = 0, trbyte = 0; +#ifdef ANSI_COLOR + int check_color; +#endif + MySignalHandler(*prevtrap) (); + + if (newBuf == NULL) + newBuf = newBuffer(INIT_BUFFER_WIDTH); + lineBuf2 = Strnew(); + + if (SETJMP(AbortLoading) != 0) { + goto _end; + } + if (fmInitialized) { + prevtrap = signal(SIGINT, KeyAbort); + term_cbreak(); + } + + if (newBuf->sourcefile == NULL && uf->scheme != SCM_LOCAL) { + 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') + 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; + showProgress(&linelen, &trbyte); + 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; + if (showLineNum) { + Str tmp = Sprintf("%4d:", nlines); + Strcat(tmp, lineBuf2); + lineBuf2 = tmp; + } +#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 ANSI_COLOR + colorBuffer, &check_color, +#endif + LINELEN); + addnewline(newBuf, lineBuf2->ptr, propBuffer, +#ifdef ANSI_COLOR + check_color ? colorBuffer : NULL, +#endif + lineBuf2->length, nlines); + } + _end: + if (fmInitialized) { + signal(SIGINT, prevtrap); + term_raw(); + } + newBuf->topLine = newBuf->firstLine; + newBuf->currentLine = newBuf->firstLine; + newBuf->trbyte = trbyte + linelen; +#ifdef JP_CHARSET + newBuf->document_code = code; +#endif /* JP_CHARSET */ + if (src) + fclose(src); + + return newBuf; +} + +/* + * saveBuffer: write buffer to file + */ + +void +saveBuffer(Buffer * buf, FILE * f) +{ + saveBufferDelNum(buf, f, FALSE); +} + +#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 + +void +saveBufferDelNum(Buffer * buf, FILE * f, int del) +{ + Line *l = buf->firstLine; + Str tmp; + char *p; + +#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); + if (del && (p = strchr(tmp->ptr, ':')) != NULL) + Strdelete(tmp, 0, p - tmp->ptr + 1); +#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); + if (buf == NULL) + return NULL; + return buf; +} + +/* + * getshell: execute shell command and get the result into a buffer + */ +Buffer * +getshell(char *cmd) +{ + Buffer *buf; + Str bn; + buf = loadcmdout(cmd, loadBuffer, NULL); + buf->filename = cmd; + bn = Sprintf("%s %s", SHELLBUFFERNAME, cmd); + buf->buffername = bn->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; + Str bn; + + 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; + bn = Sprintf("%s %s", PIPEBUFFERNAME, cmd); + buf->buffername = bn->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; + buf->bufferprop |= BP_PIPE; +#ifdef JP_CHARSET + buf->document_code = DocumentCode; +#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 (!strcmp(t, "text/html")) { + buf = loadHTMLBuffer(&uf, t_buf); + buf->type = "text/html"; + } + else if (is_plain_text_type(t)) { + buf = openPagerBuffer(stream, t_buf); + buf->type = "text/plain"; + } + else { + if (doExternal(uf, "-", t, &buf, t_buf)) { + ; + } + else { /* unknown type is regarded as text/plain */ + buf = openPagerBuffer(stream, t_buf); + buf->type = "text/plain"; + } + } + buf->real_type = t; + buf->encoding = uf.encoding; + 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; + int linelen = buf->linelen, trbyte = buf->trbyte; + Str lineBuf2; + char pre_lbuf = '\0'; + URLFile uf; + char code; + int squeeze_flag = 0; +#ifdef 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 (showLineNum) { + char *p; + if ((p = strchr(pl->lineBuf, ':')) != NULL) + pre_lbuf = *(p + 1); + } + if (pre_lbuf == '\0') + pre_lbuf = '\n'; + } + +#ifdef JP_CHARSET + code = buf->document_code; +#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, 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; + if (showLineNum) { + Str tmp = Sprintf("%4d:", nlines); + Strcat(tmp, lineBuf2); + lineBuf2 = tmp; + } + Strchop(lineBuf2); + lineBuf2 = checkType(lineBuf2, propBuffer, +#ifdef ANSI_COLOR + colorBuffer, &check_color, +#endif + LINELEN); + len = lineBuf2->length; + l = New(Line); + l->lineBuf = lineBuf2->ptr; + l->propBuf = New_N(Lineprop, len); + bcopy((void *) propBuffer, (void *) l->propBuf, len * sizeof(Lineprop)); +#ifdef ANSI_COLOR + if (check_color) { + l->colorBuf = New_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 (squeezeBlankLine) { + l->real_linenumber = nlines; + l->linenumber = (pl == NULL ? nlines : pl->linenumber + 1); + } + else { + l->real_linenumber = l->linenumber = nlines; + } + 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; + int linelen = 0, trbyte = 0; + MySignalHandler(*prevtrap) (); + 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; + } + if (fmInitialized) { + prevtrap = signal(SIGINT, KeyAbort); + 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 stat; + Buffer *buf = NULL; + + if (!(mcap = searchExtViewer(type))) + return 0; + + tmpf = tmpfname(TMPF_DFL, NULL); + + if (mcap->nametemplate) { + Str tmp = unquote_mailcap(mcap->nametemplate, NULL, tmpf->ptr, NULL); + if (Strncmp(tmpf, tmp, tmpf->length) == 0) { + tmpf = tmp; + goto _save; + } + } + if (uf.ext && *uf.ext) { + Strcat_charp(tmpf, uf.ext); + } + _save: + if (save2tmp(uf, tmpf->ptr) < 0) + return 0; + command = unquote_mailcap(mcap->viewer, type, tmpf->ptr, &stat); +#ifndef __EMX__ + if (!(stat & MCSTAT_REPNAME)) { + Str tmp = Sprintf("(%s) < %s", command->ptr, tmpf->ptr); + command = tmp; + } +#endif + if (mcap->flags & (MAILCAP_HTMLOUTPUT|MAILCAP_COPIOUSOUTPUT)) { + if (defaultbuf == NULL) + defaultbuf = newBuffer(INIT_BUFFER_WIDTH); + defaultbuf->sourcefile = tmpf->ptr; + } + if (mcap->flags & MAILCAP_HTMLOUTPUT) { + buf = loadcmdout(command->ptr, loadHTMLBuffer, defaultbuf); + if (buf) + buf->type = "text/html"; + } + else if (mcap->flags & MAILCAP_COPIOUSOUTPUT) { + buf = loadcmdout(command->ptr, loadBuffer, defaultbuf); + if (buf) + buf->type = "text/plain"; + } + 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 = lastFileName(path); + buf->edit = mcap->edit; + } + *bufp = buf; + pushText(fileToDelete, tmpf->ptr); + return 1; +} + +static int +_MoveFile(char *path1, char *path2) +{ + InputStream f1; + FILE *f2; + int is_pipe; + int 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; + char filen[256]; + char *p, *q; + + if (fmInitialized) { + p = searchKeyData(); + if (p == NULL || *p == '\0') { + p = inputLineHist("(Download)Save file to: ", + defstr, IN_COMMAND, SaveHist); + if (p == NULL || *p == '\0') + return; + } + if (*p != '|' || !PermitSaveToPipe) { + 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); + p = fgets(filen, sizeof(filen), stdin); + if (p == NULL || filen[0] == '\0') + return; + q = filen; + } + 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; + char filen[256]; + 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; + } + 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); + p = fgets(filen, sizeof(filen), stdin); + if (p == NULL || filen[0] == '\0') + return; + q = filen; + } + 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 buf[2]; + char *ans = NULL; + + if (stat(path, &st) < 0) + return 0; + if (fmInitialized) { + ans = inputStr("File exists. Overwrite? (y or n)", ""); + } + else { + printf("File exists. Overwrite? (y or n)"); + ans = fgets(buf, 2, stdin); + } + if (ans != NULL && (*ans == '\0' || tolower(*ans) == 'y')) + return 0; + else + return -1; +} + +static void +sig_chld(int signo) +{ + int stat; +#ifdef HAVE_WAITPID + pid_t pid; + + while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) { + ; + } +#elif HAVE_WAIT3 + int pid; + + while ((pid = wait3(&stat, WNOHANG, NULL)) > 0) { + ; + } +#else + wait(&stat); +#endif + return; +} + +#ifdef __EMX__ +#define GUNZIP_CMD "gzip" +#define BUNZIP2_CMD "bzip2" +#else /* not __EMX__ */ +#define GUNZIP_CMD "gunzip" +#define BUNZIP2_CMD "bunzip2" +#endif /* not __EMX__ */ +#define INFLATE_CMD "inflate" +#define GUNZIP_NAME "gunzip" +#define BUNZIP2_NAME "bunzip2" +#define INFLATE_NAME "inflate" + +void +gunzip_stream(URLFile *uf) +{ + int pid1; + int fd1[2]; + char *expand_cmd = GUNZIP_CMD; + char *expand_name = GUNZIP_NAME; + char *tmpf = NULL; + + switch (uf->compression) { + case CMP_COMPRESS: + case CMP_GZIP: + expand_cmd = GUNZIP_CMD; + expand_name = GUNZIP_NAME; + break; + case CMP_BZIP2: + expand_cmd = BUNZIP2_CMD; + expand_name = BUNZIP2_NAME; + break; + case CMP_DEFLATE: + expand_cmd = INFLATE_CMD; + expand_name = INFLATE_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 (uf->scheme != SCM_FTP) + UFclose(uf); + pushText(fileToDelete, tmpf); + } + +#ifdef SIGCHLD + signal(SIGCHLD, sig_chld); +#endif + flush_tty(); + /* fd1[0]: read, fd1[1]: write */ + if ((pid1 = fork()) == 0) { + signal(SIGINT, SIG_DFL); + close(fd1[0]); + if (tmpf) { +#ifdef __CYGWIN__ + 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]; +#ifdef SIGCHLD + signal(SIGCHLD, sig_chld); +#endif + 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); + 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->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 + +char * +guess_save_name(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; +} + +/* Local Variables: */ +/* c-basic-offset: 4 */ +/* tab-width: 8 */ +/* End: */ -- cgit v1.2.3