diff options
Diffstat (limited to 'src/nvim/diff.c')
| -rw-r--r-- | src/nvim/diff.c | 83 | 
1 files changed, 55 insertions, 28 deletions
diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 8699c16351..878971a35c 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -44,6 +44,7 @@ static int diff_busy = FALSE;    // ex_diffgetput() is busy  #define DIFF_IWHITE     4        // ignore change in white space  #define DIFF_HORIZONTAL 8        // horizontal splits  #define DIFF_VERTICAL   16       // vertical splits +#define DIFF_HIDDEN_OFF 32       // diffoff when hidden  static int diff_flags = DIFF_FILLER;  #define LBUFLEN 50               // length of line in diff file @@ -1597,6 +1598,34 @@ static bool diff_equal_entry(diff_T *dp, int idx1, int idx2)    return true;  } +// Compare the characters at "p1" and "p2".  If they are equal (possibly +// ignoring case) return true and set "len" to the number of bytes. +static bool diff_equal_char(const char_u *const p1, const char_u *const p2, +                            int *const len) +{ +  const int l = utfc_ptr2len(p1); + +  if (l != utfc_ptr2len(p2)) { +    return false; +  } +  if (l > 1) { +    if (STRNCMP(p1, p2, l) != 0 +        && (!(diff_flags & DIFF_ICASE) +            || utf_fold(utf_ptr2char(p1)) != utf_fold(utf_ptr2char(p2)))) { +      return false; +    } +    *len = l; +  } else { +    if ((*p1 != *p2) +        && (!(diff_flags & DIFF_ICASE) +            || TOLOWER_LOC(*p1) != TOLOWER_LOC(*p2))) { +      return false; +    } +    *len = 1; +  } +  return true; +} +  /// Compare strings "s1" and "s2" according to 'diffopt'.  /// Return non-zero when they are different.  /// @@ -1623,30 +1652,12 @@ static int diff_cmp(char_u *s1, char_u *s2)        p1 = skipwhite(p1);        p2 = skipwhite(p2);      } else { -      int l  = (*mb_ptr2len)(p1); -      if (l != (*mb_ptr2len)(p2)) { +      int l; +      if (!diff_equal_char(p1, p2, &l)) {          break;        } - -      if (l > 1) { -        if ((STRNCMP(p1, p2, l) != 0) -            && (!enc_utf8 -                || !(diff_flags & DIFF_ICASE) -                || (utf_fold(utf_ptr2char(p1)) -                    != utf_fold(utf_ptr2char(p2))))) { -          break; -        } -        p1 += l; -        p2 += l; -      } else { -        if ((*p1 != *p2) -            && (!(diff_flags & DIFF_ICASE) -                || (TOLOWER_LOC(*p1) != TOLOWER_LOC(*p2)))) { -          break; -        } -        ++p1; -        ++p2; -      } +      p1 += l; +      p2 += l;      }    } @@ -1828,6 +1839,9 @@ int diffopt_changed(void)      } else if ((STRNCMP(p, "foldcolumn:", 11) == 0) && ascii_isdigit(p[11])) {        p += 11;        diff_foldcolumn_new = getdigits_int(&p); +    } else if (STRNCMP(p, "hiddenoff", 9) == 0) { +      p += 9; +      diff_flags_new |= DIFF_HIDDEN_OFF;      }      if ((*p != ',') && (*p != NUL)) { @@ -1870,6 +1884,12 @@ bool diffopt_horizontal(void)    return (diff_flags & DIFF_HORIZONTAL) != 0;  } +// Return true if 'diffopt' contains "hiddenoff". +bool diffopt_hiddenoff(void) +{ +  return (diff_flags & DIFF_HIDDEN_OFF) != 0; +} +  /// Find the difference within a changed line.  ///  /// @param  wp      window whose current buffer to check @@ -1887,6 +1907,7 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)    int ei_org;    int ei_new;    bool added = true; +  int l;    // Make a copy of the line, the next ml_get() will invalidate it.    char_u *line_org = vim_strsave(ml_get_buf(wp->w_buffer, lnum, FALSE)); @@ -1933,11 +1954,11 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)            si_org = (int)(skipwhite(line_org + si_org) - line_org);            si_new = (int)(skipwhite(line_new + si_new) - line_new);          } else { -          if (line_org[si_org] != line_new[si_new]) { +          if (!diff_equal_char(line_org + si_org, line_new + si_new, &l)) {              break;            } -          ++si_org; -          ++si_new; +          si_org += l; +          si_new += l;          }        } @@ -1972,11 +1993,17 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)                ei_new--;              }            } else { -            if (line_org[ei_org] != line_new[ei_new]) { +            const char_u *p1 = line_org + ei_org; +            const char_u *p2 = line_new + ei_new; + +            p1 -= utf_head_off(line_org, p1); +            p2 -= utf_head_off(line_new, p2); + +            if (!diff_equal_char(p1, p2, &l)) {                break;              } -            ei_org--; -            ei_new--; +            ei_org -= l; +            ei_new -= l;            }          }  | 
