aboutsummaryrefslogtreecommitdiffstats
path: root/file.c
diff options
context:
space:
mode:
authorAkinori Ito <aito@eie.yz.yamagata-u.ac.jp>2001-11-08 05:14:08 +0000
committerAkinori Ito <aito@eie.yz.yamagata-u.ac.jp>2001-11-08 05:14:08 +0000
commit68a07bf03b7624c9924065cce9ffa45497225834 (patch)
treec2adb06a909a8594445e4a3f8587c4bad46e3ecd /file.c
downloadw3m-68a07bf03b7624c9924065cce9ffa45497225834.tar.gz
w3m-68a07bf03b7624c9924065cce9ffa45497225834.zip
Initial revision
Diffstat (limited to '')
-rw-r--r--file.c6002
1 files changed, 6002 insertions, 0 deletions
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 <sys/types.h>
+#include "myctype.h"
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <time.h>
+#ifdef __EMX__
+#include <strings.h>
+#endif /* __EMX__ */
+#include <sys/stat.h>
+#include <fcntl.h>
+/* 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 <select> */
+FormSelectOption select_option[MAX_SELECT];
+static int n_select;
+static int cur_option_maxwidth;
+#endif /* MENU_SELECT */
+
+static Str cur_textarea;
+Str textarea_str[MAX_TEXTAREA];
+static int cur_textarea_size;
+static int cur_textarea_rows;
+static int n_textarea;
+
+static int http_response_code;
+
+#ifdef JP_CHARSET
+static char content_charset = '\0';
+static char guess_charset(char *p);
+#ifdef NEW_FORM
+static char check_charset(char *p);
+static char check_accept_charset(char *p);
+#endif
+char DocumentCode = '\0';
+#endif
+
+static Str save_line = NULL;
+static int save_prevchar = ' ';
+
+struct link_stack {
+ int cmd;
+ short offset;
+ short pos;
+ struct link_stack *next;
+};
+
+static struct link_stack *link_stack = NULL;
+
+#define FORMSTACK_SIZE 10
+#define FRAMESTACK_SIZE 10
+
+#ifdef USE_NNTP
+#define Str_news_endline(s) ((s)->ptr[0]=='.'&&((s)->ptr[1]=='\n'||(s)->ptr[1]=='\r'||(s)->ptr[1]=='\0'))
+#endif /* USE_NNTP */
+
+#ifdef NEW_FORM
+#define INITIAL_FORM_SIZE 10
+static FormList **forms;
+static int *form_stack;
+static int form_max = 0;
+static int forms_size = 0;
+#define cur_form_id ((form_sp >= 0)? form_stack[form_sp] : -1)
+#else /* not NEW_FORM */
+static FormList *form_stack[FORMSTACK_SIZE];
+#endif /* not NEW_FORM */
+static int form_sp = 0;
+
+static int current_content_length;
+
+static int cur_hseq;
+
+#define MAX_UL_LEVEL 9
+#ifdef KANJI_SYMBOLS
+char *ullevel[MAX_UL_LEVEL] =
+{
+ "¡¦", "¢¢", "¡ù", "¡û", "¢£", "¡ú", "¡ý", "¡ü", "¢¤"
+};
+#define HR_RULE "¨¬"
+#define HR_RULE_WIDTH 2
+#else /* not KANJI_SYMBOLS */
+char *ullevel[MAX_UL_LEVEL] =
+{
+ NBSP "*", NBSP "+", NBSP "o", NBSP "#", NBSP "@", NBSP "-",
+ NBSP "=", "**", "--"
+};
+#define HR_RULE "\212"
+#define HR_RULE_WIDTH 1
+#endif /* not KANJI_SYMBOLS */
+
+#ifdef USE_COOKIE
+/* This array should be somewhere else */
+char *violations[COO_EMAX] = {
+ "internal error",
+ "tail match failed",
+ "wrong number of dots",
+ "RFC 2109 4.3.2 rule 1",
+ "RFC 2109 4.3.2 rule 2.1",
+ "RFC 2109 4.3.2 rule 2.2",
+ "RFC 2109 4.3.2 rule 3",
+ "RFC 2109 4.3.2 rule 4",
+ "RFC XXXX 4.3.2 rule 5"
+};
+#endif
+
+#define SAVE_BUF_SIZE 1536
+
+#ifndef STRCHR
+char *
+strchr(char *s, char c)
+{
+ while (*s) {
+ if (*s == c)
+ return s;
+ s++;
+ }
+ return NULL;
+}
+#endif /* not STRCHR */
+
+static MySignalHandler
+KeyAbort(SIGNAL_ARG)
+{
+ LONGJMP(AbortLoading, 1);
+ SIGNAL_RETURN;
+}
+
+int
+currentLn(Buffer * buf)
+{
+ if (buf->currentLine)
+ return buf->currentLine->real_linenumber + 1;
+ else
+ return 1;
+}
+
+static Buffer *
+loadSomething(URLFile * f,
+ char *path,
+ Buffer * (*loadproc) (URLFile *, Buffer *),
+ Buffer * defaultbuf)
+{
+ Buffer *buf;
+
+ if ((buf = loadproc(f, defaultbuf)) == NULL)
+ return NULL;
+
+ buf->filename = path;
+ if (buf->buffername == NULL || buf->buffername[0] == '\0')
+ buf->buffername = lastFileName(path);
+ if (buf->currentURL.scheme == SCM_UNKNOWN)
+ buf->currentURL.scheme = f->scheme;
+ buf->real_scheme = f->scheme;
+ if (f->scheme == SCM_LOCAL && buf->sourcefile == NULL)
+ buf->sourcefile = path;
+ UFclose(f);
+ return buf;
+}
+
+int
+dir_exist(char *path)
+{
+ struct stat stbuf;
+
+ if (path == NULL || *path == '\0')
+ return 0;
+ if (stat(path, &stbuf) == -1)
+ return 0;
+ return IS_DIRECTORY(stbuf.st_mode);
+}
+
+static int
+is_dump_text_type(char *type)
+{
+ struct mailcap *mcap;
+ return (type && (mcap = searchExtViewer(type)) &&
+ (mcap->flags & (MAILCAP_HTMLOUTPUT|MAILCAP_COPIOUSOUTPUT)));
+}
+
+static int
+is_text_type(char *type)
+{
+ return (type == NULL || type[0] == '\0' ||
+ strncasecmp(type, "text/", 5) == 0);
+}
+
+static int
+is_plain_text_type(char *type)
+{
+ return ((type && strcasecmp(type, "text/plain") == 0) ||
+ (is_text_type(type) && !is_dump_text_type(type)));
+}
+
+static void
+check_compression(char *path, URLFile *uf)
+{
+ int len;
+
+ if (path == NULL)
+ return;
+
+ len = strlen(path);
+ uf->compression = CMP_NOCOMPRESS;
+ if (len > 2 && strcasecmp(&path[len - 2], ".Z") == 0) {
+ uf->compression = CMP_COMPRESS;
+ uf->guess_type = "application/x-compress";
+ }
+ else if (len > 3 && strcasecmp(&path[len - 3], ".gz") == 0) {
+ uf->compression = CMP_GZIP;
+ uf->guess_type = "application/x-gzip";
+ }
+ else if (len > 4 && strcasecmp(&path[len - 4], ".bz2") == 0) {
+ uf->compression = CMP_BZIP2;
+ uf->guess_type = "application/x-bzip";
+ }
+}
+
+static char *
+compress_application_type(int compression)
+{
+ switch (compression) {
+ case CMP_COMPRESS:
+ return "application/x-compress";
+ case CMP_GZIP:
+ return "application/x-gzip";
+ case CMP_BZIP2:
+ return "application/x-bzip";
+ case CMP_DEFLATE:
+ return "application/x-deflate";
+ default:
+ return NULL;
+ }
+}
+
+static char *
+uncompressed_file_type(char *path, char **ext)
+{
+ int len, slen;
+ Str fn;
+ char *t0;
+
+ if (path == NULL)
+ return NULL;
+
+ len = strlen(path);
+ if (len > 2 && strcasecmp(&path[len - 2], ".Z") == 0) {
+ slen = 2;
+ }
+ else if (len > 3 && strcasecmp(&path[len - 3], ".gz") == 0) {
+ slen = 3;
+ }
+ else if (len > 4 && strcasecmp(&path[len - 4], ".bz2") == 0) {
+ slen = 4;
+ }
+ else
+ return NULL;
+
+ fn = Strnew_charp(path);
+ Strshrink(fn, slen);
+ if (ext)
+ *ext = filename_extension(fn->ptr, 0);
+ t0 = guessContentType(fn->ptr);
+ if (t0 == NULL)
+ t0 = "text/plain";
+ return t0;
+}
+
+void
+examineFile(char *path, URLFile *uf)
+{
+ struct stat stbuf;
+
+ uf->guess_type = NULL;
+ if (path == NULL || *path == '\0' ||
+ stat(path, &stbuf) == -1 || NOT_REGULAR(stbuf.st_mode)) {
+ uf->stream = NULL;
+ return;
+ }
+ uf->stream = openIS(path);
+ if (!do_download) {
+ if (use_lessopen && getenv("LESSOPEN") != NULL) {
+ FILE *fp;
+ uf->guess_type = guessContentType(path);
+ if (uf->guess_type == NULL)
+ uf->guess_type = "text/plain";
+ if (strcasecmp(uf->guess_type, "text/html") == 0)
+ return;
+ if ((fp = lessopen_stream(path))) {
+ UFclose(uf);
+ uf->stream = newFileStream(fp, (void (*)()) pclose);
+ uf->guess_type = "text/plain";
+ return;
+ }
+ }
+ check_compression(path, uf);
+ if (uf->compression != CMP_NOCOMPRESS) {
+ char *ext = uf->ext;
+ char *t0 = uncompressed_file_type(path, &ext);
+ uf->guess_type = t0;
+ uf->ext = ext;
+ gunzip_stream(uf);
+ return;
+ }
+ }
+}
+
+/*
+ * convert line
+ */
+Str
+convertLine(URLFile * uf, Str line, char *code, int mode)
+{
+#ifdef JP_CHARSET
+ char ic;
+ if ((ic = checkShiftCode(line, *code)) != '\0')
+ line = conv_str(line, (*code = ic), InnerCode);
+#endif /* JP_CHARSET */
+ cleanup_line(line, mode);
+#ifdef USE_NNTP
+ if (uf->scheme == SCM_NEWS)
+ Strchop(line);
+#endif /* USE_NNTP */
+ return line;
+}
+
+/*
+ * loadFile: load file to buffer
+ */
+Buffer *
+loadFile(char *path)
+{
+ URLFile uf;
+ init_stream(&uf, SCM_LOCAL, NULL);
+ examineFile(path, &uf);
+ if (uf.stream == NULL)
+ return NULL;
+ current_content_length = 0;
+ return loadSomething(&uf, path, loadBuffer, NULL);
+}
+
+#ifdef USE_COOKIE
+static int
+matchattr(char *p, char *attr, int len, Str * value)
+{
+ int quoted;
+ char *q = NULL;
+
+ if (strncasecmp(p, attr, len) == 0) {
+ p += len;
+ SKIP_BLANKS(p);
+ if (value) {
+ *value = Strnew();
+ if (*p == '=') {
+ p++;
+ SKIP_BLANKS(p);
+ quoted = 0;
+ while (!IS_ENDL(*p) && (quoted || *p != ';')) {
+ if (!IS_SPACE(*p))
+ q = p;
+ if (*p == '"')
+ quoted = (quoted) ? 0 : 1;
+ else
+ Strcat_char(*value, *p);
+ p++;
+ }
+ if (q)
+ Strshrink(*value, p - q - 1);
+ }
+ return 1;
+ }
+ else {
+ if (IS_ENDT(*p)) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+#endif /* USE_COOKIE */
+
+void
+readHeader(URLFile * uf,
+ Buffer * newBuf,
+ int thru,
+ ParsedURL * pu)
+{
+ char *p, *q, *emsg;
+ char c;
+ Str lineBuf2 = NULL;
+ Str tmp;
+ TextList *headerlist;
+#ifdef JP_CHARSET
+ char code = DocumentCode, ic;
+#endif
+ extern int w3m_dump_head;
+
+ headerlist = newBuf->document_header = newTextList();
+ if (uf->scheme == SCM_HTTP
+#ifdef USE_SSL
+ || uf->scheme == SCM_HTTPS
+#endif /* USE_SSL */
+ )
+ http_response_code = -1;
+ else
+ http_response_code = 0;
+
+ while ((tmp = StrmyUFgets(uf))->length) {
+#ifdef HTTP_DEBUG
+ {
+ FILE *ff;
+ ff = fopen("zzrequest", "a");
+ Strfputs(tmp, ff);
+ fclose(ff);
+ }
+#endif /* HTTP_DEBUG */
+ cleanup_line(tmp, HEADER_MODE);
+ if ((tmp->ptr[0] == '\n' ||
+ tmp->ptr[0] == '\r' ||
+ tmp->ptr[0] == '\0')
+#ifdef USE_NNTP
+ ||
+ (uf->scheme == SCM_NEWS &&
+ Str_news_endline(tmp) &&
+ (iseos(uf->stream) = TRUE))
+#endif /* USE_NNTP */
+ ) {
+ if (!lineBuf2)
+ /* there is no header */
+ break;
+ /* last header */
+ }
+ else if (!w3m_dump_head) {
+ if (lineBuf2) {
+ Strcat(lineBuf2, tmp);
+ }
+ else {
+ lineBuf2 = tmp;
+ }
+ c = UFgetc(uf);
+ UFundogetc(uf);
+ if (c == ' ' || c == '\t')
+ /* header line is continued */
+ continue;
+ lineBuf2 = decodeMIME(lineBuf2->ptr);
+#ifdef JP_CHARSET
+ if ((ic = checkShiftCode(lineBuf2, code)) != '\0')
+ lineBuf2 = conv_str(lineBuf2, (code = ic), InnerCode);
+#endif /* JP_CHARSET */
+ /* separated with line and stored */
+ tmp = Strnew_size(lineBuf2->length);
+ for (p = lineBuf2->ptr; *p; p = q) {
+ for (q = p; *q && *q != '\r' && *q != '\n'; q++);
+ lineBuf2 = checkType(Strnew_charp(p), propBuffer,
+#ifdef ANSI_COLOR
+ NULL, NULL,
+#endif
+ min(LINELEN, q - p));
+ Strcat(tmp, lineBuf2);
+ if (thru)
+ addnewline(newBuf, lineBuf2->ptr, propBuffer,
+#ifdef ANSI_COLOR
+ NULL,
+#endif
+ lineBuf2->length, -1);
+ for (; *q && (*q == '\r' || *q == '\n'); q++);
+ }
+ lineBuf2 = tmp;
+ }
+ else {
+ lineBuf2 = tmp;
+ }
+ if ((uf->scheme == SCM_HTTP
+#ifdef USE_SSL
+ || uf->scheme == SCM_HTTPS
+#endif /* USE_SSL */
+ ) && http_response_code == -1) {
+ p = lineBuf2->ptr;
+ while (*p && !IS_SPACE(*p))
+ p++;
+ while (*p && IS_SPACE(*p))
+ p++;
+ http_response_code = atoi(p);
+ if (fmInitialized) {
+ message(lineBuf2->ptr, 0, 0);
+ refresh();
+ }
+ }
+ if (!strncasecmp(lineBuf2->ptr, "content-transfer-encoding:", 26)) {
+ p = lineBuf2->ptr + 26;
+ while (IS_SPACE(*p))
+ p++;
+ if (!strncasecmp(p, "base64", 6))
+ uf->encoding = ENC_BASE64;
+ else if (!strncasecmp(p, "quoted-printable", 16))
+ uf->encoding = ENC_QUOTE;
+ else
+ uf->encoding = ENC_7BIT;
+ }
+ else if (!strncasecmp(lineBuf2->ptr, "content-encoding:", 17)) {
+ p = lineBuf2->ptr + 17;
+ while (IS_SPACE(*p))
+ p++;
+ if ((!strncasecmp(p, "x-gzip", 6) || !strncasecmp(p, "gzip", 4)) ||
+ (!strncasecmp(p, "x-compress", 10) || !strncasecmp(p, "compress", 8))) {
+ uf->compression = CMP_GZIP;
+ }
+ else if (!strncasecmp(p, "x-bzip", 6) ||
+ !strncasecmp(p, "bzip", 4) ||
+ !strncasecmp(p, "bzip2", 5)) {
+ uf->compression = CMP_BZIP2;
+ }
+ else if (!strncasecmp(p, "x-deflate", 9) ||
+ !strncasecmp(p, "deflate", 7)) {
+ uf->compression = CMP_DEFLATE;
+ }
+ }
+#ifdef USE_COOKIE
+ else if (use_cookie && accept_cookie &&
+ pu && check_cookie_accept_domain(pu->host) &&
+ (!strncasecmp(lineBuf2->ptr, "Set-Cookie:", 11) ||
+ !strncasecmp(lineBuf2->ptr, "Set-Cookie2:", 12))) {
+ Str name = Strnew(), value = Strnew(), domain = NULL, path = NULL,
+ comment = NULL, commentURL = NULL, port = NULL, tmp;
+ int version, quoted, flag = 0;
+ time_t expires = (time_t) - 1;
+
+ q = NULL;
+ if (lineBuf2->ptr[10] == '2') {
+ p = lineBuf2->ptr + 12;
+ version = 1;
+ }
+ else {
+ p = lineBuf2->ptr + 11;
+ version = 0;
+ }
+#ifdef DEBUG
+ fprintf(stderr, "Set-Cookie: [%s]\n", p);
+#endif /* DEBUG */
+ SKIP_BLANKS(p);
+ while (*p != '=' && !IS_ENDT(*p))
+ Strcat_char(name, *(p++));
+ Strremovetrailingspaces(name);
+ if (*p == '=') {
+ p++;
+ SKIP_BLANKS(p);
+ quoted = 0;
+ while (!IS_ENDL(*p) && (quoted || *p != ';')) {
+ if (!IS_SPACE(*p))
+ q = p;
+ if (*p == '"')
+ quoted = (quoted) ? 0 : 1;
+ Strcat_char(value, *(p++));
+ }
+ if (q)
+ Strshrink(value, p - q - 1);
+ }
+ while (*p == ';') {
+ p++;
+ SKIP_BLANKS(p);
+ if (matchattr(p, "expires", 7, &tmp)) {
+ /* version 0 */
+ expires = mymktime(tmp->ptr);
+ }
+ else if (matchattr(p, "max-age", 7, &tmp)) {
+ /* XXX Is there any problem with max-age=0? (RFC 2109 ss. 4.2.1, 4.2.2 */
+ expires = time(NULL) + atol(tmp->ptr);
+ }
+ else if (matchattr(p, "domain", 6, &tmp)) {
+ domain = tmp;
+ }
+ else if (matchattr(p, "path", 4, &tmp)) {
+ path = tmp;
+ }
+ else if (matchattr(p, "secure", 6, NULL)) {
+ flag |= COO_SECURE;
+ }
+ else if (matchattr(p, "comment", 7, &tmp)) {
+ comment = tmp;
+ }
+ else if (matchattr(p, "version", 7, &tmp)) {
+ version = atoi(tmp->ptr);
+ }
+ else if (matchattr(p, "port", 4, &tmp)) {
+ /* version 1, Set-Cookie2 */
+ port = tmp;
+ }
+ else if (matchattr(p, "commentURL", 10, &tmp)) {
+ /* version 1, Set-Cookie2 */
+ commentURL = tmp;
+ }
+ else if (matchattr(p, "discard", 7, NULL)) {
+ /* version 1, Set-Cookie2 */
+ flag |= COO_DISCARD;
+ }
+ quoted = 0;
+ while (!IS_ENDL(*p) && (quoted || *p != ';')) {
+ if (*p == '"')
+ quoted = (quoted) ? 0 : 1;
+ p++;
+ }
+ }
+ if (pu && name->length > 0) {
+ int err;
+ if (flag & COO_SECURE)
+ disp_message_nsec("Received a secured cookie", FALSE, 1, TRUE, FALSE);
+ else
+ disp_message_nsec(Sprintf("Received cookie: %s=%s",
+ name->ptr, value->ptr)->ptr, FALSE, 1, TRUE, FALSE);
+ err = add_cookie(pu, name, value, expires, domain, path, flag,
+ comment, version, port, commentURL);
+ if (err) {
+ char *ans = (accept_bad_cookie == TRUE) ? "y" : NULL;
+ if (fmInitialized && (err & COO_OVERRIDE_OK) &&
+ accept_bad_cookie == PERHAPS) {
+ Str msg = Sprintf("Accept bad cookie from %s for %s? (y or n) ",
+ pu->host, domain->ptr);
+ if (msg->length > COLS - 4)
+ Strshrink(msg, msg->length - (COLS - 4));
+ term_raw();
+ ans = inputStr(msg->ptr, FALSE);
+ }
+ if (ans == NULL || tolower(*ans) != 'y' ||
+ (err = add_cookie(pu, name, value, expires, domain, path,
+ flag | COO_OVERRIDE,
+ comment, version, port, commentURL))) {
+ err = (err & ~COO_OVERRIDE_OK) - 1;
+ if (err >= 0 && err < COO_EMAX)
+ emsg = Sprintf("This cookie was rejected "
+ "to prevent security violation. [%s]",
+ violations[err])->ptr;
+ else
+ emsg = "This cookie was rejected to prevent security violation.";
+ record_err_message(emsg);
+ disp_message_nsec(emsg, FALSE, 10, TRUE, FALSE);
+ } else
+ disp_message_nsec(Sprintf("Accepting invalid cookie: %s=%s",
+ name->ptr,value->ptr)->ptr, FALSE, 1, TRUE, FALSE);
+ }
+ }
+ }
+#endif /* USE_COOKIE */
+ else if (!strncasecmp(lineBuf2->ptr, "w3m-control:", 12) &&
+ uf->scheme == SCM_LOCAL_CGI) {
+ Str funcname = Strnew();
+ int f;
+ extern int w3mNFuncList;
+
+ p = lineBuf2->ptr + 12;
+ SKIP_BLANKS(p);
+ while (*p && !IS_SPACE(*p))
+ Strcat_char(funcname, *(p++));
+ SKIP_BLANKS(p);
+ f = getFuncList(funcname->ptr, w3mFuncList, w3mNFuncList);
+ if (f >= 0) {
+ tmp = Strnew_charp(p);
+ Strchop(tmp);
+ pushEvent(f, tmp->ptr);
+ }
+ }
+ if (headerlist)
+ pushText(headerlist, lineBuf2->ptr);
+ Strfree(lineBuf2);
+ lineBuf2 = NULL;
+ }
+ if (thru)
+ addnewline(newBuf, "", propBuffer,
+#ifdef ANSI_COLOR
+ NULL,
+#endif
+ 0, -1);
+}
+
+char *
+checkHeader(Buffer * buf, char *field)
+{
+ int len = strlen(field);
+ TextListItem *i;
+ char *p;
+
+ if (buf == NULL || field == NULL)
+ return NULL;
+ for (i = buf->document_header->first; i != NULL; i = i->next) {
+ if (!strncasecmp(i->ptr, field, len)) {
+ p = i->ptr + len;
+ SKIP_BLANKS(p);
+ return p;
+ }
+ }
+ return NULL;
+}
+
+char *
+checkContentType(Buffer * buf)
+{
+ char *p;
+ Str r;
+ p = checkHeader(buf, "Content-Type:");
+ if (p == NULL)
+ return NULL;
+ r = Strnew();
+ while (*p && *p != ';' && !IS_SPACE(*p))
+ Strcat_char(r, *p++);
+#ifdef JP_CHARSET
+ content_charset = '\0';
+ if ((p = strcasestr(p, "charset")) != NULL) {
+ p += 7;
+ SKIP_BLANKS(p);
+ if (*p == '=') {
+ p++;
+ SKIP_BLANKS(p);
+ content_charset = guess_charset(p);
+ }
+ }
+#endif
+ return r->ptr;
+}
+
+static Str
+extractRealm(char *q)
+{
+ Str p = Strnew();
+ char c;
+
+ SKIP_BLANKS(q);
+ if (strncasecmp(q, "Basic ", 6) != 0) {
+ /* complicated authentication... not implemented */
+ return NULL;
+ }
+ q += 6;
+ SKIP_BLANKS(q);
+ if (strncasecmp(q, "realm=", 6) != 0) {
+ /* no realm attribute... get confused */
+ return NULL;
+ }
+ q += 6;
+ SKIP_BLANKS(q);
+ c = '\0';
+ if (*q == '"')
+ c = *q++;
+ while (*q != '\0' && *q != c)
+ Strcat_char(p, *q++);
+ return p;
+}
+
+static Str
+getAuthCookie(char *realm, char *auth_header, TextList * extra_header, ParsedURL * pu)
+{
+ Str ss;
+ Str uname, pwd;
+ Str tmp;
+ TextListItem *i, **i0;
+ int a_found;
+ int auth_header_len = strlen(auth_header);
+
+ a_found = FALSE;
+ for (i0 = &(extra_header->first), i = *i0; i != NULL; i0 = &(i->next), i = *i0) {
+ if (!strncasecmp(i->ptr, auth_header, auth_header_len)) {
+ a_found = TRUE;
+ break;
+ }
+ }
+ if (a_found) {
+ /* This means that *-Authenticate: header is received after *
+ * Authorization: header is sent to the server. */
+ if (fmInitialized) {
+ message("Wrong username or password", 0, 0);
+ refresh();
+ }
+ else
+ fprintf(stderr, "Wrong username or password\n");
+ sleep(1);
+ ss = NULL;
+ *i0 = i->next; /* delete Authenticate: header from *
+ * extra_header */
+ }
+ else
+ ss = find_auth_cookie(pu->host, realm);
+ if (ss == NULL) {
+ /* input username and password */
+ sleep(2);
+ if (fmInitialized) {
+ char *pp;
+ term_raw();
+ if ((pp = inputStr(Sprintf("Username for %s: ", realm)->ptr, NULL)) == NULL)
+ return NULL;
+ uname = Strnew_charp(pp);
+ if ((pp = inputLine(Sprintf("Password for %s: ", realm)->ptr, NULL, IN_PASSWORD)) == NULL)
+ return NULL;
+ pwd = Strnew_charp(pp);
+ term_cbreak();
+ }
+ else {
+ printf("Username: ");
+ fflush(stdout);
+ uname = Strfgets(stdin);
+ Strchop(uname);
+ pwd = Strnew_charp((char *) getpass("Password: "));
+ }
+ Strcat_char(uname, ':');
+ Strcat(uname, pwd);
+ ss = encodeB(uname->ptr);
+ }
+ tmp = Strnew_charp(auth_header);
+ Strcat_charp(tmp, " Basic ");
+ Strcat(tmp, ss);
+ Strcat_charp(tmp, "\r\n");
+ pushText(extra_header, tmp->ptr);
+ return ss;
+}
+
+/*
+ * loadGeneralFile: load file to buffer
+ */
+Buffer *
+loadGeneralFile(char *path, ParsedURL * current, char *referer, int flag, FormList * request)
+{
+ URLFile f, *of = NULL;
+ ParsedURL pu;
+ Buffer *b = NULL, *(*proc) ();
+ char *tpath;
+ char *t, *p, *real_type = NULL;
+ Buffer *t_buf = NULL;
+ int searchHeader = SearchHeader;
+ int searchHeader_through = TRUE;
+ MySignalHandler(*prevtrap) ();
+ TextList *extra_header = newTextList();
+ Str ss;
+ Str realm;
+ int add_auth_cookie_flag;
+ unsigned char status = HTST_NORMAL;
+ URLOption url_option;
+ Str tmp;
+ extern int w3m_dump, w3m_dump_source;
+
+ tpath = path;
+ prevtrap = NULL;
+ add_auth_cookie_flag = 0;
+
+ if (proxy_auth_cookie != NULL) {
+ pushText(extra_header, Sprintf("Proxy-Authorization: Basic %s\r\n",
+ proxy_auth_cookie->ptr)->ptr);
+ }
+ load_doc:
+ url_option.referer = referer;
+ url_option.flag = flag;
+ f = openURL(tpath, &pu, current, &url_option, request, extra_header, of, &status);
+ of = NULL;
+#ifdef JP_CHARSET
+ content_charset = '\0';
+#endif
+ if (f.stream == NULL) {
+ /* openURL failure: it means either (1) the requested URL is a directory name
+ * on an FTP server, or (2) is a local directory name.
+ */
+ extern Str FTPDIRtmp;
+ if (fmInitialized && prevtrap) {
+ term_raw();
+ signal(SIGINT, prevtrap);
+ }
+ switch (f.scheme) {
+ case SCM_FTPDIR:
+ if (FTPDIRtmp->length > 0) {
+ b = loadHTMLString(FTPDIRtmp);
+ if (b) {
+ if (b->currentURL.host == NULL && b->currentURL.file == NULL)
+ copyParsedURL(&b->currentURL, &pu);
+ b->real_scheme = pu.scheme;
+ }
+ return b;
+ }
+ break;
+ case SCM_LOCAL:
+ {
+ struct stat st;
+ if (stat(pu.file, &st) < 0)
+ return NULL;
+ if (S_ISDIR(st.st_mode)) {
+ if (UseExternalDirBuffer) {
+ Str tmp = Strnew_charp(DirBufferCommand);
+ Strcat_m_charp(tmp, "?",
+ pu.file,
+ "#current",
+ NULL);
+ b = loadGeneralFile(tmp->ptr, NULL, NO_REFERER, 0, NULL);
+ if (b != NULL && b != NO_BUFFER) {
+ copyParsedURL(&b->currentURL, &pu);
+ b->filename = b->currentURL.file;
+ }
+ return b;
+ }
+ else {
+ b = dirBuffer(pu.file);
+ if (b == NULL)
+ return NULL;
+ t = "text/html";
+ b->real_scheme = pu.scheme;
+ goto loaded;
+ }
+ }
+ }
+ }
+ return NULL;
+ }
+
+ /* openURL() succeeded */
+ if (SETJMP(AbortLoading) != 0) {
+ /* transfer interrupted */
+ if (fmInitialized) {
+ term_raw();
+ signal(SIGINT, prevtrap);
+ }
+ if (b)
+ discardBuffer(b);
+ UFclose(&f);
+ return NULL;
+ }
+
+ b = NULL;
+ if (f.is_cgi) {
+ /* local CGI */
+ searchHeader = TRUE;
+ searchHeader_through = FALSE;
+ }
+ if (fmInitialized) {
+ prevtrap = signal(SIGINT, KeyAbort);
+ term_cbreak();
+ }
+ if (pu.scheme == SCM_HTTP ||
+#ifdef USE_SSL
+ pu.scheme == SCM_HTTPS ||
+#endif /* USE_SSL */
+ ((
+#ifdef USE_GOPHER
+ (pu.scheme == SCM_GOPHER && non_null(GOPHER_proxy)) ||
+#endif /* USE_GOPHER */
+ (pu.scheme == SCM_FTP && non_null(FTP_proxy))
+ ) && !Do_not_use_proxy && !check_no_proxy(pu.host))) {
+
+ if (fmInitialized) {
+ message(Sprintf("%s contacted. Waiting for reply...", pu.host)->ptr, 0, 0);
+ refresh();
+ }
+ if (t_buf == NULL)
+ t_buf = newBuffer(INIT_BUFFER_WIDTH);
+#ifdef USE_SSL
+ if (IStype(f.stream) == IST_SSL) {
+ Str s = ssl_get_certificate(f.stream);
+ if (s != NULL)
+ t_buf->ssl_certificate = s->ptr;
+ }
+#endif
+ readHeader(&f, t_buf, FALSE, &pu);
+ t = checkContentType(t_buf);
+ if (t == NULL)
+ t = "text/plain";
+ if (http_response_code >= 301 && http_response_code <= 303 && (p = checkHeader(t_buf, "Location:")) != NULL) {
+ /* document moved */
+ tmp = Strnew_charp(p);
+ Strchop(tmp);
+ tpath = tmp->ptr;
+ request = NULL;
+ UFclose(&f);
+ add_auth_cookie_flag = 0;
+ current = New(ParsedURL);
+ copyParsedURL(current, &pu);
+ t_buf->bufferprop |= BP_REDIRECTED;
+ status = HTST_NORMAL;
+ goto load_doc;
+ }
+ if ((p = checkHeader(t_buf, "WWW-Authenticate:")) != NULL &&
+ http_response_code == 401) {
+ /* Authentication needed */
+ realm = extractRealm(p);
+ if (realm != NULL) {
+ ss = getAuthCookie(realm->ptr, "Authorization:", extra_header, &pu);
+ if (ss == NULL) {
+ /* abort */
+ UFclose(&f);
+ signal(SIGINT, prevtrap);
+ return NULL;
+ }
+ UFclose(&f);
+ add_auth_cookie_flag = 1;
+ status = HTST_NORMAL;
+ goto load_doc;
+ }
+ }
+ if ((p = checkHeader(t_buf, "Proxy-Authenticate:")) != NULL &&
+ http_response_code == 407) {
+ /* Authentication needed */
+ realm = extractRealm(p);
+ if (realm != NULL) {
+ ss = getAuthCookie(realm->ptr,
+ "Proxy-Authorization:",
+ extra_header,
+ &HTTP_proxy_parsed);
+ proxy_auth_cookie = ss;
+ if (ss == NULL) {
+ /* abort */
+ UFclose(&f);
+ signal(SIGINT, prevtrap);
+ return NULL;
+ }
+ UFclose(&f);
+ status = HTST_NORMAL;
+ goto load_doc;
+ }
+ }
+ if (add_auth_cookie_flag)
+ /* If authorization is required and passed */
+ add_auth_cookie(pu.host, realm->ptr, ss);
+ if (status == HTST_CONNECT) {
+ of = &f;
+ goto load_doc;
+ }
+ }
+#ifdef USE_NNTP
+ else if (pu.scheme == SCM_NEWS) {
+ t_buf = newBuffer(INIT_BUFFER_WIDTH);
+ readHeader(&f, t_buf, TRUE, &pu);
+ t = checkContentType(t_buf);
+ if (t == NULL)
+ t = "text/plain";
+ }
+#endif /* USE_NNTP */
+#ifdef USE_GOPHER
+ else if (pu.scheme == SCM_GOPHER) {
+ switch (*pu.file) {
+ case '0':
+ t = "text/plain";
+ break;
+ case '1':
+ t = "gopher:directory";
+ break;
+ case 'm':
+ t = "gopher:directory";
+ break;
+ case 's':
+ t = "audio/basic";
+ break;
+ case 'g':
+ t = "image/gif";
+ break;
+ case 'h':
+ t = "text/html";
+ break;
+ }
+ }
+#endif /* USE_GOPHER */
+ else if (pu.scheme == SCM_FTP) {
+ check_compression(path, &f);
+ if (f.compression != CMP_NOCOMPRESS) {
+ char *t1 = uncompressed_file_type(pu.file, NULL);
+ real_type = f.guess_type;
+ if (t1 && strncasecmp(t1, "application/", 12) == 0) {
+ f.compression = CMP_NOCOMPRESS;
+ t = real_type;
+ }
+ else if (t1)
+ t = t1;
+ else
+ t = real_type;
+ }
+ else {
+ real_type = guessContentType(pu.file);
+ if (real_type == NULL)
+ real_type = "text/plain";
+ t = real_type;
+ }
+ if (!strncasecmp(t, "application/", 12)) {
+ char *tmpf = tmpfname(TMPF_DFL, NULL)->ptr;
+ current_content_length = 0;
+ if (save2tmp(f, tmpf) < 0)
+ UFclose(&f);
+ else {
+ if (fmInitialized) {
+ term_raw();
+ signal(SIGINT, prevtrap);
+ }
+ doFileMove(tmpf, guess_save_name(pu.file));
+ }
+ return NO_BUFFER;
+ }
+ }
+ else if (searchHeader) {
+ t_buf = newBuffer(INIT_BUFFER_WIDTH);
+ readHeader(&f, t_buf, searchHeader_through, &pu);
+ t = checkContentType(t_buf);
+ if (t == NULL)
+ t = "text/plain";
+ if (f.is_cgi && (p = checkHeader(t_buf, "Location:")) != NULL) {
+ /* document moved */
+ tmp = Strnew_charp(p);
+ Strchop(tmp);
+ tpath = tmp->ptr;
+ request = NULL;
+ UFclose(&f);
+ add_auth_cookie_flag = 0;
+ current = New(ParsedURL);
+ copyParsedURL(current, &pu);
+ t_buf->bufferprop |= BP_REDIRECTED;
+ status = HTST_NORMAL;
+ goto load_doc;
+ }
+ searchHeader = SearchHeader = FALSE;
+ }
+ else if (DefaultType) {
+ t = DefaultType;
+ DefaultType = NULL;
+ }
+ else {
+ t = guessContentType(pu.file);
+ if (t == NULL)
+ t = "text/plain";
+ real_type = t;
+ if (f.guess_type)
+ t = f.guess_type;
+ }
+ if (real_type == NULL)
+ real_type = t;
+ proc = loadBuffer;
+
+ if (do_download) {
+ /* download only */
+ if (fmInitialized) {
+ term_raw();
+ signal(SIGINT, prevtrap);
+ }
+ doFileSave(f, guess_save_name(pu.file));
+ UFclose(&f);
+ return NO_BUFFER;
+ }
+
+ if (f.compression != CMP_NOCOMPRESS) {
+ if (!w3m_dump_source &&
+ (w3m_dump || is_text_type(t) || searchExtViewer(t))) {
+ gunzip_stream(&f);
+ uncompressed_file_type(pu.file, &f.ext);
+ }
+ else {
+ t = compress_application_type(f.compression);
+ f.compression = CMP_NOCOMPRESS;
+ }
+ }
+
+ if (!strcasecmp(t, "text/html"))
+ proc = loadHTMLBuffer;
+ else if (is_plain_text_type(t))
+ proc = loadBuffer;
+#ifdef USE_GOPHER
+ else if (!strcasecmp(t, "gopher:directory")) {
+ proc = loadGopherDir;
+ }
+#endif /* USE_GOPHER */
+ else if (w3m_backend) ;
+ else if (!w3m_dump || is_dump_text_type(t)) {
+ if (!do_download && doExternal(f, pu.file, t, &b, t_buf)) {
+ if (b && b != NO_BUFFER) {
+ b->real_scheme = f.scheme;
+ b->real_type = real_type;
+ if (b->currentURL.host == NULL && b->currentURL.file == NULL)
+ copyParsedURL(&b->currentURL, &pu);
+ }
+ UFclose(&f);
+ if (fmInitialized) {
+ term_raw();
+ signal(SIGINT, prevtrap);
+ }
+ return b;
+ }
+ else {
+ if (fmInitialized) {
+ term_raw();
+ signal(SIGINT, prevtrap);
+ }
+ if (pu.scheme == SCM_LOCAL) {
+ UFclose(&f);
+ doFileCopy(pu.file, guess_save_name(pu.file));
+ }
+ else {
+ doFileSave(f, guess_save_name(pu.file));
+ UFclose(&f);
+ }
+ return NO_BUFFER;
+ }
+ }
+
+ current_content_length = 0;
+ if ((p = checkHeader(t_buf, "Content-Length:")) != NULL)
+ current_content_length = atoi(p);
+
+ if (flag & RG_FRAME) {
+ t_buf = newBuffer(INIT_BUFFER_WIDTH);
+ t_buf->bufferprop |= BP_FRAME;
+ }
+#ifdef USE_SSL
+ if (IStype(f.stream) == IST_SSL) {
+ Str s = ssl_get_certificate(f.stream);
+ if (s != NULL)
+ t_buf->ssl_certificate = s->ptr;
+ }
+#endif
+ b = loadSomething(&f, pu.file, proc, t_buf);
+ UFclose(&f);
+ if (b) {
+ b->real_scheme = f.scheme;
+ b->real_type = real_type;
+ loaded:
+ if (b->currentURL.host == NULL && b->currentURL.file == NULL)
+ copyParsedURL(&b->currentURL, &pu);
+ if (!strcmp(t, "text/html"))
+ b->type = "text/html";
+ else if (w3m_backend) {
+ Str s = Strnew_charp(t);
+ b->type = s->ptr;
+ }
+ else
+ b->type = "text/plain";
+ if (pu.label) {
+ if (proc == loadHTMLBuffer) {
+ Anchor *a;
+#ifdef JP_CHARSET
+ a = searchURLLabel(b, conv(pu.label, b->document_code, InnerCode)->ptr);
+#else /* not JP_CHARSET */
+ a = searchURLLabel(b, pu.label);
+#endif /* not JP_CHARSET */
+ if (a != NULL) {
+ gotoLine(b, a->start.line);
+ b->pos = a->start.pos;
+ arrangeCursor(b);
+ }
+ }
+ else { /* plain text */
+ int l = atoi(pu.label);
+ gotoLine(b,l);
+ b->pos = 0;
+ arrangeCursor(b);
+ }
+ }
+ }
+ if (fmInitialized) {
+ term_raw();
+ signal(SIGINT, prevtrap);
+ }
+ return b;
+}
+
+#define TAG_IS(s,tag,len)\
+ (strncasecmp(s,tag,len)==0&&(s[len] == '>' || IS_SPACE((int)s[len])))
+
+static char *
+has_hidden_link(struct readbuffer *obuf, int cmd)
+{
+ Str line = obuf->line;
+ struct link_stack *p;
+
+ if (Strlastchar(line) != '>')
+ return NULL;
+
+ for (p = link_stack; p; p = p->next)
+ if (p->cmd == cmd)
+ break;
+ if (!p)
+ return NULL;
+
+ if (obuf->pos == p->pos)
+ return line->ptr + p->offset;
+
+ return NULL;
+}
+
+static void
+push_link(int cmd, int offset, int pos)
+{
+ struct link_stack *p;
+ p = New(struct link_stack);
+ p->cmd = cmd;
+ p->offset = offset;
+ p->pos = pos;
+ p->next = link_stack;
+ link_stack = p;
+}
+
+static int
+is_period_char(int ch)
+{
+ switch (ch) {
+ case ',':
+ case '.':
+ case ':':
+ case ';':
+ case '?':
+ case '!':
+ case ')':
+ case ']':
+ case '}':
+ case '>':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int
+is_beginning_char(int ch)
+{
+ switch (ch) {
+ case '(':
+ case '[':
+ case '{':
+ case '`':
+ case '<':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int
+is_word_char(int ch)
+{
+#ifdef JP_CHARSET
+ if (is_wckanji(ch) || IS_CNTRL(ch))
+ return 0;
+#else
+ if (IS_CNTRL(ch))
+ return 0;
+#endif
+
+ if (IS_ALNUM(ch))
+ return 1;
+
+ switch (ch) {
+ case ',':
+ case '.':
+ case '\"': /* " */
+ case '\'':
+ case '$':
+ case '%':
+ case '+':
+ case '-':
+ case '@':
+ case '~':
+ case '_':
+ return 1;
+ }
+ if (ch == TIMES_CODE || ch == DIVIDE_CODE || ch == ANSP_CODE)
+ return 0;
+ if (ch >= AGRAVE_CODE || ch == NBSP_CODE)
+ return 1;
+ return 0;
+}
+
+int
+is_boundary(int ch1, int ch2)
+{
+ if (!ch1 || !ch2)
+ return 1;
+
+ if (ch1 == ' ' && ch2 == ' ')
+ return 0;
+
+ if (ch1 != ' ' && is_period_char(ch2))
+ return 0;
+
+ if (ch2 != ' ' && is_beginning_char(ch1))
+ return 0;
+
+ if (is_word_char(ch1) && is_word_char(ch2))
+ return 0;
+
+ return 1;
+}
+
+
+static void
+set_breakpoint(struct readbuffer *obuf, int tag_length)
+{
+ obuf->bp.len = obuf->line->length;
+ obuf->bp.pos = obuf->pos;
+ obuf->bp.tlen = tag_length;
+ obuf->bp.flag = obuf->flag;
+#ifdef FORMAT_NICE
+ obuf->bp.flag &= ~RB_FILL;
+#endif /* FORMAT_NICE */
+
+ if (!obuf->bp.init_flag)
+ return;
+
+ obuf->bp.anchor = obuf->anchor;
+ obuf->bp.anchor_target = obuf->anchor_target;
+ obuf->bp.anchor_hseq = obuf->anchor_hseq;
+ obuf->bp.img_alt = obuf->img_alt;
+ obuf->bp.in_bold = obuf->in_bold;
+ obuf->bp.in_under = obuf->in_under;
+ obuf->bp.nobr_level = obuf->nobr_level;
+ obuf->bp.prev_ctype = obuf->prev_ctype;
+ obuf->bp.init_flag = 0;
+}
+
+static void
+back_to_breakpoint(struct readbuffer *obuf)
+{
+ obuf->flag = obuf->bp.flag;
+ obuf->anchor = obuf->bp.anchor;
+ obuf->anchor_target = obuf->bp.anchor_target;
+ obuf->anchor_hseq = obuf->bp.anchor_hseq;
+ obuf->img_alt = obuf->bp.img_alt;
+ obuf->in_bold = obuf->bp.in_bold;
+ obuf->in_under = obuf->bp.in_under;
+ obuf->prev_ctype = obuf->bp.prev_ctype;
+ obuf->pos = obuf->bp.pos;
+ if (obuf->flag & RB_NOBR)
+ obuf->nobr_level = obuf->bp.nobr_level;
+}
+
+static void
+append_tags(struct readbuffer *obuf)
+{
+ int i;
+ int len = obuf->line->length;
+ int set_bp = 0;
+
+ for (i = 0; i < obuf->tag_sp; i++) {
+ switch (obuf->tag_stack[i]->cmd) {
+ case HTML_A:
+ case HTML_IMG_ALT:
+ case HTML_B:
+ case HTML_U:
+ push_link(obuf->tag_stack[i]->cmd, obuf->line->length, obuf->pos);
+ break;
+ }
+ Strcat_charp(obuf->line, obuf->tag_stack[i]->cmdname);
+ switch (obuf->tag_stack[i]->cmd) {
+ case HTML_NOBR:
+ if (obuf->nobr_level > 1)
+ break;
+ case HTML_WBR:
+ set_bp = 1;
+ break;
+ }
+ }
+ obuf->tag_sp = 0;
+ if (set_bp)
+ set_breakpoint(obuf, obuf->line->length - len);
+}
+
+static void
+push_tag(struct readbuffer *obuf, char *cmdname, int cmd)
+{
+ obuf->tag_stack[obuf->tag_sp] = New(struct cmdtable);
+ obuf->tag_stack[obuf->tag_sp]->cmdname = allocStr(cmdname, 0);
+ obuf->tag_stack[obuf->tag_sp]->cmd = cmd;
+ obuf->tag_sp++;
+ if (obuf->tag_sp >= TAG_STACK_SIZE ||
+ obuf->flag & (RB_SPECIAL & ~RB_NOBR))
+ append_tags(obuf);
+}
+
+static void
+push_nchars(struct readbuffer *obuf, int width,
+ char *str, int len, Lineprop mode)
+{
+ int delta = get_mclen(mode);
+ append_tags(obuf);
+ Strcat_charp_n(obuf->line, str, len);
+ obuf->pos += width;
+ if (width > 0 && len >= delta) {
+ obuf->prevchar = mctowc(&str[len - delta], mode);
+ obuf->prev_ctype = mode;
+ }
+ obuf->flag |= RB_NFLUSHED;
+}
+
+#define push_charp(obuf, width, str, mode)\
+push_nchars(obuf, width, str, strlen(str), mode)
+
+#define push_str(obuf, width, str, mode)\
+push_nchars(obuf, width, str->ptr, str->length, mode)
+
+static void
+check_breakpoint(struct readbuffer *obuf, int pre_mode, int ch)
+{
+ int tlen, len = obuf->line->length;
+
+ append_tags(obuf);
+ if (pre_mode)
+ return;
+ tlen = obuf->line->length - len;
+ if (tlen > 0 || is_boundary(obuf->prevchar, ch))
+ set_breakpoint(obuf, tlen);
+}
+
+static void
+push_char(struct readbuffer *obuf, int pre_mode, char ch)
+{
+ check_breakpoint(obuf, pre_mode, (unsigned char)ch);
+ Strcat_char(obuf->line, ch);
+ obuf->pos++;
+ obuf->prevchar = (unsigned char) ch;
+ if (ch != ' ')
+ obuf->prev_ctype = PC_ASCII;
+ obuf->flag |= RB_NFLUSHED;
+}
+
+#define PUSH(c) push_char(obuf, obuf->flag & RB_SPECIAL, c)
+
+static void
+push_spaces(struct readbuffer *obuf, int pre_mode, int width)
+{
+ int i;
+
+ if (width <= 0)
+ return;
+ check_breakpoint(obuf, pre_mode, ' ');
+ for (i = 0; i < width; i++)
+ Strcat_char(obuf->line, ' ');
+ obuf->pos += width;
+ obuf->prevchar = ' ';
+ obuf->flag |= RB_NFLUSHED;
+}
+
+static void
+proc_mchar(struct readbuffer *obuf, int pre_mode,
+ int width, char **str, Lineprop mode)
+{
+ int ch = mctowc(*str, mode);
+
+ check_breakpoint(obuf, pre_mode, ch);
+ obuf->pos += width;
+#ifdef JP_CHARSET
+ if (IS_KANJI1(**str) && mode == PC_ASCII)
+ Strcat_char(obuf->line, ' ');
+ else if (mode == PC_KANJI)
+ Strcat_charp_n(obuf->line, *str, 2);
+ else
+#endif
+ Strcat_char(obuf->line, **str);
+ if (width > 0) {
+ obuf->prevchar = ch;
+ if (ch != ' ')
+ obuf->prev_ctype = mode;
+ }
+ (*str) += get_mclen(mode);
+ obuf->flag |= RB_NFLUSHED;
+}
+
+void
+push_render_image(Str str, int width, struct html_feed_environ *h_env)
+{
+ struct readbuffer *obuf = h_env->obuf;
+ int indent = h_env->envs[h_env->envc].indent;
+
+ push_str(obuf, width, str, PC_ASCII);
+ if (width > 0)
+ flushline(h_env, obuf, indent, 0, h_env->limit);
+}
+
+static int
+sloppy_parse_line(char **str)
+{
+ if (**str == '<') {
+ while (**str && **str != '>')
+ (*str)++;
+ if (**str == '>')
+ (*str)++;
+ return 1;
+ }
+ else {
+ while (**str && **str != '<')
+ (*str)++;
+ return 0;
+ }
+}
+
+static void
+passthrough(struct readbuffer *obuf, char *str, int back)
+{
+ int status, cmd;
+ Str tok = Strnew();
+ char *str_bak;
+
+ if (back) {
+ Str str_save = Strnew_charp(str);
+ Strshrink(obuf->line, obuf->line->ptr + obuf->line->length - str);
+ str = str_save->ptr;
+ }
+ while (*str) {
+ str_bak = str;
+ if (sloppy_parse_line(&str)) {
+ char *q = str_bak;
+ cmd = gethtmlcmd(&q, &status);
+ if (back) {
+ struct link_stack *p;
+ for (p = link_stack; p; p = p->next) {
+ if (p->cmd == cmd) {
+ link_stack = p->next;
+ break;
+ }
+ }
+ back = 0;
+ }
+ else {
+ Strcat_charp_n(tok, str_bak, str - str_bak);
+ push_tag(obuf, tok->ptr, cmd);
+ Strclear(tok);
+ }
+ }
+ else {
+ push_nchars(obuf, 0, str_bak, str - str_bak, obuf->prev_ctype);
+ }
+ }
+}
+
+#if 0
+int
+is_blank_line(char *line, int indent)
+{
+ int i, is_blank = 0;
+
+ for (i = 0; i < indent; i++) {
+ if (line[i] == '\0') {
+ is_blank = 1;
+ }
+ else if (line[i] != ' ') {
+ break;
+ }
+ }
+ if (i == indent && line[i] == '\0')
+ is_blank = 1;
+ return is_blank;
+}
+#endif
+
+void
+fillline(struct readbuffer *obuf, int indent)
+{
+ push_spaces(obuf, 1, indent - obuf->pos);
+ obuf->flag &= ~RB_NFLUSHED;
+}
+
+void
+flushline(struct html_feed_environ *h_env, struct readbuffer *obuf, int indent, int force, int width)
+{
+ TextLineList *buf = h_env->buf;
+ FILE *f = h_env->f;
+ Str line = obuf->line, pass = NULL;
+ char *hidden_anchor = NULL, *hidden_img = NULL, *hidden_bold = NULL,
+ *hidden_under = NULL, *hidden = NULL;
+
+ if (w3m_debug) {
+ FILE *f = fopen("zzzproc1", "a");
+ fprintf(f, "flushline(%s,%d,%d,%d)\n", obuf->line->ptr, indent, force, width);
+ if (buf) {
+ TextLineListItem *p;
+ for (p = buf->first; p; p = p->next) {
+ fprintf(f, "buf=\"%s\"\n", p->ptr->line->ptr);
+ }
+ }
+ fclose(f);
+ }
+
+ if (!(obuf->flag & (RB_SPECIAL & ~RB_NOBR)) && Strlastchar(line) == ' ') {
+ Strshrink(line, 1);
+ obuf->pos--;
+ }
+
+ append_tags(obuf);
+
+ if (obuf->anchor)
+ hidden = hidden_anchor = has_hidden_link(obuf, HTML_A);
+ if (obuf->img_alt) {
+ if ((hidden_img = has_hidden_link(obuf, HTML_IMG_ALT)) != NULL) {
+ if (!hidden || hidden_img < hidden)
+ hidden = hidden_img;
+ }
+ }
+ if (obuf->in_bold) {
+ if ((hidden_bold = has_hidden_link(obuf, HTML_B)) != NULL) {
+ if (!hidden || hidden_bold < hidden)
+ hidden = hidden_bold;
+ }
+ }
+ if (obuf->in_under) {
+ if ((hidden_under = has_hidden_link(obuf, HTML_U)) != NULL) {
+ if (!hidden || hidden_under < hidden)
+ hidden = hidden_under;
+ }
+ }
+ if (hidden) {
+ pass = Strnew_charp(hidden);
+ Strshrink(line, line->ptr + line->length - hidden);
+ }
+
+ if (!(obuf->flag & (RB_SPECIAL & ~RB_NOBR)) && obuf->pos > width) {
+ char *tp = &line->ptr[obuf->bp.len - obuf->bp.tlen];
+ char *ep = &line->ptr[line->length];
+
+ if (obuf->bp.pos == obuf->pos && tp <= ep &&
+ tp > line->ptr && tp[-1] == ' ') {
+ bcopy(tp, tp - 1, ep - tp + 1);
+ line->length--;
+ obuf->pos--;
+ }
+ }
+
+ if (obuf->anchor && !hidden_anchor)
+ Strcat_charp(line, "</a>");
+ if (obuf->img_alt && !hidden_img)
+ Strcat_charp(line, "</img_alt>");
+ if (obuf->in_bold && !hidden_bold)
+ Strcat_charp(line, "</b>");
+ if (obuf->in_under && !hidden_under)
+ Strcat_charp(line, "</u>");
+
+ if (force == 1 || obuf->flag & RB_NFLUSHED) {
+ TextLine *lbuf = newTextLine(line, obuf->pos);
+ if (RB_GET_ALIGN(obuf) == RB_CENTER) {
+ align(lbuf, width, ALIGN_CENTER);
+ }
+ else if (RB_GET_ALIGN(obuf) == RB_RIGHT) {
+ align(lbuf, width, ALIGN_RIGHT);
+ }
+#ifdef FORMAT_NICE
+ else if (obuf->flag & RB_FILL) {
+ char *p;
+ int rest, rrest;
+ int nspace, d, i;
+
+ rest = width - line->length;
+ if (rest > 1) {
+ nspace = 0;
+ for (p = line->ptr + indent; *p; p++) {
+ if (*p == ' ')
+ nspace++;
+ }
+ if (nspace > 0) {
+ int indent_here = 0;
+ d = rest / nspace;
+ p = line->ptr;
+ while (IS_SPACE(*p)) {
+ p++;
+ indent_here++;
+ }
+ rrest = rest - d * nspace;
+ line = Strnew_size(width + 1);
+ for (i = 0; i < indent_here; i++)
+ Strcat_char(line, ' ');
+ for (; *p; p++) {
+ Strcat_char(line, *p);
+ if (*p == ' ') {
+ for (i = 0; i < d; i++)
+ Strcat_char(line, ' ');
+ if (rrest > 0) {
+ Strcat_char(line, ' ');
+ rrest--;
+ }
+ }
+ }
+ lbuf = newTextLine(line, width);
+ }
+ }
+ }
+#endif /* FORMAT_NICE */
+#ifdef TABLE_DEBUG
+ if (w3m_debug) {
+ FILE *f = fopen("zzzproc1", "a");
+ fprintf(f, "pos=%d,%d, maxlimit=%d\n",
+ visible_length(lbuf->line->ptr), lbuf->pos, h_env->maxlimit);
+ fclose(f);
+ }
+#endif
+ if (lbuf->pos > h_env->maxlimit)
+ h_env->maxlimit = lbuf->pos;
+ if (buf) {
+ pushTextLine(buf, lbuf);
+ if (w3m_backend) {
+ Strcat(backend_halfdump_str, lbuf->line);
+ Strcat_char(backend_halfdump_str, '\n');
+ }
+ }
+ else {
+ Strfputs(lbuf->line, f);
+ fputc('\n', f);
+ }
+ if (obuf->flag & RB_SPECIAL || obuf->flag & RB_NFLUSHED)
+ h_env->blank_lines = 0;
+ else
+ h_env->blank_lines++;
+ }
+ else {
+ char *p = line->ptr, *q;
+ Str tmp = Strnew(), tmp2 = Strnew();
+
+#define APPEND(str) \
+ if (buf) { \
+ appendTextLine(buf,(str),0); \
+ if (w3m_backend) \
+ Strcat(backend_halfdump_str, (str)); \
+ } else \
+ Strfputs((str),f)
+
+ while (*p) {
+ q = p;
+ if (sloppy_parse_line(&p)) {
+ Strcat_charp_n(tmp, q, p - q);
+ if (force == 2)
+ APPEND(tmp);
+ else
+ Strcat(tmp2, tmp);
+ Strclear(tmp);
+ }
+ }
+ if (force == 2) {
+ if (pass) {
+ APPEND(pass);
+ }
+ pass = NULL;
+ }
+ else {
+ if (pass)
+ Strcat(tmp2, pass);
+ pass = tmp2;
+ }
+ }
+ obuf->line = Strnew_size(256);
+ obuf->pos = 0;
+ obuf->prevchar = ' ';
+ obuf->bp.init_flag = 1;
+ obuf->flag &= ~RB_NFLUSHED;
+ set_breakpoint(obuf, 0);
+ obuf->prev_ctype = PC_ASCII;
+ link_stack = NULL;
+ fillline(obuf, indent);
+ if (pass)
+ passthrough(obuf, pass->ptr, 0);
+ if (!hidden_anchor && obuf->anchor) {
+ Str tmp;
+ if (obuf->anchor_hseq > 0)
+ obuf->anchor_hseq = -obuf->anchor_hseq;
+ tmp = Sprintf("<A HSEQ=\"%d\" HREF=\"", obuf->anchor_hseq);
+ Strcat_charp(tmp, htmlquote_str(obuf->anchor->ptr));
+ if (obuf->anchor_target) {
+ Strcat_charp(tmp, "\" TARGET=\"");
+ Strcat_charp(tmp, htmlquote_str(obuf->anchor_target->ptr));
+ }
+ Strcat_charp(tmp, "\">");
+ push_tag(obuf, tmp->ptr, HTML_A);
+ }
+ if (!hidden_img && obuf->img_alt) {
+ Str tmp = Strnew_charp("<IMG_ALT SRC=\"");
+ Strcat_charp(tmp, htmlquote_str(obuf->img_alt->ptr));
+ Strcat_charp(tmp, "\">");
+ push_tag(obuf, tmp->ptr, HTML_IMG_ALT);
+ }
+ if (!hidden_bold && obuf->in_bold)
+ push_tag(obuf, "<B>", HTML_B);
+ if (!hidden_under && obuf->in_under)
+ push_tag(obuf, "<U>", HTML_U);
+}
+
+static void
+discardline(struct readbuffer *obuf, int indent)
+{
+ append_tags(obuf);
+ Strclear(obuf->line);
+ obuf->pos = 0;
+ obuf->prevchar = ' ';
+ obuf->bp.init_flag = 1;
+ set_breakpoint(obuf, 0);
+ obuf->prev_ctype = PC_ASCII;
+ fillline(obuf, indent);
+}
+
+void
+do_blankline(struct html_feed_environ *h_env, struct readbuffer *obuf, int indent, int indent_incr, int width)
+{
+ if (h_env->buf && h_env->blank_lines == 0)
+ flushline(h_env, obuf, indent, 1, width);
+ else if (h_env->f)
+ flushline(h_env, obuf, indent, 1, width);
+}
+
+void
+purgeline(struct html_feed_environ *h_env)
+{
+ char *p, *q;
+ Str tmp;
+
+ if (h_env->buf == NULL || h_env->blank_lines == 0)
+ return;
+
+ p = rpopTextLine(h_env->buf)->line->ptr;
+ tmp = Strnew();
+ while (*p) {
+ q = p;
+ if (sloppy_parse_line(&p)) {
+ Strcat_charp_n(tmp, q, p - q);
+ appendTextLine(h_env->buf ,tmp, 0);
+ }
+ }
+ h_env->blank_lines--;
+}
+
+static int
+close_effect0(struct readbuffer *obuf, int cmd)
+{
+ int i;
+ char *p;
+
+ for (i = obuf->tag_sp - 1; i >= 0; i--) {
+ if (obuf->tag_stack[i]->cmd == cmd)
+ break;
+ }
+ if (i >= 0) {
+ obuf->tag_sp--;
+ bcopy(&obuf->tag_stack[i + 1], &obuf->tag_stack[i],
+ (obuf->tag_sp - i) * sizeof(struct cmdtable *));
+ return 1;
+ }
+ else if ((p = has_hidden_link(obuf, cmd)) != NULL) {
+ passthrough(obuf, p, 1);
+ return 1;
+ }
+ return 0;
+}
+
+static void
+close_anchor(struct html_feed_environ *h_env, struct readbuffer *obuf)
+{
+ if (obuf->anchor) {
+ int i;
+ char *p = NULL;
+ int is_erased = 0;
+
+ for (i = obuf->tag_sp - 1; i >= 0; i--) {
+ if (obuf->tag_stack[i]->cmd == HTML_A)
+ break;
+ }
+ if (i < 0 && obuf->anchor_hseq > 0 &&
+ Strlastchar(obuf->line) == ' ') {
+ Strshrink(obuf->line, 1);
+ obuf->pos--;
+ is_erased = 1;
+ }
+
+ if (i >= 0 || (p = has_hidden_link(obuf, HTML_A))) {
+ if (obuf->anchor_hseq > 0) {
+ HTMLlineproc1(ANSP, h_env);
+ obuf->prevchar = ' ';
+ }
+ else {
+ if (i >= 0) {
+ obuf->tag_sp--;
+ bcopy(&obuf->tag_stack[i + 1], &obuf->tag_stack[i],
+ (obuf->tag_sp - i) * sizeof(struct cmdtable *));
+ }
+ else {
+ passthrough(obuf, p, 1);
+ }
+ obuf->anchor = NULL;
+ obuf->anchor_target = NULL;
+ return;
+ }
+ is_erased = 0;
+ }
+ if (is_erased) {
+ Strcat_char(obuf->line, ' ');
+ obuf->pos++;
+ }
+
+ push_tag(obuf, "</a>", HTML_N_A);
+ obuf->anchor = NULL;
+ }
+ obuf->anchor_target = NULL;
+}
+
+void
+save_fonteffect(struct html_feed_environ *h_env, struct readbuffer *obuf)
+{
+ if (obuf->fontstat_sp < FONT_STACK_SIZE)
+ bcopy(obuf->fontstat, obuf->fontstat_stack[obuf->fontstat_sp],
+ FONTSTAT_SIZE);
+ obuf->fontstat_sp++;
+ if (obuf->in_bold)
+ push_tag(obuf, "</b>", HTML_N_B);
+ if (obuf->in_under)
+ push_tag(obuf, "</u>", HTML_N_U);
+ bzero(obuf->fontstat, FONTSTAT_SIZE);
+}
+
+void
+restore_fonteffect(struct html_feed_environ *h_env, struct readbuffer *obuf)
+{
+ if (obuf->fontstat_sp > 0)
+ obuf->fontstat_sp--;
+ if (obuf->fontstat_sp < FONT_STACK_SIZE)
+ bcopy(obuf->fontstat_stack[obuf->fontstat_sp], obuf->fontstat,
+ FONTSTAT_SIZE);
+ if (obuf->in_bold)
+ push_tag(obuf, "<b>", HTML_B);
+ if (obuf->in_under)
+ push_tag(obuf, "<u>", HTML_U);
+}
+
+
+Str
+process_img(struct parsed_tag * tag)
+{
+ char *p, *q, *r, *r2, *s;
+ int w, i;
+ Str tmp = Strnew();
+
+ if (!parsedtag_get_value(tag, ATTR_SRC, &p))
+ return tmp;
+ q = NULL;
+ parsedtag_get_value(tag, ATTR_ALT, &q);
+ w = -1;
+ parsedtag_get_value(tag, ATTR_WIDTH, &w);
+ i = -1;
+ parsedtag_get_value(tag, ATTR_HEIGHT, &i);
+ r = NULL;
+ parsedtag_get_value(tag, ATTR_USEMAP, &r);
+
+ tmp = Strnew_size(128);
+ if (r) {
+ r2 = strchr(r, '#');
+#ifdef NEW_FORM
+ s = "<form_int method=internal action=map>";
+ process_form(parse_tag(&s, TRUE));
+ Strcat(tmp, Sprintf("<pre_int><input_alt fid=\"%d\" "
+ "type=hidden name=link value=\"",
+ cur_form_id));
+ Strcat_charp(tmp, htmlquote_str((r2) ? r2 + 1 : r));
+ Strcat(tmp, Sprintf("\"><input_alt hseq=\"%d\" fid=\"%d\" "
+ "type=submit no_effect=true>",
+ cur_hseq++, cur_form_id));
+#else /* not NEW_FORM */
+ Strcat_charp(tmp, "<form_int method=internal action=map>"
+ "<pre_int><input_alt type=hidden name=link value=\"");
+ Strcat_charp(tmp, htmlquote_str((r2) ? r2 + 1 : r));
+ Strcat(tmp, Sprintf("\"><input_alt hseq=\"%d\" type=submit "
+ "no_effect=true>", cur_hseq++));
+#endif /* not NEW_FORM */
+ }
+ if (q != NULL && *q == '\0' && ignore_null_img_alt)
+ q = NULL;
+ if (q != NULL || r != NULL)
+ Strcat_charp(tmp, "<img_alt src=\"");
+ else
+ Strcat_charp(tmp, "<nobr><img_alt src=\"");
+ Strcat_charp(tmp, htmlquote_str(p));
+ Strcat_charp(tmp, "\">");
+ if (q != NULL) {
+ Strcat_charp(tmp, htmlquote_str(q));
+ Strcat_charp(tmp, "</img_alt> ");
+ goto img_end2;
+ }
+ if (w > 0 && i > 0) {
+ /* guess what the image is! */
+ if (w < 32 && i < 48) {
+ /* must be an icon or space */
+ if (strcasestr(p, "space") || strcasestr(p, "blank"))
+ Strcat_charp(tmp, "_</img_alt>");
+ else {
+ if (w * i < 8 * 16)
+ Strcat_charp(tmp, "*</img_alt>");
+ else {
+#ifdef KANJI_SYMBOLS
+ Strcat_charp(tmp, "¡ü</img_alt>");
+#else /* not KANJI_SYMBOLS */
+ Strcat_charp(tmp, "#</img_alt>");
+#endif /* not KANJI_SYMBOLS */
+ }
+ }
+ goto img_end1;
+ }
+ if (w > 200 && i < 13) {
+ /* must be a horizontal line */
+#ifndef KANJI_SYMBOLS
+ Strcat_charp(tmp, "<_RULE>");
+#endif /* not KANJI_SYMBOLS */
+ w /= pixel_per_char;
+ for (i = 0; i < w - (HR_RULE_WIDTH - 1); i += HR_RULE_WIDTH)
+ Strcat_charp(tmp, HR_RULE);
+#ifndef KANJI_SYMBOLS
+ Strcat_charp(tmp, "</_RULE>");
+#endif /* not KANJI_SYMBOLS */
+ Strcat_charp(tmp, "</img_alt>");
+ goto img_end1;
+ }
+ }
+ for (q = p; *q; q++);
+ while (q > p && *q != '/')
+ q--;
+ if (*q == '/')
+ q++;
+ Strcat_char(tmp, '[');
+ p = q;
+ for (; *q; q++) {
+ if (!IS_ALNUM(*q) && *q != '_' && *q != '-') {
+ break;
+ }
+ else if (w > 0 && !IS_ALNUM(*q) && q - p + 2 > (int)(w / pixel_per_char)) {
+ Strcat_charp(tmp, "..");
+ break;
+ }
+ Strcat_char(tmp, *q);
+ }
+ Strcat_charp(tmp, "]</img_alt>");
+ img_end1:
+ if (r == NULL)
+ Strcat_charp(tmp, "</nobr>");
+ img_end2:
+ if (r) {
+#ifdef NEW_FORM
+ Strcat_charp(tmp, "</input_alt></pre_int>");
+ process_n_form();
+#else /* not NEW_FORM */
+ Strcat_charp(tmp, "</input_alt></pre_int></form_int>");
+#endif /* not NEW_FORM */
+ }
+ return tmp;
+}
+
+Str
+process_anchor(struct parsed_tag * tag, char *tagbuf)
+{
+ if (parsedtag_need_reconstruct(tag)) {
+ parsedtag_set_value(tag, ATTR_HSEQ, Sprintf("%d", cur_hseq++)->ptr);
+ return parsedtag2str(tag);
+ }
+ else {
+ Str tmp = Sprintf("<a hseq=\"%d\"", cur_hseq++);
+ Strcat_charp(tmp, tagbuf + 2);
+ return tmp;
+ }
+}
+
+Str
+process_input(struct parsed_tag * tag)
+{
+ int i, w, v, x, y;
+ char *q , *p, *r, *p2;
+ Str tmp;
+ char *qq = "";
+ int qlen = 0;
+
+ p = "text";
+ parsedtag_get_value(tag, ATTR_TYPE, &p);
+ q = NULL;
+ parsedtag_get_value(tag, ATTR_VALUE, &q);
+ r = "";
+ parsedtag_get_value(tag, ATTR_NAME, &r);
+ w = 20;
+ parsedtag_get_value(tag, ATTR_SIZE, &w);
+ i = 20;
+ parsedtag_get_value(tag, ATTR_MAXLENGTH, &i);
+ p2 = NULL;
+ parsedtag_get_value(tag, ATTR_ALT, &p2);
+ x = parsedtag_exists(tag, ATTR_CHECKED);
+ y = parsedtag_exists(tag, ATTR_ACCEPT);
+
+ v = formtype(p);
+ if (v == FORM_UNKNOWN)
+ return NULL;
+
+ if (!q) {
+ switch (v) {
+ case FORM_INPUT_IMAGE:
+ case FORM_INPUT_SUBMIT:
+ case FORM_INPUT_BUTTON:
+ q = "SUBMIT";
+ break;
+ case FORM_INPUT_RESET:
+ q = "RESET";
+ break;
+ /* if no VALUE attribute is specified in * <INPUT
+ * TYPE=CHECHBOX> tag, then the value "on" is used * as a
+ * default value. It is not a part of HTML4.0 * specification,
+ * but an imitation of Netscape * behaviour. */
+ case FORM_INPUT_CHECKBOX:
+ q = "on";
+ }
+ }
+ /* VALUE attribute is not allowed in <INPUT TYPE=FILE> tag. */
+ if (v == FORM_INPUT_FILE)
+ q = NULL;
+ if (q) {
+ qq = htmlquote_str(q);
+ qlen = strlen(q);
+ }
+
+ tmp = Strnew_charp("<pre_int>");
+ 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("<input_alt hseq=\"%d\" fid=\"%d\" type=%s "
+ "name=\"%s\" width=%d maxlength=%d value=\"%s\"",
+ cur_hseq++, cur_form_id,
+ p, htmlquote_str(r), w, i, qq));
+#else /* not NEW_FORM */
+ Strcat(tmp, Sprintf("<input_alt hseq=\"%d\" type=%s "
+ "name=\"%s\" width=%d maxlength=%d value=\"%s\"",
+ cur_hseq++, p, htmlquote_str(r), w, i, qq));
+#endif /* not NEW_FORM */
+ if (x)
+ Strcat_charp(tmp, " checked");
+ if (y)
+ Strcat_charp(tmp, " accept");
+ Strcat_char(tmp, '>');
+
+ if (v == FORM_INPUT_HIDDEN)
+ Strcat_charp(tmp, "</input_alt></pre_int>");
+ else {
+ switch (v) {
+ case FORM_INPUT_PASSWORD:
+ case FORM_INPUT_TEXT:
+ case FORM_INPUT_FILE:
+ Strcat_charp(tmp, "<u>");
+ 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, "</u>");
+ break;
+ case FORM_INPUT_IMAGE:
+ case FORM_INPUT_SUBMIT:
+ case FORM_INPUT_BUTTON:
+ case FORM_INPUT_RESET:
+ Strcat_charp(tmp, "]");
+ }
+ Strcat_charp(tmp, "</input_alt>");
+ 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, "</pre_int>");
+ }
+ 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("<pre_int>[<input_alt hseq=\"%d\" "
+ "fid=\"%d\" type=select name=\"%s\" selectnumber=%d",
+ cur_hseq++, cur_form_id, htmlquote_str(p), n_select);
+#else /* not NEW_FORM */
+ select_str = Sprintf("<pre_int><input_alt hseq=\"%d\" "
+ "type=select name=\"%s\" selectnumber=%d",
+ cur_hseq++, htmlquote_str(p), n_select);
+#endif /* not NEW_FORM */
+ Strcat_charp(select_str, ">");
+ 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, "</input_alt>]</pre_int>");
+ 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, "<br>");
+ 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("<br><pre_int>%c<input_alt hseq=\"%d\" "
+ "fid=\"%d\" type=%s name=\"%s\" value=\"%s\"",
+ begin_char, cur_hseq++, cur_form_id,
+#else /* not NEW_FORM */
+ Strcat(select_str, Sprintf("<br><pre_int><input_alt hseq=\"%d\" "
+ "type=%s name=\"%s\" value=\"%s\"",
+ cur_hseq++,
+#endif /* not NEW_FORM */
+ select_is_multiple ? "checkbox" : "radio",
+ htmlquote_str(cur_select->ptr),
+ htmlquote_str(cur_option_value->ptr)));
+ if (cur_option_selected)
+ Strcat_charp(select_str, " checked>*</input_alt>");
+ else
+ Strcat_charp(select_str, "> </input_alt>");
+#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, "</pre_int>");
+ 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("<pre_int>[<input_alt hseq=\"%d\" fid=\"%d\" type=textarea "
+ "name=\"%s\" size=%d rows=%d textareanumber=%d><u>",
+ cur_hseq++, cur_form_id, htmlquote_str(cur_textarea->ptr),
+ cur_textarea_size, cur_textarea_rows, n_textarea);
+#else /* not NEW_FORM */
+ tmp = Sprintf("<pre_int>[<input_alt hseq=\"%d\" type=textarea "
+ "name=\"%s\" size=%d rows=%d textareanumber=%d><u>",
+ 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, "</u></input_alt>]</pre_int>");
+ 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("<nobr>");
+ 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,"<div align=center>");
+ break;
+ case ALIGN_RIGHT:
+ Strcat_charp(tmp,"<div align=right>");
+ break;
+ case ALIGN_LEFT:
+ Strcat_charp(tmp,"<div align=left>");
+ 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, "</_RULE>");
+#endif /* not KANJI_SYMBOLS */
+ Strcat_charp(tmp,"</div></nobr>");
+ 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("</b>", 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("<b>", h_env);
+ return 1;
+ case HTML_N_EM:
+ HTMLlineproc1("</b>", 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("<b>", h_env);
+ set_alignment(obuf, tag);
+ return 1;
+ case HTML_N_H:
+ HTMLlineproc1("</b>", 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("<b>", 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_alt title=\"",
+ htmlquote_str(h_env->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("<a hseq=\"%d\" href=\"%s\">",
+ cur_hseq++, q)->ptr, HTML_A);
+ if (r)
+ q = htmlquote_str(r);
+ push_charp(obuf, strlen(q), q, PC_ASCII);
+ push_tag(obuf, "</a>", 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, "</pre_int>", 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("</script>");
+ return 1;
+ case HTML_N_SCRIPT:
+ /* should not be reached */
+ return 1;
+ case HTML_STYLE:
+ obuf->flag |= RB_IGNORE;
+ obuf->ignore_tag = Strnew_charp("</style>");
+ 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, "</img_alt>", 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("<form method=get action=\"",
+ htmlquote_str(q),
+ "\">",
+ htmlquote_str(p),
+ "<input type=text name=\"\" accept></form>",
+ 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) <a hseq=\"%d\" href=\"%s\">%s</a>",
+ 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("<U>[DEL:</U>", h_env);
+ return 1;
+ case HTML_N_DEL:
+ HTMLlineproc1("<U>:DEL]</U>", h_env);
+ return 1;
+ case HTML_INS:
+ HTMLlineproc1("<U>[INS:</U>", h_env);
+ return 1;
+ case HTML_N_INS:
+ HTMLlineproc1("<U>:INS]</U>", 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("<A HREF=\"%s\">bgsound(%s)</A>", 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("<A HREF=\"%s\">embed(%s)</A>", 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("<A HREF=\"%s\">applet archive(%s)</A>", 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("<IMG SRC=\"%s\" ALT=\"bg image(%s)\"><BR>",
+ 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 <form>..</form> */
+#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>..</form> */
+ 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 *
+ * <map>..</map> */
+ 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("&lt;", 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 *
+ * <script>..</script>, 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 <table>..</table>, 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:
+ /* </table> 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("<table_alt tid=%d>", 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:
+ /* <table> 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, "</img_alt>", HTML_N_IMG_ALT);
+ obuf->img_alt = NULL;
+ }
+ if (obuf->in_bold) {
+ push_tag(obuf, "</b>", HTML_N_B);
+ obuf->in_bold = 0;
+ }
+ if (obuf->in_under) {
+ push_tag(obuf, "</u>", HTML_N_U);
+ obuf->in_under = 0;
+ }
+ /* for unbalanced select tag */
+ if (obuf->flag & RB_INSELECT)
+ HTMLlineproc1("</select>", 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("</table>", 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("<br>Transfer Interrupted!<br>", &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') { /* <META> */
+ 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("<A HSEQ=\"%d\" HREF=\"gopher://", hseq++);
+ Strcat(lbuf, host);
+ Strcat_char(lbuf, ':');
+ Strcat(lbuf, port);
+ Strcat_char(lbuf, '/');
+ Strcat(lbuf, file);
+ Strcat_charp(lbuf, "\">");
+ 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: */