add_keybinding: always allocate the new keybinding
[tig] / tig.c
diff --git a/tig.c b/tig.c
index ef3fe0d..6c2b7d0 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -12,7 +12,7 @@
  */
 
 #ifndef        VERSION
-#define VERSION        "tig-0.4.git"
+#define VERSION        "tig-0.5.git"
 #endif
 
 #ifndef DEBUG
@@ -451,6 +451,17 @@ parse_options(int argc, char *argv[])
        for (i = 1; i < argc; i++) {
                char *opt = argv[i];
 
+               if (!strcmp(opt, "log") ||
+                   !strcmp(opt, "diff") ||
+                   !strcmp(opt, "show")) {
+                       opt_request = opt[0] == 'l'
+                                   ? REQ_VIEW_LOG : REQ_VIEW_DIFF;
+                       break;
+               }
+
+               if (opt[0] && opt[0] != '-')
+                       break;
+
                if (!strcmp(opt, "-l")) {
                        opt_request = REQ_VIEW_LOG;
                        continue;
@@ -486,17 +497,6 @@ parse_options(int argc, char *argv[])
                        break;
                }
 
-               if (!strcmp(opt, "log") ||
-                   !strcmp(opt, "diff") ||
-                   !strcmp(opt, "show")) {
-                       opt_request = opt[0] == 'l'
-                                   ? REQ_VIEW_LOG : REQ_VIEW_DIFF;
-                       break;
-               }
-
-               if (opt[0] && opt[0] != '-')
-                       break;
-
                die("unknown option '%s'\n\n%s", opt, usage);
        }
 
@@ -1164,6 +1164,9 @@ struct view_ops;
 static struct view *display[2];
 static unsigned int current_view;
 
+/* Reading from the prompt? */
+static bool input_mode = FALSE;
+
 #define foreach_displayed_view(view, i) \
        for (i = 0; i < ARRAY_SIZE(display) && (view = display[i]); i++)
 
@@ -1301,7 +1304,10 @@ redraw_view_from(struct view *view, int lineno)
        }
 
        redrawwin(view->win);
-       wrefresh(view->win);
+       if (input_mode)
+               wnoutrefresh(view->win);
+       else
+               wrefresh(view->win);
 }
 
 static void
@@ -1316,33 +1322,44 @@ static void
 update_view_title(struct view *view)
 {
        char buf[SIZEOF_STR];
-       size_t bufpos = 0;
+       char state[SIZEOF_STR];
+       size_t bufpos = 0, statelen = 0;
 
        assert(view_is_displayed(view));
 
-       string_format_from(buf, &bufpos, "[%s]", view->name);
-       if (*view->ref)
-               string_format_from(buf, &bufpos, " %s", view->ref);
-
        if (view->lines || view->pipe) {
                unsigned int view_lines = view->offset + view->height;
                unsigned int lines = view->lines
                                   ? MIN(view_lines, view->lines) * 100 / view->lines
                                   : 0;
 
-               string_format_from(buf, &bufpos, " - %s %d of %d (%d%%)",
+               string_format_from(state, &statelen, "- %s %d of %d (%d%%)",
                                   view->ops->type,
                                   view->lineno + 1,
                                   view->lines,
                                   lines);
+
+               if (view->pipe) {
+                       time_t secs = time(NULL) - view->start_time;
+
+                       /* Three git seconds are a long time ... */
+                       if (secs > 2)
+                               string_format_from(state, &statelen, " %lds", secs);
+               }
        }
 
-       if (view->pipe) {
-               time_t secs = time(NULL) - view->start_time;
+       string_format_from(buf, &bufpos, "[%s]", view->name);
+       if (*view->ref && bufpos < view->width) {
+               size_t refsize = strlen(view->ref);
+               size_t minsize = bufpos + 1 + /* abbrev= */ 7 + 1 + statelen;
+
+               if (minsize < view->width)
+                       refsize = view->width - minsize + 7;
+               string_format_from(buf, &bufpos, " %.*s", refsize, view->ref);
+       }
 
-               /* Three git seconds are a long time ... */
-               if (secs > 2)
-                       string_format_from(buf, &bufpos, " %lds", secs);
+       if (statelen && bufpos < view->width) {
+               string_format_from(buf, &bufpos, " %s", state);
        }
 
        if (view == display[current_view])
@@ -1350,10 +1367,14 @@ update_view_title(struct view *view)
        else
                wbkgdset(view->title, get_line_attr(LINE_TITLE_BLUR));
 
-       werase(view->title);
        mvwaddnstr(view->title, 0, 0, buf, bufpos);
+       wclrtoeol(view->title);
        wmove(view->title, 0, view->width - 1);
-       wrefresh(view->title);
+
+       if (input_mode)
+               wnoutrefresh(view->title);
+       else
+               wrefresh(view->title);
 }
 
 static void
@@ -3110,26 +3131,30 @@ static bool cursed = FALSE;
 /* The status window is used for polling keystrokes. */
 static WINDOW *status_win;
 
+static bool status_empty = TRUE;
+
 /* Update status and title window. */
 static void
 report(const char *msg, ...)
 {
-       static bool empty = TRUE;
        struct view *view = display[current_view];
 
-       if (!empty || *msg) {
+       if (input_mode)
+               return;
+
+       if (!status_empty || *msg) {
                va_list args;
 
                va_start(args, msg);
 
-               werase(status_win);
                wmove(status_win, 0, 0);
                if (*msg) {
                        vwprintw(status_win, msg, args);
-                       empty = FALSE;
+                       status_empty = FALSE;
                } else {
-                       empty = TRUE;
+                       status_empty = TRUE;
                }
+               wclrtoeol(status_win);
                wrefresh(status_win);
 
                va_end(args);
@@ -3199,10 +3224,16 @@ read_prompt(const char *prompt)
                struct view *view;
                int i, key;
 
+               input_mode = TRUE;
+
                foreach_view (view, i)
                        update_view(view);
 
-               report("%s%.*s", prompt, pos, buf);
+               input_mode = FALSE;
+
+               mvwprintw(status_win, 0, 0, "%s%.*s", prompt, pos, buf);
+               wclrtoeol(status_win);
+
                /* Refresh, accept single keystroke of input */
                key = wgetch(status_win);
                switch (key) {
@@ -3237,11 +3268,12 @@ read_prompt(const char *prompt)
                }
        }
 
-       if (status == CANCEL) {
-               /* Clear the status window */
-               report("");
+       /* Clear the status window */
+       status_empty = FALSE;
+       report("");
+
+       if (status == CANCEL)
                return NULL;
-       }
 
        buf[pos++] = 0;
 
@@ -3499,6 +3531,8 @@ main(int argc, char *argv[])
 
                /* Refresh, accept single keystroke of input */
                key = wgetch(status_win);
+               if (key == ERR)
+                       continue;
 
                request = get_keybinding(display[current_view]->keymap, key);