diff options
author | Akinori Ito <aito@eie.yz.yamagata-u.ac.jp> | 2001-11-08 05:14:08 +0000 |
---|---|---|
committer | Akinori Ito <aito@eie.yz.yamagata-u.ac.jp> | 2001-11-08 05:14:08 +0000 |
commit | 68a07bf03b7624c9924065cce9ffa45497225834 (patch) | |
tree | c2adb06a909a8594445e4a3f8587c4bad46e3ecd /parsetagx.c | |
download | w3m-68a07bf03b7624c9924065cce9ffa45497225834.tar.gz w3m-68a07bf03b7624c9924065cce9ffa45497225834.zip |
Initial revision
Diffstat (limited to 'parsetagx.c')
-rw-r--r-- | parsetagx.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/parsetagx.c b/parsetagx.c new file mode 100644 index 0000000..712fbe8 --- /dev/null +++ b/parsetagx.c @@ -0,0 +1,273 @@ +#include "fm.h" +#include "myctype.h" +#include "indep.h" +#include "Str.h" +#include "parsetagx.h" +#include "hash.h" + +#include "html.c" + +/* parse HTML tag */ + +static int noConv(char *, char **); +static int toNumber(char *, int *); +static int toLength(char *, int *); +static int toAlign(char *, int *); +static int toVAlign(char *, int *); + +static int (*toValFunc[]) () = { + noConv, /* VTYPE_NONE */ + noConv, /* VTYPE_STR */ + toNumber, /* VTYPE_NUMBER */ + toLength, /* VTYPE_LENGTH */ + toAlign, /* VTYPE_ALIGN */ + toVAlign, /* VTYPE_VALIGN */ + noConv, /* VTYPE_ACTION */ + noConv, /* VTYPE_ENCTYPE */ + noConv, /* VTYPE_METHOD */ + noConv, /* VTYPE_MLENGTH */ + noConv, /* VTYPE_TYPE */ +}; + +static int +noConv(char *oval, char **str) +{ + *str = oval; + return 1; +} + +static int +toNumber(char *oval, int *num) +{ + *num = atoi(oval); + return 1; +} + +static int +toLength(char *oval, int *len) +{ + int w; + if (!IS_DIGIT(oval[0])) + return 0; + w = atoi(oval); + if (w < 0) + return 0; + if (w == 0) + w = 1; + if (oval[strlen(oval) - 1] == '%') + *len = -w; + else + *len = w; + return 1; +} + +static int +toAlign(char *oval, int *align) +{ + if (strcasecmp(oval, "left") == 0) + *align = ALIGN_LEFT; + else if (strcasecmp(oval, "right") == 0) + *align = ALIGN_RIGHT; + else if (strcasecmp(oval, "center") == 0) + *align = ALIGN_CENTER; + else + return 0; + return 1; +} + +static int +toVAlign(char *oval, int *valign) +{ + if (strcasecmp(oval, "top") == 0 || + strcasecmp(oval, "baseline") == 0) + *valign = VALIGN_TOP; + else if (strcasecmp(oval, "bottom") == 0) + *valign = VALIGN_BOTTOM; + else if (strcasecmp(oval, "middle") == 0) + *valign = VALIGN_MIDDLE; + else + return 0; + return 1; +} + +extern Hash_si tagtable; +#define MAX_TAG_LEN 64 + +struct parsed_tag * +parse_tag(char **s, int internal) +{ + struct parsed_tag *tag = NULL; + int tag_id; + char *tagname = NewAtom_N(char, MAX_TAG_LEN), + attrname[MAX_TAG_LEN]; + char *p, *q; + int i, attr_id, nattr; + + /* Parse tag name */ + q = (*s) + 1; + p = tagname; + if (*q == '/') { + *(p++) = *(q++); + SKIP_BLANKS(q); + } + while (*q && !IS_SPACE(*q) && *q != '>' && + p - tagname < MAX_TAG_LEN - 1) { + *(p++) = tolower(*(q++)); + } + *p = '\0'; + + tag_id = getHash_si(&tagtable, tagname, HTML_UNKNOWN); + + if (tag_id == HTML_UNKNOWN || + (!internal && TagMAP[tag_id].flag & TFLG_INT)) + goto skip_parse_tagarg; + + tag = New(struct parsed_tag); + bzero(tag, sizeof(struct parsed_tag)); + tag->tagid = tag_id; + tag->tagname = tagname; + + if ((nattr = TagMAP[tag_id].max_attribute) > 0) { + tag->attrid = NewAtom_N(unsigned char, nattr); + tag->value = New_N(char *, nattr); + tag->map = NewAtom_N(unsigned char, MAX_TAGATTR); + memset(tag->map, MAX_TAGATTR, MAX_TAGATTR); + memset(tag->attrid, ATTR_UNKNOWN, nattr); + for (i = 0; i < nattr; i++) + tag->map[TagMAP[tag_id].accept_attribute[i]] = i; + } + + /* Parse tag arguments */ + SKIP_BLANKS(q); + while (1) { + Str value = NULL; + if (*q == '>' || *q == '\0') + goto done_parse_tag; + p = attrname; + while (*q && *q != '=' && !IS_SPACE(*q) && + *q != '>' && p - attrname < MAX_TAG_LEN - 1) { + *(p++) = tolower(*(q++)); + } + if (q == p) { + q++; + continue; + } + *p = '\0'; + SKIP_BLANKS(q); + if (*q == '=') { + /* get value */ + value = Strnew(); + q++; + SKIP_BLANKS(q); + if (*q == '"') { + q++; + while (*q && *q != '"') { + if (*q != '\n') + Strcat_char(value, *q); + if (!tag->need_reconstruct && htmlquote_char(*q)) + tag->need_reconstruct = TRUE; + q++; + } + if (*q == '"') + q++; + } + else if (*q == '\'') { + q++; + while (*q && *q != '\'') { + if (*q != '\n') + Strcat_char(value, *q); + if (!tag->need_reconstruct && htmlquote_char(*q)) + tag->need_reconstruct = TRUE; + q++; + } + if (*q == '\'') + q++; + } + else if (*q) { + while (*q && !IS_SPACE(*q) && *q != '>') + Strcat_char(value, *q++); + } + } + for (i = 0; i < nattr; i++) { + if ((tag)->attrid[i] == ATTR_UNKNOWN && + strcmp(AttrMAP[TagMAP[tag_id].accept_attribute[i]].name, + attrname) == 0) { + attr_id = TagMAP[tag_id].accept_attribute[i]; + break; + } + } + if (i != nattr) { + if (!internal && + ((AttrMAP[attr_id].flag & AFLG_INT) || + (value && AttrMAP[attr_id].vtype == VTYPE_METHOD && + !strcasecmp(value->ptr, "internal")))) { + tag->need_reconstruct = TRUE; + continue; + } + tag->attrid[i] = attr_id; + if (value) + tag->value[i] = cleanup_str(value->ptr); + else + tag->value[i] = NULL; + } + } + + skip_parse_tagarg: + while (*q != '>' && *q) + q++; + done_parse_tag: + if (*q == '>') + q++; + *s = q; + return tag; +} + +int +parsedtag_set_value(struct parsed_tag *tag, int id, char *value) +{ + int i; + + if (!parsedtag_accepts(tag, id)) + return 0; + + i = tag->map[id]; + tag->attrid[i] = id; + if (value) + tag->value[i] = allocStr(value, 0); + else + tag->value[i] = NULL; + tag->need_reconstruct = TRUE; + return 1; +} + +int +parsedtag_get_value(struct parsed_tag *tag, int id, void *value) +{ + int i; + if (!parsedtag_exists(tag, id) || + !tag->value[i = tag->map[id]]) + return 0; + return toValFunc[AttrMAP[id].vtype](tag->value[i], value); +} + +Str +parsedtag2str(struct parsed_tag *tag) +{ + int i; + int tag_id = tag->tagid; + int nattr = TagMAP[tag_id].max_attribute; + Str tagstr = Strnew(); + Strcat_char(tagstr, '<'); + Strcat_charp(tagstr, tag->tagname); + for (i = 0; i < nattr; i++) { + if (tag->attrid[i] != ATTR_UNKNOWN) { + Strcat_char(tagstr, ' '); + Strcat_charp(tagstr, AttrMAP[tag->attrid[i]].name); + if (tag->value[i]) + Strcat(tagstr, + Sprintf("=\"%s\"", htmlquote_str(tag->value[i]))); + } + } + Strcat_char(tagstr, '>'); + return tagstr; +} |