aboutsummaryrefslogtreecommitdiffstats
path: root/etc.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 /etc.c
downloadw3m-68a07bf03b7624c9924065cce9ffa45497225834.tar.gz
w3m-68a07bf03b7624c9924065cce9ffa45497225834.zip
Initial revision
Diffstat (limited to 'etc.c')
-rw-r--r--etc.c1493
1 files changed, 1493 insertions, 0 deletions
diff --git a/etc.c b/etc.c
new file mode 100644
index 0000000..8603142
--- /dev/null
+++ b/etc.c
@@ -0,0 +1,1493 @@
+/* $Id: etc.c,v 1.1 2001/11/08 05:14:33 a-ito Exp $ */
+#include "fm.h"
+#include <pwd.h>
+#include "myctype.h"
+#include "html.h"
+#include "local.h"
+#include "hash.h"
+#include "terms.h"
+
+#ifdef GETCWD
+#include <unistd.h>
+#include <sys/param.h>
+#endif /* GETCWD */
+
+#include <sys/types.h>
+#include <time.h>
+#include <sys/wait.h>
+
+#ifdef __WATT32__
+#define read(a,b,c) read_s(a,b,c)
+#define close(x) close_s(x)
+#endif /* __WATT32__ */
+
+#ifndef STRCASECMP
+int
+strcasecmp(char *s1, char *s2)
+{
+ int x;
+ while (*s1) {
+ x = tolower(*s1) - tolower(*s2);
+ if (x != 0)
+ break;
+ s1++;
+ s2++;
+ }
+ if (x != 0)
+ return x;
+ return -tolower(*s2);
+}
+
+int
+strncasecmp(char *s1, char *s2, int n)
+{
+ int x;
+ while (*s1 && n) {
+ x = tolower(*s1) - tolower(*s2);
+ if (x != 0)
+ break;
+ s1++;
+ s2++;
+ n--;
+ }
+ if (x != 0)
+ return x;
+ return 0;
+}
+#endif /* not STRCASECMP */
+
+int
+arg_is(char *str, char *tag)
+{
+ while (*tag) {
+ if (tolower(*tag) != tolower(*str))
+ return 0;
+ tag++;
+ str++;
+ }
+ while (*str && (*str == ' ' || *str == '\t'))
+ str++;
+ return (*str == '=');
+}
+
+int
+columnSkip(Buffer * buf, int offset)
+{
+ int i, maxColumn;
+ int column = buf->currentColumn + offset;
+ int nlines = LASTLINE + 1;
+ Line *l;
+
+ maxColumn = 0;
+ for (i = 0, l = buf->topLine;
+ i < nlines && l != NULL;
+ i++, l = l->next) {
+ if (l->width < 0)
+ l->width = COLPOS(l, l->len);
+ if (l->width - 1 > maxColumn)
+ maxColumn = l->width - 1;
+ }
+ maxColumn -= COLS - 1;
+ if (column < maxColumn)
+ maxColumn = column;
+ if (maxColumn < 0)
+ maxColumn = 0;
+
+ if (buf->currentColumn == maxColumn)
+ return 0;
+ buf->currentColumn = maxColumn;
+ return 1;
+}
+
+int
+columnPos(Line * line, int column)
+{
+ int i;
+
+ for (i = 1; i < line->len; i++) {
+ if (COLPOS(line, i) > column) {
+#ifdef JP_CHARSET
+ if (CharType(line->propBuf[i - 1]) == PC_KANJI2)
+ return i - 2;
+#endif
+ return i - 1;
+ }
+ }
+ return i - 1;
+}
+
+Line *
+lineSkip(Buffer * buf, Line * line, int offset, int last)
+{
+ int i;
+ Line *l;
+
+ l = currentLineSkip(buf, line, offset, last);
+ for (i = (LASTLINE - 1) - (buf->lastLine->linenumber - l->linenumber);
+ i > 0 && l->prev != NULL;
+ i--, l = l->prev);
+ return l;
+}
+
+Line *
+currentLineSkip(Buffer * buf, Line * line, int offset, int last)
+{
+ int i, n;
+ Line *l = line;
+
+ if (buf->pagerSource && !(buf->bufferprop & BP_CLOSE)) {
+ n = line->linenumber + offset + LASTLINE;
+ if (buf->lastLine->linenumber < n)
+ getNextPage(buf, n - buf->lastLine->linenumber);
+ while ((last || (buf->lastLine->linenumber < n)) &&
+ (getNextPage(buf, 1) != NULL));
+ if (last)
+ l = buf->lastLine;
+ }
+
+ if (offset == 0)
+ return l;
+ if (offset > 0)
+ for (i = 0; i < offset && l->next != NULL; i++, l = l->next);
+ else
+ for (i = 0; i < -offset && l->prev != NULL; i++, l = l->prev);
+ return l;
+}
+
+#define MAX_CMD_LEN 128
+
+static int
+get_cmd(Hash_si * hash,
+ char **s,
+ char *args,
+ char termchar,
+ int defaultcmd,
+ int allow_space,
+ int *status)
+{
+ char cmdstr[MAX_CMD_LEN];
+ char *p = cmdstr;
+ char *save = *s;
+ int cmd;
+ if (status)
+ *status = 0;
+ (*s)++;
+ /* first character */
+ if (IS_ALNUM(**s) || **s == '_' || **s == '/')
+ *(p++) = tolower(*((*s)++));
+ else
+ return defaultcmd;
+ if (p[-1] == '/')
+ SKIP_BLANKS(*s);
+ while ((IS_ALNUM(**s) || **s == '_') &&
+ p - cmdstr < MAX_CMD_LEN) {
+ *(p++) = tolower(*((*s)++));
+ }
+ if (p - cmdstr == MAX_CMD_LEN) {
+ /* buffer overflow: perhaps caused by bad HTML source */
+ *s = save + 1;
+ if (status)
+ *status = -1;
+ return defaultcmd;
+ }
+ *p = '\0';
+
+ /* hash search */
+ cmd = getHash_si(hash, cmdstr, defaultcmd);
+ if (args != NULL) {
+ p = args;
+ while (**s == ' ' || **s == '\t')
+ (*s)++;
+ while (**s && **s != '\n' && **s != '\r' && **s != termchar) {
+ *(p++) = *((*s)++);
+ }
+ *p = '\0';
+ }
+ else if (allow_space) {
+ while (**s && **s != termchar)
+ (*s)++;
+ }
+ if (**s == termchar)
+ (*s)++;
+ else if (status)
+ *status = -1;
+ return cmd;
+}
+
+int
+gethtmlcmd(char **s, int *status)
+{
+ extern Hash_si tagtable;
+ return get_cmd(&tagtable, s, NULL, '>', HTML_UNKNOWN, TRUE, status);
+}
+
+static char *
+searchAnchorArg(char **arg)
+{
+ char *p;
+ if (**arg == '"') {
+ (*arg)++;
+ p = *arg;
+ while (*p && *p != '"')
+ p++;
+ }
+ else {
+ p = *arg;
+ while (*p && *p != '>' && *p != ' ' && *p != ',' &&
+ *p != '\t' && *p != '\n')
+ p++;
+ }
+ return p;
+}
+
+char *
+getAnchor(char *arg, char **arg_return)
+{
+ char *p;
+ char buf[LINELEN];
+
+ if (arg_is(arg, "name")) {
+ arg += 4;
+ while (*arg && (*arg == ' ' || *arg == '\t'))
+ arg++;
+ if (*arg != '=')
+ return NULL;
+ arg++;
+ while (*arg && (*arg == ' ' || *arg == '\t'))
+ arg++;
+ p = searchAnchorArg(&arg);
+ buf[0] = '#';
+ strncpy(&buf[1], arg, p - arg);
+ if (arg_return)
+ *arg_return = p;
+ return allocStr(buf, p - arg + 1);
+ }
+ while (*arg && *arg != '=')
+ arg++;
+ if (*arg == '\0')
+ return NULL;
+ arg++;
+ while (*arg && (*arg == ' ' || *arg == '\t'))
+ arg++;
+ p = searchAnchorArg(&arg);
+ if (arg_return)
+ *arg_return = p;
+ if (p == arg)
+ return allocStr(" ", 1);
+ return allocStr(arg, p - arg);
+}
+
+#ifdef ANSI_COLOR
+static int
+parse_ansi_color(char **str, Lineprop *effect, Linecolor *color)
+{
+ char *p = *str, *q;
+ Lineprop e = *effect;
+ Linecolor c = *color;
+ int i;
+
+ if (*p != ESC_CODE || *(p+1) != '[')
+ return 0;
+ p += 2;
+ for (q = p; IS_DIGIT(*q) || *q == ';'; q++)
+ ;
+ if (*q != 'm')
+ return 0;
+ *str = q + 1;
+ while (1) {
+ if (*p == 'm') {
+ e = PE_NORMAL;
+ c = 0;
+ break;
+ }
+ if (IS_DIGIT(*p)) {
+ q = p;
+ for (p++; IS_DIGIT(*p); p++)
+ ;
+ i = atoi(allocStr(q, p - q));
+ switch (i) {
+ case 0:
+ e = PE_NORMAL;
+ c = 0;
+ break;
+ case 1:
+ case 5:
+ e = PE_BOLD;
+ break;
+ case 4:
+ e = PE_UNDER;
+ break;
+ case 7:
+ e = PE_STAND;
+ break;
+ case 100: /* for EWS4800 kterm */
+ c = 0;
+ break;
+ case 39:
+ c &= 0xf0;
+ break;
+ case 49:
+ c &= 0x0f;
+ break;
+ default:
+ if (i >= 30 && i <= 37)
+ c = (c & 0xf0) | (i - 30) | 0x08;
+ else if (i >= 40 && i <= 47)
+ c = (c & 0x0f) | ((i - 40) << 4) | 0x80;
+ break;
+ }
+ if (*p == 'm')
+ break;
+ } else {
+ e = PE_NORMAL;
+ c = 0;
+ break;
+ }
+ p++; /* *p == ';' */
+ }
+ *effect = e;
+ *color = c;
+ return 1;
+}
+#endif
+
+/*
+ * Check character type
+ */
+
+Str
+checkType(Str s, Lineprop * oprop,
+#ifdef ANSI_COLOR
+ Linecolor * ocolor, int * check_color,
+#endif
+ int len)
+{
+ Lineprop mode;
+ Lineprop effect = PE_NORMAL;
+ Lineprop *prop = oprop;
+ char *str = s->ptr, *endp = &s->ptr[s->length], *bs = NULL;
+#ifdef ANSI_COLOR
+ Lineprop ceffect = PE_NORMAL;
+ Linecolor cmode = 0;
+ Linecolor *color = NULL;
+ char *es = NULL;
+#endif
+ int do_copy = FALSE;
+ int size = (len < s->length) ? len : s->length;
+
+#ifdef ANSI_COLOR
+ if (check_color)
+ *check_color = FALSE;
+#endif
+ if (ShowEffect) {
+ bs = memchr(str, '\b', s->length);
+#ifdef ANSI_COLOR
+ if (ocolor) {
+ es = memchr(str, ESC_CODE, s->length);
+ if (es)
+ color = ocolor;
+ }
+#endif
+ if (s->length > size || (bs != NULL)
+#ifdef ANSI_COLOR
+ || (es != NULL)
+#endif
+ ) {
+ s = Strnew_size(size);
+ do_copy = TRUE;
+ }
+ }
+
+ while (str < endp) {
+ if (prop - oprop >= len)
+ break;
+ if (bs != NULL) {
+ if (str == bs - 2 && !strncmp(str, "__\b\b", 4)) {
+ str += 4;
+ effect = PE_UNDER;
+ if (str < endp)
+ bs = memchr(str, '\b', endp - str);
+ continue;
+ }
+ else if (str == bs - 1 && *str == '_') {
+ str += 2;
+ effect = PE_UNDER;
+ if (str < endp)
+ bs = memchr(str, '\b', endp - str);
+ continue;
+ }
+ else if (str == bs) {
+ if (*(str + 1) == '_') {
+#ifdef JP_CHARSET
+ if (s->length > 1 && CharType(*(prop - 2)) == PC_KANJI1) {
+ str += 2;
+ *(prop - 1) |= PE_UNDER;
+ *(prop - 2) |= PE_UNDER;
+ }
+ else
+#endif /* JP_CHARSET */
+ if (s->length > 0) {
+ str += 2;
+ *(prop - 1) |= PE_UNDER;
+ }
+ else {
+ str++;
+ }
+ }
+ else if (!strncmp(str + 1, "\b__", 3)) {
+#ifdef JP_CHARSET
+ if (s->length > 1 && CharType(*(prop - 2)) == PC_KANJI1) {
+ str += 4;
+ *(prop - 1) |= PE_UNDER;
+ *(prop - 2) |= PE_UNDER;
+ }
+ else
+#endif /* JP_CHARSET */
+ if (s->length > 0) {
+ str += 3;
+ *(prop - 1) |= PE_UNDER;
+ }
+ else {
+ str += 2;
+ }
+ }
+ else if (*(str + 1) == '\b') {
+#ifdef JP_CHARSET
+ if (s->length > 1 && CharType(*(prop - 2)) == PC_KANJI1) {
+ if (str + 4 <= endp &&
+ !strncmp(str - 2, str + 2, 2)) {
+ *(prop - 1) |= PE_BOLD;
+ *(prop - 2) |= PE_BOLD;
+ str += 4;
+ }
+ else {
+ Strshrink(s, 2);
+ prop -= 2;
+ str += 2;
+ }
+ }
+ else
+#endif /* JP_CHARSET */
+ if (s->length > 0) {
+ if (str + 3 <= endp &&
+ *(str - 1) == *(str + 2)) {
+ *(prop - 1) |= PE_BOLD;
+ str += 3;
+ }
+ else {
+ Strshrink(s, 1);
+ prop--;
+ str += 2;
+ }
+ }
+ else {
+ str += 2;
+ }
+ }
+ else {
+#ifdef JP_CHARSET
+ if (s->length > 1 && CharType(*(prop - 2)) == PC_KANJI1) {
+ if (str + 3 <= endp &&
+ !strncmp(str - 2, str + 1, 2)) {
+ *(prop - 1) |= PE_BOLD;
+ *(prop - 2) |= PE_BOLD;
+ str += 3;
+ }
+ else {
+ Strshrink(s, 2);
+ prop -= 2;
+ str++;
+ }
+ }
+ else
+#endif /* JP_CHARSET */
+ if (s->length > 0) {
+ if (str + 2 <= endp &&
+ *(str - 1) == *(str + 1)) {
+ *(prop - 1) |= PE_BOLD;
+ str += 2;
+ }
+ else {
+ Strshrink(s, 1);
+ prop--;
+ str++;
+ }
+ }
+ else {
+ str++;
+ }
+ }
+ if (str < endp)
+ bs = memchr(str, '\b', endp - str);
+ continue;
+ }
+#ifdef ANSI_COLOR
+ else if (str > bs)
+ bs = memchr(str, '\b', endp - str);
+#endif
+ }
+#ifdef ANSI_COLOR
+ if (es != NULL) {
+ if (str == es) {
+ int ok = parse_ansi_color(&str, &ceffect, &cmode);
+ if (str < endp)
+ es = memchr(str, ESC_CODE, endp - str);
+ if (ok) {
+ if (cmode)
+ *check_color = TRUE;
+ continue;
+ }
+ }
+ else if (str > es)
+ es = memchr(str, ESC_CODE, endp - str);
+ }
+#endif
+
+ mode = get_mctype(str);
+#ifdef ANSI_COLOR
+ effect |= ceffect;
+#endif
+#ifdef JP_CHARSET
+ if (mode == PC_KANJI) {
+ prop[0] = (effect | PC_KANJI1);
+ prop[1] = (effect | PC_KANJI2);
+ if (do_copy) {
+ Strcat_char(s, str[0]);
+ Strcat_char(s, str[1]);
+ }
+ prop += 2;
+ str += 2;
+#ifdef ANSI_COLOR
+ if (color) {
+ color[0] = cmode;
+ color[1] = cmode;
+ color += 2;
+ }
+#endif
+ }
+ else
+#endif /* JP_CHARSET */
+ {
+ *prop = (effect | mode);
+ if (do_copy)
+ Strcat_char(s, *str);
+ prop++;
+ str++;
+#ifdef ANSI_COLOR
+ if (color) {
+ *color = cmode;
+ color++;
+ }
+#endif
+ }
+ effect = PE_NORMAL;
+ }
+ return s;
+}
+
+int
+calcPosition(char *l, Lineprop *pr, int len, int pos, int bpos, int mode)
+{
+ static short realColumn[LINELEN + 1];
+ static char *prevl = NULL;
+ int i, j;
+
+ if (l == NULL || len == 0)
+ return bpos;
+ if (l == prevl && mode == CP_AUTO) {
+ if (pos <= len)
+ return realColumn[pos];
+ }
+ prevl = l;
+ j = bpos;
+ for (i = 0;; i++) {
+ realColumn[i] = j;
+ if (i == len)
+ break;
+ if (l[i] == '\t' && pr[i] == PC_CTRL)
+ j = (j + Tabstop) / Tabstop * Tabstop;
+#ifndef KANJI_SYMBOLS
+ else if (pr[i] & PC_RULE)
+ j++;
+#endif
+ else if (IS_UNPRINTABLE_ASCII(l[i], pr[i]))
+ j = j + 4;
+ else if (IS_UNPRINTABLE_CONTROL(l[i], pr[i]))
+ j = j + 2;
+ else
+ j++;
+ }
+ if (pos >= i)
+ return j;
+ return realColumn[pos];
+}
+
+char *
+lastFileName(char *path)
+{
+ char *p, *q;
+
+ p = q = path;
+ while (*p != '\0') {
+ if (*p == '/')
+ q = p + 1;
+ p++;
+ }
+
+ return allocStr(q, 0);
+}
+
+#ifdef NOBCOPY
+void
+bcopy(void *src, void *dest, int len)
+{
+ int i;
+ if (src == dest)
+ return;
+ if (src < dest) {
+ for (i = len - 1; i >= 0; i--)
+ dest[i] = src[i];
+ }
+ else { /* src > dest */
+ for (i = 0; i < len; i++)
+ dest[i] = src[i];
+ }
+}
+
+void
+bzero(void *ptr, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ *(ptr++) = 0;
+}
+#endif /* NOBCOPY */
+
+char *
+mybasename(char *s)
+{
+ char *p = s;
+ while (*p)
+ p++;
+ while (s <= p && *p != '/')
+ p--;
+ if (*p == '/')
+ p++;
+ else
+ p = s;
+ return allocStr(p, 0);
+}
+
+char *
+mydirname(char *s)
+{
+ char *p = s;
+ while (*p)
+ p++;
+ if (s != p)
+ p--;
+ while (s != p && *p == '/')
+ p--;
+ while (s != p && *p != '/')
+ p--;
+ if (*p != '/')
+ return ".";
+ while (s != p && *p == '/')
+ p--;
+ return allocStr(s, strlen(s) - strlen(p) + 1);
+}
+
+#ifndef STRERROR
+char *
+strerror(int errno)
+{
+ extern char *sys_errlist[];
+ return sys_errlist[errno];
+}
+#endif /* not STRERROR */
+
+#ifndef SYS_ERRLIST
+char **sys_errlist;
+
+prepare_sys_errlist()
+{
+ int i, n;
+
+ i = 1;
+ while (strerror(i) != NULL)
+ i++;
+ n = i;
+ sys_errlist = New_N(char *, n);
+ sys_errlist[0] = "";
+ for (i = 1; i < n; i++)
+ sys_errlist[i] = strerror(i);
+}
+#endif /* not SYS_ERRLIST */
+
+int
+next_status(char c, int *status)
+{
+ switch (*status) {
+ case R_ST_NORMAL:
+ if (c == '<') {
+ *status = R_ST_TAG0;
+ return 0;
+ }
+ else if (c == '&') {
+ *status = R_ST_AMP;
+ return 1;
+ }
+ else
+ return 1;
+ break;
+ case R_ST_TAG0:
+ if (c == '!') {
+ *status = R_ST_CMNT1;
+ return 0;
+ }
+ *status = R_ST_TAG;
+ /* continues to next case */
+ case R_ST_TAG:
+ if (c == '>')
+ *status = R_ST_NORMAL;
+ else if (c == '=')
+ *status = R_ST_EQL;
+ return 0;
+ case R_ST_EQL:
+ if (c == '"')
+ *status = R_ST_DQUOTE;
+ else if (c == '\'')
+ *status = R_ST_QUOTE;
+ else if (IS_SPACE(c))
+ *status = R_ST_EQL;
+ else if (c == '>')
+ *status = R_ST_NORMAL;
+ else
+ *status = R_ST_TAG;
+ return 0;
+ case R_ST_QUOTE:
+ if (c == '\'')
+ *status = R_ST_TAG;
+ return 0;
+ case R_ST_DQUOTE:
+ if (c == '"')
+ *status = R_ST_TAG;
+ return 0;
+ case R_ST_AMP:
+ if (c == ';') {
+ *status = R_ST_NORMAL;
+ return 0;
+ }
+ else if (c != '#' && !IS_ALNUM(c) && c != '_') {
+ /* something's wrong! */
+ *status = R_ST_NORMAL;
+ return 0;
+ }
+ else
+ return 0;
+ case R_ST_CMNT1:
+ switch (c) {
+ case '-':
+ *status = R_ST_CMNT2;
+ break;
+ case '>':
+ *status = R_ST_NORMAL;
+ break;
+ default:
+ *status = R_ST_IRRTAG;
+ }
+ return 0;
+ case R_ST_CMNT2:
+ switch (c) {
+ case '-':
+ *status = R_ST_CMNT;
+ break;
+ case '>':
+ *status = R_ST_NORMAL;
+ break;
+ default:
+ *status = R_ST_IRRTAG;
+ }
+ return 0;
+ case R_ST_CMNT:
+ if (c == '-')
+ *status = R_ST_NCMNT1;
+ return 0;
+ case R_ST_NCMNT1:
+ if (c == '-')
+ *status = R_ST_NCMNT2;
+ else
+ *status = R_ST_CMNT;
+ return 0;
+ case R_ST_NCMNT2:
+ switch (c) {
+ case '>':
+ *status = R_ST_NORMAL;
+ break;
+ case '-':
+ *status = R_ST_NCMNT2;
+ break;
+ default:
+ if (IS_SPACE(c))
+ *status = R_ST_NCMNT3;
+ else
+ *status = R_ST_CMNT;
+ break;
+ }
+ break;
+ case R_ST_NCMNT3:
+ switch (c) {
+ case '>':
+ *status = R_ST_NORMAL;
+ break;
+ case '-':
+ *status = R_ST_NCMNT1;
+ break;
+ default:
+ if (IS_SPACE(c))
+ *status = R_ST_NCMNT3;
+ else
+ *status = R_ST_CMNT;
+ break;
+ }
+ return 0;
+ case R_ST_IRRTAG:
+ if (c == '>')
+ *status = R_ST_NORMAL;
+ return 0;
+ }
+ /* notreached */
+ return 0;
+}
+
+int
+read_token(Str buf, char **instr, int *status, int pre, int append)
+{
+ char *p;
+ int prev_status;
+
+ if (!append)
+ Strclear(buf);
+ if (**instr == '\0')
+ return 0;
+ for (p = *instr; *p; p++) {
+ prev_status = *status;
+ next_status(*p, status);
+ switch (*status) {
+ case R_ST_NORMAL:
+ if (prev_status == R_ST_AMP && *p != ';') {
+ p--;
+ break;
+ }
+ if (prev_status == R_ST_NCMNT2 || prev_status == R_ST_NCMNT3 ||
+ prev_status == R_ST_IRRTAG || prev_status == R_ST_CMNT1) {
+ if (prev_status == R_ST_CMNT1 && !append)
+ Strclear(buf);
+ p++;
+ goto proc_end;
+ }
+ Strcat_char(buf, (!pre && IS_SPACE(*p)) ? ' ' : *p);
+ if (ST_IS_REAL_TAG(prev_status)) {
+ *instr = p + 1;
+ if (buf->length < 2 ||
+ buf->ptr[buf->length - 2] != '<' ||
+ buf->ptr[buf->length - 1] != '>')
+ return 1;
+ Strshrink(buf, 2);
+ }
+ break;
+ case R_ST_TAG0:
+ case R_ST_TAG:
+ if (prev_status == R_ST_NORMAL && p != *instr) {
+ *instr = p;
+ *status = prev_status;
+ return 1;
+ }
+ if (*status == R_ST_TAG0 &&
+ !REALLY_THE_BEGINNING_OF_A_TAG(p)) {
+ /* it seems that this '<' is not a beginning of a tag */
+ Strcat_charp(buf, "&lt;");
+ *status = R_ST_NORMAL;
+ }
+ else
+ Strcat_char(buf, *p);
+ break;
+ case R_ST_EQL:
+ case R_ST_QUOTE:
+ case R_ST_DQUOTE:
+ case R_ST_AMP:
+ Strcat_char(buf, *p);
+ break;
+ case R_ST_CMNT:
+ case R_ST_IRRTAG:
+ if (!append)
+ Strclear(buf);
+ break;
+ case R_ST_CMNT1:
+ case R_ST_CMNT2:
+ case R_ST_NCMNT1:
+ case R_ST_NCMNT2:
+ case R_ST_NCMNT3:
+ /* do nothing */
+ break;
+ }
+ }
+ proc_end:
+ *instr = p;
+ return 1;
+}
+
+Str
+correct_irrtag(int status)
+{
+ char c;
+ Str tmp = Strnew();
+
+ while (status != R_ST_NORMAL) {
+ switch (status) {
+ case R_ST_CMNT: /* required "-->" */
+ case R_ST_NCMNT1: /* required "->" */
+ c = '-';
+ break;
+ case R_ST_NCMNT2:
+ case R_ST_NCMNT3:
+ case R_ST_IRRTAG:
+ case R_ST_CMNT1:
+ case R_ST_CMNT2:
+ case R_ST_TAG:
+ case R_ST_TAG0:
+ case R_ST_EQL: /* required ">" */
+ c = '>';
+ break;
+ case R_ST_QUOTE:
+ c = '\'';
+ break;
+ case R_ST_DQUOTE:
+ c = '"';
+ break;
+ case R_ST_AMP:
+ c = ';';
+ break;
+ default:
+ return tmp;
+ }
+ next_status(c, &status);
+ Strcat_char(tmp, c);
+ }
+ return tmp;
+}
+
+/* authentication */
+struct auth_cookie *
+find_auth(char *host, char *realm)
+{
+ struct auth_cookie *p;
+
+ for (p = Auth_cookie; p != NULL; p = p->next) {
+ if (!Strcasecmp_charp(p->host, host) &&
+ !Strcasecmp_charp(p->realm, realm))
+ return p;
+ }
+ return NULL;
+}
+
+Str
+find_auth_cookie(char *host, char *realm)
+{
+ struct auth_cookie *p = find_auth(host, realm);
+ if (p)
+ return p->cookie;
+ return NULL;
+}
+
+void
+add_auth_cookie(char *host, char *realm, Str cookie)
+{
+ struct auth_cookie *p;
+
+ p = find_auth(host, realm);
+ if (p) {
+ p->cookie = cookie;
+ return;
+ }
+ p = New(struct auth_cookie);
+ p->host = Strnew_charp(host);
+ p->realm = Strnew_charp(realm);
+ p->cookie = cookie;
+ p->next = Auth_cookie;
+ Auth_cookie = p;
+}
+
+/* get last modified time */
+char *
+last_modified(Buffer * buf)
+{
+ TextListItem *ti;
+ struct stat st;
+
+ if (buf->document_header) {
+ for (ti = buf->document_header->first; ti; ti = ti->next) {
+ if (strncasecmp(ti->ptr, "Last-modified: ", 15) == 0) {
+ return ti->ptr + 15;
+ }
+ }
+ return "unknown";
+ }
+ else if (buf->currentURL.scheme == SCM_LOCAL) {
+ if (stat(buf->currentURL.file, &st) < 0)
+ return "unknown";
+ return ctime(&st.st_mtime);
+ }
+ return "unknown";
+}
+
+static char roman_num1[] =
+{
+ 'i', 'x', 'c', 'm', '*',
+};
+static char roman_num5[] =
+{
+ 'v', 'l', 'd', '*',
+};
+
+static Str
+romanNum2(int l, int n)
+{
+ Str s = Strnew();
+
+ switch (n) {
+ case 1:
+ case 2:
+ case 3:
+ for (; n > 0; n--)
+ Strcat_char(s, roman_num1[l]);
+ break;
+ case 4:
+ Strcat_char(s, roman_num1[l]);
+ Strcat_char(s, roman_num5[l]);
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ Strcat_char(s, roman_num5[l]);
+ for (n -= 5; n > 0; n--)
+ Strcat_char(s, roman_num1[l]);
+ break;
+ case 9:
+ Strcat_char(s, roman_num1[l]);
+ Strcat_char(s, roman_num1[l + 1]);
+ break;
+ }
+ return s;
+}
+
+Str
+romanNumeral(int n)
+{
+ Str r = Strnew();
+
+ if (n <= 0)
+ return r;
+ if (n >= 4000) {
+ Strcat_charp(r, "**");
+ return r;
+ }
+ Strcat(r, romanNum2(3, n / 1000));
+ Strcat(r, romanNum2(2, (n % 1000) / 100));
+ Strcat(r, romanNum2(1, (n % 100) / 10));
+ Strcat(r, romanNum2(0, n % 10));
+
+ return r;
+}
+
+Str
+romanAlphabet(int n)
+{
+ Str r = Strnew();
+ int l;
+ char buf[14];
+
+ if (n <= 0)
+ return r;
+
+ l = 0;
+ while (n) {
+ buf[l++] = 'a' + (n - 1) % 26;
+ n = (n - 1) / 26;
+ }
+ l--;
+ for (; l >= 0; l--)
+ Strcat_char(r, buf[l]);
+
+ return r;
+}
+
+Str
+quoteShell(char *string)
+{
+ Str str = Strnew();
+
+ while (*string != '\0') {
+ if (!IS_ALNUM(*string) && *string != '_' && *string != '.' &&
+ *string != ':' && *string != '/')
+ Strcat_char(str, '\\');
+ Strcat_char(str, *(string++));
+ }
+ return str;
+}
+
+void
+mySystem(char *command, int background)
+{
+#ifdef __EMX__ /* jsawa */
+ if (background){
+ Str cmd = Strnew_charp("start /f ");
+ Strcat_charp(cmd, command);
+ system(cmd->ptr);
+ }else
+ system(command);
+#else
+ Str cmd = Strnew_charp(command);
+ if (background)
+ cmd = Sprintf("(%s) >/dev/null 2>&1 &", cmd->ptr);
+ system(cmd->ptr);
+#endif
+}
+
+char *
+expandName(char *name)
+{
+ Str userName = NULL;
+ char *p;
+ struct passwd *passent, *getpwnam(const char *);
+ Str extpath = Strnew();
+
+ p = name;
+ if (*p == '/' && *(p + 1) == '~' && IS_ALPHA(*(p + 2))) {
+ if (personal_document_root != NULL) {
+ userName = Strnew();
+ p += 2;
+ while (IS_ALNUM(*p) || *p == '_' || *p == '-')
+ Strcat_char(userName, *(p++));
+ passent = getpwnam(userName->ptr);
+ if (passent == NULL) {
+ p = name;
+ goto rest;
+ }
+ Strcat_charp(extpath, passent->pw_dir);
+ Strcat_char(extpath, '/');
+ Strcat_charp(extpath, personal_document_root);
+ if (Strcmp_charp(extpath, "/") == 0 && *p == '/')
+ p++;
+ }
+ }
+ else
+ p = expandPath(p);
+ rest:
+ Strcat_charp(extpath, p);
+ return extpath->ptr;
+}
+
+static char *tmpf_base[MAX_TMPF_TYPE] =
+{
+ "tmp", "src", "frame", "cache"
+};
+static unsigned int tmpf_seq[MAX_TMPF_TYPE];
+
+Str
+tmpfname(int type, char *ext)
+{
+ Str tmpf;
+ tmpf = Sprintf("%s/w3m%s%d-%d%s",
+ rc_dir,
+ tmpf_base[type],
+ (int) getpid(),
+ tmpf_seq[type]++,
+ (ext)? ext : ""
+ );
+ return tmpf;
+}
+
+#ifdef USE_COOKIE
+static char *monthtbl[] =
+{
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static int
+get_day(char **s)
+{
+ Str tmp = Strnew();
+ int day;
+ char *ss = *s;
+
+ if (!**s)
+ return -1;
+
+ while (**s && IS_DIGIT(**s))
+ Strcat_char(tmp, *((*s)++));
+
+ day = atoi(tmp->ptr);
+
+ if (day < 1 || day > 31) {
+ *s = ss;
+ return -1;
+ }
+ return day;
+}
+
+static int
+get_month(char **s)
+{
+ Str tmp = Strnew();
+ int mon;
+ char *ss = *s;
+
+ if (!**s)
+ return -1;
+
+ while (**s && IS_DIGIT(**s))
+ Strcat_char(tmp, *((*s)++));
+ if (tmp->length > 0) {
+ mon = atoi(tmp->ptr);
+ }
+ else {
+ while (**s && IS_ALPHA(**s))
+ Strcat_char(tmp, *((*s)++));
+ for (mon = 1; mon <= 12; mon++) {
+ if (strncmp(tmp->ptr, monthtbl[mon - 1], 3) == 0)
+ break;
+ }
+ }
+ if (mon < 1 || mon > 12) {
+ *s = ss;
+ return -1;
+ }
+ return mon;
+}
+
+static int
+get_year(char **s)
+{
+ Str tmp = Strnew();
+ int year;
+ char *ss = *s;
+
+ if (!**s)
+ return -1;
+
+ while (**s && IS_DIGIT(**s))
+ Strcat_char(tmp, *((*s)++));
+ if (tmp->length != 2 && tmp->length != 4) {
+ *s = ss;
+ return -1;
+ }
+
+ year = atoi(tmp->ptr);
+ if (tmp->length == 2) {
+ if (year >= 70)
+ year += 1900;
+ else
+ year += 2000;
+ }
+ return year;
+}
+
+static int
+get_time(char **s, int *hour, int *min, int *sec)
+{
+ Str tmp = Strnew();
+ char *ss = *s;
+
+ if (!**s)
+ return -1;
+
+ while (**s && IS_DIGIT(**s))
+ Strcat_char(tmp, *((*s)++));
+ if (**s != ':') {
+ *s = ss;
+ return -1;
+ }
+ *hour = atoi(tmp->ptr);
+
+ (*s)++;
+ Strclear(tmp);
+ while (**s && IS_DIGIT(**s))
+ Strcat_char(tmp, *((*s)++));
+ if (**s != ':') {
+ *s = ss;
+ return -1;
+ }
+ *min = atoi(tmp->ptr);
+
+ (*s)++;
+ Strclear(tmp);
+ while (**s && IS_DIGIT(**s))
+ Strcat_char(tmp, *((*s)++));
+ *sec = atoi(tmp->ptr);
+
+ if (*hour < 0 || *hour >= 24 ||
+ *min < 0 || *min >= 60 ||
+ *sec < 0 || *sec >= 60) {
+ *s = ss;
+ return -1;
+ }
+ return 0;
+}
+
+/* RFC 1123 or RFC 850 or ANSI C asctime() format string -> time_t */
+time_t
+mymktime(char *timestr)
+{
+ char *s;
+ int day, mon, year, hour, min, sec;
+
+ if (!(timestr && *timestr))
+ return -1;
+ s = timestr;
+
+#ifdef DEBUG
+ fprintf(stderr, "mktime: %s\n", timestr);
+#endif /* DEBUG */
+
+ while (*s && IS_ALPHA(*s))
+ s++;
+ while (*s && !IS_ALNUM(*s))
+ s++;
+
+ if (IS_DIGIT(*s)) {
+ /* RFC 1123 or RFC 850 format */
+ if ((day = get_day(&s)) == -1)
+ return -1;
+
+ while (*s && !IS_ALNUM(*s))
+ s++;
+ if ((mon = get_month(&s)) == -1)
+ return -1;
+
+ while (*s && !IS_DIGIT(*s))
+ s++;
+ if ((year = get_year(&s)) == -1)
+ return -1;
+
+ while (*s && !IS_DIGIT(*s))
+ s++;
+ if (!*s) {
+ hour = 0;
+ min = 0;
+ sec = 0;
+ }
+ else if (get_time(&s, &hour, &min, &sec) == -1) {
+ return -1;
+ }
+ }
+ else {
+ /* ANSI C asctime() format. */
+ while (*s && !IS_ALNUM(*s))
+ s++;
+ if ((mon = get_month(&s)) == -1)
+ return -1;
+
+ while (*s && !IS_DIGIT(*s))
+ s++;
+ if ((day = get_day(&s)) == -1)
+ return -1;
+
+ while (*s && !IS_DIGIT(*s))
+ s++;
+ if (get_time(&s, &hour, &min, &sec) == -1)
+ return -1;
+
+ while (*s && !IS_DIGIT(*s))
+ s++;
+ if ((year = get_year(&s)) == -1)
+ return -1;
+ }
+#ifdef DEBUG
+ fprintf(stderr, "year=%d month=%d day=%d hour:min:sec=%d:%d:%d\n",
+ year, mon, day, hour, min, sec);
+#endif /* DEBUG */
+
+ mon -= 3;
+ if (mon < 0) {
+ mon += 12;
+ year--;
+ }
+ day += (year - 1968) * 1461 / 4;
+ day += ((((mon * 153) + 2) / 5) - 672);
+ return (time_t) ((day * 60 * 60 * 24) +
+ (hour * 60 * 60) +
+ (min * 60) +
+ sec);
+}
+
+#ifdef INET6
+#include <sys/socket.h>
+#endif /* INET6 */
+#include <netdb.h>
+char *
+FQDN(char *host)
+{
+ char *p;
+#ifndef INET6
+ struct hostent *entry;
+#else /* INET6 */
+ int *af;
+#endif /* INET6 */
+
+ if (host == NULL)
+ return NULL;
+
+ if (strcasecmp(host, "localhost") == 0)
+ return host;
+
+ for (p = host; *p && *p != '.'; p++);
+
+ if (*p == '.')
+ return host;
+
+#ifndef INET6
+ if (!(entry = gethostbyname(host)))
+ return NULL;
+
+ return allocStr(entry->h_name, 0);
+#else /* INET6 */
+ for (af = ai_family_order_table[DNS_order];; af++) {
+ int error;
+ struct addrinfo hints;
+ struct addrinfo *res, *res0;
+ char *namebuf;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = *af;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(host, NULL, &hints, &res0);
+ if (error) {
+ if (*af == PF_UNSPEC) {
+ /* all done */
+ break;
+ }
+ /* try next address family */
+ continue;
+ }
+ for (res = res0; res != NULL; res = res->ai_next) {
+ if (res->ai_canonname) {
+ /* found */
+ namebuf = strdup(res->ai_canonname);
+ freeaddrinfo(res0);
+ return namebuf;
+ }
+ }
+ freeaddrinfo(res0);
+ if (*af == PF_UNSPEC) {
+ break;
+ }
+ }
+ /* all failed */
+ return NULL;
+#endif /* INET6 */
+}
+
+#endif /* USE_COOKIE */