Code

Rename & move read_properties and git_properties
[tig.git] / tig.c
diff --git a/tig.c b/tig.c
index 486b0c7444cd29526195bdb7faa61511c3505c42..dc1d2251464c031c7744d22bd9ebac928975c0a4 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -652,7 +652,54 @@ run_io_buf(const char **argv, char buf[], size_t bufsize)
        return done_io(&io) || error;
 }
 
-static int read_properties(struct io *io, const char *separators, int (*read)(char *, size_t, char *, size_t));
+static int
+io_load(struct io *io, const char *separators,
+       int (*read_property)(char *, size_t, char *, size_t))
+{
+       char *name;
+       int state = OK;
+
+       if (!start_io(io))
+               return ERR;
+
+       while (state == OK && (name = io_get(io, '\n', TRUE))) {
+               char *value;
+               size_t namelen;
+               size_t valuelen;
+
+               name = chomp_string(name);
+               namelen = strcspn(name, separators);
+
+               if (name[namelen]) {
+                       name[namelen] = 0;
+                       value = chomp_string(name + namelen + 1);
+                       valuelen = strlen(value);
+
+               } else {
+                       value = "";
+                       valuelen = 0;
+               }
+
+               state = read_property(name, namelen, value, valuelen);
+       }
+
+       if (state != ERR && io_error(io))
+               state = ERR;
+       done_io(io);
+
+       return state;
+}
+
+static int
+run_io_load(const char **argv, const char *separators,
+           int (*read_property)(char *, size_t, char *, size_t))
+{
+       struct io io = {};
+
+       return init_io_rd(&io, argv, NULL, FORMAT_NONE)
+               ? io_load(&io, separators, read_property) : ERR;
+}
+
 
 /*
  * User requests
@@ -1649,8 +1696,8 @@ read_option(char *opt, size_t optlen, char *value, size_t valuelen)
        }
 
        if (status == ERR) {
-               fprintf(stderr, "Error on line %d, near '%.*s': %s\n",
-                       config_lineno, (int) optlen, opt, config_msg);
+               warn("Error on line %d, near '%.*s': %s",
+                    config_lineno, (int) optlen, opt, config_msg);
                config_errors = TRUE;
        }
 
@@ -1670,9 +1717,9 @@ load_option_file(const char *path)
        config_lineno = 0;
        config_errors = FALSE;
 
-       if (read_properties(&io, " \t", read_option) == ERR ||
+       if (io_load(&io, " \t", read_option) == ERR ||
            config_errors == TRUE)
-               fprintf(stderr, "Errors while loading %s.\n", path);
+               warn("Errors while loading %s.", path);
 }
 
 static int
@@ -1766,6 +1813,7 @@ struct view {
        struct line *curline;   /* Line currently being drawn. */
        enum line_type curtype; /* Attribute currently used for drawing. */
        unsigned long col;      /* Column when drawing. */
+       bool has_scrolled;      /* View was scrolled. */
 
        /* Loading */
        struct io io;
@@ -2103,19 +2151,6 @@ redraw_view(struct view *view)
 }
 
 
-static void
-update_display_cursor(struct view *view)
-{
-       /* Move the cursor to the right-most column of the cursor line.
-        *
-        * XXX: This could turn out to be a bit expensive, but it ensures that
-        * the cursor does not jump around. */
-       if (view->lines) {
-               wmove(view->win, view->lineno - view->offset, view->width - 1);
-               wnoutrefresh(view->win);
-       }
-}
-
 static void
 update_view_title(struct view *view)
 {
@@ -2168,7 +2203,6 @@ update_view_title(struct view *view)
 
        mvwaddnstr(view->title, 0, 0, buf, bufpos);
        wclrtoeol(view->title);
-       wmove(view->title, 0, view->width - 1);
        wnoutrefresh(view->title);
 }
 
@@ -2235,9 +2269,6 @@ redraw_display(bool clear)
                redraw_view(view);
                update_view_title(view);
        }
-
-       if (display[current_view])
-               update_display_cursor(display[current_view]);
 }
 
 static void
@@ -2295,6 +2326,7 @@ do_scroll_view(struct view *view, int lines)
                wnoutrefresh(view->win);
        }
 
+       view->has_scrolled = TRUE;
        report("");
 }
 
@@ -2786,7 +2818,7 @@ update_view(struct view *view)
                if (view->lines == 0) {
                        time_t secs = time(NULL) - view->start_time;
 
-                       if (secs > view->update_secs) {
+                       if (secs > 1 && secs > view->update_secs) {
                                if (view->update_secs == 0)
                                        redraw_view(view);
                                update_view_title(view);
@@ -2856,7 +2888,6 @@ update_view(struct view *view)
        /* Update the title _after_ the redraw so that if the redraw picks up a
         * commit reference in view->ref it'll be available here. */
        update_view_title(view);
-       update_display_cursor(view);
        return TRUE;
 }
 
@@ -6118,6 +6149,10 @@ utf8_length(const char *string, int *width, size_t max_width, int *trimmed, bool
 /* Whether or not the curses interface has been initialized. */
 static bool cursed = FALSE;
 
+/* Terminal hacks and workarounds. */
+static bool use_scroll_redrawwin;
+static bool use_scroll_status_wclear;
+
 /* The status window is used for polling keystrokes. */
 static WINDOW *status_win;
 
@@ -6156,6 +6191,8 @@ report(const char *msg, ...)
                va_start(args, msg);
 
                wmove(status_win, 0, 0);
+               if (view->has_scrolled && use_scroll_status_wclear)
+                       wclear(status_win);
                if (*msg) {
                        vwprintw(status_win, msg, args);
                        status_empty = FALSE;
@@ -6169,7 +6206,6 @@ report(const char *msg, ...)
        }
 
        update_view_title(view);
-       update_display_cursor(view);
 }
 
 /* Controls when nodelay should be in effect when polling user input. */
@@ -6186,6 +6222,7 @@ set_nonblocking_input(bool loading)
 static void
 init_display(void)
 {
+       const char *term;
        int x, y;
 
        /* Initialize the curses library */
@@ -6206,7 +6243,7 @@ init_display(void)
        nonl();         /* Tell curses not to do NL->CR/NL on output */
        cbreak();       /* Take input chars one at a time, no wait for \n */
        noecho();       /* Don't echo input */
-       leaveok(stdscr, TRUE);
+       leaveok(stdscr, FALSE);
 
        if (has_colors())
                init_colors();
@@ -6224,20 +6261,58 @@ init_display(void)
        if (opt_line_graphics) {
                line_graphics[LINE_GRAPHIC_VLINE] = ACS_VLINE;
        }
+
+       term = getenv("XTERM_VERSION") ? NULL : getenv("COLORTERM");
+       if (term && !strcmp(term, "gnome-terminal")) {
+               /* In the gnome-terminal-emulator, the message from
+                * scrolling up one line when impossible followed by
+                * scrolling down one line causes corruption of the
+                * status line. This is fixed by calling wclear. */
+               use_scroll_status_wclear = TRUE;
+               use_scroll_redrawwin = FALSE;
+
+       } else if (term && !strcmp(term, "xrvt-xpm")) {
+               /* No problems with full optimizations in xrvt-(unicode)
+                * and aterm. */
+               use_scroll_status_wclear = use_scroll_redrawwin = FALSE;
+
+       } else {
+               /* When scrolling in (u)xterm the last line in the
+                * scrolling direction will update slowly. */
+               use_scroll_redrawwin = TRUE;
+               use_scroll_status_wclear = FALSE;
+       }
 }
 
 static int
-get_input(bool prompting)
+get_input(int prompt_position)
 {
        struct view *view;
-       int i, key;
+       int i, key, cursor_y, cursor_x;
 
-       if (prompting)
+       if (prompt_position)
                input_mode = TRUE;
 
-       while (true) {
-               foreach_view (view, i)
+       while (TRUE) {
+               foreach_view (view, i) {
                        update_view(view);
+                       if (view_is_displayed(view) && view->has_scrolled &&
+                           use_scroll_redrawwin)
+                               redrawwin(view->win);
+                       view->has_scrolled = FALSE;
+               }
+
+               /* Update the cursor position. */
+               if (prompt_position) {
+                       getbegyx(status_win, cursor_y, cursor_x);
+                       cursor_x = prompt_position;
+               } else {
+                       view = display[current_view];
+                       getbegyx(view->win, cursor_y, cursor_x);
+                       cursor_x = view->width - 1;
+                       cursor_y += view->lineno - view->offset;
+               }
+               setsyx(cursor_y, cursor_x);
 
                /* Refresh, accept single keystroke of input */
                doupdate();
@@ -6252,8 +6327,6 @@ get_input(bool prompting)
 
                        getmaxyx(stdscr, height, width);
 
-                       /* Resize the status view first so the cursor is
-                        * placed properly. */
                        wresize(status_win, 1, width);
                        mvwin(status_win, height - 1, 0);
                        wnoutrefresh(status_win);
@@ -6282,7 +6355,7 @@ prompt_input(const char *prompt, input_handler handler, void *data)
                mvwprintw(status_win, 0, 0, "%s%.*s", prompt, pos, buf);
                wclrtoeol(status_win);
 
-               key = get_input(TRUE);
+               key = get_input(pos + 1);
                switch (key) {
                case KEY_RETURN:
                case KEY_ENTER:
@@ -6362,17 +6435,6 @@ read_prompt(const char *prompt)
  * Repository properties
  */
 
-static int
-git_properties(const char **argv, const char *separators,
-              int (*read_property)(char *, size_t, char *, size_t))
-{
-       struct io io = {};
-
-       if (init_io_rd(&io, argv, NULL, FORMAT_NONE))
-               return read_properties(&io, separators, read_property);
-       return ERR;
-}
-
 static struct ref *refs = NULL;
 static size_t refs_alloc = 0;
 static size_t refs_size = 0;
@@ -6547,7 +6609,7 @@ load_refs(void)
        while (id_refs_size > 0)
                free(id_refs[--id_refs_size]);
 
-       return git_properties(ls_remote_argv, "\t", read_ref);
+       return run_io_load(ls_remote_argv, "\t", read_ref);
 }
 
 static int
@@ -6589,7 +6651,7 @@ load_git_config(void)
 {
        const char *config_list_argv[] = { "git", GIT_CONFIG, "--list", NULL };
 
-       return git_properties(config_list_argv, "=", read_repo_config_option);
+       return run_io_load(config_list_argv, "=", read_repo_config_option);
 }
 
 static int
@@ -6636,45 +6698,7 @@ load_repo_info(void)
                }
        }
 
-       return git_properties(rev_parse_argv, "=", read_repo_info);
-}
-
-static int
-read_properties(struct io *io, const char *separators,
-               int (*read_property)(char *, size_t, char *, size_t))
-{
-       char *name;
-       int state = OK;
-
-       if (!start_io(io))
-               return ERR;
-
-       while (state == OK && (name = io_get(io, '\n', TRUE))) {
-               char *value;
-               size_t namelen;
-               size_t valuelen;
-
-               name = chomp_string(name);
-               namelen = strcspn(name, separators);
-
-               if (name[namelen]) {
-                       name[namelen] = 0;
-                       value = chomp_string(name + namelen + 1);
-                       valuelen = strlen(value);
-
-               } else {
-                       value = "";
-                       valuelen = 0;
-               }
-
-               state = read_property(name, namelen, value, valuelen);
-       }
-
-       if (state != ERR && io_error(io))
-               state = ERR;
-       done_io(io);
-
-       return state;
+       return run_io_load(rev_parse_argv, "=", read_repo_info);
 }
 
 
@@ -6779,7 +6803,7 @@ main(int argc, const char *argv[])
        }
 
        while (view_driver(display[current_view], request)) {
-               int key = get_input(FALSE);
+               int key = get_input(0);
 
                view = display[current_view];
                request = get_keybinding(view->keymap, key);