+static char *repolink(char *title, char *class, char *page, char *head,
+ char *path)
+{
+ char *delim = "?";
+
+ html("<a");
+ if (title) {
+ html(" title='");
+ html_attr(title);
+ html("'");
+ }
+ if (class) {
+ html(" class='");
+ html_attr(class);
+ html("'");
+ }
+ html(" href='");
+ if (cgit_virtual_root) {
+ html_attr(cgit_virtual_root);
+ if (cgit_virtual_root[strlen(cgit_virtual_root) - 1] != '/')
+ html("/");
+ html_attr(cgit_repo->url);
+ if (cgit_repo->url[strlen(cgit_repo->url) - 1] != '/')
+ html("/");
+ if (page) {
+ html(page);
+ html("/");
+ if (path)
+ html_attr(path);
+ }
+ } else {
+ html(cgit_script_name);
+ html("?url=");
+ html_attr(cgit_repo->url);
+ if (cgit_repo->url[strlen(cgit_repo->url) - 1] != '/')
+ html("/");
+ if (page) {
+ html(page);
+ html("/");
+ if (path)
+ html_attr(path);
+ }
+ delim = "&";
+ }
+ if (head && strcmp(head, cgit_repo->defbranch)) {
+ html(delim);
+ html("h=");
+ html_attr(head);
+ delim = "&";
+ }
+ return fmt("%s", delim);
+}
+
+static void reporevlink(char *page, char *name, char *title, char *class,
+ char *head, char *rev, char *path)
+{
+ char *delim;
+
+ delim = repolink(title, class, page, head, path);
+ if (rev && strcmp(rev, cgit_query_head)) {
+ html(delim);
+ html("id=");
+ html_attr(rev);
+ }
+ html("'>");
+ html_txt(name);
+ html("</a>");
+}
+
+void cgit_tree_link(char *name, char *title, char *class, char *head,
+ char *rev, 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 *delim;
+
+ delim = repolink(title, class, "log", head, path);
+ if (rev && strcmp(rev, cgit_query_head)) {
+ html(delim);
+ html("id=");
+ html_attr(rev);
+ delim = "&";
+ }
+ if (ofs > 0) {
+ html(delim);
+ html("ofs=");
+ htmlf("%d", ofs);
+ }
+ html("'>");
+ html_txt(name);
+ html("</a>");
+}
+
+void cgit_commit_link(char *name, char *title, char *class, char *head,
+ char *rev)
+{
+ if (strlen(name) > cgit_max_msg_len && cgit_max_msg_len >= 15) {
+ name[cgit_max_msg_len] = '\0';
+ name[cgit_max_msg_len - 1] = '.';
+ name[cgit_max_msg_len - 2] = '.';
+ name[cgit_max_msg_len - 3] = '.';
+ }
+ reporevlink("commit", name, title, class, head, rev, NULL);
+}
+
+void cgit_snapshot_link(char *name, char *title, char *class, char *head,
+ char *rev, 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)
+{
+ char *delim;
+
+ delim = repolink(title, class, "diff", head, path);
+ if (new_rev && strcmp(new_rev, cgit_query_head)) {
+ html(delim);
+ html("id=");
+ html_attr(new_rev);
+ delim = "&";
+ }
+ if (old_rev) {
+ html(delim);
+ html("id2=");
+ html_attr(old_rev);
+ }
+ html("'>");
+ html_txt(name);
+ html("</a>");
+}