+ push_rev_graph(graph->next, graph->rev[graph->pos]);
+ }
+
+ /* Interleave the new revision parent(s). */
+ for (i = 0; i < graph->parents->size; i++)
+ push_rev_graph(graph->next, graph->parents->rev[i]);
+
+ /* Lastly, put any remaining revisions. */
+ for (i = graph->pos + 1; i < graph->size; i++)
+ push_rev_graph(graph->next, graph->rev[i]);
+}
+
+static void
+update_rev_graph(struct rev_graph *graph)
+{
+ /* If this is the finalizing update ... */
+ if (graph->commit)
+ prepare_rev_graph(graph);
+
+ /* Graph visualization needs a one rev look-ahead,
+ * so the first update doesn't visualize anything. */
+ if (!graph->prev->commit)
+ return;
+
+ draw_rev_graph(graph->prev);
+ done_rev_graph(graph->prev->prev);
+}
+
+
+/*
+ * Main view backend
+ */
+
+static bool
+main_draw(struct view *view, struct line *line, unsigned int lineno, bool selected)
+{
+ char buf[DATE_COLS + 1];
+ struct commit *commit = line->data;
+ enum line_type type;
+ int col = 0;
+ size_t timelen;
+ size_t authorlen;
+ int trimmed = 1;
+
+ if (!*commit->author)
+ return FALSE;
+
+ wmove(view->win, lineno, col);
+
+ if (selected) {
+ type = LINE_CURSOR;
+ wattrset(view->win, get_line_attr(type));
+ wchgat(view->win, -1, 0, type, NULL);
+
+ } else {
+ type = LINE_MAIN_COMMIT;
+ wattrset(view->win, get_line_attr(LINE_MAIN_DATE));
+ }
+
+ timelen = strftime(buf, sizeof(buf), DATE_FORMAT, &commit->time);
+ waddnstr(view->win, buf, timelen);
+ waddstr(view->win, " ");
+
+ col += DATE_COLS;
+ wmove(view->win, lineno, col);
+ if (type != LINE_CURSOR)
+ wattrset(view->win, get_line_attr(LINE_MAIN_AUTHOR));
+
+ if (opt_utf8) {
+ authorlen = utf8_length(commit->author, AUTHOR_COLS - 2, &col, &trimmed);
+ } else {
+ authorlen = strlen(commit->author);
+ if (authorlen > AUTHOR_COLS - 2) {
+ authorlen = AUTHOR_COLS - 2;
+ trimmed = 1;
+ }
+ }
+
+ if (trimmed) {
+ waddnstr(view->win, commit->author, authorlen);
+ if (type != LINE_CURSOR)
+ wattrset(view->win, get_line_attr(LINE_MAIN_DELIM));
+ waddch(view->win, '~');
+ } else {
+ waddstr(view->win, commit->author);
+ }
+
+ col += AUTHOR_COLS;
+ if (type != LINE_CURSOR)
+ wattrset(view->win, A_NORMAL);
+
+ if (opt_rev_graph && commit->graph_size) {
+ size_t i;
+
+ wmove(view->win, lineno, col);
+ /* Using waddch() instead of waddnstr() ensures that
+ * they'll be rendered correctly for the cursor line. */
+ for (i = 0; i < commit->graph_size; i++)
+ waddch(view->win, commit->graph[i]);
+
+ waddch(view->win, ' ');
+ col += commit->graph_size + 1;
+ }
+
+ wmove(view->win, lineno, col);
+
+ if (commit->refs) {
+ size_t i = 0;
+
+ do {
+ if (type == LINE_CURSOR)
+ ;
+ else if (commit->refs[i]->tag)
+ wattrset(view->win, get_line_attr(LINE_MAIN_TAG));
+ else if (commit->refs[i]->remote)
+ wattrset(view->win, get_line_attr(LINE_MAIN_REMOTE));
+ else
+ wattrset(view->win, get_line_attr(LINE_MAIN_REF));
+ waddstr(view->win, "[");
+ waddstr(view->win, commit->refs[i]->name);
+ waddstr(view->win, "]");
+ if (type != LINE_CURSOR)
+ wattrset(view->win, A_NORMAL);
+ waddstr(view->win, " ");
+ col += strlen(commit->refs[i]->name) + STRING_SIZE("[] ");
+ } while (commit->refs[i++]->next);