|  | 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;
}
 |