* html.c: implementation of html.h.
*/
-#include <assert.h>
-#include <stddef.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <time.h>
-
+#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
struct html {
{
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) {
unsigned long *xi1, unsigned long *xi2)
{
size_t pathlen = strlen(path);
+ int c1 = path[pathlen], c2 = (pathlen > 0 ? path[pathlen-1] : 0);
*xi1 = trie_before(t, path);
- path[pathlen] = '\001';
- path[pathlen+1] = '\0';
+ make_successor(path);
*xi2 = trie_before(t, path);
- path[pathlen] = '\0';
+ path[pathlen] = c1;
+ if (pathlen > 0)
+ path[pathlen-1] = c2;
}
static unsigned long long fetch_size(const void *t, char *path,
#define PIXEL_SIZE 600 /* FIXME: configurability? */
static void write_report_line(struct html *ctx, struct vector *vec)
{
- unsigned long long size, asize;
+ unsigned long long size, asize, divisor;
int pix, newpix;
int i;
/*
+ * A line with literally zero space usage should not be
+ * printed at all if it's a link to a subdirectory (since it
+ * probably means the whole thing was excluded by some
+ * --exclude-path wildcard). If it's [files] or the top-level
+ * line, though, we must always print _something_, and in that
+ * case we must fiddle about to prevent divisions by zero in
+ * the code below.
+ */
+ if (!vec->sizes[MAXCOLOUR] && vec->want_href)
+ return;
+ divisor = ctx->totalsize;
+ if (!divisor) {
+ divisor = 1;
+ }
+
+ /*
* Find the total size of this subdirectory.
*/
size = vec->sizes[MAXCOLOUR];
htprintf(ctx, "<tr>\n"
"<td style=\"padding: 0.2em; text-align: right\">%lluMb</td>\n",
- ((size + ((1<<11)-1)) >> 11)); /* convert to Mb, rounding up */
+ ((size + ((1<<20)-1)) >> 20)); /* convert to Mb, rounding up */
/*
* Generate a colour bar.
pix = 0;
for (i = 0; i <= MAXCOLOUR; i++) {
asize = vec->sizes[i];
- newpix = asize * PIXEL_SIZE / ctx->totalsize;
+ newpix = asize * PIXEL_SIZE / divisor;
add_to_colour_bar(ctx, i, newpix - pix);
pix = newpix;
}
* Output size as a percentage of totalsize.
*/
htprintf(ctx, "<td style=\"padding: 0.2em; text-align: right\">"
- "%.2f%%</td>\n", (double)size / ctx->totalsize * 100.0);
+ "%.2f%%</td>\n", (double)size / divisor * 100.0);
/*
* Output a subdirectory marker.
htprintf(ctx, "</td>\n</tr>\n");
}
-char *html_query(const void *t, unsigned long index, const char *format)
+char *html_query(const void *t, unsigned long index,
+ const struct html_config *cfg)
{
struct html actx, *ctx = &actx;
char *path, *path2, *p, *q, *href;
char agebuf1[80], agebuf2[80];
- size_t pathlen, hreflen;
+ size_t pathlen, subdirpos, hreflen;
unsigned long index2;
int i;
struct vector **vecs;
ctx->buf = NULL;
ctx->buflen = ctx->bufsize = 0;
ctx->t = t;
- ctx->format = format;
+ ctx->format = cfg->format;
htprintf(ctx, "<html>\n");
path = snewn(1+trie_maxpathlen(t), char);
ctx->path2 = path2 = snewn(1+trie_maxpathlen(t), char);
- if (format) {
- hreflen = strlen(format) + 100;
+ if (cfg->format) {
+ hreflen = strlen(cfg->format) + 100;
href = snewn(hreflen, char);
} else {
hreflen = 0;
*/
htprintf(ctx, "<head>\n");
trie_getpath(t, index, path);
- htprintf(ctx, "<title>agedu: ");
+ htprintf(ctx, "<title>%s: ", PNAME);
htescape(ctx, path, strlen(path), 0);
htprintf(ctx, "</title>\n");
htprintf(ctx, "</head>\n");
*/
htprintf(ctx, "<p align=center>\n<code>");
q = path;
- for (p = strchr(path, '/'); p; p = strchr(p+1, '/')) {
+ for (p = strchr(path, pathsep); p && p[1]; p = strchr(p, pathsep)) {
int doing_href = 0;
+ char c, *zp;
+
/*
* See if this path prefix exists in the trie. If so,
* generate a hyperlink.
*/
- *p = '\0';
+ zp = p;
+ if (p == path) /* special case for "/" at start */
+ zp++;
+
+ p++;
+
+ c = *zp;
+ *zp = '\0';
index2 = trie_before(t, path);
trie_getpath(t, index2, path2);
- if (!strcmp(path, path2) && format) {
- snprintf(href, hreflen, format, index2);
+ if (!strcmp(path, path2) && cfg->format) {
+ snprintf(href, hreflen, cfg->format, index2);
+ if (!*href) /* special case that we understand */
+ strcpy(href, "./");
htprintf(ctx, "<a href=\"%s\">", href);
doing_href = 1;
}
- *p = '/';
- htescape(ctx, q, p - q, 1);
- q = p + 1;
+ *zp = c;
+ htescape(ctx, q, zp - q, 1);
if (doing_href)
htprintf(ctx, "</a>");
- htprintf(ctx, "/");
+ htescape(ctx, zp, p - zp, 1);
+ q = p;
}
htescape(ctx, q, strlen(q), 1);
htprintf(ctx, "</code>\n");
* Decide on the age limit of our colour coding, establish the
* colour thresholds, and write out a key.
*/
- ctx->oldest = index_order_stat(t, 0.05); /* FIXME: configurability? */
- ctx->newest = index_order_stat(t, 1.0);
ctx->now = time(NULL);
- ctx->oldest = round_and_format_age(ctx, ctx->oldest, agebuf1, -1);
- ctx->newest = round_and_format_age(ctx, ctx->newest, agebuf2, +1);
+ if (cfg->autoage) {
+ ctx->oldest = index_order_stat(t, 0.05);
+ ctx->newest = index_order_stat(t, 1.0);
+ ctx->oldest = round_and_format_age(ctx, ctx->oldest, agebuf1, -1);
+ ctx->newest = round_and_format_age(ctx, ctx->newest, agebuf2, +1);
+ } else {
+ ctx->oldest = cfg->oldest;
+ ctx->newest = cfg->newest;
+ 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++) {
ctx->thresholds[i] =
ctx->oldest + (ctx->newest - ctx->oldest) * i / MAXCOLOUR;
get_indices(t, path, &xi1, &xi2);
xi1++;
pathlen = strlen(path);
+ subdirpos = pathlen + 1;
+ if (pathlen > 0 && path[pathlen-1] == pathsep)
+ subdirpos--;
while (xi1 < xi2) {
trie_getpath(t, xi1, path2);
get_indices(t, ctx->path2, &xj1, &xj2);
vecs = sresize(vecs, vecsize, struct vector *);
}
assert(strlen(path2) > pathlen);
- vecs[nvecs] = make_vector(ctx, path2, 1, path2 + pathlen + 1);
+ vecs[nvecs] = make_vector(ctx, path2, 1, path2 + subdirpos);
for (i = 0; i <= MAXCOLOUR; i++)
vecs[0]->sizes[i] -= vecs[nvecs]->sizes[i];
nvecs++;