#include static void print(FILE* out, const char* txt, int pre, int indent) { int i; for(i = 0;; i++) { if(i == 0 || txt[i] == '\n' || txt[i] == 0) { int j; if(pre ? (txt[i] == '\n') : (i > 0)) fprintf(out, "\n"); if(txt[i] == 0) break; if(!pre) for(j = 0; j < indent; j++) fprintf(out, "\t"); } if(txt[i] != '\n') fprintf(out, "%c", txt[i]); } } static void accept_attr(const char* top, char* text, int spec, xl_node_t* element, ...) { xl_attribute_t* attr = element->first_attribute; text[0] = 0; while(attr != NULL) { va_list va; const char* s; va_start(va, element); while((s = va_arg(va, const char*)) != NULL) { if(strcmp(attr->key, s) != 0) continue; if(attr->value == NULL) { sprintf(text + strlen(text), " %s", attr->key); } else { char* t; if(spec && (strcmp(attr->key, "href") == 0 || strcmp(attr->key, "src") == 0)) { t = u_path(top, attr->value); } else { t = u_strdup(attr->value); } sprintf(text + strlen(text), " %s=\"%s\"", attr->key, t); free(t); } } va_end(va); attr = attr->next; } } void default_head(FILE* out, const char* top, xl_node_t* element, const char* input, int indent) { xl_node_t* child; char tag[2048]; char end[128]; int add = 0; tag[0] = end[0] = 0; if(element->name == NULL) return; if(strcmp(element->name, "link") == 0) { char text[2048]; accept_attr(top, text, 0, element, "rel", "href", NULL); sprintf(tag, "<%s%s>", element->name, text); } if(tag[0] != 0) print(out, tag, 0, indent); child = element->first_child; while(child != NULL) { if(child->type == XL_NODE_NODE && child->name != NULL) { default_head(out, top, child, input, indent + 1 + add); } else if(child->type == XL_NODE_TEXT && child->text != NULL) { /* most likely junk */ #if 0 print(out, child->text, indent + 1 + add); #endif } child = child->next; } if(end[0] != 0) print(out, end, 0, indent); } void default_body(FILE* out, const char* top, xl_node_t* element, const char* input, int spec, int pre, int indent) { xl_node_t* child; char tag[2048]; /* enough for most cases... :) */ char end[128]; char text[2048]; int add = 0; tag[0] = end[0] = 0; if(element->name == NULL) return; if(strcmp(element->name, "section") == 0) { char* title = xl_get_attribute(element, "title"); char* id = u_section_id(element); if(id != NULL) sprintf(tag, "
%s
", id, title); } else if(strcmp(element->name, "fixme") == 0 || /**/ strcmp(element->name, "warning") == 0 || /**/ strcmp(element->name, "note") == 0) { char* say = ""; char author[2048]; char* attr; author[0] = 0; accept_attr(top, text, 0, element, "id", "class", NULL); if(strcmp(element->name, "fixme") == 0) { say = "Fixme"; strcpy(author, " ()"); if((attr = xl_get_attribute(element, "author")) != NULL) sprintf(author, " (%s)", attr); } else if(strcmp(element->name, "warning") == 0) { say = "Warning"; } else if(strcmp(element->name, "note") == 0) { say = "Note"; } sprintf(tag + strlen(tag), "
\n", element->name, text); sprintf(tag + strlen(tag), " \n"); sprintf(tag + strlen(tag), " \n"); sprintf(tag + strlen(tag), " \n"); sprintf(tag + strlen(tag), " \n"); sprintf(tag + strlen(tag), " \n"); sprintf(tag + strlen(tag), " \n"); sprintf(tag + strlen(tag), " \n"); sprintf(end + strlen(end), " \n"); sprintf(end + strlen(end), "
\n"); sprintf(tag + strlen(tag), " \"%s\"\n", top, element->name, say); sprintf(tag + strlen(tag), " \n"); sprintf(tag + strlen(tag), " %s%s\n", say, author); sprintf(tag + strlen(tag), "
"); sprintf(end + strlen(end), "
\n"); sprintf(end + strlen(end), "
", element->name); add = 3; } else if(strcmp(element->name, "p") == 0 || /**/ strcmp(element->name, "code") == 0 || /**/ strcmp(element->name, "pre") == 0 || /**/ strcmp(element->name, "blockquote") == 0 || /**/ strcmp(element->name, "li") == 0 || /**/ strcmp(element->name, "dt") == 0 || /**/ strcmp(element->name, "dd") == 0 || /**/ strcmp(element->name, "strong") == 0 || /**/ strcmp(element->name, "del") == 0 || /**/ strcmp(element->name, "u") == 0 || /**/ strcmp(element->name, "sub") == 0 || /**/ strcmp(element->name, "sup") == 0 || /**/ strcmp(element->name, "tr") == 0 || /**/ strcmp(element->name, "em") == 0 || /**/ strcmp(element->name, "h1") == 0 || /**/ strcmp(element->name, "h2") == 0 || /**/ strcmp(element->name, "h3") == 0 || /**/ strcmp(element->name, "h4") == 0 || /**/ strcmp(element->name, "h5") == 0 || /**/ strcmp(element->name, "h6") == 0) { accept_attr(top, text, 0, element, "id", "class", NULL); if(strcmp(element->name, "pre") == 0) pre = 1; sprintf(tag, "<%s%s>", element->name, text); sprintf(end, "", element->name); } else if(strcmp(element->name, "ul") == 0 || /**/ strcmp(element->name, "ol") == 0) { accept_attr(top, text, 0, element, "id", "class", "spacing", NULL); sprintf(tag, "<%s%s>", element->name, text); sprintf(end, "", element->name); } else if(strcmp(element->name, "a") == 0) { accept_attr(top, text, 0, element, "id", "class", "href", "title", "rel", NULL); sprintf(tag, "<%s%s>", element->name, text); sprintf(end, "", element->name); } else if(strcmp(element->name, "th") == 0 || /**/ strcmp(element->name, "td") == 0) { accept_attr(top, text, 0, element, "id", "class", "rowspan", "colspan", "width", "height", NULL); sprintf(tag, "<%s%s>", element->name, text); sprintf(end, "", element->name); } else if(strcmp(element->name, "img") == 0) { char* r; char* w; char* h; int ws, hs; accept_attr(top, text, 0, element, "src", "alt", "title", "height", "width", "id", "class", NULL); w = xl_get_attribute(element, "width"); h = xl_get_attribute(element, "height"); if((w == NULL || h == NULL) && (r = xl_get_attribute(element, "src")) != NULL) { if(u_image_size(top, r, u_http_path, &ws, &hs)) { if(w == NULL && h == NULL) { sprintf(text + strlen(text), "width=\"%d\" height=\"%d\"", ws, hs); } else if(w != NULL) { sprintf(text + strlen(text), "width=\"%d\" height=\"%d\"", atoi(w), hs * atoi(w) / ws); } else if(h != NULL) { sprintf(text + strlen(text), "width=\"%d\" height=\"%d\"", ws * atoi(h) / hs, atoi(h)); } } } sprintf(tag, "<%s%s border=\"0\">", element->name, text); } else if(strcmp(element->name, "script") == 0) { accept_attr(top, text, 0, element, "src", "type", NULL); sprintf(tag, "<%s%s>", element->name, text); sprintf(end, "", element->name); } else if(strcmp(element->name, "table") == 0) { char* t = xl_get_attribute(element, "class"); accept_attr(top, text, 0, element, "id", NULL); sprintf(tag, "<%s%s class=\"grid%s%s\" width=\"100%%\" cellpadding=\"3\" cellspacing=\"2\" border=\"1\">", element->name, text, t == NULL ? "" : " ", t == NULL ? "" : t); sprintf(end, "", element->name); } else if(strcmp(element->name, "hr") == 0 || /**/ strcmp(element->name, "br") == 0) { accept_attr(top, text, 0, element, "id", "class", NULL); sprintf(tag, "<%s%s>", element->name, text); } if(tag[0] != 0) print(out, tag, pre, indent); child = element->first_child; while(child != NULL) { if(child->type == XL_NODE_NODE && child->name != NULL) { default_body(out, top, child, input, spec, pre, indent + 1 + add); } else if(child->type == XL_NODE_TEXT && (pre ? (child->text_raw != NULL) : (child->text != NULL))) { print(out, pre ? child->text_raw : child->text, pre, pre ? 0 : (indent + 1 + add)); } child = child->next; } if(end[0] != 0) print(out, end, pre, indent); if(strcmp(end, "") == 0) fprintf(out, "\n"); } static int sort_xml(const void* a, const void* b) { const char* sa = *(const char**)a; const char* sb = *(const char**)b; int na = 0; int nb = 0; int i; for(i = 0; sa[i] != 0; i++) { if(sa[i] == '/') na++; } for(i = 0; sb[i] != 0; i++) { if(sb[i] == '/') nb++; } if(na == nb) return strcmp(sa, sb); return a > b ? 1 : -1; } static char** scan_xml(const char* path, const char* path2, xl_node_t** excludes, int layer) { IO_DIR* dir; char** arr = NULL; if((dir = io_opendir(path)) != NULL) { struct io_dirent* d; while((d = io_readdir(dir)) != NULL) { char* p; struct io_stat s; if(strcmp(d->d_name, "..") == 0 || strcmp(d->d_name, ".") == 0) continue; p = u_strvacat(path, d->d_name, NULL); if(io_stat(p, &s) == 0) { if(IO_S_ISDIR(s.st_mode)) { char* p2; char** arr2; int i; if(layer > 0 || layer == -0xffff) { char* p3 = u_strvacat(path2, d->d_name, "/", NULL); p2 = u_strvacat(p, "/", NULL); arr2 = scan_xml(p2, p3, excludes, layer - 1); free(p3); for(i = 0; i < arrlen(arr2); i++) { arrput(arr, arr2[i]); } arrfree(arr2); free(p2); free(p); } } else if(strcmp(d->d_name, "index.xml") == 0) { char* p3 = u_strvacat(path2, d->d_name, NULL); int i; if(excludes != NULL) { for(i = 0; excludes[i] != NULL; i++) { if(excludes[i]->text == NULL) continue; if(strcmp(excludes[i]->text, p3) == 0) break; if(strlen(excludes[i]->text) > 0 && excludes[i]->text[strlen(excludes[i]->text) - 1] == '/' && strstr(p3, excludes[i]->text) == p3) break; if(strlen(excludes[i]->text) > 0) { char* p4 = u_strvacat(excludes[i]->text, "/", NULL); if(strstr(p3, p4) == p3) { free(p4); break; } free(p4); } } } free(p3); if(excludes == NULL || excludes[i] == NULL) arrput(arr, p); } else { free(p); } } else { free(p); } } io_closedir(dir); } qsort(arr, arrlen(arr), sizeof(char*), sort_xml); return arr; } void default_nav(FILE* out, const char* top, xl_node_t* element, const char* input, int indent) { int i; if(element->name == NULL) return; if(strcmp(element->name, "if") == 0) { int cond = 0; xl_attribute_t* attr = element->first_attribute; while(attr != NULL) { if(strcmp(attr->key, "under") == 0 && attr->value != NULL) { char* p = u_path_combine("site/content", attr->value); char* p2 = u_strvacat(p, "/", NULL); if(strstr(input, p2) == input) { free(p2); free(p); cond = 1; break; } free(p2); free(p); } attr = attr->next; } if(cond) { xl_node_t* child = element->first_child; while(child != NULL) { default_nav(out, top, child, input, indent); child = child->next; } } } else if(strcmp(element->name, "link") == 0) { char* link; char* name; if((link = xl_get_attribute(element, "href")) == NULL) link = "https://invalid.link"; if((name = xl_get_attribute(element, "name")) == NULL) name = ""; link = u_path(top, link); for(i = 0; i < indent; i++) fprintf(out, "\t"); fprintf(out, " - %s
\n", link, name); free(link); } else if(strcmp(element->name, "group") == 0) { char* title; xl_node_t* child; if((title = xl_get_attribute(element, "title")) == NULL) title = ""; if(title != NULL) { for(i = 0; i < indent; i++) fprintf(out, "\t"); fprintf(out, "
- %s
\n", title); } for(i = 0; i < indent; i++) fprintf(out, "\t"); fprintf(out, "
\n"); child = element->first_child; while(child != NULL) { default_nav(out, top, child, input, indent + 1); child = child->next; } for(i = 0; i < indent; i++) fprintf(out, "\t"); fprintf(out, "
\n"); } else if(strcmp(element->name, "autogenerate") == 0) { char** xml; int i; char* layer; xl_node_t* child; xl_node_t** excludes; char* p; char* p2; if((layer = xl_get_attribute(element, "layer")) == NULL) layer = "*"; excludes = xl_get_path(element, "exclude"); if((p = xl_get_attribute(element, "path")) == NULL) { p = u_path_combine("site/content", ""); } else { p = u_path_combine("site/content", p); } p2 = u_strvacat(p, "/", NULL); free(p); xml = scan_xml(p2, "", excludes, strcmp(layer, "*") == 0 ? 0xffff : (atoi(layer) - 1)); free(p2); if(excludes != NULL) free(excludes); for(i = 0; i < arrlen(xml); i++) { xemil_t* handle; if((handle = xl_open_file(xml[i])) != NULL && (handle->param.new_text = handle->param.do_xinclude = 1) && xl_parse(handle)) { xl_node_t** nodes = xl_get_path(handle->root, "header.title"); if(nodes != NULL && nodes[0]->text != NULL) { int j; xml[i][strlen(xml[i]) - strlen("index.xml")] = 0; for(j = 0; j < indent; j++) fprintf(out, "\t"); fprintf(out, " - %s
\n", top, xml[i] + strlen("site/content/"), nodes[0]->text); free(nodes); } } if(handle != NULL) xl_close(handle); } for(i = 0; i < arrlen(xml); i++) free(xml[i]); arrfree(xml); } }