From 72f72d64a422d6628c4796f5c0bf2e508f134214 Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Wed, 4 May 2011 16:05:14 +0900 Subject: Adding upstream version 0.5.1 --- file.c | 8016 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 8016 insertions(+) create mode 100644 file.c (limited to 'file.c') diff --git a/file.c b/file.c new file mode 100644 index 0000000..18346e9 --- /dev/null +++ b/file.c @@ -0,0 +1,8016 @@ +/* $Id: file.c,v 1.235 2004/04/16 18:47:19 ukai Exp $ */ +#include "fm.h" +#include +#include "myctype.h" +#include +#include +#if defined(HAVE_WAITPID) || defined(HAVE_WAIT3) +#include +#endif +#include +#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 char *guess_filename(char *file); +static int _MoveFile(char *path1, char *path2); +static void uncompress_stream(URLFile *uf, char **src); +static FILE *lessopen_stream(char *path); +static Buffer *loadcmdout(char *cmd, + Buffer *(*loadproc) (URLFile *, Buffer *), + Buffer *defaultbuf); +#ifndef USE_ANSI_COLOR +#define addnewline(a,b,c,d,e,f,g) _addnewline(a,b,c,e,f,g) +#endif +static void addnewline(Buffer *buf, char *line, Lineprop *prop, + Linecolor *color, int pos, int width, int nlines); +static void addLink(Buffer *buf, struct parsed_tag *tag); + +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 USE_M17N +static char cur_document_charset; +#endif +#endif + +static Str cur_title; +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 = get_strwidth(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 = ']'; + int len; + + 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) { + len = get_Str_strwidth(cur_option_label); + if (len > cur_option_maxwidth) + cur_option_maxwidth = len; + 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 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; + } + w /= symbol_width; + if (w <= 0) + w = 1; + push_symbol(tmp, HR_SYMBOL, symbol_width, w); + Strcat_charp(tmp, ""); + return tmp; +} + +#ifdef USE_M17N +static char * +check_charset(char *p) +{ + return wc_guess_charset(p, 0) ? p : NULL; +} + +static char * +check_accept_charset(char *ac) +{ + char *s = ac, *e; + + while (*s) { + while (*s && (IS_SPACE(*s) || *s == ',')) + s++; + if (!*s) + break; + e = s; + while (*e && !(IS_SPACE(*e) || *e == ',')) + e++; + if (wc_guess_charset(Strnew_charp_n(s, e - s)->ptr, 0)) + return ac; + s = e; + } + return NULL; +} +#endif + +static Str +process_form_int(struct parsed_tag *tag, int fid) +{ + char *p, *q, *r, *s, *tg, *n; + + p = "get"; + parsedtag_get_value(tag, ATTR_METHOD, &p); + q = "!CURRENT_URL!"; + parsedtag_get_value(tag, ATTR_ACTION, &q); + r = NULL; +#ifdef USE_M17N + if (parsedtag_get_value(tag, ATTR_ACCEPT_CHARSET, &r)) + r = check_accept_charset(r); + if (!r && parsedtag_get_value(tag, ATTR_CHARSET, &r)) + r = check_charset(r); +#endif + 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, r, 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);\ + obuf->flag &= ~RB_P;\ + } + +#define CLOSE_A \ + CLOSE_P; \ + close_anchor(h_env, obuf); + +#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 +getMetaRefreshParam(char *q, Str *refresh_uri) +{ + int refresh_interval; + char *r; + Str s_tmp = NULL; + + if (q == NULL || refresh_uri == NULL) + return 0; + + refresh_interval = atoi(q); + if (refresh_interval < 0) + return 0; + + 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++; + } + *refresh_uri = s_tmp; + return refresh_interval; +} + +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_Q: + HTMLlineproc1("`", h_env); + return 1; + case HTML_N_Q: + HTMLlineproc1("'", h_env); + return 1; + case HTML_P: + case HTML_N_P: + CLOSE_A; + 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_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_A; + 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_A; + 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_A; + 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_A; + 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); + tmp = Strnew(); + switch (envs[h_env->envc].type) { + case 'd': + push_symbol(tmp, UL_SYMBOL_DISC, symbol_width, 1); + break; + case 'c': + push_symbol(tmp, UL_SYMBOL_CIRCLE, symbol_width, 1); + break; + case 's': + push_symbol(tmp, UL_SYMBOL_SQUARE, symbol_width, 1); + break; + default: + push_symbol(tmp, + UL_SYMBOL((h_env->envc_real - + 1) % MAX_UL_LEVEL), symbol_width, + 1); + break; + } + if (symbol_width == 1) + push_charp(obuf, 1, NBSP, PC_ASCII); + push_str(obuf, symbol_width, tmp, PC_ASCII); + push_charp(obuf, 1, NBSP, PC_ASCII); + set_space_to_prevchar(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 + Strcat_char(num, '.'); + push_spaces(obuf, 1, INDENT_INCR - num->length); + push_str(obuf, num->length, num, PC_ASCII); + if (INDENT_INCR >= 4) + set_space_to_prevchar(obuf->prevchar); + 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_A; + 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_A; + 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: + close_anchor(h_env, obuf); + process_title(tag); + obuf->flag |= RB_TITLE; + obuf->end_tag = HTML_N_TITLE; + return 1; + case HTML_N_TITLE: + if (!(obuf->flag & RB_TITLE)) + return 1; + obuf->flag &= ~RB_TITLE; + obuf->end_tag = 0; + tmp = process_n_title(tag); + if (tmp) + HTMLlineproc1(tmp->ptr, h_env); + return 1; + case HTML_TITLE_ALT: + if (parsedtag_get_value(tag, ATTR_TITLE, &p)) + h_env->title = html_unquote(p); + return 0; + 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_A; + 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_A; + 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, get_strwidth(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: + close_anchor(h_env, obuf); + tmp = process_hr(tag, h_env->limit, envs[h_env->envc].indent); + HTMLlineproc1(tmp->ptr, h_env); + set_space_to_prevchar(obuf->prevchar); + return 1; + case HTML_PRE: + x = parsedtag_exists(tag, ATTR_FOR_TABLE); + CLOSE_A; + if (!(obuf->flag & RB_IGNORE_P)) { + flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); + if (!x) + do_blankline(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); + if (!(obuf->flag & RB_IGNORE_P)) { + do_blankline(h_env, obuf, envs[h_env->envc].indent, 0, + h_env->limit); + obuf->flag |= RB_IGNORE_P; + } + 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) { + set_prevchar(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_PRE_PLAIN: + CLOSE_A; + if (!(obuf->flag & 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); + } + obuf->flag |= (RB_PRE | RB_IGNORE_P); + return 1; + case HTML_N_PRE_PLAIN: + CLOSE_A; + if (!(obuf->flag & 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); + obuf->flag |= RB_IGNORE_P; + } + obuf->flag &= ~RB_PRE; + return 1; + case HTML_LISTING: + case HTML_XMP: + case HTML_PLAINTEXT: + CLOSE_A; + if (!(obuf->flag & 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); + } + obuf->flag |= (RB_PLAIN | RB_IGNORE_P); + switch (cmd) { + case HTML_LISTING: + obuf->end_tag = HTML_N_LISTING; + break; + case HTML_XMP: + obuf->end_tag = HTML_N_XMP; + break; + case HTML_PLAINTEXT: + obuf->end_tag = MAX_HTMLTAG; + break; + } + return 1; + case HTML_N_LISTING: + case HTML_N_XMP: + CLOSE_A; + if (!(obuf->flag & 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); + obuf->flag |= RB_IGNORE_P; + } + obuf->flag &= ~RB_PLAIN; + obuf->end_tag = 0; + return 1; + case HTML_SCRIPT: + obuf->flag |= RB_SCRIPT; + obuf->end_tag = HTML_N_SCRIPT; + return 1; + case HTML_STYLE: + obuf->flag |= RB_STYLE; + obuf->end_tag = HTML_N_STYLE; + return 1; + case HTML_N_SCRIPT: + obuf->flag &= ~RB_SCRIPT; + obuf->end_tag = 0; + return 1; + case HTML_N_STYLE: + obuf->flag &= ~RB_STYLE; + obuf->end_tag = 0; + return 1; + case HTML_A: + if (obuf->anchor.url) + close_anchor(h_env, obuf); + + hseq = 0; + + if (parsedtag_get_value(tag, ATTR_HREF, &p)) + obuf->anchor.url = Strnew_charp(p)->ptr; + if (parsedtag_get_value(tag, ATTR_TARGET, &p)) + obuf->anchor.target = Strnew_charp(p)->ptr; + if (parsedtag_get_value(tag, ATTR_REFERER, &p)) + obuf->anchor.referer = Strnew_charp(p)->ptr; + if (parsedtag_get_value(tag, ATTR_TITLE, &p)) + obuf->anchor.title = Strnew_charp(p)->ptr; + if (parsedtag_get_value(tag, ATTR_ACCESSKEY, &p)) + obuf->anchor.accesskey = (unsigned char)*p; + if (parsedtag_get_value(tag, ATTR_HSEQ, &hseq)) + obuf->anchor.hseq = hseq; + + if (hseq == 0 && obuf->anchor.url) { + 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: + close_anchor(h_env, obuf); + 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; + table_mode[obuf->table_level].end_tag = 0; /* HTML_UNKNOWN */ +#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_A; + 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_A; + 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_A; + 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_A; + flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); + RB_RESTORE_FLAG(obuf); + return 1; + case HTML_DIV_INT: + 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_INT: + 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_A; + 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_A; + 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: + close_anchor(h_env, obuf); + tmp = process_input(tag); + if (tmp) + HTMLlineproc1(tmp->ptr, h_env); + return 1; + case HTML_SELECT: + close_anchor(h_env, obuf); + tmp = process_select(tag); + if (tmp) + HTMLlineproc1(tmp->ptr, h_env); + obuf->flag |= RB_INSELECT; + obuf->end_tag = HTML_N_SELECT; + return 1; + case HTML_N_SELECT: + obuf->flag &= ~RB_INSELECT; + obuf->end_tag = 0; + tmp = process_n_select(); + if (tmp) + HTMLlineproc1(tmp->ptr, h_env); + return 1; + case HTML_OPTION: + /* nothing */ + return 1; + case HTML_TEXTAREA: + close_anchor(h_env, obuf); + tmp = process_textarea(tag, h_env->limit); + if (tmp) + HTMLlineproc1(tmp->ptr, h_env); + obuf->flag |= RB_INTXTA; + obuf->end_tag = HTML_N_TEXTAREA; + return 1; + case HTML_N_TEXTAREA: + obuf->flag &= ~RB_INTXTA; + obuf->end_tag = 0; + tmp = process_n_textarea(); + if (tmp) + HTMLlineproc1(tmp->ptr, 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 USE_M17N + 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 = wc_guess_charset(q, 0); + } + } + else +#endif + if (p && q && !strcasecmp(p, "refresh")) { + int refresh_interval; + tmp = NULL; + refresh_interval = getMetaRefreshParam(q, &tmp); + if (tmp) { + q = html_quote(tmp->ptr); + tmp = Sprintf("Refresh (%d sec) %s", + refresh_interval, q, q); + } + else if (refresh_interval > 0) + tmp = Sprintf("Refresh (%d sec)", refresh_interval); + if (tmp) { + HTMLlineproc1(tmp->ptr, h_env); + do_blankline(h_env, obuf, envs[h_env->envc].indent, 0, + h_env->limit); + if (!is_redisplay && + !((obuf->flag & RB_NOFRAMES) && RenderFrame)) { + tag->need_reconstruct = TRUE; + return 0; + } + } + } + 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: + if (displayInsDel) + HTMLlineproc1("[DEL:", h_env); + else + obuf->flag |= RB_DEL; + return 1; + case HTML_N_DEL: + if (displayInsDel) + HTMLlineproc1(":DEL]", h_env); + else + obuf->flag &= ~RB_DEL; + return 1; + case HTML_S: + if (displayInsDel) + HTMLlineproc1("[S:", h_env); + else + obuf->flag |= RB_S; + return 1; + case HTML_N_S: + if (displayInsDel) + HTMLlineproc1(":S]", h_env); + else + obuf->flag &= ~RB_S; + return 1; + case HTML_INS: + if (displayInsDel) + HTMLlineproc1("[INS:", h_env); + return 1; + case HTML_N_INS: + if (displayInsDel) + HTMLlineproc1(":INS]", h_env); + return 1; + case HTML_SUP: + if (!(obuf->flag & (RB_DEL | RB_S))) + HTMLlineproc1("^", h_env); + return 1; + case HTML_N_SUP: + return 1; + case HTML_SUB: + if (!(obuf->flag & (RB_DEL | RB_S))) + HTMLlineproc1("[", h_env); + return 1; + case HTML_N_SUB: + if (!(obuf->flag & (RB_DEL | RB_S))) + HTMLlineproc1("]", 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_HEAD: + if (obuf->flag & RB_TITLE) + HTMLlineproc1("", h_env); + case HTML_HEAD: + 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++;} +#define PSIZE \ + if (out_size <= pos + 1) { \ + out_size = pos * 3 / 2; \ + outc = New_Reuse(char, outc, out_size); \ + outp = New_Reuse(Lineprop, outp, out_size); \ + } + +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) +{ + static char *outc = NULL; + static Lineprop *outp = NULL; + static int out_size = 0; + Anchor *a_href = NULL, *a_img = NULL, *a_form = NULL; + char *p, *q, *r, *s, *t, *str; + Lineprop mode, effect; + int pos; + int nlines; +#ifdef DEBUG + FILE *debug = NULL; +#endif + 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; + char symbol = '\0'; + int internal = 0; + Anchor **a_textarea = NULL; +#ifdef MENU_SELECT + Anchor **a_select = NULL; +#endif + + if (out_size == 0) { + out_size = LINELEN; + outc = NewAtom_N(char, out_size); + outp = NewAtom_N(Lineprop, out_size); + } + + 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 + +#ifdef DEBUG + if (w3m_debug) + debug = fopen("zzzerr", "a"); +#endif + + effect = 0; + nlines = 0; + while ((line = feed()) != NULL) { +#ifdef DEBUG + if (w3m_debug) { + Strfputs(line, debug); + fputc('\n', debug); + } +#endif + 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) { + PSIZE; + mode = get_mctype(str); + if (effect & PC_SYMBOL && *str != '<') { +#ifdef USE_M17N + char **buf = set_symbol(symbol_width0); + int len; + + p = buf[(int)symbol]; + len = get_mclen(p); + mode = get_mctype(p); + PPUSH(mode | effect, *(p++)); + if (--len) { + mode = (mode & ~PC_WCHAR1) | PC_WCHAR2; + while (len--) { + PSIZE; + PPUSH(mode | effect, *(p++)); + } + } +#else + PPUSH(PC_ASCII | effect, SYMBOL_BASE + symbol); +#endif + str += symbol_width; + } +#ifdef USE_M17N + else if (mode == PC_CTRL || mode == PC_UNDEF) { +#else + else if (mode == PC_CTRL || IS_INTSPACE(*str)) { +#endif + PPUSH(PC_ASCII | effect, ' '); + str++; + } +#ifdef USE_M17N + else if (mode & PC_UNKNOWN) { + PPUSH(PC_ASCII | effect, ' '); + str += get_mclen(str); + } +#endif + else if (*str != '<' && *str != '&') { +#ifdef USE_M17N + int len = get_mclen(str); +#endif + PPUSH(mode | effect, *(str++)); +#ifdef USE_M17N + if (--len) { + mode = (mode & ~PC_WCHAR1) | PC_WCHAR2; + while (len--) { + PSIZE; + PPUSH(mode | effect, *(str++)); + } + } +#endif + } + else if (*str == '&') { + /* + * & escape processing + */ + p = getescapecmd(&str); + while (*p) { + PSIZE; + mode = get_mctype((unsigned char *)p); +#ifdef USE_M17N + if (mode == PC_CTRL || mode == PC_UNDEF) { +#else + if (mode == PC_CTRL || IS_INTSPACE(*str)) { +#endif + PPUSH(PC_ASCII | effect, ' '); + p++; + } +#ifdef USE_M17N + else if (mode & PC_UNKNOWN) { + PPUSH(PC_ASCII | effect, ' '); + p += get_mclen(p); + } +#endif + else { +#ifdef USE_M17N + int len = get_mclen(p); +#endif + PPUSH(mode | effect, *(p++)); +#ifdef USE_M17N + if (--len) { + mode = (mode & ~PC_WCHAR1) | PC_WCHAR2; + while (len--) { + PSIZE; + PPUSH(mode | effect, *(p++)); + } + } +#endif + } + } + } + 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_charset); + if (!idFrame || strcmp(idFrame->body->name, p)) { + idFrame = search_frame(renderFrameSet, p); + if (idFrame && idFrame->body->attr != F_BODY) + idFrame = NULL; + } + } + p = r = s = NULL; + q = buf->baseTarget; + t = ""; + hseq = 0; + id = NULL; + if (parsedtag_get_value(tag, ATTR_NAME, &id)) { + id = url_quote_conv(id, buf->document_charset); + registerName(buf, id, currentLn(buf), pos); + } + if (parsedtag_get_value(tag, ATTR_HREF, &p)) + p = url_quote_conv(remove_space(p), + buf->document_charset); + if (parsedtag_get_value(tag, ATTR_TARGET, &q)) + q = url_quote_conv(q, buf->document_charset); + if (parsedtag_get_value(tag, ATTR_REFERER, &r)) + r = url_quote_conv(r, buf->document_charset); + parsedtag_get_value(tag, ATTR_TITLE, &s); + parsedtag_get_value(tag, ATTR_ACCESSKEY, &t); + 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, NULL, '\0', + currentLn(buf), pos); + if (p) { + effect |= PE_ANCHOR; + a_href = registerHref(buf, p, q, r, s, + *t, currentLn(buf), pos); + a_href->hseq = ((hseq > 0) ? hseq : -hseq) - 1; + a_href->slave = (hseq > 0) ? FALSE : TRUE; + } + 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_LINK: + addLink(buf, tag); + 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 + s = NULL; + parsedtag_get_value(tag, ATTR_TITLE, &s); + p = url_quote_conv(remove_space(p), + buf->document_charset); + a_img = registerImg(buf, p, s, 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; + if (!uncompressed_file_type(u.file, &image->ext)) + image->ext = filename_extension(u.file, TRUE); + image->cache = NULL; + image->width = + (w > MAX_IMAGE_SIZE) ? MAX_IMAGE_SIZE : w; + image->height = + (h > MAX_IMAGE_SIZE) ? MAX_IMAGE_SIZE : 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 = url_quote_conv(remove_space(p), + buf->document_charset); + t = NULL; + parsedtag_get_value(tag, ATTR_TARGET, &t); + 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, t, 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 = url_quote_conv(remove_space(p), + buf->document_charset); + 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_charset); + break; + case HTML_META: + p = q = NULL; + parsedtag_get_value(tag, ATTR_HTTP_EQUIV, &p); + parsedtag_get_value(tag, ATTR_CONTENT, &q); + if (p && q && !strcasecmp(p, "refresh") && MetaRefresh) { + Str tmp = NULL; + int refresh_interval = getMetaRefreshParam(q, &tmp); +#ifdef USE_ALARM + if (tmp) { + p = url_quote_conv(remove_space(tmp->ptr), + buf->document_charset); + buf->event = setAlarmEvent(buf->event, + refresh_interval, + AL_IMPLICIT_ONCE, + FUNCNAME_gorURL, p); + } + else if (refresh_interval > 0) + buf->event = setAlarmEvent(buf->event, + refresh_interval, + AL_IMPLICIT, + FUNCNAME_reload, NULL); +#else + if (tmp && refresh_interval == 0) { + p = url_quote_conv(remove_space(tmp->ptr), + buf->document_charset); + pushEvent(FUNCNAME_gorURL, p); + } +#endif + } + 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; + case HTML_SYMBOL: + effect |= PC_SYMBOL; + if (parsedtag_get_value(tag, ATTR_TYPE, &p)) + symbol = (char)atoi(p); + break; + case HTML_N_SYMBOL: + effect &= ~PC_SYMBOL; + break; + } +#ifdef ID_EXT + id = NULL; + if (parsedtag_get_value(tag, ATTR_ID, &id)) { + id = url_quote_conv(id, buf->document_charset); + registerName(buf, id, currentLn(buf), pos); + } + if (renderFrameSet && + parsedtag_get_value(tag, ATTR_FRAMENAME, &p)) { + p = url_quote_conv(p, buf->document_charset); + 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, NULL, '\0', + currentLn(buf), pos); +#endif /* ID_EXT */ + } + } + /* end of processing for one line */ + if (!internal) + addnewline(buf, outc, outp, NULL, pos, -1, nlines); + if (internal == HTML_N_INTERNAL) + internal = 0; + if (str != endp) { + line = Strsubstr(line, str - line->ptr, endp - str); + goto proc_again; + } + } +#ifdef DEBUG + if (w3m_debug) + fclose(debug); +#endif + 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 +} + +static void +addLink(Buffer *buf, struct parsed_tag *tag) +{ + char *href = NULL, *title = NULL, *ctype = NULL, *rel = NULL, *rev = NULL; + char type = LINK_TYPE_NONE; + LinkList *l; + + parsedtag_get_value(tag, ATTR_HREF, &href); + if (href) + href = url_quote_conv(remove_space(href), buf->document_charset); + parsedtag_get_value(tag, ATTR_TITLE, &title); + parsedtag_get_value(tag, ATTR_TYPE, &ctype); + parsedtag_get_value(tag, ATTR_REL, &rel); + if (rel != NULL) { + /* forward link type */ + type = LINK_TYPE_REL; + if (title == NULL) + title = rel; + } + parsedtag_get_value(tag, ATTR_REV, &rev); + if (rev != NULL) { + /* reverse link type */ + type = LINK_TYPE_REV; + if (title == NULL) + title = rev; + } + + l = New(LinkList); + l->url = href; + l->title = title; + l->ctype = ctype; + l->type = type; + l->next = NULL; + if (buf->linklist) { + LinkList *i; + for (i = buf->linklist; i->next; i = i->next) ; + i->next = l; + } + else + buf->linklist = l; +} + +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 = PC_ASCII; + + 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; + + estr = conv_entity(ech); + check_breakpoint(obuf, obuf->flag & RB_SPECIAL, estr); + width = get_strwidth(estr); + if (width == 1 && ech == (unsigned char)*estr && + ech != '&' && ech != '<' && ech != '>') { + if (IS_CNTRL(ech)) + mode = PC_CTRL; + push_charp(obuf, width, estr, mode); + } + else + push_nchars(obuf, width, str, n_add, mode); + set_prevchar(obuf->prevchar, estr, strlen(estr)); + 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 *line, struct html_feed_environ *h_env, int internal) +{ + Lineprop mode; + 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; +#ifdef USE_M17N + int is_hangul, prev_is_hangul = 0; +#endif + +#ifdef DEBUG + 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_SCRIPT | RB_STYLE)) ? 'S' : ' '); + fprintf(f, "HTMLlineproc1(\"%s\",%d,%lx)\n", line, h_env->limit, + (unsigned long)h_env); + fclose(f); + } +#endif + + 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 (*line != '\0') { + char *str, *p; + int is_tag = FALSE; + int pre_mode = (obuf->table_level >= 0) ? tbl_mode->pre_mode : + obuf->flag; + int end_tag = (obuf->table_level >= 0) ? tbl_mode->end_tag : + obuf->end_tag; + + if (*line == '<' || obuf->status != R_ST_NORMAL) { + /* + * Tag processing + */ + if (obuf->status == R_ST_EOL) + obuf->status = R_ST_NORMAL; + else { + read_token(h_env->tagbuf, &line, &obuf->status, + pre_mode & RB_PREMODE, obuf->status != R_ST_NORMAL); + if (obuf->status != R_ST_NORMAL) + return; + } + if (h_env->tagbuf->length == 0) + continue; + str = h_env->tagbuf->ptr; + if (*str == '<') { + if (str[1] && REALLY_THE_BEGINNING_OF_A_TAG(str)) + is_tag = TRUE; + else if (!(pre_mode & (RB_PLAIN | RB_INTXTA | RB_INSELECT | + RB_SCRIPT | RB_STYLE | RB_TITLE))) { + line = Strnew_m_charp(str + 1, line, NULL)->ptr; + str = "<"; + } + } + } + else { + read_token(tokbuf, &line, &obuf->status, pre_mode & RB_PREMODE, 0); + if (obuf->status != R_ST_NORMAL) /* R_ST_AMP ? */ + obuf->status = R_ST_NORMAL; + str = tokbuf->ptr; + } + + if (pre_mode & (RB_PLAIN | RB_INTXTA | RB_INSELECT | RB_SCRIPT | + RB_STYLE | RB_TITLE)) { + if (is_tag) { + p = str; + if ((tag = parse_tag(&p, internal))) { + if (tag->tagid == end_tag || + (pre_mode & RB_INSELECT && tag->tagid == HTML_N_FORM) + || (pre_mode & RB_TITLE + && (tag->tagid == HTML_N_HEAD + || tag->tagid == HTML_BODY))) + goto proc_normal; + } + } + /* title */ + if (pre_mode & RB_TITLE) { + feed_title(str); + continue; + } + /* select */ + if (pre_mode & RB_INSELECT) { + if (obuf->table_level >= 0) + goto proc_normal; + feed_select(str); + continue; + } + if (is_tag) { + if (strncmp(str, "