Fix index refreshing into separate call so diff-files is always run
[tig] / tig.c
diff --git a/tig.c b/tig.c
index d749945..73aa991 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -58,7 +58,7 @@ static void warn(const char *msg, ...);
 static void report(const char *msg, ...);
 static int read_properties(FILE *pipe, const char *separators, int (*read)(char *, size_t, char *, size_t));
 static void set_nonblocking_input(bool loading);
-static size_t utf8_length(const char *string, size_t max_width, int *coloffset, int *trimmed);
+static size_t utf8_length(const char *string, size_t max_width, int *trimmed, bool reserve);
 
 #define ABS(x)         ((x) >= 0  ? (x) : -(x))
 #define MIN(x, y)      ((x) < (y) ? (x) :  (y))
@@ -110,7 +110,7 @@ static size_t utf8_length(const char *string, size_t max_width, int *coloffset,
        "git ls-remote $(git rev-parse --git-dir) 2>/dev/null"
 
 #define TIG_DIFF_CMD \
-       "git show --no-color --root --patch-with-stat --find-copies-harder -C %s 2>/dev/null"
+       "git show --pretty=fuller --no-color --root --patch-with-stat --find-copies-harder -C %s 2>/dev/null"
 
 #define TIG_LOG_CMD    \
        "git log --no-color --cc --stat -n100 %s 2>/dev/null"
@@ -1460,44 +1460,34 @@ static int
 draw_text(struct view *view, const char *string, int max_len, int col,
          bool use_tilde, int tilde_attr)
 {
-       int n;
+       int len = 0;
+       int trimmed = FALSE;
 
-       n = 0;
-       if (max_len > 0) {
-               int len;
-               int trimmed = FALSE;
-
-               if (opt_utf8) {
-                       int pad = 0;
+       if (max_len <= 0)
+               return 0;
 
-                       len = utf8_length(string, max_len, &pad, &trimmed);
-                       if (trimmed && use_tilde) {
+       if (opt_utf8) {
+               len = utf8_length(string, max_len, &trimmed, use_tilde);
+       } else {
+               len = strlen(string);
+               if (len > max_len) {
+                       if (use_tilde) {
                                max_len -= 1;
-                               len = utf8_length(
-                                       string, max_len, &pad, &trimmed);
                        }
-                       n = len;
-               } else {
-                       len = strlen(string);
-                       if (len > max_len) {
-                               if (use_tilde) {
-                                       max_len -= 1;
-                               }
-                               len = max_len;
-                               trimmed = TRUE;
-                       }
-                       n = len;
-               }
-               waddnstr(view->win, string, n);
-               if (trimmed && use_tilde) {
-                       if (tilde_attr != -1)
-                               wattrset(view->win, tilde_attr);
-                       waddch(view->win, '~');
-                       n++;
+                       len = max_len;
+                       trimmed = TRUE;
                }
        }
 
-       return n;
+       waddnstr(view->win, string, len);
+       if (trimmed && use_tilde) {
+               if (tilde_attr != -1)
+                       wattrset(view->win, tilde_attr);
+               waddch(view->win, '~');
+               len++;
+       }
+
+       return len;
 }
 
 static bool
@@ -3366,7 +3356,7 @@ error_out:
 
 /* Don't show unmerged entries in the staged section. */
 #define STATUS_DIFF_INDEX_CMD "git diff-index -z --diff-filter=ACDMRTXB --cached -M HEAD"
-#define STATUS_DIFF_FILES_CMD "git update-index -q --refresh && git diff-files -z"
+#define STATUS_DIFF_FILES_CMD "git diff-files -z"
 #define STATUS_LIST_OTHER_CMD \
        "git ls-files -z --others --exclude-per-directory=.gitignore"
 
@@ -3410,6 +3400,8 @@ status_open(struct view *view)
                        return FALSE;
        }
 
+       system("git update-index -q --refresh");
+
        if (!status_run(view, STATUS_DIFF_INDEX_CMD, TRUE, LINE_STAT_STAGED) ||
            !status_run(view, STATUS_DIFF_FILES_CMD, TRUE, LINE_STAT_UNSTAGED) ||
            !status_run(view, cmd, FALSE, LINE_STAT_UNTRACKED))
@@ -4559,19 +4551,16 @@ utf8_to_unicode(const char *string, size_t length)
 
 /* Calculates how much of string can be shown within the given maximum width
  * and sets trimmed parameter to non-zero value if all of string could not be
- * shown.
- *
- * Additionally, adds to coloffset how many many columns to move to align with
- * the expected position. Takes into account how multi-byte and double-width
- * characters will effect the cursor position.
+ * shown. If the reserve flag is TRUE, it will reserve at least one
+ * trailing character, which can be useful when drawing a delimiter.
  *
  * Returns the number of bytes to output from string to satisfy max_width. */
 static size_t
-utf8_length(const char *string, size_t max_width, int *coloffset, int *trimmed)
+utf8_length(const char *string, size_t max_width, int *trimmed, bool reserve)
 {
        const char *start = string;
        const char *end = strchr(string, '\0');
-       size_t mbwidth = 0;
+       unsigned char last_bytes = 0;
        size_t width = 0;
 
        *trimmed = 0;
@@ -4597,27 +4586,16 @@ utf8_length(const char *string, size_t max_width, int *coloffset, int *trimmed)
                width  += ucwidth;
                if (width > max_width) {
                        *trimmed = 1;
+                       if (reserve && width - ucwidth == max_width) {
+                               string -= last_bytes;
+                       }
                        break;
                }
 
-               /* The column offset collects the differences between the
-                * number of bytes encoding a character and the number of
-                * columns will be used for rendering said character.
-                *
-                * So if some character A is encoded in 2 bytes, but will be
-                * represented on the screen using only 1 byte this will and up
-                * adding 1 to the multi-byte column offset.
-                *
-                * Assumes that no double-width character can be encoding in
-                * less than two bytes. */
-               if (bytes > ucwidth)
-                       mbwidth += bytes - ucwidth;
-
                string  += bytes;
+               last_bytes = bytes;
        }
 
-       *coloffset += mbwidth;
-
        return string - start;
 }