|
const char * wiki_getline (XML * target, const char * attr, const char * src)
{
const char * mark;
mark = src;
while (*mark && *mark != '\n') mark++;
xml_attrncat (target, attr, src, mark - src);
if (*mark) mark++;
return (mark);
}
XML * wiki_parse (const char * src)
{
XML * ret;
XML * cur;
XML * new;
XML * check;
const char * mark;
const char * mark2;
int ital = 0;
int bold = 0;
int list = 0;
int oldindent = 0;
int listindent = 0;
int indent = 0;
int blockquote = 0;
int link = 0;
int nofile;
int linestart = 1;
XML * image;
ret = xml_create ("wiki");
cur = ret;
mark = src;
while (*mark) {
if (linestart) {
/* Deal with line breaks first. */
while (*mark == '\r') mark++;
while (*mark == '\n') {
xml_append (cur, xml_createtextlen (src, mark - src));
xml_append (cur, xml_create ("br"));
xml_append (cur, xml_create ("br"));
mark += 1; while (*mark == '\r') mark++;
src = mark;
}
/* Now deal with indentation. */
oldindent = indent; indent = 0;
while (*mark == ' ') {
indent++;
mark++;
}
if (list) {
if (indent < listindent) {
xml_append (cur, xml_createtextlen (src, mark - src - indent));
if (xml_is (cur, "li")) cur = xml_parent (cur); /* pop */
cur = xml_parent (cur); /* pop */
list = 0;
src = mark;
}
} else if (blockquote && indent < oldindent) {
xml_append (cur, xml_createtextlen (src, mark - src - indent));
cur = xml_parent (cur); /* pop */
blockquote = 0;
src = mark;
}
if (indent > oldindent) {
if (*mark == '-') {
xml_append (cur, xml_createtextlen (src, mark - src - indent));
new = xml_create ("ul");
xml_append (cur, new);
cur = new;
list = 1;
} else if (!list) {
xml_append (cur, xml_createtextlen (src, mark - src - indent));
new = xml_create ("blockquote");
xml_append (cur, new);
cur = new;
blockquote = 1;
}
}
if (list && *mark == '-') {
if (xml_is (cur, "li")) {
xml_append (cur, xml_createtextlen (src, mark - src - indent));
cur = xml_parent (cur); /* pop */
}
new = xml_create ("li");
xml_append (cur, new);
cur = new; /* push */
mark ++;
while (*mark && *mark == ' ') mark++;
src = mark;
}
}
/* We're past the start of the line now -- let's deal with everything else! */
linestart = 0;
switch (*mark) {
case '\n':
if (!strncmp (mark, "\n\n", 2) || !strncmp (mark, "\n\r\n", 3)) {
linestart = 1;
}
break;
case '\'':
if (!strncmp (mark, "''''", 4)) {
xml_append (cur, xml_createtextlen (src, mark - src));
if (!bold) {
new = xml_create ("b");
xml_append (cur, new);
cur = new; /* push */
bold = 1;
} else {
cur = xml_parent (cur);
bold = 0;
}
mark += 3;
src = mark + 1;
} else if (!strncmp (mark, "'''", 3)) {
xml_append (cur, xml_createtextlen (src, mark - src));
src = mark;
if (!ital) {
new = xml_create ("i");
xml_append (cur, new);
cur = new;
ital = 1;
} else {
cur = xml_parent (cur);
ital = 0;
}
mark += 2;
src = mark + 1;
}
break;
case '{':
if (mark[1] == '{') {
xml_append (cur, xml_createtextlen (src, mark - src));
src = mark + 2;
mark = strchr (src, '}');
if (mark) {
if (*src == '/') {
/* Terminate last style (and anything else on the way.) */
check = cur;
while (check && !xml_is (check, "span")) check = xml_parent(check);
if (check) cur = xml_parent(check);
} else {
/* Start new style span. */
new = xml_create ("span");
xml_set (new, "class", "");
xml_attrncat (new, "class", src, mark - src);
xml_append (cur, new);
cur = new;
}
while (*mark == '}') mark++;
src = mark;
mark --;
}
}
break;
case '*': /* directive or link */
if (mark[1] == '-') {
xml_append (cur, xml_createtextlen (src, mark - src));
/* directive */
src = mark + 2;
for (mark = src; *mark && *mark != ':' && *mark != '\n'; mark++);
if (*mark == ':') { /* well-formed directive */
if (mark - src == 4 && !strncmp (src, "list", 4)) {
new = xml_create ("wiki:embed");
xml_set (new, "type", "list");
xml_set (new, "object", "");
src = mark + 1;
mark = src;
while (isalnum(*mark) || *mark == '_') mark++;
xml_attrncat (new, "object", src, mark - src);
while (*mark == ' ') mark++;
if (*mark == '(') { /* Sort column. */
src = mark + 1;
mark++;
while (isalnum (*mark) || *mark == '_') mark++;
xml_set (new, "order", "");
xml_attrncat (new, "order", src, mark - src);
while (*mark == ' ') mark++;
if (*mark == '#') { xml_set (new, "op", "num"); mark ++; while (*mark == ' ') mark++; }
if (*mark == '-') { /* Do something with dir="desc" */ mark++; while (*mark == ' ') mark++; }
if (*mark == ')') { mark++; while (*mark == ' ') mark++; }
src = mark + 1;
while (*mark == ' ') mark++;
}
if (*mark != '.') {
xml_set (new, "content", "");
while (*mark && strncmp (mark, "*-EOF", 5)) {
mark = wiki_getline (new, "content", mark);
xml_attrcat (new, "content", "\n");
}
xml_attrcat (new, "content", "");
check = xml_parse (xml_attrval (new, "content"));
xml_copyinto (new, check);
xml_free (check);
xml_set (new, "content", "");
}
while (*mark && *mark != '\n') mark++;
xml_append (cur, new);
}
else if (mark - src == 6 && !strncmp (src, "layout", 6)) {
src = mark + 1;
new = xml_create ("wiki:embed");
xml_set (new, "type", "layout");
mark = src;
while (*mark == ' ') mark++;
if (*mark != '.') {
xml_set (new, "content", "");
while (*mark && strncmp (mark, "*-EOF", 5)) {
mark = wiki_getline (new, "content", mark);
xml_attrcat (new, "content", "\n");
}
xml_attrcat (new, "content", "");
check = xml_parse (xml_attrval (new, "content"));
xml_copyinto (new, check);
xml_free (check);
xml_set (new, "content", "");
}
while (*mark && *mark != '\n') mark++;
xml_append (cur, new);
}
else if (mark - src == 4 && !strncmp (src, "text", 4)) {
new = xml_create ("wiki:text");
xml_set (new, "name", "");
src = mark + 1;
mark = src;
while (isalnum(*mark) || *mark == '_') mark++;
xml_attrncat (new, "name", src, mark - src);
if (!*xml_attrval (new, "name")) xml_set (new, "name", "text");
while (*mark == ' ') mark++;
if (*mark != '.') {
xml_set (new, "content", "");
while (*mark && strncmp (mark, "*-EOF", 5)) {
mark = wiki_getline (new, "content", mark);
xml_attrcat (new, "content", "\n");
}
check = wiki_parse (xml_attrval (new, "content"));
xml_copyinto (new, check);
xml_free (check);
xml_set (new, "content", "");
}
while (*mark && *mark != '\n') mark++;
xml_append (cur, new);
}
}
if (*mark) mark++;
src = mark;
mark --;
} else if (isalnum (mark[1]) || mark[1] == '_') {
xml_append (cur, xml_createtextlen (src, mark - src));
/* link: internal, external, or tagged? */
mark++; src = mark;
while (isalnum (*mark) || (*mark == '_')) mark++;
new = xml_create ("link");
xml_append (cur, new);
xml_set (new, "linktype", "page");
if (*mark == ':') {
/* Object specification. */
if (mark - src == 4 && !strncmp (src, "http", 4)) {
xml_set (new, "linktype", "url");
} else if (mark - src == 5 && !strncmp (src, "https", 5)) {
xml_set (new, "linktype", "url");
} else if (mark - src == 6 && !strncmp (src, "mailto", 6)) {
xml_set (new, "linktype", "url");
} else if (mark - src == 3 && !strncmp (src, "ftp", 3)) {
xml_set (new, "linktype", "url");
} else if (mark - src == 4 && !strncmp (src, "link", 4)) {
xml_set (new, "linktype", "link");
src = mark + 1;
mark = src;
} else {
xml_set (new, "linktype", "object");
xml_set (new, "object", "");
xml_attrncat (new, "object", src, mark - src);
src = mark + 1;
mark = src;
}
while (*mark &&
*mark != ' ' &&
*mark != '\n' &&
*mark != '\r' &&
*mark != '\t' &&
*mark != '"') mark++;
}
xml_set (new, "link", "");
xml_attrncat (new, "link", src, mark - src);
if (*mark == '"') {
link ++;
cur = new;
src = mark +1;
mark = src;
break;
} else {
if (!strcmp (xml_attrval (new, "linktype"), "url")) {
if (strncmp (xml_attrval (new, "link"), "mailto:", 7))
xml_append (new, xml_createtext (xml_attrval (new, "link")));
else
xml_append (new, xml_createtext (xml_attrval (new, "link") + 7));
}
src = mark;
}
}
break;
case '"':
if (link) {
xml_append (cur, xml_createtextlen (src, mark - src));
src = mark + 1;
link--;
cur = xml_parent (cur);
}
break;
case '[':
if (mark[1] == '[') {
xml_append (cur, xml_createtextlen (src, mark - src));
src = mark + 2;
mark = src;
while (isalnum (*mark) || (*mark == '_')) mark++;
image = xml_create ("image");
xml_set (image, "name", "");
xml_attrncat (image, "name", src, mark - src);
xml_append (cur, image);
do {
while (*mark == ' ') mark++;
switch (*mark) {
case '"':
src = mark+1; mark = src;
while (*mark && *mark != '"') mark++;
xml_set (image, "alt", "");
xml_attrncat (image, "alt", src, mark - src);
mark++;
break;
case '!':
src = mark+1; mark = src;
while (isalpha(*mark)) mark++;
xml_set (image, "align", "");
xml_attrncat (image, "align", src, mark - src);
break;
}
} while (*mark == ' ');
while (*mark && (*mark != ']')) mark++;
while (*mark == ']') mark++;
src = mark;
mark --;
}
break;
}
if (*mark) mark ++;
}
xml_append (cur, xml_createtext (src));
return ret;
}
|