X-Git-Url: https://gitweb.ps.run/ps-cgit/blobdiff_plain/f3c1a187fe2bc33f8423cd535d5045899699995b..820df9c66073b1345397642b46f1885b40b620e3:/ui-shared.c diff --git a/ui-shared.c b/ui-shared.c index 2596023..7ab2ab1 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -7,6 +7,8 @@ */ #include "cgit.h" +#include "ui-shared.h" +#include "cmd.h" #include "html.h" const char cgit_doctype[] = @@ -19,61 +21,90 @@ static char *http_date(time_t t) {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static char month[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Now", "Dec"}; + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; struct tm *tm = gmtime(&t); return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday], - tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year, + tm->tm_mday, month[tm->tm_mon], 1900 + tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec); } -void cgit_print_error(char *msg) +void cgit_print_error(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + cgit_vprint_error(fmt, ap); + va_end(ap); +} + +void cgit_vprint_error(const char *fmt, va_list ap) +{ + va_list cp; html("
"); - html_txt(msg); + va_copy(cp, ap); + html_vtxtf(fmt, cp); + va_end(cp); html("
\n"); } -char *cgit_rooturl() +const char *cgit_httpscheme() +{ + if (ctx.env.https && !strcmp(ctx.env.https, "on")) + return "https://"; + else + return "http://"; +} + +const char *cgit_hosturl() +{ + if (ctx.env.http_host) + return ctx.env.http_host; + if (!ctx.env.server_name) + return NULL; + if (!ctx.env.server_port || atoi(ctx.env.server_port) == 80) + return ctx.env.server_name; + return fmtalloc("%s:%s", ctx.env.server_name, ctx.env.server_port); +} + +const char *cgit_rooturl() { if (ctx.cfg.virtual_root) - return fmt("%s/", ctx.cfg.virtual_root); + return ctx.cfg.virtual_root; else return ctx.cfg.script_name; } char *cgit_repourl(const char *reponame) { - if (ctx.cfg.virtual_root) { - return fmt("%s/%s/", ctx.cfg.virtual_root, reponame); - } else { - return fmt("?r=%s", reponame); - } + if (ctx.cfg.virtual_root) + return fmtalloc("%s%s/", ctx.cfg.virtual_root, reponame); + else + return fmtalloc("?r=%s", reponame); } char *cgit_fileurl(const char *reponame, const char *pagename, const char *filename, const char *query) { - char *tmp; + struct strbuf sb = STRBUF_INIT; char *delim; if (ctx.cfg.virtual_root) { - tmp = fmt("%s/%s/%s/%s", ctx.cfg.virtual_root, reponame, - pagename, (filename ? filename:"")); + strbuf_addf(&sb, "%s%s/%s/%s", ctx.cfg.virtual_root, reponame, + pagename, (filename ? filename:"")); delim = "?"; } else { - tmp = fmt("?url=%s/%s/%s", reponame, pagename, - (filename ? filename : "")); - delim = "&"; + strbuf_addf(&sb, "?url=%s/%s/%s", reponame, pagename, + (filename ? filename : "")); + delim = "&"; } if (query) - tmp = fmt("%s%s%s", tmp, delim, query); - return tmp; + strbuf_addf(&sb, "%s%s", delim, query); + return strbuf_detach(&sb, NULL); } char *cgit_pageurl(const char *reponame, const char *pagename, const char *query) { - return cgit_fileurl(reponame,pagename,0,query); + return cgit_fileurl(reponame, pagename, 0, query); } const char *cgit_repobasename(const char *reponame) @@ -82,39 +113,85 @@ const char *cgit_repobasename(const char *reponame) static char rvbuf[1024]; int p; const char *rv; - strncpy(rvbuf,reponame,sizeof(rvbuf)); - if(rvbuf[sizeof(rvbuf)-1]) + strncpy(rvbuf, reponame, sizeof(rvbuf)); + if (rvbuf[sizeof(rvbuf)-1]) die("cgit_repobasename: truncated repository name '%s'", reponame); p = strlen(rvbuf)-1; /* strip trailing slashes */ - while(p && rvbuf[p]=='/') rvbuf[p--]=0; + while (p && rvbuf[p] == '/') rvbuf[p--] = 0; /* strip trailing .git */ - if(p>=3 && !strncmp(&rvbuf[p-3],".git",4)) { + if (p >= 3 && !strncmp(&rvbuf[p-3], ".git", 4)) { p -= 3; rvbuf[p--] = 0; } /* strip more trailing slashes if any */ - while( p && rvbuf[p]=='/') rvbuf[p--]=0; + while ( p && rvbuf[p] == '/') rvbuf[p--] = 0; /* find last slash in the remaining string */ rv = strrchr(rvbuf,'/'); - if(rv) + if (rv) return ++rv; return rvbuf; } -char *cgit_currurl() +static void site_url(const char *page, const char *search, const char *sort, int ofs) { - if (!ctx.cfg.virtual_root) - return ctx.cfg.script_name; - else if (ctx.qry.page) - return fmt("%s/%s/%s/", ctx.cfg.virtual_root, ctx.qry.repo, ctx.qry.page); - else if (ctx.qry.repo) - return fmt("%s/%s/", ctx.cfg.virtual_root, ctx.qry.repo); + char *delim = "?"; + + if (ctx.cfg.virtual_root) + html_attr(ctx.cfg.virtual_root); else - return fmt("%s/", ctx.cfg.virtual_root); + html(ctx.cfg.script_name); + + if (page) { + htmlf("?p=%s", page); + delim = "&"; + } + if (search) { + html(delim); + html("q="); + html_attr(search); + delim = "&"; + } + if (sort) { + html(delim); + html("s="); + html_attr(sort); + delim = "&"; + } + if (ofs) { + html(delim); + htmlf("ofs=%d", ofs); + } +} + +static void site_link(const char *page, const char *name, const char *title, + const char *class, const char *search, const char *sort, int ofs) +{ + html(""); + html_txt(name); + html(""); +} + +void cgit_index_link(const char *name, const char *title, const char *class, + const char *pattern, const char *sort, int ofs) +{ + site_link(NULL, name, title, class, pattern, sort, ofs); } -static char *repolink(char *title, char *class, char *page, char *head, - char *path) +static char *repolink(const char *title, const char *class, const char *page, + const char *head, const char *path) { char *delim = "?"; @@ -131,96 +208,120 @@ static char *repolink(char *title, char *class, char *page, char *head, } html(" href='"); if (ctx.cfg.virtual_root) { - html_attr(ctx.cfg.virtual_root); - if (ctx.cfg.virtual_root[strlen(ctx.cfg.virtual_root) - 1] != '/') - html("/"); - html_attr(ctx.repo->url); + html_url_path(ctx.cfg.virtual_root); + html_url_path(ctx.repo->url); if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/') html("/"); if (page) { - html(page); + html_url_path(page); html("/"); if (path) - html_attr(path); + html_url_path(path); } } else { html(ctx.cfg.script_name); html("?url="); - html_attr(ctx.repo->url); + html_url_arg(ctx.repo->url); if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/') html("/"); if (page) { - html(page); + html_url_arg(page); html("/"); if (path) - html_attr(path); + html_url_arg(path); } delim = "&"; } if (head && strcmp(head, ctx.repo->defbranch)) { html(delim); html("h="); - html_attr(head); + html_url_arg(head); delim = "&"; } return fmt("%s", delim); } -static void reporevlink(char *page, char *name, char *title, char *class, - char *head, char *rev, char *path) +static void reporevlink(const char *page, const char *name, const char *title, + const char *class, const char *head, const char *rev, + const char *path) { char *delim; delim = repolink(title, class, page, head, path); - if (rev && strcmp(rev, ctx.qry.head)) { + if (rev && ctx.qry.head != NULL && strcmp(rev, ctx.qry.head)) { html(delim); html("id="); - html_attr(rev); + html_url_arg(rev); } html("'>"); html_txt(name); html(""); } -void cgit_tree_link(char *name, char *title, char *class, char *head, - char *rev, char *path) +void cgit_summary_link(const char *name, const char *title, const char *class, + const char *head) +{ + reporevlink(NULL, name, title, class, head, NULL, NULL); +} + +void cgit_tag_link(const char *name, const char *title, const char *class, + const char *head, const char *rev) +{ + reporevlink("tag", name, title, class, head, rev, NULL); +} + +void cgit_tree_link(const char *name, const char *title, const char *class, + const char *head, const char *rev, const char *path) { reporevlink("tree", name, title, class, head, rev, path); } -void cgit_log_link(char *name, char *title, char *class, char *head, - char *rev, char *path, int ofs, char *grep, char *pattern) +void cgit_plain_link(const char *name, const char *title, const char *class, + const char *head, const char *rev, const char *path) +{ + reporevlink("plain", name, title, class, head, rev, path); +} + +void cgit_log_link(const char *name, const char *title, const char *class, + const char *head, const char *rev, const char *path, + int ofs, const char *grep, const char *pattern, int showmsg) { char *delim; delim = repolink(title, class, "log", head, path); - if (rev && strcmp(rev, ctx.qry.head)) { + if (rev && ctx.qry.head && strcmp(rev, ctx.qry.head)) { html(delim); html("id="); - html_attr(rev); - delim = "&"; + html_url_arg(rev); + delim = "&"; } if (grep && pattern) { html(delim); html("qt="); - html_attr(grep); - delim = "&"; + html_url_arg(grep); + delim = "&"; html(delim); html("q="); - html_attr(pattern); + html_url_arg(pattern); } if (ofs > 0) { html(delim); html("ofs="); htmlf("%d", ofs); + delim = "&"; + } + if (showmsg) { + html(delim); + html("showmsg=1"); } html("'>"); html_txt(name); html(""); } -void cgit_commit_link(char *name, char *title, char *class, char *head, - char *rev) +void cgit_commit_link(char *name, const char *title, const char *class, + const char *head, const char *rev, const char *path, + int toggle_ssdiff) { if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) { name[ctx.cfg.max_msg_len] = '\0'; @@ -228,89 +329,259 @@ void cgit_commit_link(char *name, char *title, char *class, char *head, name[ctx.cfg.max_msg_len - 2] = '.'; name[ctx.cfg.max_msg_len - 3] = '.'; } - reporevlink("commit", name, title, class, head, rev, NULL); + + char *delim; + + delim = repolink(title, class, "commit", head, path); + if (rev && ctx.qry.head && strcmp(rev, ctx.qry.head)) { + html(delim); + html("id="); + html_url_arg(rev); + delim = "&"; + } + if ((ctx.qry.ssdiff && !toggle_ssdiff) || (!ctx.qry.ssdiff && toggle_ssdiff)) { + html(delim); + html("ss=1"); + delim = "&"; + } + if (ctx.qry.context > 0 && ctx.qry.context != 3) { + html(delim); + html("context="); + htmlf("%d", ctx.qry.context); + delim = "&"; + } + if (ctx.qry.ignorews) { + html(delim); + html("ignorews=1"); + delim = "&"; + } + html("'>"); + if (name[0] != '\0') + html_txt(name); + else + html_txt("(no commit message)"); + html(""); } -void cgit_refs_link(char *name, char *title, char *class, char *head, - char *rev, char *path) +void cgit_refs_link(const char *name, const char *title, const char *class, + const char *head, const char *rev, const char *path) { reporevlink("refs", name, title, class, head, rev, path); } -void cgit_snapshot_link(char *name, char *title, char *class, char *head, - char *rev, char *archivename) +void cgit_snapshot_link(const char *name, const char *title, const char *class, + const char *head, const char *rev, + const char *archivename) { reporevlink("snapshot", name, title, class, head, rev, archivename); } -void cgit_diff_link(char *name, char *title, char *class, char *head, - char *new_rev, char *old_rev, char *path) +void cgit_diff_link(const char *name, const char *title, const char *class, + const char *head, const char *new_rev, const char *old_rev, + const char *path, int toggle_ssdiff) { char *delim; delim = repolink(title, class, "diff", head, path); - if (new_rev && strcmp(new_rev, ctx.qry.head)) { + if (new_rev && ctx.qry.head != NULL && strcmp(new_rev, ctx.qry.head)) { html(delim); html("id="); - html_attr(new_rev); + html_url_arg(new_rev); delim = "&"; } if (old_rev) { html(delim); html("id2="); - html_attr(old_rev); + html_url_arg(old_rev); + delim = "&"; + } + if ((ctx.qry.ssdiff && !toggle_ssdiff) || (!ctx.qry.ssdiff && toggle_ssdiff)) { + html(delim); + html("ss=1"); + delim = "&"; + } + if (ctx.qry.context > 0 && ctx.qry.context != 3) { + html(delim); + html("context="); + htmlf("%d", ctx.qry.context); + delim = "&"; + } + if (ctx.qry.ignorews) { + html(delim); + html("ignorews=1"); + delim = "&"; } html("'>"); html_txt(name); html(""); } -void cgit_patch_link(char *name, char *title, char *class, char *head, - char *rev) +void cgit_patch_link(const char *name, const char *title, const char *class, + const char *head, const char *rev, const char *path) { - reporevlink("patch", name, title, class, head, rev, NULL); + reporevlink("patch", name, title, class, head, rev, path); +} + +void cgit_stats_link(const char *name, const char *title, const char *class, + const char *head, const char *path) +{ + reporevlink("stats", name, title, class, head, NULL, path); +} + +static void cgit_self_link(char *name, const char *title, const char *class, + struct cgit_context *ctx) +{ + if (!strcmp(ctx->qry.page, "repolist")) + cgit_index_link(name, title, class, ctx->qry.search, ctx->qry.sort, + ctx->qry.ofs); + else if (!strcmp(ctx->qry.page, "summary")) + cgit_summary_link(name, title, class, ctx->qry.head); + else if (!strcmp(ctx->qry.page, "tag")) + cgit_tag_link(name, title, class, ctx->qry.head, + ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL); + else if (!strcmp(ctx->qry.page, "tree")) + cgit_tree_link(name, title, class, ctx->qry.head, + ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL, + ctx->qry.path); + else if (!strcmp(ctx->qry.page, "plain")) + cgit_plain_link(name, title, class, ctx->qry.head, + ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL, + ctx->qry.path); + else if (!strcmp(ctx->qry.page, "log")) + cgit_log_link(name, title, class, ctx->qry.head, + ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL, + ctx->qry.path, ctx->qry.ofs, + ctx->qry.grep, ctx->qry.search, + ctx->qry.showmsg); + else if (!strcmp(ctx->qry.page, "commit")) + cgit_commit_link(name, title, class, ctx->qry.head, + ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL, + ctx->qry.path, 0); + else if (!strcmp(ctx->qry.page, "patch")) + cgit_patch_link(name, title, class, ctx->qry.head, + ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL, + ctx->qry.path); + else if (!strcmp(ctx->qry.page, "refs")) + cgit_refs_link(name, title, class, ctx->qry.head, + ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL, + ctx->qry.path); + else if (!strcmp(ctx->qry.page, "snapshot")) + cgit_snapshot_link(name, title, class, ctx->qry.head, + ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL, + ctx->qry.path); + else if (!strcmp(ctx->qry.page, "diff")) + cgit_diff_link(name, title, class, ctx->qry.head, + ctx->qry.sha1, ctx->qry.sha2, + ctx->qry.path, 0); + else if (!strcmp(ctx->qry.page, "stats")) + cgit_stats_link(name, title, class, ctx->qry.head, + ctx->qry.path); + else { + /* Don't known how to make link for this page */ + repolink(title, class, ctx->qry.page, ctx->qry.head, ctx->qry.path); + html(">"); + html_txt(name); + html(""); + } } void cgit_object_link(struct object *obj) { - char *page, *arg, *url; + char *page, *shortrev, *fullrev, *name; + fullrev = sha1_to_hex(obj->sha1); + shortrev = xstrdup(fullrev); + shortrev[10] = '\0'; if (obj->type == OBJ_COMMIT) { - cgit_commit_link(fmt("commit %s", sha1_to_hex(obj->sha1)), NULL, NULL, - ctx.qry.head, sha1_to_hex(obj->sha1)); + cgit_commit_link(fmt("commit %s...", shortrev), NULL, NULL, + ctx.qry.head, fullrev, NULL, 0); return; - } else if (obj->type == OBJ_TREE) { + } else if (obj->type == OBJ_TREE) page = "tree"; - arg = "id"; - } else if (obj->type == OBJ_TAG) { + else if (obj->type == OBJ_TAG) page = "tag"; - arg = "id"; - } else { + else page = "blob"; - arg = "id"; + name = fmt("%s %s...", typename(obj->type), shortrev); + reporevlink(page, name, NULL, NULL, ctx.qry.head, fullrev, NULL); +} + +static struct string_list_item *lookup_path(struct string_list *list, + const char *path) +{ + struct string_list_item *item; + + while (path && path[0]) { + if ((item = string_list_lookup(list, path))) + return item; + if (!(path = strchr(path, '/'))) + break; + path++; } + return NULL; +} - url = cgit_pageurl(ctx.qry.repo, page, - fmt("%s=%s", arg, sha1_to_hex(obj->sha1))); - html_link_open(url, NULL, NULL); - htmlf("%s %s", typename(obj->type), - sha1_to_hex(obj->sha1)); - html_link_close(); +void cgit_submodule_link(const char *class, char *path, const char *rev) +{ + struct string_list *list; + struct string_list_item *item; + char tail, *dir; + size_t len; + + len = 0; + tail = 0; + list = &ctx.repo->submodules; + item = lookup_path(list, path); + if (!item) { + len = strlen(path); + tail = path[len - 1]; + if (tail == '/') { + path[len - 1] = 0; + item = lookup_path(list, path); + } + } + html("module_link, dir, rev); + } else { + html("#"); + } + html("'>"); + html_txt(path); + html(""); + html_txtf(" @ %.7s", rev); + if (item && tail) + path[len - 1] = tail; } -void cgit_print_date(time_t secs, char *format) +void cgit_print_date(time_t secs, const char *format, int local_time) { char buf[64]; struct tm *time; if (!secs) return; - time = gmtime(&secs); + if (local_time) + time = localtime(&secs); + else + time = gmtime(&secs); strftime(buf, sizeof(buf)-1, format, time); html_txt(buf); } -void cgit_print_age(time_t t, time_t max_relative, char *format) +void cgit_print_age(time_t t, time_t max_relative, const char *format) { time_t now, secs; @@ -320,7 +591,7 @@ void cgit_print_age(time_t t, time_t max_relative, char *format) secs = now - t; if (secs > max_relative && max_relative >= 0) { - cgit_print_date(t, format); + cgit_print_date(t, format, ctx.cfg.local_time); return; } @@ -355,21 +626,39 @@ void cgit_print_age(time_t t, time_t max_relative, char *format) void cgit_print_http_headers(struct cgit_context *ctx) { + if (ctx->env.no_http && !strcmp(ctx->env.no_http, "1")) + return; + + if (ctx->page.status) + htmlf("Status: %d %s\n", ctx->page.status, ctx->page.statusmsg); if (ctx->page.mimetype && ctx->page.charset) htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype, ctx->page.charset); else if (ctx->page.mimetype) htmlf("Content-Type: %s\n", ctx->page.mimetype); + if (ctx->page.size) + htmlf("Content-Length: %zd\n", ctx->page.size); if (ctx->page.filename) htmlf("Content-Disposition: inline; filename=\"%s\"\n", ctx->page.filename); htmlf("Last-Modified: %s\n", http_date(ctx->page.modified)); htmlf("Expires: %s\n", http_date(ctx->page.expires)); + if (ctx->page.etag) + htmlf("ETag: \"%s\"\n", ctx->page.etag); html("\n"); + if (ctx->env.request_method && !strcmp(ctx->env.request_method, "HEAD")) + exit(0); } void cgit_print_docstart(struct cgit_context *ctx) { + if (ctx->cfg.embedded) { + if (ctx->cfg.header) + html_include(ctx->cfg.header); + return; + } + + const char *host = cgit_hosturl(); html(cgit_doctype); html("\n"); html("\n"); @@ -382,80 +671,83 @@ void cgit_print_docstart(struct cgit_context *ctx) html("\n"); + if (ctx->cfg.favicon) { + html("\n"); + } + if (host && ctx->repo && ctx->qry.head) { + struct strbuf sb = STRBUF_INIT; + strbuf_addf(&sb, "h=%s", ctx->qry.head); + + html("\n"); + strbuf_release(&sb); + } + if (ctx->cfg.head_include) + html_include(ctx->cfg.head_include); html("\n"); html("\n"); + if (ctx->cfg.header) + html_include(ctx->cfg.header); } void cgit_print_docend() { - html("\n\n\n\n\n"); + html(" \n"); + if (ctx.cfg.embedded) { + html(" \n"); + if (ctx.cfg.footer) + html_include(ctx.cfg.footer); + return; + } + if (ctx.cfg.footer) + html_include(ctx.cfg.footer); + else { + htmlf("\n"); + } + html(" \n"); + html("\n\n"); } -int print_branch_option(const char *refname, const unsigned char *sha1, - int flags, void *cb_data) +static int print_branch_option(const char *refname, const unsigned char *sha1, + int flags, void *cb_data) { char *name = (char *)refname; html_option(name, name, ctx.qry.head); return 0; } -int print_archive_ref(const char *refname, const unsigned char *sha1, - int flags, void *cb_data) -{ - struct tag *tag; - struct taginfo *info; - struct object *obj; - char buf[256], *url; - unsigned char fileid[20]; - int *header = (int *)cb_data; - - if (prefixcmp(refname, "refs/archives")) - return 0; - strncpy(buf, refname+14, sizeof(buf)); - obj = parse_object(sha1); - if (!obj) - return 1; - if (obj->type == OBJ_TAG) { - tag = lookup_tag(sha1); - if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) - return 0; - hashcpy(fileid, tag->tagged->sha1); - } else if (obj->type != OBJ_BLOB) { - return 0; - } else { - hashcpy(fileid, sha1); - } - if (!*header) { - html("

download

\n"); - *header = 1; - } - url = cgit_pageurl(ctx.qry.repo, "blob", - fmt("id=%s&path=%s", sha1_to_hex(fileid), - buf)); - html_link_open(url, NULL, "menu"); - html_txt(strlpart(buf, 20)); - html_link_close(); - return 0; -} - -void add_hidden_formfields(int incl_head, int incl_search, char *page) +void cgit_add_hidden_formfields(int incl_head, int incl_search, + const char *page) { - char *url; - if (!ctx.cfg.virtual_root) { - url = fmt("%s/%s", ctx.qry.repo, page); - if (ctx.qry.path) - url = fmt("%s/%s", url, ctx.qry.path); - html_hidden("url", url); + struct strbuf url = STRBUF_INIT; + + strbuf_addf(&url, "%s/%s", ctx.qry.repo, page); + if (ctx.qry.vpath) + strbuf_addf(&url, "/%s", ctx.qry.vpath); + html_hidden("url", url.buf); + strbuf_release(&url); } - if (incl_head && strcmp(ctx.qry.head, ctx.repo->defbranch)) + if (incl_head && ctx.qry.head && ctx.repo->defbranch && + strcmp(ctx.qry.head, ctx.repo->defbranch)) html_hidden("h", ctx.qry.head); if (ctx.qry.sha1) html_hidden("id", ctx.qry.sha1); if (ctx.qry.sha2) html_hidden("id2", ctx.qry.sha2); + if (ctx.qry.showmsg) + html_hidden("showmsg", "1"); if (incl_search) { if (ctx.qry.grep) @@ -465,97 +757,158 @@ void add_hidden_formfields(int incl_head, int incl_search, char *page) } } -void cgit_print_pageheader(struct cgit_context *ctx) +static const char *hc(struct cgit_context *ctx, const char *page) { - static const char *default_info = "This is cgit, a fast webinterface for git repositories"; - int header = 0; - char *url; - - html("\n"); - html("