#include "form.h"
static int compare_attr(attr_t *a0, attr_t *a1);
static int compare_elements(char **e0, char **e1);
static int parse_attr(tree_t *t, FILE *fp);
static int parse_element(tree_t *t, FILE *fp);
static char *elements[] =
{
"",
"!--",
"ARC",
"BOX",
"BR",
"B",
"CUPSFORM",
"DEFVAR",
"FONT",
"H1",
"H2",
"H3",
"H4",
"H5",
"H6",
"HEAD",
"IMG",
"I",
"LINE",
"PAGE",
"PIE",
"POLY",
"PRE",
"P",
"RECT",
"TEXT",
"TT",
"VAR"
};
void
formDelete(tree_t *t)
{
}
char *
formGetAttr(tree_t *t,
const char *name)
{
}
tree_t *
formNew(tree_t *p)
{
tree_t *t;
if ((t = (tree_t *)calloc(sizeof(tree_t), 1)) == NULL)
return (NULL);
if (p == NULL)
{
t->bg[0] = 1.0;
t->bg[1] = 1.0;
t->bg[2] = 1.0;
t->halign = HALIGN_LEFT;
t->valign = VALIGN_MIDDLE;
t->typeface = "Courier";
t->size = 12.0;
}
else
{
memcpy(t, p, sizeof(tree_t));
t->prev = NULL;
t->next = NULL;
t->child = NULL;
t->last_child = NULL;
t->parent = NULL;
t->num_attrs = 0;
t->attrs = NULL;
t->data = NULL;
}
return (t);
}
tree_t *
formRead(FILE *fp,
tree_t *p)
{
int ch,
closech,
have_whitespace;
static char s[10240];
uchar *ptr,
glyph[16],
*glyphptr;
tree_t *tree,
*t,
*prev,
*temp;
uchar *face,
*color,
*size;
prev = NULL;
tree = NULL;
while ((ch = getc(fp)) != EOF)
{
have_whitespace = 0;
closech = '/';
if (p == NULL || !p->preformatted)
{
while (isspace(ch & 255))
{
have_whitespace = 1;
ch = getc(fp);
}
if (ch == EOF)
break;
}
t = formNew(p);
if (ch == '<')
{
ch = getc(fp);
if (ch == ' ')
{
free(t);
continue;
}
if (ch != '/')
ungetc(ch, fp);
if (parse_element(t, fp) < 0)
{
free(t);
break;
}
if ((closech = getc(fp)) == '/')
getc(fp);
if (ch == '/')
{
for (temp = p; temp != NULL; temp = temp->p)
if (temp->element == t->element)
break;
free(t);
if (temp != NULL)
break;
else
continue;
}
}
else if (t->preformatted)
{
ptr = s;
while (ch != '<' && ch != EOF && ptr < (s + sizeof(s) - 1))
{
if (ch == '&')
{
for (glyphptr = glyph;
(ch = getc(fp)) != EOF && (glyphptr - glyph) < 15;
glyphptr ++)
if (!isalnum(ch & 255))
break;
else
*glyphptr = ch;
*glyphptr = '\0';
if (atoi(glyph) > 0)
ch = atoi(glyph);
else if (strcmp(glyph, "lt") == 0)
ch = '<';
else if (strcmp(glyph, "gt") == 0)
ch = '>';
else if (strcmp(glyph, "quot") == 0)
ch = '\'';
else if (strcmp(glyph, "nbsp") == 0)
ch = ' ';
else
ch = '&';
}
if (ch != 0)
*ptr++ = ch;
if (ch == '\n')
break;
ch = getc(fp);
}
*ptr = '\0';
if (ch == '<')
ungetc(ch, fp);
t->element = ELEMENT_FRAGMENT;
t->data = strdup(s);
}
else
{
ptr = s;
if (have_whitespace)
*ptr++ = ' ';
while (!isspace(ch & 255) && ch != '<' && ch != EOF && ptr < (s + sizeof(s) - 1))
{
if (ch == '&')
{
for (glyphptr = glyph;
(ch = getc(fp)) != EOF && (glyphptr - glyph) < 15;
glyphptr ++)
if (!isalnum(ch & 255))
break;
else
*glyphptr = ch;
*glyphptr = '\0';
if (atoi(glyph) > 0)
ch = atoi(glyph);
else if (strcmp(glyph, "lt") == 0)
ch = '<';
else if (strcmp(glyph, "gt") == 0)
ch = '>';
else if (strcmp(glyph, "quot") == 0)
ch = '\'';
else if (strcmp(glyph, "nbsp") == 0)
ch = ' ';
else
ch = '&';
}
if (ch != 0)
*ptr++ = ch;
ch = getc(fp);
}
if (isspace(ch & 255))
*ptr++ = ' ';
*ptr = '\0';
if (ch == '<')
ungetc(ch, fp);
t->element = ELEMENT_FRAGMENT;
t->data = strdup(s);
}
if (p != NULL && prev == NULL)
p->child = t;
if (p != NULL)
p->last_child = t;
t->parent = p;
t->prev = prev;
if (prev != NULL)
prev->next = t;
else
tree = t;
prev = t;
if (closech == '>')
t->child = formRead(t, fp);
}
return (tree);
}
void
formSetAttr(tree_t *t,
const char *name,
const char *value)
{
}
static int
compare_attr(attr_t *a0,
attr_t *a1)
{
return (strcasecmp(a0->name, a1->name));
}
static int
compare_elements(char **e0,
char **e1)
{
return (strcasecmp(*e0, *e1));
}
static int
parse_attr(tree_t *t,
FILE *fp)
{
char name[1024],
value[10240],
*ptr;
int ch;
ptr = name;
while ((ch = getc(fp)) != EOF)
if (isalnum(ch & 255))
{
if (ptr < (name + sizeof(name) - 1))
*ptr++ = ch;
}
else
break;
*ptr = '\0';
while (isspace(ch & 255) || ch == '\r')
ch = getc(fp);
switch (ch)
{
default :
ungetc(ch, fp);
return (formSetAttr(t, name, NULL));
case EOF :
return (-1);
case '=' :
ptr = value;
ch = getc(fp);
while (isspace(ch & 255) || ch == '\r')
ch = getc(fp);
if (ch == EOF)
return (-1);
if (ch == '\'')
{
while ((ch = getc(fp)) != EOF)
if (ch == '\'')
break;
else if (ptr < (value + sizeof(value) - 1))
*ptr++ = ch;
*ptr = '\0';
}
else if (ch == '\"')
{
while ((ch = getc(fp)) != EOF)
if (ch == '\"')
break;
else if (ptr < (value + sizeof(value) - 1))
*ptr++ = ch;
*ptr = '\0';
}
else
{
*ptr++ = ch;
while ((ch = getc(fp)) != EOF)
if (isspace(ch & 255) || ch == '>' || ch == '/' || ch == '\r')
break;
else if (ptr < (value + sizeof(value) - 1))
*ptr++ = ch;
*ptr = '\0';
if (ch == '>' || ch == '/')
ungetc(ch, fp);
}
return (formSetAttr(t, name, value));
}
}
static int
parse_element(tree_t *t,
FILE *fp)
{
int ch;
char element[255],
*eptr,
comment[10240],
*cptr,
**temp;
eptr = element;
while ((ch = getc(fp)) != EOF && eptr < (element + sizeof(element) - 1))
if (ch == '>' || ch == '/' || isspace(ch & 255))
break;
else
*eptr++ = ch;
*eptr = '\0';
if (ch == EOF)
return (ELEMENT_ERROR);
eptr = element;
temp = bsearch(&mptr, elements, sizeof(elements) / sizeof(elements[0]),
sizeof(elements[0]),
(int (*)(const void *, const void *))compare_elements);
if (temp == NULL)
{
t->element = ELEMENT_COMMENT;
strcpy(comment, element);
cptr = comment + strlen(comment);
}
else
{
t->element = (element_t)((char **)temp - elements);
cptr = comment;
}
if (t->element == ELEMENT_COMMENT)
{
while (ch != EOF && ch != '>' && cptr < (comment + sizeof(comment) - 1))
{
*cptr++ = ch;
ch = getc(fp);
}
*cptr = '\0';
t->data = strdup(comment);
}
else
{
while (ch != EOF && ch != '>' && ch != '/')
{
if (!isspace(ch & 255))
{
ungetc(ch, fp);
parse_variable(t, fp);
}
ch = getc(fp);
}
if (ch != EOF)
ungetc(ch, fp);
}
return (t->element);
}