index 8b8d593122b1d813f056ed5a5079a1c9b9078038..180661a4fcfbc94067a795898df1a6fc6a6e0330 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -109,7 +109,6 @@ static size_t utf8_length(const char **string, size_t col, int *width, size_t ma
/* The default interval between line numbers. */
#define NUMBER_INTERVAL 5
-#define SCROLL_INTERVAL 1
#define TAB_SIZE 8
@@ -117,6 +116,8 @@ static size_t utf8_length(const char **string, size_t col, int *width, size_t ma
#define NULL_ID "0000000000000000000000000000000000000000"
+#define S_ISGITLINK(mode) (((mode) & S_IFMT) == 0160000)
+
#ifndef GIT_CONFIG
#define GIT_CONFIG "config"
#endif
static bool opt_rev_graph = FALSE;
static bool opt_show_refs = TRUE;
static int opt_num_interval = NUMBER_INTERVAL;
+static double opt_hscroll = 0.50;
static int opt_tab_size = TAB_SIZE;
static int opt_author_cols = AUTHOR_COLS-1;
static char opt_path[SIZEOF_STR] = "";
#define set_attribute(attr, name) map_enum(attr, attr_map, name)
+static int parse_step(double *opt, const char *arg)
+{
+ *opt = atoi(arg);
+ if (!strchr(arg, '%'))
+ return OK;
+
+ /* "Shift down" so 100% and 1 does not conflict. */
+ *opt = (*opt - 1) / 100;
+ if (*opt >= 1.0) {
+ *opt = 0.99;
+ config_msg = "Step value larger than 100%";
+ return ERR;
+ }
+ if (*opt < 0.0) {
+ *opt = 1;
+ config_msg = "Invalid step value";
+ return ERR;
+ }
+ return OK;
+}
+
static int
parse_int(int *opt, const char *arg, int min, int max)
{
}
arg += 1; arglen -= 2;
default:
- string_ncopy_do(opt, optsize, arg, strlen(arg));
+ string_ncopy_do(opt, optsize, arg, arglen);
return OK;
}
}
if (!strcmp(argv[0], "author-width"))
return parse_int(&opt_author_cols, argv[2], 0, 1024);
+ if (!strcmp(argv[0], "horizontal-scroll"))
+ return parse_step(&opt_hscroll, argv[2]);
+
if (!strcmp(argv[0], "tab-size"))
return parse_int(&opt_tab_size, argv[2], 1, 1024);
enum line_type curtype; /* Attribute currently used for drawing. */
unsigned long col; /* Column when drawing. */
bool has_scrolled; /* View was scrolled. */
- bool can_hscroll; /* View can be scrolled horizontally. */
/* Loading */
struct io io;
LINE_GRAPHIC_VLINE
};
-static int line_graphics[] = {
+static chtype line_graphics[] = {
/* LINE_GRAPHIC_VLINE: */ '|'
};
col++;
}
- if (view->col + col >= view->width + view->yoffset)
- view->can_hscroll = TRUE;
-
return col;
}
while (spaces > 0) {
int len = MIN(spaces, sizeof(space) - 1);
- col += draw_chars(view, type, space, spaces, FALSE);
+ col += draw_chars(view, type, space, len, FALSE);
spaces -= len;
}
return col;
}
-static bool
-draw_lineno(struct view *view, unsigned int lineno)
-{
- size_t skip = view->yoffset > view->col ? view->yoffset - view->col : 0;
- char number[10];
- int digits3 = view->digits < 3 ? 3 : view->digits;
- int max_number = MIN(digits3, STRING_SIZE(number));
- int max = view->width - view->col;
- int col;
-
- if (max < max_number)
- max_number = max;
-
- lineno += view->offset + 1;
- if (lineno == 1 || (lineno % opt_num_interval) == 0) {
- static char fmt[] = "%1ld";
-
- if (view->digits <= 9)
- fmt[1] = '0' + digits3;
-
- if (!string_format(number, fmt, lineno))
- number[0] = 0;
- col = draw_chars(view, LINE_LINE_NUMBER, number, max_number, TRUE);
- } else {
- col = draw_space(view, LINE_LINE_NUMBER, max_number, max_number);
- }
-
- if (col < max && skip <= col) {
- set_view_attr(view, LINE_DEFAULT);
- waddch(view->win, line_graphics[LINE_GRAPHIC_VLINE]);
- }
- col++;
-
- view->col += col;
- if (col < max && skip <= col)
- col = draw_space(view, LINE_DEFAULT, max - col, 1);
- view->col++;
-
- return view->width + view->yoffset <= view->col;
-}
-
static bool
draw_text(struct view *view, enum line_type type, const char *string, bool trim)
{
view->col += draw_chars(view, type, string, view->width + view->yoffset - view->col, trim);
- return view->width - view->col <= 0;
+ return view->width + view->yoffset <= view->col;
}
static bool
draw_graphic(struct view *view, enum line_type type, chtype graphic[], size_t size)
{
size_t skip = view->yoffset > view->col ? view->yoffset - view->col : 0;
- int max = view->width - view->col;
+ int max = view->width + view->yoffset - view->col;
int i;
if (max < size)
@@ -1959,13 +1940,13 @@ draw_graphic(struct view *view, enum line_type type, chtype graphic[], size_t si
waddch(view->win, ' ');
view->col++;
- return view->width - view->col <= 0;
+ return view->width + view->yoffset <= view->col;
}
static bool
draw_field(struct view *view, enum line_type type, const char *text, int len, bool trim)
{
- int max = MIN(view->width - view->col, len);
+ int max = MIN(view->width + view->yoffset - view->col, len);
int col;
if (text)
static bool
draw_mode(struct view *view, mode_t mode)
{
- static const char dir_mode[] = "drwxr-xr-x";
- static const char link_mode[] = "lrwxrwxrwx";
- static const char exe_mode[] = "-rwxr-xr-x";
- static const char file_mode[] = "-rw-r--r--";
const char *str;
if (S_ISDIR(mode))
- str = dir_mode;
+ str = "drwxr-xr-x";
else if (S_ISLNK(mode))
- str = link_mode;
- else if (mode & S_IXUSR)
- str = exe_mode;
+ str = "lrwxrwxrwx";
+ else if (S_ISGITLINK(mode))
+ str = "m---------";
+ else if (S_ISREG(mode) && mode & S_IXUSR)
+ str = "-rwxr-xr-x";
+ else if (S_ISREG(mode))
+ str = "-rw-r--r--";
else
- str = file_mode;
+ str = "----------";
+
+ return draw_field(view, LINE_MODE, str, STRING_SIZE("-rw-r--r-- "), FALSE);
+}
+
+static bool
+draw_lineno(struct view *view, unsigned int lineno)
+{
+ char number[10];
+ int digits3 = view->digits < 3 ? 3 : view->digits;
+ int max = MIN(view->width + view->yoffset - view->col, digits3);
+ char *text = NULL;
+
+ lineno += view->offset + 1;
+ if (lineno == 1 || (lineno % opt_num_interval) == 0) {
+ static char fmt[] = "%1ld";
- return draw_field(view, LINE_MODE, str, sizeof(file_mode), FALSE);
+ fmt[1] = '0' + (view->digits <= 9 ? digits3 : 1);
+ if (string_format(number, fmt, lineno))
+ text = number;
+ }
+ if (text)
+ view->col += draw_chars(view, LINE_LINE_NUMBER, text, max, TRUE);
+ else
+ view->col += draw_space(view, LINE_LINE_NUMBER, max, digits3);
+ return draw_graphic(view, LINE_DEFAULT, &line_graphics[LINE_GRAPHIC_VLINE], 1);
}
static bool
{
assert(0 <= lineno && lineno < view->height);
- if (lineno == 0)
- view->can_hscroll = FALSE;
-
for (; lineno < view->height; lineno++) {
if (!draw_view_line(view, lineno))
break;
@@ -2283,6 +2284,15 @@ goto_view_line(struct view *view, unsigned long offset, unsigned long lineno)
return FALSE;
}
+static int
+apply_step(double step, int value)
+{
+ if (step >= 1)
+ return (int) step;
+ value *= step + 0.01;
+ return value ? value : 1;
+}
+
/* Scrolling backend */
static void
do_scroll_view(struct view *view, int lines)
report("Cannot scroll beyond the first column");
return;
}
- if (view->yoffset <= SCROLL_INTERVAL)
+ if (view->yoffset <= apply_step(opt_hscroll, view->width))
view->yoffset = 0;
else
- view->yoffset -= SCROLL_INTERVAL;
+ view->yoffset -= apply_step(opt_hscroll, view->width);
redraw_view_from(view, 0);
report("");
return;
case REQ_SCROLL_RIGHT:
- if (!view->can_hscroll) {
- report("Cannot scroll beyond the last column");
- return;
- }
- view->yoffset += SCROLL_INTERVAL;
+ view->yoffset += apply_step(opt_hscroll, view->width);
redraw_view(view);
report("");
return;
return TRUE;
if (!io_can_read(view->pipe)) {
- if (view->lines == 0) {
+ if (view->lines == 0 && view_is_displayed(view)) {
time_t secs = time(NULL) - view->start_time;
if (secs > 1 && secs > view->update_secs) {
{
int i;
- if (request == REQ_NONE) {
- doupdate();
+ if (request == REQ_NONE)
return TRUE;
- }
if (request > REQ_NONE) {
open_run_request(request);
struct line *pos = view->line + view->lines;
int files = 0;
int file, done;
+ int cursor_y, cursor_x;
if (!status_update_prepare(&io, line->type))
return FALSE;
files++;
string_copy(buf, view->ref);
+ getsyx(cursor_y, cursor_x);
for (file = 0, done = 5; result && file < files; line++, file++) {
int almost_done = file * 100 / files;
string_format(view->ref, "updating file %u of %u (%d%% done)",
file, files, done);
update_view_title(view);
+ setsyx(cursor_y, cursor_x);
doupdate();
}
result = status_update_write(&io, line->data, line->type);