X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/agedu/blobdiff_plain/256c29a27ba79677a78bc676a3cc73ee1aad2d68..9827dd71b88e2c1080f1f31a40802cd44c98bf16:/html.c diff --git a/html.c b/html.c index be13590..22cdc17 100644 --- a/html.c +++ b/html.c @@ -2,26 +2,14 @@ * html.c: implementation of html.h. */ -#include -#include -#include -#include -#include -#include -#include -#include - +#include "agedu.h" #include "html.h" -#include "malloc.h" +#include "alloc.h" #include "trie.h" #include "index.h" -#define lenof(x) ( sizeof((x)) / sizeof(*(x)) ) - #define MAXCOLOUR 511 -extern char pathsep; - struct html { char *buf; size_t buflen, bufsize; @@ -31,7 +19,8 @@ struct html { char *href; size_t hreflen; const char *format; - unsigned long long thresholds[MAXCOLOUR-1]; + unsigned long long thresholds[MAXCOLOUR]; + char *titletexts[MAXCOLOUR+1]; time_t now; }; @@ -39,9 +28,16 @@ static void vhtprintf(struct html *ctx, char *fmt, va_list ap) { va_list ap2; int size, size2; + char testbuf[2]; va_copy(ap2, ap); - size = vsnprintf(NULL, 0, fmt, ap2); + /* + * Some C libraries (Solaris, I'm looking at you) don't like + * an output buffer size of zero in vsnprintf, but will return + * sensible values given any non-zero buffer size. Hence, we + * use testbuf to gauge the length of the string. + */ + size = vsnprintf(testbuf, 1, fmt, ap2); va_end(ap2); if (ctx->buflen + size >= ctx->bufsize) { @@ -176,14 +172,25 @@ static void get_indices(const void *t, char *path, path[pathlen-1] = c2; } -static unsigned long long fetch_size(const void *t, char *path, +static unsigned long long fetch_size(const void *t, + unsigned long xi1, unsigned long xi2, unsigned long long atime) { - unsigned long xi1, xi2; - - get_indices(t, path, &xi1, &xi2); - - return index_query(t, xi2, atime) - index_query(t, xi1, atime); + if (xi2 - xi1 == 1) { + /* + * We are querying an individual file, so we should not + * depend on the index entries either side of the node, + * since they almost certainly don't both exist. Instead, + * just look up the file's size and atime in the main trie. + */ + const struct trie_file *f = trie_getfile(t, xi1); + if (f->atime < atime) + return f->size; + else + return 0; + } else { + return index_query(t, xi2, atime) - index_query(t, xi1, atime); + } } static void htescape(struct html *ctx, const char *s, int n, int italics) @@ -218,7 +225,6 @@ static void begin_colour_bar(struct html *ctx) static void add_to_colour_bar(struct html *ctx, int colour, int pixels) { int r, g, b; - char buf[80]; if (colour >= 0 && colour < 256) /* red -> yellow fade */ r = 255, g = colour, b = 0; @@ -227,26 +233,12 @@ static void add_to_colour_bar(struct html *ctx, int colour, int pixels) else /* background grey */ r = g = b = 240; - if (colour < 0) { - /* no title text here */ - } else if (colour == 0) { - strcpy(buf, "< "); - round_and_format_age(ctx, ctx->thresholds[0], buf+5, 0); - } else if (colour == MAXCOLOUR) { - strcpy(buf, "> "); - round_and_format_age(ctx, ctx->thresholds[MAXCOLOUR-1], buf+5, 0); - } else { - unsigned long long midrange = - (ctx->thresholds[colour] + ctx->thresholds[colour+1]) / 2; - round_and_format_age(ctx, midrange, buf, 0); - } - if (pixels > 0) { htprintf(ctx, "= 0) - htprintf(ctx, " title=\"%s\"", buf); + htprintf(ctx, " title=\"%s\"", ctx->titletexts[colour]); htprintf(ctx, ">\n"); } } @@ -257,8 +249,9 @@ static void end_colour_bar(struct html *ctx) } struct vector { - int want_href; + int want_href, essential; char *name; + int literal; /* should the name be formatted in fixed-pitch? */ unsigned long index; unsigned long long sizes[MAXCOLOUR+1]; }; @@ -282,18 +275,25 @@ int vec_compare(const void *av, const void *bv) return -1; else if (a->index > b->index) return +1; + else if (a->essential < b->essential) + return +1; + else if (a->essential > b->essential) + return -1; return 0; } static struct vector *make_vector(struct html *ctx, char *path, - int want_href, char *name) + int want_href, int essential, + char *name, int literal) { unsigned long xi1, xi2; struct vector *vec = snew(struct vector); int i; vec->want_href = want_href; + vec->essential = essential; vec->name = name ? dupstr(name) : NULL; + vec->literal = literal; get_indices(ctx->t, path, &xi1, &xi2); @@ -305,7 +305,7 @@ static struct vector *make_vector(struct html *ctx, char *path, atime = ULLONG_MAX; else atime = ctx->thresholds[i]; - vec->sizes[i] = fetch_size(ctx->t, path, atime); + vec->sizes[i] = fetch_size(ctx->t, xi1, xi2, atime); } return vec; @@ -333,7 +333,7 @@ static void write_report_line(struct html *ctx, struct vector *vec) * case we must fiddle about to prevent divisions by zero in * the code below. */ - if (!vec->sizes[MAXCOLOUR] && vec->want_href) + if (!vec->sizes[MAXCOLOUR] && !vec->essential) return; divisor = ctx->totalsize; if (!divisor) { @@ -382,13 +382,29 @@ static void write_report_line(struct html *ctx, struct vector *vec) htprintf(ctx, "", ctx->href); doing_href = 1; } + if (vec->literal) + htprintf(ctx, ""); htescape(ctx, vec->name, strlen(vec->name), 1); + if (vec->literal) + htprintf(ctx, ""); if (doing_href) htprintf(ctx, ""); } htprintf(ctx, "\n\n"); } +int strcmptrailingpathsep(const char *a, const char *b) +{ + while (*a == *b && *a) + a++, b++; + + if ((*a == pathsep && !a[1] && !*b) || + (*b == pathsep && !b[1] && !*a)) + return 0; + + return (int)(unsigned char)*a - (int)(unsigned char)*b; +} + char *html_query(const void *t, unsigned long index, const struct html_config *cfg) { @@ -428,7 +444,7 @@ char *html_query(const void *t, unsigned long index, */ htprintf(ctx, "\n"); trie_getpath(t, index, path); - htprintf(ctx, "agedu: "); + htprintf(ctx, "<title>%s: ", PNAME); htescape(ctx, path, strlen(path), 0); htprintf(ctx, "\n"); htprintf(ctx, "\n"); @@ -446,7 +462,7 @@ char *html_query(const void *t, unsigned long index, */ htprintf(ctx, "

\n"); q = path; - for (p = strchr(path, pathsep); p; p = strchr(p, pathsep)) { + for (p = strchr(path, pathsep); p && p[1]; p = strchr(p, pathsep)) { int doing_href = 0; char c, *zp; @@ -464,8 +480,10 @@ char *html_query(const void *t, unsigned long index, *zp = '\0'; index2 = trie_before(t, path); trie_getpath(t, index2, path2); - if (!strcmp(path, path2) && cfg->format) { + if (!strcmptrailingpathsep(path, path2) && cfg->format) { snprintf(href, hreflen, cfg->format, index2); + if (!*href) /* special case that we understand */ + strcpy(href, "./"); htprintf(ctx, "", href); doing_href = 1; } @@ -495,9 +513,26 @@ char *html_query(const void *t, unsigned long index, ctx->oldest = round_and_format_age(ctx, ctx->oldest, agebuf1, 0); ctx->newest = round_and_format_age(ctx, ctx->newest, agebuf2, 0); } - for (i = 0; i < MAXCOLOUR-1; i++) { + for (i = 0; i < MAXCOLOUR; i++) { ctx->thresholds[i] = - ctx->oldest + (ctx->newest - ctx->oldest) * i / MAXCOLOUR; + ctx->oldest + (ctx->newest - ctx->oldest) * i / (MAXCOLOUR-1); + } + for (i = 0; i <= MAXCOLOUR; i++) { + char buf[80]; + + if (i == 0) { + strcpy(buf, "< "); + round_and_format_age(ctx, ctx->thresholds[0], buf+5, 0); + } else if (i == MAXCOLOUR) { + strcpy(buf, "> "); + round_and_format_age(ctx, ctx->thresholds[MAXCOLOUR-1], buf+5, 0); + } else { + unsigned long long midrange = + (ctx->thresholds[i-1] + ctx->thresholds[i]) / 2; + round_and_format_age(ctx, midrange, buf, 0); + } + + ctx->titletexts[i] = dupstr(buf); } htprintf(ctx, "

Key to colour coding (mouse over for more detail):\n"); htprintf(ctx, "

totalsize = fetch_size(t, path, ULLONG_MAX); + get_indices(t, path, &xi1, &xi2); + ctx->totalsize = fetch_size(t, xi1, xi2, ULLONG_MAX); /* * Generate a report line for the whole subdirectory. @@ -526,7 +562,7 @@ char *html_query(const void *t, unsigned long index, vecsize = 64; vecs = snewn(vecsize, struct vector *); nvecs = 1; - vecs[0] = make_vector(ctx, path, 0, NULL); + vecs[0] = make_vector(ctx, path, 0, 1, NULL, 0); print_heading(ctx, "Overall"); write_report_line(ctx, vecs[0]); @@ -547,14 +583,15 @@ char *html_query(const void *t, unsigned long index, trie_getpath(t, xi1, path2); get_indices(t, ctx->path2, &xj1, &xj2); xi1 = xj2; - if (xj2 - xj1 <= 1) + if (!cfg->showfiles && xj2 - xj1 <= 1) continue; /* skip individual files */ if (nvecs >= vecsize) { vecsize = nvecs * 3 / 2 + 64; vecs = sresize(vecs, vecsize, struct vector *); } assert(strlen(path2) > pathlen); - vecs[nvecs] = make_vector(ctx, path2, 1, path2 + subdirpos); + vecs[nvecs] = make_vector(ctx, path2, (xj2 - xj1 > 1), 0, + path2 + subdirpos, 1); for (i = 0; i <= MAXCOLOUR; i++) vecs[0]->sizes[i] -= vecs[nvecs]->sizes[i]; nvecs++;