summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c19f801)
raw | patch | inline | side by side (parent: c19f801)
author | Jonas Fonseca <fonseca@diku.dk> | |
Wed, 24 May 2006 01:23:43 +0000 (03:23 +0200) | ||
committer | Jonas Fonseca <fonseca@antimatter.localdomain> | |
Wed, 24 May 2006 01:30:38 +0000 (03:30 +0200) |
Somewhat experimental. This will call get_line_type() on every read line.
tig.c | patch | blob | history |
index 52abe0fda6cb031741ec9b721a0b7598a51e592f..7fca9a875057e7e5fc5e397fae046157348ae9f4 100644 (file)
--- a/tig.c
+++ b/tig.c
}
}
+struct line {
+ enum line_type type;
+ void *data; /* User data */
+};
+
/**
* ENVIRONMENT VARIABLES
**/
struct view;
+struct view_ops;
/* The display array of active views and the index of the current view. */
static struct view *display[2];
static char ref_commit[SIZEOF_REF] = "HEAD";
static char ref_head[SIZEOF_REF] = "HEAD";
-
struct view {
const char *name; /* View name */
const char *cmd_fmt; /* Default command line format */
const char *cmd_env; /* Command line set via environment */
const char *id; /* Points to either of ref_{head,commit} */
- struct view_ops {
- /* What type of content being displayed. Used in the
- * title bar. */
- const char *type;
- /* Draw one line; @lineno must be < view->height. */
- bool (*draw)(struct view *view, unsigned int lineno);
- /* Read one line; updates view->line. */
- bool (*read)(struct view *view, char *line);
- /* Depending on view, change display based on current line. */
- bool (*enter)(struct view *view);
- } *ops;
+ struct view_ops *ops; /* View operations */
char cmd[SIZEOF_CMD]; /* Command buffer */
char ref[SIZEOF_REF]; /* Hovered commit reference */
/* Buffering */
unsigned long lines; /* Total number of lines */
- void **line; /* Line index; each line contains user data */
+ struct line *line; /* Line index */
unsigned int digits; /* Number of digits in the lines member. */
/* Loading */
time_t start_time;
};
+struct view_ops {
+ /* What type of content being displayed. Used in the title bar. */
+ const char *type;
+ /* Draw one line; @lineno must be < view->height. */
+ bool (*draw)(struct view *view, struct line *line, unsigned int lineno);
+ /* Read one line; updates view->line. */
+ bool (*read)(struct view *view, struct line *prev, char *data);
+ /* Depending on view, change display based on current line. */
+ bool (*enter)(struct view *view, struct line *line);
+};
+
static struct view_ops pager_ops;
static struct view_ops main_ops;
#define VIEW(req) (&views[(req) - REQ_OFFSET - 1])
+static bool
+draw_view_line(struct view *view, unsigned int lineno)
+{
+ if (view->offset + lineno >= view->lines)
+ return FALSE;
+
+ return view->ops->draw(view, &view->line[view->offset + lineno], lineno);
+}
+
static void
redraw_view_from(struct view *view, int lineno)
{
assert(0 <= lineno && lineno < view->height);
for (; lineno < view->height; lineno++) {
- if (!view->ops->draw(view, lineno))
+ if (!draw_view_line(view, lineno))
break;
}
wscrl(view->win, lines);
for (; line < end; line++) {
- if (!view->ops->draw(view, line))
+ if (!draw_view_line(view, line))
break;
}
}
/* Move current line into the view. */
if (view->lineno < view->offset) {
view->lineno = view->offset;
- view->ops->draw(view, 0);
+ draw_view_line(view, 0);
} else if (view->lineno >= view->offset + view->height) {
if (view->lineno == view->offset + view->height) {
wclrtoeol(view->win);
}
view->lineno = view->offset + view->height - 1;
- view->ops->draw(view, view->lineno - view->offset);
+ draw_view_line(view, view->lineno - view->offset);
}
assert(view->offset <= view->lineno && view->lineno < view->lines);
wmove(view->win, prev_lineno, 0);
wclrtoeol(view->win);
- view->ops->draw(view, prev_lineno);
+ draw_view_line(view, prev_lineno);
}
/* Check whether the view needs to be scrolled */
}
/* Draw the current line */
- view->ops->draw(view, view->lineno - view->offset);
+ draw_view_line(view, view->lineno - view->offset);
if (!redraw)
return;
int i;
for (i = 0; i < view->lines; i++)
- if (view->line[i])
- free(view->line[i]);
+ if (view->line[i].data)
+ free(view->line[i].data);
free(view->line);
view->line = NULL;
{
char buffer[BUFSIZ];
char *line;
- void **tmp;
+ struct line *tmp;
/* The number of lines to read. If too low it will cause too much
* redrawing (and possible flickering), if too high responsiveness
* will suffer. */
while ((line = fgets(buffer, sizeof(buffer), view->pipe))) {
int linelen = strlen(line);
+ struct line *prev = view->lines
+ ? &view->line[view->lines - 1]
+ : NULL;
+
if (linelen)
line[linelen - 1] = 0;
- if (!view->ops->read(view, line))
+ if (!view->ops->read(view, prev, line))
goto alloc_error;
if (lines-- == 1)
report("Nothing to enter");
break;
}
- return view->ops->enter(view);
+ return view->ops->enter(view, &view->line[view->lineno]);
case REQ_VIEW_NEXT:
{
*/
static bool
-pager_draw(struct view *view, unsigned int lineno)
+pager_draw(struct view *view, struct line *line, unsigned int lineno)
{
- enum line_type type;
- char *line;
- int linelen;
+ char *text = line->data;
+ enum line_type type = line->type;
+ int textlen = strlen(text);
int attr;
- if (view->offset + lineno >= view->lines)
- return FALSE;
-
- line = view->line[view->offset + lineno];
- type = get_line_type(line);
-
wmove(view->win, lineno, 0);
if (view->offset + lineno == view->lineno) {
if (type == LINE_COMMIT) {
- string_copy(view->ref, line + 7);
+ string_copy(view->ref, text + 7);
string_copy(ref_commit, view->ref);
}
attr = get_line_attr(type);
wattrset(view->win, attr);
- linelen = strlen(line);
-
if (opt_line_number || opt_tab_size < TABSIZE) {
static char spaces[] = " ";
int col_offset = 0, col = 0;
col_offset = view->digits + 2;
}
- while (line && col_offset + col < view->width) {
+ while (text && col_offset + col < view->width) {
int cols_max = view->width - col_offset - col;
- char *text = line;
+ char *pos = text;
int cols;
- if (*line == '\t') {
+ if (*text == '\t') {
+ text++;
assert(sizeof(spaces) > TABSIZE);
- line++;
- text = spaces;
+ pos = spaces;
cols = opt_tab_size - (col % opt_tab_size);
} else {
- line = strchr(line, '\t');
- cols = line ? line - text : strlen(text);
+ text = strchr(text, '\t');
+ cols = line ? text - pos : strlen(pos);
}
- waddnstr(view->win, text, MIN(cols, cols_max));
+ waddnstr(view->win, pos, MIN(cols, cols_max));
col += cols;
}
} else {
int col = 0, pos = 0;
- for (; pos < linelen && col < view->width; pos++, col++)
- if (line[pos] == '\t')
+ for (; pos < textlen && col < view->width; pos++, col++)
+ if (text[pos] == '\t')
col += TABSIZE - (col % TABSIZE) - 1;
- waddnstr(view->win, line, pos);
+ waddnstr(view->win, text, pos);
}
return TRUE;
}
static bool
-pager_read(struct view *view, char *line)
+pager_read(struct view *view, struct line *prev, char *line)
{
/* Compress empty lines in the help view. */
if (view == VIEW(REQ_VIEW_HELP) &&
- !*line &&
- view->lines &&
- !*((char *) view->line[view->lines - 1]))
+ !*line && prev && !*((char *) prev->data))
return TRUE;
- view->line[view->lines] = strdup(line);
- if (!view->line[view->lines])
+ view->line[view->lines].data = strdup(line);
+ if (!view->line[view->lines].data)
return FALSE;
+ view->line[view->lines].type = get_line_type(line);
+
view->lines++;
return TRUE;
}
static bool
-pager_enter(struct view *view)
+pager_enter(struct view *view, struct line *line)
{
- char *line = view->line[view->lineno];
int split = 0;
if ((view == VIEW(REQ_VIEW_LOG) ||
view == VIEW(REQ_VIEW_PAGER)) &&
- get_line_type(line) == LINE_COMMIT) {
+ line->type == LINE_COMMIT) {
open_view(view, REQ_VIEW_DIFF, OPEN_SPLIT);
split = 1;
}
};
static bool
-main_draw(struct view *view, unsigned int lineno)
+main_draw(struct view *view, struct line *line, unsigned int lineno)
{
char buf[DATE_COLS + 1];
- struct commit *commit;
+ struct commit *commit = line->data;
enum line_type type;
int col = 0;
size_t timelen;
size_t authorlen;
int trimmed;
- if (view->offset + lineno >= view->lines)
- return FALSE;
-
- commit = view->line[view->offset + lineno];
if (!*commit->author)
return FALSE;
/* Reads git log --pretty=raw output and parses it into the commit struct. */
static bool
-main_read(struct view *view, char *line)
+main_read(struct view *view, struct line *prev, char *line)
{
enum line_type type = get_line_type(line);
struct commit *commit;
line += STRING_SIZE("commit ");
- view->line[view->lines++] = commit;
+ view->line[view->lines++].data = commit;
string_copy(commit->id, line);
commit->refs = get_refs(commit->id);
break;
char *ident = line + STRING_SIZE("author ");
char *end = strchr(ident, '<');
+ if (!prev)
+ break;
+
+ commit = prev->data;
+
if (end) {
for (; end > ident && isspace(end[-1]); end--) ;
*end = 0;
}
- commit = view->line[view->lines - 1];
string_copy(commit->author, ident);
/* Parse epoch and timezone */
break;
}
default:
- /* We should only ever end up here if there has already been a
- * commit line, however, be safe. */
- if (view->lines == 0)
+ if (!prev)
break;
+ commit = prev->data;
+
/* Fill in the commit title if it has not already been set. */
- commit = view->line[view->lines - 1];
if (commit->title[0])
break;
}
static bool
-main_enter(struct view *view)
+main_enter(struct view *view, struct line *line)
{
enum open_flags flags = display[0] == view ? OPEN_SPLIT : OPEN_DEFAULT;