- html("<table id='layout'>");
- html("<tr><td id='header'><a href='");
- html_attr(cgit_rooturl());
- html("'>");
- html_txt(cgit_root_title);
- html("</a></td><td id='logo'>");
- html("<a href='");
- html_attr(cgit_logo_link);
- htmlf("'><img src='%s' alt='logo'/></a>", cgit_logo);
- html("</td></tr>");
- html("<tr><td id='crumb'>");
- if (cgit_query_repo) {
- html_txt(cgit_repo->name);
- html(" (");
- html_txt(cgit_query_head);
- html(") : ");
- reporevlink(NULL, "summary", NULL, NULL, cgit_query_head,
- NULL, NULL);
- html(" ");
- cgit_log_link("log", NULL, NULL, cgit_query_head,
- cgit_query_sha1, cgit_query_path, 0);
- html(" ");
- cgit_tree_link("tree", NULL, NULL, cgit_query_head,
- cgit_query_sha1, NULL);
- html(" ");
- cgit_commit_link("commit", NULL, NULL, cgit_query_head,
- cgit_query_sha1);
- html(" ");
- cgit_diff_link("diff", NULL, NULL, cgit_query_head,
- cgit_query_sha1, cgit_query_sha2,
- cgit_query_path);
+ va_list ap;
+ ctx.page.expires = ctx.cfg.cache_dynamic_ttl;
+ ctx.page.status = code;
+ ctx.page.statusmsg = msg;
+ cgit_print_layout_start();
+ va_start(ap, fmt);
+ cgit_vprint_error(fmt, ap);
+ va_end(ap);
+ cgit_print_layout_end();
+}
+
+void cgit_print_layout_start(void)
+{
+ cgit_print_http_headers();
+ cgit_print_docstart();
+ cgit_print_pageheader();
+}
+
+void cgit_print_layout_end(void)
+{
+ cgit_print_docend();
+}
+
+static void add_clone_urls(void (*fn)(const char *), char *txt, char *suffix)
+{
+ struct strbuf **url_list = strbuf_split_str(txt, ' ', 0);
+ int i;
+
+ for (i = 0; url_list[i]; i++) {
+ strbuf_rtrim(url_list[i]);
+ if (url_list[i]->len == 0)
+ continue;
+ if (suffix && *suffix)
+ strbuf_addf(url_list[i], "/%s", suffix);
+ fn(url_list[i]->buf);
+ }
+
+ strbuf_list_free(url_list);
+}
+
+void cgit_add_clone_urls(void (*fn)(const char *))
+{
+ if (ctx.repo->clone_url)
+ add_clone_urls(fn, expand_macros(ctx.repo->clone_url), NULL);
+ else if (ctx.cfg.clone_prefix)
+ add_clone_urls(fn, ctx.cfg.clone_prefix, ctx.repo->url);
+}
+
+static int print_branch_option(const char *refname, const struct object_id *oid,
+ int flags, void *cb_data)
+{
+ char *name = (char *)refname;
+ html_option(name, name, ctx.qry.head);
+ return 0;
+}
+
+void cgit_add_hidden_formfields(int incl_head, int incl_search,
+ const char *page)
+{
+ if (!ctx.cfg.virtual_root) {
+ 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 && ctx.qry.head && ctx.repo->defbranch &&
+ strcmp(ctx.qry.head, ctx.repo->defbranch))
+ html_hidden("h", ctx.qry.head);
+
+ if (ctx.qry.oid)
+ html_hidden("id", ctx.qry.oid);
+ if (ctx.qry.oid2)
+ html_hidden("id2", ctx.qry.oid2);
+ if (ctx.qry.showmsg)
+ html_hidden("showmsg", "1");
+
+ if (incl_search) {
+ if (ctx.qry.grep)
+ html_hidden("qt", ctx.qry.grep);
+ if (ctx.qry.search)
+ html_hidden("q", ctx.qry.search);
+ }
+}
+
+static const char *hc(const char *page)
+{
+ if (!ctx.qry.page)
+ return NULL;
+
+ return strcmp(ctx.qry.page, page) ? NULL : "active";
+}
+
+static void cgit_print_path_crumbs(char *path)
+{
+ char *old_path = ctx.qry.path;
+ char *p = path, *q, *end = path + strlen(path);
+ int levels = 0;
+
+ ctx.qry.path = NULL;
+ cgit_self_link("root", NULL, NULL);
+ ctx.qry.path = p = path;
+ while (p < end) {
+ if (!(q = strchr(p, '/')) || levels > 15)
+ q = end;
+ *q = '\0';
+ html_txt("/");
+ cgit_self_link(p, NULL, NULL);
+ if (q < end)
+ *q = '/';
+ p = q + 1;
+ ++levels;
+ }
+ ctx.qry.path = old_path;
+}
+
+static void print_header(void)
+{
+ char *logo = NULL, *logo_link = NULL;
+
+ html("<table id='header'>\n");
+ html("<tr>\n");
+
+ if (ctx.repo && ctx.repo->logo && *ctx.repo->logo)
+ logo = ctx.repo->logo;
+ else
+ logo = ctx.cfg.logo;
+ if (ctx.repo && ctx.repo->logo_link && *ctx.repo->logo_link)
+ logo_link = ctx.repo->logo_link;
+ else
+ logo_link = ctx.cfg.logo_link;
+ if (logo && *logo) {
+ html("<td class='logo' rowspan='2'><a href='");
+ if (logo_link && *logo_link)
+ html_attr(logo_link);
+ else
+ html_attr(cgit_rooturl());
+ html("'><img src='");
+ html_attr(logo);
+ html("' alt='cgit logo'/></a></td>\n");
+ }
+
+ html("<td class='main'>");
+ if (ctx.repo) {
+ cgit_index_link("index", NULL, NULL, NULL, NULL, 0, 1);
+ html(" : ");
+ cgit_summary_link(ctx.repo->name, NULL, NULL, NULL);
+ if (ctx.env.authenticated) {
+ html("</td><td class='form'>");
+ html("<form method='get'>\n");
+ cgit_add_hidden_formfields(0, 1, ctx.qry.page);
+ html("<select name='h' onchange='this.form.submit();'>\n");
+ for_each_branch_ref(print_branch_option, ctx.qry.head);
+ if (ctx.repo->enable_remote_branches)
+ for_each_remote_ref(print_branch_option, ctx.qry.head);
+ html("</select> ");
+ html("<input type='submit' value='switch'/>");
+ html("</form>");
+ }
+ } else
+ html_txt(ctx.cfg.root_title);
+ html("</td></tr>\n");
+
+ html("<tr><td class='sub'>");
+ if (ctx.repo) {
+ html_txt(ctx.repo->desc);
+ html("</td><td class='sub right'>");
+ if (ctx.repo->owner_filter) {
+ cgit_open_filter(ctx.repo->owner_filter);
+ html_txt(ctx.repo->owner);
+ cgit_close_filter(ctx.repo->owner_filter);
+ } else {
+ html_txt(ctx.repo->owner);
+ }