void redraw_view_from(struct view *view, int lineno) { assert(0 <= lineno && lineno < view->height); if (view->columns && view_column_info_changed(view, false)) { int i; view_column_reset(view); for (i = 0; i < view->lines; i++) { view_column_info_update(view, &view->line[i]); } } for (; lineno < view->height; lineno++) { if (!draw_view_line(view, lineno)) break; } wnoutrefresh(view->win); }
static bool tree_read(struct view *view, struct buffer *buf) { struct tree_state *state = view->private; struct tree_entry *data; struct line *entry, *line; enum line_type type; char *path; size_t size; if (state->read_date || !buf) return tree_read_date(view, buf, state); if (buf->size <= SIZEOF_TREE_ATTR) return FALSE; if (view->lines == 0 && !tree_entry(view, LINE_HEADER, view->env->directory, NULL, NULL, 0)) return FALSE; size = parse_size(buf->data + SIZEOF_TREE_ATTR); path = strchr(buf->data + SIZEOF_TREE_ATTR, '\t'); if (!path) return FALSE; path++; /* Strip the path part ... */ if (*view->env->directory) { size_t pathlen = strlen(path); size_t striplen = strlen(view->env->directory); if (pathlen > striplen) memmove(path, path + striplen, pathlen - striplen + 1); /* Insert "link" to parent directory. */ if (view->lines == 1 && !tree_entry(view, LINE_DIRECTORY, "..", "040000", view->ref, 0)) return FALSE; } type = buf->data[SIZEOF_TREE_MODE] == 't' ? LINE_DIRECTORY : LINE_FILE; entry = tree_entry(view, type, path, buf->data, buf->data + TREE_ID_OFFSET, size); if (!entry) return FALSE; data = entry->data; view_column_info_update(view, entry); /* Skip "Directory ..." and ".." line. */ for (line = &view->line[1 + !!*view->env->directory]; line < entry; line++) { if (tree_compare_entry(line, entry) <= 0) continue; memmove(line + 1, line, (entry - line) * sizeof(*entry)); line->data = data; line->type = type; line->dirty = line->cleareol = 1; for (line++; line <= entry; line++) { line->dirty = line->cleareol = 1; line->lineno++; } return TRUE; } /* Move the current line to the first tree entry. */ if (!check_position(&view->prev_pos) && !check_position(&view->pos)) goto_view_line(view, 0, 1); return TRUE; }
static bool tree_read_date(struct view *view, struct buffer *buf, struct tree_state *state) { char *text = buf ? buf->data : NULL; if (!text && state->read_date) { state->read_date = FALSE; return TRUE; } else if (!text) { /* Find next entry to process */ const char *log_file[] = { "git", "log", encoding_arg, "--no-color", "--pretty=raw", "--cc", "--raw", view->ops->id, "--", "%(directory)", NULL }; if (!view->lines) { tree_entry(view, LINE_HEADER, view->env->directory, NULL, NULL, 0); tree_entry(view, LINE_DIRECTORY, "..", "040000", view->ref, 0); report("Tree is empty"); return TRUE; } if (!begin_update(view, repo.cdup, log_file, OPEN_EXTRA)) { report("Failed to load tree data"); return TRUE; } state->read_date = TRUE; return FALSE; } else if (*text == 'c' && get_line_type(text) == LINE_COMMIT) { string_copy_rev_from_commit_line(state->commit, text); } else if (*text == 'a' && get_line_type(text) == LINE_AUTHOR) { parse_author_line(text + STRING_SIZE("author "), &state->author, &state->author_time); } else if (*text == ':') { char *pos; size_t annotated = 1; size_t i; pos = strrchr(text, '\t'); if (!pos) return TRUE; text = pos + 1; if (*view->env->directory && !strncmp(text, view->env->directory, strlen(view->env->directory))) text += strlen(view->env->directory); pos = strchr(text, '/'); if (pos) *pos = 0; for (i = 1; i < view->lines; i++) { struct line *line = &view->line[i]; struct tree_entry *entry = line->data; annotated += !!entry->author; if (entry->author || strcmp(entry->name, text)) continue; string_copy_rev(entry->commit, state->commit); entry->author = state->author; entry->time = state->author_time; line->dirty = 1; view_column_info_update(view, line); break; } if (annotated == view->lines) io_kill(view->pipe); } return TRUE; }