Patch 8.2.3390
Problem:    Included xdiff code is outdated.
Solution:   Sync with xdiff in git 2.33. (Christian Brabandt, closes #8431)
Files:      src/diff.c, src/xdiff/README.txt, src/xdiff/xdiff.h,
            src/xdiff/xdiffi.c, src/xdiff/xdiffi.h, src/xdiff/xemit.c,
            src/xdiff/xemit.h, src/xdiff/xhistogram.c, src/xdiff/xinclude.h,
            src/xdiff/xmacros.h, src/xdiff/xpatience.c, src/xdiff/xprepare.h,
            src/xdiff/xtypes.h, src/xdiff/xutils.c, src/xdiff/xutils.h


*** ../vim-8.2.3389/src/diff.c  2021-07-27 22:00:39.741712405 +0200
--- src/diff.c  2021-08-31 20:27:29.074489143 +0200
***************
*** 1095,1101 ****
  
      emit_cfg.ctxlen = 0; // don't need any diff_context here
      emit_cb.priv = &diffio->dio_diff;
!     emit_cb.outf = xdiff_out;
      if (xdl_diff(&diffio->dio_orig.din_mmfile,
                &diffio->dio_new.din_mmfile,
                &param, &emit_cfg, &emit_cb) < 0)
--- 1095,1101 ----
  
      emit_cfg.ctxlen = 0; // don't need any diff_context here
      emit_cb.priv = &diffio->dio_diff;
!     emit_cb.out_line = xdiff_out;
      if (xdl_diff(&diffio->dio_orig.din_mmfile,
                &diffio->dio_new.din_mmfile,
                &param, &emit_cfg, &emit_cb) < 0)
*** ../vim-8.2.3389/src/xdiff/README.txt        2018-09-10 21:17:33.000000000 
+0200
--- src/xdiff/README.txt        2021-08-31 20:27:29.074489143 +0200
***************
*** 1,6 ****
  The files in this directory come from the xdiff implementation in git.
  You can find it here: https://github.com/git/git/tree/master/xdiff
! The files were last updated 2018 September 10.
  
  This is originally based on libxdiff, which can be found here:
  http://www.xmailserver.org/xdiff-lib.html
--- 1,6 ----
  The files in this directory come from the xdiff implementation in git.
  You can find it here: https://github.com/git/git/tree/master/xdiff
! The files were last updated August 31, 2021 from git release v.2.33.0
  
  This is originally based on libxdiff, which can be found here:
  http://www.xmailserver.org/xdiff-lib.html
*** ../vim-8.2.3389/src/xdiff/xdiff.h   2019-12-04 22:12:40.000000000 +0100
--- src/xdiff/xdiff.h   2021-08-31 20:27:29.074489143 +0200
***************
*** 25,33 ****
  
  #ifdef __cplusplus
  extern "C" {
! #endif // #ifdef __cplusplus
  
! // xpparm_t.flags
  #define XDF_NEED_MINIMAL (1 << 0)
  
  #define XDF_IGNORE_WHITESPACE (1 << 1)
--- 25,33 ----
  
  #ifdef __cplusplus
  extern "C" {
! #endif /* #ifdef __cplusplus */
  
! /* xpparm_t.flags */
  #define XDF_NEED_MINIMAL (1 << 0)
  
  #define XDF_IGNORE_WHITESPACE (1 << 1)
***************
*** 48,69 ****
  
  #define XDF_INDENT_HEURISTIC (1 << 23)
  
! // xdemitconf_t.flags
  #define XDL_EMIT_FUNCNAMES (1 << 0)
  #define XDL_EMIT_FUNCCONTEXT (1 << 2)
  
! // merge simplification levels
  #define XDL_MERGE_MINIMAL 0
  #define XDL_MERGE_EAGER 1
  #define XDL_MERGE_ZEALOUS 2
  #define XDL_MERGE_ZEALOUS_ALNUM 3
  
! // merge favor modes
  #define XDL_MERGE_FAVOR_OURS 1
  #define XDL_MERGE_FAVOR_THEIRS 2
  #define XDL_MERGE_FAVOR_UNION 3
  
! // merge output styles
  #define XDL_MERGE_DIFF3 1
  
  typedef struct s_mmfile {
--- 48,70 ----
  
  #define XDF_INDENT_HEURISTIC (1 << 23)
  
! /* xdemitconf_t.flags */
  #define XDL_EMIT_FUNCNAMES (1 << 0)
+ #define XDL_EMIT_NO_HUNK_HDR (1 << 1)
  #define XDL_EMIT_FUNCCONTEXT (1 << 2)
  
! /* merge simplification levels */
  #define XDL_MERGE_MINIMAL 0
  #define XDL_MERGE_EAGER 1
  #define XDL_MERGE_ZEALOUS 2
  #define XDL_MERGE_ZEALOUS_ALNUM 3
  
! /* merge favor modes */
  #define XDL_MERGE_FAVOR_OURS 1
  #define XDL_MERGE_FAVOR_THEIRS 2
  #define XDL_MERGE_FAVOR_UNION 3
  
! /* merge output styles */
  #define XDL_MERGE_DIFF3 1
  
  typedef struct s_mmfile {
***************
*** 79,92 ****
  typedef struct s_xpparam {
        unsigned long flags;
  
!       // See Documentation/diff-options.txt.
        char **anchors;
        size_t anchors_nr;
  } xpparam_t;
  
  typedef struct s_xdemitcb {
        void *priv;
!       int (*outf)(void *, mmbuffer_t *, int);
  } xdemitcb_t;
  
  typedef long (*find_func_t)(const char *line, long line_len, char *buffer, 
long buffer_size, void *priv);
--- 80,103 ----
  typedef struct s_xpparam {
        unsigned long flags;
  
!       /* -I<regex> */
!  #if 0  // unused by Vim
!       regex_t **ignore_regex;
!       size_t ignore_regex_nr;
! #endif
! 
!       /* See Documentation/diff-options.txt. */
        char **anchors;
        size_t anchors_nr;
  } xpparam_t;
  
  typedef struct s_xdemitcb {
        void *priv;
!       int (*out_hunk)(void *,
!                       long old_begin, long old_nr,
!                       long new_begin, long new_nr,
!                       const char *func, long funclen);
!       int (*out_line)(void *, mmbuffer_t *, int);
  } xdemitcb_t;
  
  typedef long (*find_func_t)(const char *line, long line_len, char *buffer, 
long buffer_size, void *priv);
***************
*** 130,138 ****
        int level;
        int favor;
        int style;
!       const char *ancestor;   // label for orig
!       const char *file1;      // label for mf1
!       const char *file2;      // label for mf2
  } xmparam_t;
  
  #define DEFAULT_CONFLICT_MARKER_SIZE 7
--- 141,149 ----
        int level;
        int favor;
        int style;
!       const char *ancestor;   /* label for orig */
!       const char *file1;      /* label for mf1 */
!       const char *file2;      /* label for mf2 */
  } xmparam_t;
  
  #define DEFAULT_CONFLICT_MARKER_SIZE 7
***************
*** 142,147 ****
  
  #ifdef __cplusplus
  }
! #endif // #ifdef __cplusplus
  
! #endif // #if !defined(XDIFF_H)
--- 153,158 ----
  
  #ifdef __cplusplus
  }
! #endif /* #ifdef __cplusplus */
  
! #endif /* #if !defined(XDIFF_H) */
*** ../vim-8.2.3389/src/xdiff/xdiffi.c  2019-12-04 22:10:52.000000000 +0100
--- src/xdiff/xdiffi.c  2021-08-31 20:27:29.074489143 +0200
***************
*** 38,46 ****
   * Basically considers a "box" (off1, off2, lim1, lim2) and scan from both
   * the forward diagonal starting from (off1, off2) and the backward diagonal
   * starting from (lim1, lim2). If the K values on the same diagonal crosses
!  * returns the furthest point of reach. We might end up having to expensive
!  * cases using this algorithm is full, so a little bit of heuristic is needed
!  * to cut the search and to return a suboptimal point.
   */
  static long xdl_split(unsigned long const *ha1, long off1, long lim1,
                      unsigned long const *ha2, long off2, long lim2,
--- 38,46 ----
   * Basically considers a "box" (off1, off2, lim1, lim2) and scan from both
   * the forward diagonal starting from (off1, off2) and the backward diagonal
   * starting from (lim1, lim2). If the K values on the same diagonal crosses
!  * returns the furthest point of reach. We might encounter expensive edge 
cases
!  * using this algorithm, so a little bit of heuristic is needed to cut the
!  * search and to return a suboptimal point.
   */
  static long xdl_split(unsigned long const *ha1, long off1, long lim1,
                      unsigned long const *ha2, long off2, long lim2,
***************
*** 63,73 ****
                int got_snake = 0;
  
                /*
!                * We need to extent the diagonal "domain" by one. If the next
                 * values exits the box boundaries we need to change it in the
!                * opposite direction because (max - min) must be a power of 
two.
                 * Also we initialize the external K value to -1 so that we can
!                * avoid extra conditions check inside the core loop.
                 */
                if (fmin > dmin)
                        kvdf[--fmin - 1] = -1;
--- 63,75 ----
                int got_snake = 0;
  
                /*
!                * We need to extend the diagonal "domain" by one. If the next
                 * values exits the box boundaries we need to change it in the
!                * opposite direction because (max - min) must be a power of
!                * two.
!                *
                 * Also we initialize the external K value to -1 so that we can
!                * avoid extra conditions in the check inside the core loop.
                 */
                if (fmin > dmin)
                        kvdf[--fmin - 1] = -1;
***************
*** 98,108 ****
                }
  
                /*
!                * We need to extent the diagonal "domain" by one. If the next
                 * values exits the box boundaries we need to change it in the
!                * opposite direction because (max - min) must be a power of 
two.
                 * Also we initialize the external K value to -1 so that we can
!                * avoid extra conditions check inside the core loop.
                 */
                if (bmin > dmin)
                        kvdb[--bmin - 1] = XDL_LINE_MAX;
--- 100,112 ----
                }
  
                /*
!                * We need to extend the diagonal "domain" by one. If the next
                 * values exits the box boundaries we need to change it in the
!                * opposite direction because (max - min) must be a power of
!                * two.
!                *
                 * Also we initialize the external K value to -1 so that we can
!                * avoid extra conditions in the check inside the core loop.
                 */
                if (bmin > dmin)
                        kvdb[--bmin - 1] = XDL_LINE_MAX;
***************
*** 138,144 ****
                /*
                 * If the edit cost is above the heuristic trigger and if
                 * we got a good snake, we sample current diagonals to see
!                * if some of the, have reached an "interesting" path. Our
                 * measure is a function of the distance from the diagonal
                 * corner (i1 + i2) penalized with the distance from the
                 * mid diagonal itself. If this value is above the current
--- 142,148 ----
                /*
                 * If the edit cost is above the heuristic trigger and if
                 * we got a good snake, we sample current diagonals to see
!                * if some of them have reached an "interesting" path. Our
                 * measure is a function of the distance from the diagonal
                 * corner (i1 + i2) penalized with the distance from the
                 * mid diagonal itself. If this value is above the current
***************
*** 196,203 ****
                }
  
                /*
!                * Enough is enough. We spent too much time here and now we 
collect
!                * the furthest reaching path using the (i1 + i2) measure.
                 */
                if (ec >= xenv->mxcost) {
                        long fbest, fbest1, bbest, bbest1;
--- 200,208 ----
                }
  
                /*
!                * Enough is enough. We spent too much time here and now we
!                * collect the furthest reaching path using the (i1 + i2)
!                * measure.
                 */
                if (ec >= xenv->mxcost) {
                        long fbest, fbest1, bbest, bbest1;
***************
*** 244,252 ****
  
  
  /*
!  * Rule: "Divide et Impera". Recursively split the box in sub-boxes by calling
!  * the box splitting function. Note that the real job (marking changed lines)
!  * is done in the two boundary reaching checks.
   */
  int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
                 diffdata_t *dd2, long off2, long lim2,
--- 249,257 ----
  
  
  /*
!  * Rule: "Divide et Impera" (divide & conquer). Recursively split the box in
!  * sub-boxes by calling the box splitting function. Note that the real job
!  * (marking changed lines) is done in the two boundary reaching checks.
   */
  int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
                 diffdata_t *dd2, long off2, long lim2,
***************
*** 323,329 ****
        }
  
        /*
!        * Allocate and setup K vectors to be used by the differential 
algorithm.
         * One is to store the forward path and one to store the backward path.
         */
        ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3;
--- 328,336 ----
        }
  
        /*
!        * Allocate and setup K vectors to be used by the differential
!        * algorithm.
!        *
         * One is to store the forward path and one to store the backward path.
         */
        ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3;
***************
*** 418,430 ****
                        ret += 1;
                else if (c == '\t')
                        ret += 8 - ret % 8;
!               // ignore other whitespace characters
  
                if (ret >= MAX_INDENT)
                        return MAX_INDENT;
        }
  
!       // The line contains only whitespace.
        return -1;
  }
  
--- 425,437 ----
                        ret += 1;
                else if (c == '\t')
                        ret += 8 - ret % 8;
!               /* ignore other whitespace characters */
  
                if (ret >= MAX_INDENT)
                        return MAX_INDENT;
        }
  
!       /* The line contains only whitespace. */
        return -1;
  }
  
***************
*** 435,441 ****
   */
  #define MAX_BLANKS 20
  
! // Characteristics measured about a hypothetical split position.
  struct split_measurement {
        /*
         * Is the split at the end of the file (aside from any blank lines)?
--- 442,448 ----
   */
  #define MAX_BLANKS 20
  
! /* Characteristics measured about a hypothetical split position. */
  struct split_measurement {
        /*
         * Is the split at the end of the file (aside from any blank lines)?
***************
*** 443,450 ****
        int end_of_file;
  
        /*
!        * How much is the line immediately following the split indented (or -1 
if
!        * the line is blank):
         */
        int indent;
  
--- 450,457 ----
        int end_of_file;
  
        /*
!        * How much is the line immediately following the split indented (or -1
!        * if the line is blank):
         */
        int indent;
  
***************
*** 454,461 ****
        int pre_blank;
  
        /*
!        * How much is the nearest non-blank line above the split indented (or 
-1
!        * if there is no such line)?
         */
        int pre_indent;
  
--- 461,468 ----
        int pre_blank;
  
        /*
!        * How much is the nearest non-blank line above the split indented (or
!        * -1 if there is no such line)?
         */
        int pre_indent;
  
***************
*** 472,481 ****
  };
  
  struct split_score {
!       // The effective indent of this split (smaller is preferred).
        int effective_indent;
  
!       // Penalty for this split (smaller is preferred).
        int penalty;
  };
  
--- 479,488 ----
  };
  
  struct split_score {
!       /* The effective indent of this split (smaller is preferred). */
        int effective_indent;
  
!       /* Penalty for this split (smaller is preferred). */
        int penalty;
  };
  
***************
*** 534,549 ****
   * integer math.
   */
  
! // Penalty if there are no non-blank lines before the split
  #define START_OF_FILE_PENALTY 1
  
! // Penalty if there are no non-blank lines after the split
  #define END_OF_FILE_PENALTY 21
  
! // Multiplier for the number of blank lines around the split
  #define TOTAL_BLANK_WEIGHT (-30)
  
! // Multiplier for the number of blank lines after the split
  #define POST_BLANK_WEIGHT 6
  
  /*
--- 541,556 ----
   * integer math.
   */
  
! /* Penalty if there are no non-blank lines before the split */
  #define START_OF_FILE_PENALTY 1
  
! /* Penalty if there are no non-blank lines after the split */
  #define END_OF_FILE_PENALTY 21
  
! /* Multiplier for the number of blank lines around the split */
  #define TOTAL_BLANK_WEIGHT (-30)
  
! /* Multiplier for the number of blank lines after the split */
  #define POST_BLANK_WEIGHT 6
  
  /*
***************
*** 581,593 ****
  
  /*
   * Compute a badness score for the hypothetical split whose measurements are
!  * stored in m. The weight factors were determined empirically using the 
tools and
!  * corpus described in
   *
   *     https://github.com/mhagger/diff-slider-tools
   *
!  * Also see that project if you want to improve the weights based on, for 
example,
!  * a larger or more diverse corpus.
   */
  static void score_add_split(const struct split_measurement *m, struct 
split_score *s)
  {
--- 588,600 ----
  
  /*
   * Compute a badness score for the hypothetical split whose measurements are
!  * stored in m. The weight factors were determined empirically using the tools
!  * and corpus described in
   *
   *     https://github.com/mhagger/diff-slider-tools
   *
!  * Also see that project if you want to improve the weights based on, for
!  * example, a larger or more diverse corpus.
   */
  static void score_add_split(const struct split_measurement *m, struct 
split_score *s)
  {
***************
*** 610,616 ****
        post_blank = (m->indent == -1) ? 1 + m->post_blank : 0;
        total_blank = m->pre_blank + post_blank;
  
!       // Penalties based on nearby blank lines:
        s->penalty += TOTAL_BLANK_WEIGHT * total_blank;
        s->penalty += POST_BLANK_WEIGHT * post_blank;
  
--- 617,623 ----
        post_blank = (m->indent == -1) ? 1 + m->post_blank : 0;
        total_blank = m->pre_blank + post_blank;
  
!       /* Penalties based on nearby blank lines: */
        s->penalty += TOTAL_BLANK_WEIGHT * total_blank;
        s->penalty += POST_BLANK_WEIGHT * post_blank;
  
***************
*** 621,633 ****
  
        any_blanks = (total_blank != 0);
  
!       // Note that the effective indent is -1 at the end of the file:
        s->effective_indent += indent;
  
        if (indent == -1) {
!               // No additional adjustments needed.
        } else if (m->pre_indent == -1) {
!               // No additional adjustments needed.
        } else if (indent > m->pre_indent) {
                /*
                 * The line is indented more than its predecessor.
--- 628,640 ----
  
        any_blanks = (total_blank != 0);
  
!       /* Note that the effective indent is -1 at the end of the file: */
        s->effective_indent += indent;
  
        if (indent == -1) {
!               /* No additional adjustments needed. */
        } else if (m->pre_indent == -1) {
!               /* No additional adjustments needed. */
        } else if (indent > m->pre_indent) {
                /*
                 * The line is indented more than its predecessor.
***************
*** 669,675 ****
  
  static int score_cmp(struct split_score *s1, struct split_score *s2)
  {
!       // -1 if s1.effective_indent < s2->effective_indent, etc.
        int cmp_indents = ((s1->effective_indent > s2->effective_indent) -
                           (s1->effective_indent < s2->effective_indent));
  
--- 676,682 ----
  
  static int score_cmp(struct split_score *s1, struct split_score *s2)
  {
!       /* -1 if s1.effective_indent < s2->effective_indent, etc. */
        int cmp_indents = ((s1->effective_indent > s2->effective_indent) -
                           (s1->effective_indent < s2->effective_indent));
  
***************
*** 809,821 ****
        group_init(xdfo, &go);
  
        while (1) {
!               // If the group is empty in the to-be-compacted file, skip it:
                if (g.end == g.start)
                        goto next;
  
                /*
                 * Now shift the change up and then down as far as possible in
!                * each direction. If it bumps into any other changes, merge 
them.
                 */
                do {
                        groupsize = g.end - g.start;
--- 816,831 ----
        group_init(xdfo, &go);
  
        while (1) {
!               /*
!                * If the group is empty in the to-be-compacted file, skip it:
!                */
                if (g.end == g.start)
                        goto next;
  
                /*
                 * Now shift the change up and then down as far as possible in
!                * each direction. If it bumps into any other changes, merge
!                * them.
                 */
                do {
                        groupsize = g.end - g.start;
***************
*** 828,834 ****
                         */
                        end_matching_other = -1;
  
!                       // Shift the group backward as much as possible:
                        while (!group_slide_up(xdf, &g, flags))
                                if (group_previous(xdfo, &go))
                                        xdl_bug("group sync broken sliding up");
--- 838,844 ----
                         */
                        end_matching_other = -1;
  
!                       /* Shift the group backward as much as possible: */
                        while (!group_slide_up(xdf, &g, flags))
                                if (group_previous(xdfo, &go))
                                        xdl_bug("group sync broken sliding up");
***************
*** 842,848 ****
                        if (go.end > go.start)
                                end_matching_other = g.end;
  
!                       // Now shift the group forward as far as possible:
                        while (1) {
                                if (group_slide_down(xdf, &g, flags))
                                        break;
--- 852,858 ----
                        if (go.end > go.start)
                                end_matching_other = g.end;
  
!                       /* Now shift the group forward as far as possible: */
                        while (1) {
                                if (group_slide_down(xdf, &g, flags))
                                        break;
***************
*** 858,874 ****
                 * If the group can be shifted, then we can possibly use this
                 * freedom to produce a more intuitive diff.
                 *
!                * The group is currently shifted as far down as possible, so 
the
!                * heuristics below only have to handle upwards shifts.
                 */
  
                if (g.end == earliest_end) {
!                       // no shifting was possible
                } else if (end_matching_other != -1) {
                        /*
!                        * Move the possibly merged group of changes back to 
line
!                        * up with the last group of changes from the other file
!                        * that it can align with.
                         */
                        while (go.end == go.start) {
                                if (group_slide_up(xdf, &g, flags))
--- 868,884 ----
                 * If the group can be shifted, then we can possibly use this
                 * freedom to produce a more intuitive diff.
                 *
!                * The group is currently shifted as far down as possible, so
!                * the heuristics below only have to handle upwards shifts.
                 */
  
                if (g.end == earliest_end) {
!                       /* no shifting was possible */
                } else if (end_matching_other != -1) {
                        /*
!                        * Move the possibly merged group of changes back to
!                        * line up with the last group of changes from the
!                        * other file that it can align with.
                         */
                        while (go.end == go.start) {
                                if (group_slide_up(xdf, &g, flags))
***************
*** 879,892 ****
                } else if (flags & XDF_INDENT_HEURISTIC) {
                        /*
                         * Indent heuristic: a group of pure add/delete lines
!                        * implies two splits, one between the end of the 
"before"
!                        * context and the start of the group, and another 
between
!                        * the end of the group and the beginning of the "after"
!                        * context. Some splits are aesthetically better and 
some
!                        * are worse. We compute a badness "score" for each 
split,
!                        * and add the scores for the two splits to define a
!                        * "score" for each position that the group can be 
shifted
!                        * to. Then we pick the shift with the lowest score.
                         */
                        long shift, best_shift = -1;
                        struct split_score best_score;
--- 889,903 ----
                } else if (flags & XDF_INDENT_HEURISTIC) {
                        /*
                         * Indent heuristic: a group of pure add/delete lines
!                        * implies two splits, one between the end of the
!                        * "before" context and the start of the group, and
!                        * another between the end of the group and the
!                        * beginning of the "after" context. Some splits are
!                        * aesthetically better and some are worse. We compute
!                        * a badness "score" for each split, and add the scores
!                        * for the two splits to define a "score" for each
!                        * position that the group can be shifted to. Then we
!                        * pick the shift with the lowest score.
                         */
                        long shift, best_shift = -1;
                        struct split_score best_score;
***************
*** 921,927 ****
                }
  
        next:
!               // Move past the just-processed group:
                if (group_next(xdf, &g))
                        break;
                if (group_next(xdfo, &go))
--- 932,938 ----
                }
  
        next:
!               /* Move past the just-processed group: */
                if (group_next(xdf, &g))
                        break;
                if (group_next(xdfo, &go))
***************
*** 987,993 ****
        return 0;
  }
  
! static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags)
  {
        xdchange_t *xch;
  
--- 998,1004 ----
        return 0;
  }
  
! static void xdl_mark_ignorable_lines(xdchange_t *xscr, xdfenv_t *xe, long 
flags)
  {
        xdchange_t *xch;
  
***************
*** 1008,1013 ****
--- 1019,1066 ----
        }
  }
  
+ #if 0 // unused by Vim
+ static int record_matches_regex(xrecord_t *rec, xpparam_t const *xpp) {
+       regmatch_t regmatch;
+       int i;
+ 
+       for (i = 0; i < xpp->ignore_regex_nr; i++)
+               if (!regexec_buf(xpp->ignore_regex[i], rec->ptr, rec->size, 1,
+                                &regmatch, 0))
+                       return 1;
+ 
+       return 0;
+ }
+ 
+ static void xdl_mark_ignorable_regex(xdchange_t *xscr, const xdfenv_t *xe,
+                                    xpparam_t const *xpp)
+ {
+       xdchange_t *xch;
+ 
+       for (xch = xscr; xch; xch = xch->next) {
+               xrecord_t **rec;
+               int ignore = 1;
+               long i;
+ 
+               /*
+                * Do not override --ignore-blank-lines.
+                */
+               if (xch->ignore)
+                       continue;
+ 
+               rec = &xe->xdf1.recs[xch->i1];
+               for (i = 0; i < xch->chg1 && ignore; i++)
+                       ignore = record_matches_regex(rec[i], xpp);
+ 
+               rec = &xe->xdf2.recs[xch->i2];
+               for (i = 0; i < xch->chg2 && ignore; i++)
+                       ignore = record_matches_regex(rec[i], xpp);
+ 
+               xch->ignore = ignore;
+       }
+ }
+ #endif
+ 
  int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
             xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
        xdchange_t *xscr;
***************
*** 1027,1033 ****
        }
        if (xscr) {
                if (xpp->flags & XDF_IGNORE_BLANK_LINES)
!                       xdl_mark_ignorable(xscr, &xe, xpp->flags);
  
                if (ef(&xe, xscr, ecb, xecfg) < 0) {
  
--- 1080,1091 ----
        }
        if (xscr) {
                if (xpp->flags & XDF_IGNORE_BLANK_LINES)
!                       xdl_mark_ignorable_lines(xscr, &xe, xpp->flags);
! 
! #if 0
!               if (xpp->ignore_regex)
!                       xdl_mark_ignorable_regex(xscr, &xe, xpp);
! #endif
  
                if (ef(&xe, xscr, ecb, xecfg) < 0) {
  
*** ../vim-8.2.3389/src/xdiff/xdiffi.h  2019-12-04 22:12:58.000000000 +0100
--- src/xdiff/xdiffi.h  2021-08-31 20:27:29.074489143 +0200
***************
*** 61,64 ****
  int xdl_do_histogram_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
                xdfenv_t *env);
  
! #endif // #if !defined(XDIFFI_H)
--- 61,64 ----
  int xdl_do_histogram_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
                xdfenv_t *env);
  
! #endif /* #if !defined(XDIFFI_H) */
*** ../vim-8.2.3389/src/xdiff/xemit.c   2019-12-04 22:11:15.000000000 +0100
--- src/xdiff/xemit.c   2021-08-31 20:27:29.074489143 +0200
***************
*** 31,37 ****
  
  
  static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, 
xdemitcb_t *ecb) {
!       long size, psize = (long)strlen(pre);
        char const *rec;
  
        size = xdl_get_rec(xdf, ri, &rec);
--- 31,37 ----
  
  
  static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, 
xdemitcb_t *ecb) {
!       long size, psize = strlen(pre);
        char const *rec;
  
        size = xdl_get_rec(xdf, ri, &rec);
***************
*** 54,62 ****
        xdchange_t *xch, *xchp, *lxch;
        long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen;
        long max_ignorable = xecfg->ctxlen;
!       unsigned long ignored = 0; // number of ignored blank lines
  
!       // remove ignorable changes that are too far before other changes
        for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) {
                xch = xchp->next;
  
--- 54,62 ----
        xdchange_t *xch, *xchp, *lxch;
        long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen;
        long max_ignorable = xecfg->ctxlen;
!       unsigned long ignored = 0; /* number of ignored blank lines */
  
!       /* remove ignorable changes that are too far before other changes */
        for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) {
                xch = xchp->next;
  
***************
*** 99,107 ****
  static long def_ff(const char *rec, long len, char *buf, long sz, void *priv 
UNUSED)
  {
        if (len > 0 &&
!                       (isalpha((unsigned char)*rec) || // identifier?
!                        *rec == '_' || // also identifier?
!                        *rec == '$')) { // identifiers from VMS and other 
esoterico
                if (len > sz)
                        len = sz;
                while (0 < len && isspace((unsigned char)rec[len - 1]))
--- 99,107 ----
  static long def_ff(const char *rec, long len, char *buf, long sz, void *priv 
UNUSED)
  {
        if (len > 0 &&
!                       (isalpha((unsigned char)*rec) || /* identifier? */
!                        *rec == '_' || /* also identifier? */
!                        *rec == '$')) { /* identifiers from VMS and other 
esoterico */
                if (len > sz)
                        len = sz;
                while (0 < len && isspace((unsigned char)rec[len - 1]))
***************
*** 197,203 ****
                if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) {
                        long fs1, i1 = xch->i1;
  
!                       // Appended chunk?
                        if (i1 >= xe->xdf1.nrec) {
                                long i2 = xch->i2;
  
--- 197,203 ----
                if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) {
                        long fs1, i1 = xch->i1;
  
!                       /* Appended chunk? */
                        if (i1 >= xe->xdf1.nrec) {
                                long i2 = xch->i2;
  
***************
*** 225,232 ****
                        if (fs1 < 0)
                                fs1 = 0;
                        if (fs1 < s1) {
!                               s2 -= s1 - fs1;
                                s1 = fs1;
                        }
                }
  
--- 225,247 ----
                        if (fs1 < 0)
                                fs1 = 0;
                        if (fs1 < s1) {
!                               s2 = XDL_MAX(s2 - (s1 - fs1), 0);
                                s1 = fs1;
+ 
+                               /*
+                                * Did we extend context upwards into an
+                                * ignored change?
+                                */
+                               while (xchp != xch &&
+                                      xchp->i1 + xchp->chg1 <= s1 &&
+                                      xchp->i2 + xchp->chg2 <= s2)
+                                       xchp = xchp->next;
+ 
+                               /* If so, show it after all. */
+                               if (xchp != xch) {
+                                       xch = xchp;
+                                       goto pre_context_calculation;
+                               }
                        }
                }
  
***************
*** 249,255 ****
                        if (fe1 < 0)
                                fe1 = xe->xdf1.nrec;
                        if (fe1 > e1) {
!                               e2 += fe1 - e1;
                                e1 = fe1;
                        }
  
--- 264,270 ----
                        if (fe1 < 0)
                                fe1 = xe->xdf1.nrec;
                        if (fe1 > e1) {
!                               e2 = XDL_MIN(e2 + (fe1 - e1), xe->xdf2.nrec);
                                e1 = fe1;
                        }
  
***************
*** 281,287 ****
                        funclineprev = s1 - 1;
                }
  #endif
!               if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
                                      func_line.buf, func_line.len, ecb) < 0)
                        return -1;
  
--- 296,303 ----
                        funclineprev = s1 - 1;
                }
  #endif
!               if (!(xecfg->flags & XDL_EMIT_NO_HUNK_HDR) &&
!                   xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
                                      func_line.buf, func_line.len, ecb) < 0)
                        return -1;
  
*** ../vim-8.2.3389/src/xdiff/xemit.h   2019-12-04 22:13:10.000000000 +0100
--- src/xdiff/xemit.h   2021-08-31 20:27:29.078489138 +0200
***************
*** 33,36 ****
  
  
  
! #endif // #if !defined(XEMIT_H)
--- 33,36 ----
  
  
  
! #endif /* #if !defined(XEMIT_H) */
*** ../vim-8.2.3389/src/xdiff/xhistogram.c      2019-12-04 22:11:36.000000000 
+0100
--- src/xdiff/xhistogram.c      2021-08-31 20:27:29.078489138 +0200
***************
*** 42,49 ****
   */
  
  #include "xinclude.h"
- #include "xtypes.h"
- #include "xdiff.h"
  
  #define MAX_PTR       INT_MAX
  #define MAX_CNT       INT_MAX
--- 42,47 ----
***************
*** 55,62 ****
        struct record {
                unsigned int ptr, cnt;
                struct record *next;
!       } **records, // an occurrence
!         **line_map; // map of line to record chain
        chastore_t rcha;
        unsigned int *next_ptrs;
        unsigned int table_bits,
--- 53,60 ----
        struct record {
                unsigned int ptr, cnt;
                struct record *next;
!       } **records, /* an occurrence */
!         **line_map; /* map of line to record chain */
        chastore_t rcha;
        unsigned int *next_ptrs;
        unsigned int table_bits,
***************
*** 128,134 ****
                                 */
                                NEXT_PTR(index, ptr) = rec->ptr;
                                rec->ptr = ptr;
!                               // cap rec->cnt at MAX_CNT
                                rec->cnt = XDL_MIN(MAX_CNT, rec->cnt + 1);
                                LINE_MAP(index, ptr) = rec;
                                goto continue_scan;
--- 126,132 ----
                                 */
                                NEXT_PTR(index, ptr) = rec->ptr;
                                rec->ptr = ptr;
!                               /* cap rec->cnt at MAX_CNT */
                                rec->cnt = XDL_MIN(MAX_CNT, rec->cnt + 1);
                                LINE_MAP(index, ptr) = rec;
                                goto continue_scan;
***************
*** 154,160 ****
                LINE_MAP(index, ptr) = rec;
  
  continue_scan:
!               ; // no op
        }
  
        return 0;
--- 152,158 ----
                LINE_MAP(index, ptr) = rec;
  
  continue_scan:
!               ; /* no op */
        }
  
        return 0;
***************
*** 237,242 ****
--- 235,242 ----
                int line1, int count1, int line2, int count2)
  {
        xpparam_t xpparam;
+ 
+       memset(&xpparam, 0, sizeof(xpparam));
        xpparam.flags = xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
  
        return xdl_fall_back_diff(env, &xpparam,
***************
*** 266,272 ****
  
        index.records = NULL;
        index.line_map = NULL;
!       // in case of early xdl_cha_free()
        index.rcha.head = NULL;
  
        index.table_bits = xdl_hashbits(count1);
--- 266,272 ----
  
        index.records = NULL;
        index.line_map = NULL;
!       /* in case of early xdl_cha_free() */
        index.rcha.head = NULL;
  
        index.table_bits = xdl_hashbits(count1);
***************
*** 288,294 ****
                goto cleanup;
        memset(index.next_ptrs, 0, sz);
  
!       // lines / 4 + 1 comes from xprepare.c:xdl_prepare_ctx()
        if (xdl_cha_init(&index.rcha, sizeof(struct record), count1 / 4 + 1) < 
0)
                goto cleanup;
  
--- 288,294 ----
                goto cleanup;
        memset(index.next_ptrs, 0, sz);
  
!       /* lines / 4 + 1 comes from xprepare.c:xdl_prepare_ctx() */
        if (xdl_cha_init(&index.rcha, sizeof(struct record), count1 / 4 + 1) < 
0)
                goto cleanup;
  
*** ../vim-8.2.3389/src/xdiff/xinclude.h        2019-12-04 22:13:26.000000000 
+0100
--- src/xdiff/xinclude.h        2021-08-31 20:27:29.078489138 +0200
***************
*** 20,25 ****
--- 20,27 ----
   *
   */
  
+ // The following includes come from Vim:
+ 
  // defines HAVE_ATTRIBUTE_UNUSED
  #ifdef HAVE_CONFIG_H
  # ifdef VMS
***************
*** 44,49 ****
--- 46,52 ----
  #if !defined(XINCLUDE_H)
  #define XINCLUDE_H
  
+ // This effectively re-verts b46054b3746271d23feab0 from git
  #include <ctype.h>
  #include <stdio.h>
  #include <stdlib.h>
***************
*** 52,58 ****
  #endif
  #include <string.h>
  #include <limits.h>
! 
  #include "xmacros.h"
  #include "xdiff.h"
  #include "xtypes.h"
--- 55,64 ----
  #endif
  #include <string.h>
  #include <limits.h>
! // This include comes from git, so uncomment it
! #if 0
! #include "git-compat-util.h"
! #endif
  #include "xmacros.h"
  #include "xdiff.h"
  #include "xtypes.h"
***************
*** 62,65 ****
  #include "xemit.h"
  
  
! #endif // #if !defined(XINCLUDE_H)
--- 68,71 ----
  #include "xemit.h"
  
  
! #endif /* #if !defined(XINCLUDE_H) */
*** ../vim-8.2.3389/src/xdiff/xmacros.h 2019-12-04 22:13:37.000000000 +0100
--- src/xdiff/xmacros.h 2021-08-31 20:27:29.078489138 +0200
***************
*** 51,54 ****
  } while (0)
  
  
! #endif // #if !defined(XMACROS_H)
--- 51,54 ----
  } while (0)
  
  
! #endif /* #if !defined(XMACROS_H) */
*** ../vim-8.2.3389/src/xdiff/xpatience.c       2019-12-04 22:11:56.000000000 
+0100
--- src/xdiff/xpatience.c       2021-08-31 20:27:29.078489138 +0200
***************
*** 20,27 ****
   *
   */
  #include "xinclude.h"
- #include "xtypes.h"
- #include "xdiff.h"
  
  /*
   * The basic idea of patience diff is to find lines that are unique in
--- 20,25 ----
***************
*** 69,75 ****
                 */
                unsigned anchor : 1;
        } *entries, *first, *last;
!       // were common records found?
        unsigned long has_matches;
        mmfile_t *file1, *file2;
        xdfenv_t *env;
--- 67,73 ----
                 */
                unsigned anchor : 1;
        } *entries, *first, *last;
!       /* were common records found? */
        unsigned long has_matches;
        mmfile_t *file1, *file2;
        xdfenv_t *env;
***************
*** 78,98 ****
  
  static int is_anchor(xpparam_t const *xpp, const char *line)
  {
!       size_t i;
!       for (i = 0; i < xpp->anchors_nr; i++) {
                if (!strncmp(line, xpp->anchors[i], strlen(xpp->anchors[i])))
                        return 1;
        }
        return 0;
  }
  
! // The argument "pass" is 1 for the first file, 2 for the second.
  static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
                          int pass)
  {
        xrecord_t **records = pass == 1 ?
                map->env->xdf1.recs : map->env->xdf2.recs;
!       xrecord_t *record = records[line - 1], *other;
        /*
         * After xdl_prepare_env() (or more precisely, due to
         * xdl_classify_record()), the "ha" member of the records (AKA lines)
--- 76,96 ----
  
  static int is_anchor(xpparam_t const *xpp, const char *line)
  {
!       int i;
!       for (i = 0; i < (int)xpp->anchors_nr; i++) {
                if (!strncmp(line, xpp->anchors[i], strlen(xpp->anchors[i])))
                        return 1;
        }
        return 0;
  }
  
! /* The argument "pass" is 1 for the first file, 2 for the second. */
  static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
                          int pass)
  {
        xrecord_t **records = pass == 1 ?
                map->env->xdf1.recs : map->env->xdf2.recs;
!       xrecord_t *record = records[line - 1];
        /*
         * After xdl_prepare_env() (or more precisely, due to
         * xdl_classify_record()), the "ha" member of the records (AKA lines)
***************
*** 106,116 ****
        int index = (int)((record->ha << 1) % map->alloc);
  
        while (map->entries[index].line1) {
!               other = map->env->xdf1.recs[map->entries[index].line1 - 1];
!               if (map->entries[index].hash != record->ha ||
!                               !xdl_recmatch(record->ptr, record->size,
!                                       other->ptr, other->size,
!                                       map->xpp->flags)) {
                        if (++index >= map->alloc)
                                index = 0;
                        continue;
--- 104,110 ----
        int index = (int)((record->ha << 1) % map->alloc);
  
        while (map->entries[index].line1) {
!               if (map->entries[index].hash != record->ha) {
                        if (++index >= map->alloc)
                                index = 0;
                        continue;
***************
*** 155,161 ****
        result->xpp = xpp;
        result->env = env;
  
!       // We know exactly how large we want the hash map
        result->alloc = count1 * 2;
        result->entries = (struct entry *)
                xdl_malloc(result->alloc * sizeof(struct entry));
--- 149,155 ----
        result->xpp = xpp;
        result->env = env;
  
!       /* We know exactly how large we want the hash map */
        result->alloc = count1 * 2;
        result->entries = (struct entry *)
                xdl_malloc(result->alloc * sizeof(struct entry));
***************
*** 163,173 ****
                return -1;
        memset(result->entries, 0, result->alloc * sizeof(struct entry));
  
!       // First, fill with entries from the first file
        while (count1--)
                insert_record(xpp, line1++, result, 1);
  
!       // Then search for matches in the second file
        while (count2--)
                insert_record(xpp, line2++, result, 2);
  
--- 157,167 ----
                return -1;
        memset(result->entries, 0, result->alloc * sizeof(struct entry));
  
!       /* First, fill with entries from the first file */
        while (count1--)
                insert_record(xpp, line1++, result, 1);
  
!       /* Then search for matches in the second file */
        while (count2--)
                insert_record(xpp, line2++, result, 2);
  
***************
*** 185,197 ****
  
        while (left + 1 < right) {
                int middle = left + (right - left) / 2;
!               // by construction, no two entries can be equal
                if (sequence[middle]->line2 > entry->line2)
                        right = middle;
                else
                        left = middle;
        }
!       // return the index in "sequence", _not_ the sequence length
        return left;
  }
  
--- 179,191 ----
  
        while (left + 1 < right) {
                int middle = left + (right - left) / 2;
!               /* by construction, no two entries can be equal */
                if (sequence[middle]->line2 > entry->line2)
                        right = middle;
                else
                        left = middle;
        }
!       /* return the index in "sequence", _not_ the sequence length */
        return left;
  }
  
***************
*** 206,214 ****
   */
  static struct entry *find_longest_common_sequence(struct hashmap *map)
  {
!       struct entry **sequence = (struct entry **)xdl_malloc(map->nr * 
sizeof(struct entry *));
        int longest = 0, i;
        struct entry *entry;
        /*
         * If not -1, this entry in sequence must never be overridden.
         * Therefore, overriding entries before this has no effect, so
--- 200,209 ----
   */
  static struct entry *find_longest_common_sequence(struct hashmap *map)
  {
!       struct entry **sequence = xdl_malloc(map->nr * sizeof(struct entry *));
        int longest = 0, i;
        struct entry *entry;
+ 
        /*
         * If not -1, this entry in sequence must never be overridden.
         * Therefore, overriding entries before this has no effect, so
***************
*** 237,249 ****
                }
        }
  
!       // No common unique lines were found
        if (!longest) {
                xdl_free(sequence);
                return NULL;
        }
  
!       // Iterate starting at the last element, adjusting the "next" members
        entry = sequence[longest - 1];
        entry->next = NULL;
        while (entry->previous) {
--- 232,244 ----
                }
        }
  
!       /* No common unique lines were found */
        if (!longest) {
                xdl_free(sequence);
                return NULL;
        }
  
!       /* Iterate starting at the last element, adjusting the "next" members */
        entry = sequence[longest - 1];
        entry->next = NULL;
        while (entry->previous) {
***************
*** 258,265 ****
  {
        xrecord_t *record1 = map->env->xdf1.recs[line1 - 1];
        xrecord_t *record2 = map->env->xdf2.recs[line2 - 1];
!       return xdl_recmatch(record1->ptr, record1->size,
!               record2->ptr, record2->size, map->xpp->flags);
  }
  
  static int patience_diff(mmfile_t *file1, mmfile_t *file2,
--- 253,259 ----
  {
        xrecord_t *record1 = map->env->xdf1.recs[line1 - 1];
        xrecord_t *record2 = map->env->xdf2.recs[line2 - 1];
!       return record1->ha == record2->ha;
  }
  
  static int patience_diff(mmfile_t *file1, mmfile_t *file2,
***************
*** 273,279 ****
        int next1, next2;
  
        for (;;) {
!               // Try to grow the line ranges of common lines
                if (first) {
                        next1 = first->line1;
                        next2 = first->line2;
--- 267,273 ----
        int next1, next2;
  
        for (;;) {
!               /* Try to grow the line ranges of common lines */
                if (first) {
                        next1 = first->line1;
                        next2 = first->line2;
***************
*** 292,302 ****
                        line2++;
                }
  
!               // Recurse
                if (next1 > line1 || next2 > line2) {
-                       struct hashmap submap;
- 
-                       memset(&submap, 0, sizeof(submap));
                        if (patience_diff(map->file1, map->file2,
                                        map->xpp, map->env,
                                        line1, next1 - line1,
--- 286,293 ----
                        line2++;
                }
  
!               /* Recurse */
                if (next1 > line1 || next2 > line2) {
                        if (patience_diff(map->file1, map->file2,
                                        map->xpp, map->env,
                                        line1, next1 - line1,
***************
*** 323,328 ****
--- 314,321 ----
                int line1, int count1, int line2, int count2)
  {
        xpparam_t xpp;
+ 
+       memset(&xpp, 0, sizeof(xpp));
        xpp.flags = map->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
  
        return xdl_fall_back_diff(map->env, &xpp,
***************
*** 343,349 ****
        struct entry *first;
        int result = 0;
  
!       // trivial case: one side is empty
        if (!count1) {
                while(count2--)
                        env->xdf2.rchg[line2++ - 1] = 1;
--- 336,342 ----
        struct entry *first;
        int result = 0;
  
!       /* trivial case: one side is empty */
        if (!count1) {
                while(count2--)
                        env->xdf2.rchg[line2++ - 1] = 1;
***************
*** 359,365 ****
                        line1, count1, line2, count2))
                return -1;
  
!       // are there any matching lines at all?
        if (!map.has_matches) {
                while(count1--)
                        env->xdf1.rchg[line1++ - 1] = 1;
--- 352,358 ----
                        line1, count1, line2, count2))
                return -1;
  
!       /* are there any matching lines at all? */
        if (!map.has_matches) {
                while(count1--)
                        env->xdf1.rchg[line1++ - 1] = 1;
***************
*** 387,393 ****
        if (xdl_prepare_env(file1, file2, xpp, env) < 0)
                return -1;
  
!       // environment is cleaned up in xdl_diff()
        return patience_diff(file1, file2, xpp, env,
                        1, env->xdf1.nrec, 1, env->xdf2.nrec);
  }
--- 380,386 ----
        if (xdl_prepare_env(file1, file2, xpp, env) < 0)
                return -1;
  
!       /* environment is cleaned up in xdl_diff() */
        return patience_diff(file1, file2, xpp, env,
                        1, env->xdf1.nrec, 1, env->xdf2.nrec);
  }
*** ../vim-8.2.3389/src/xdiff/xprepare.h        2019-12-04 22:13:59.000000000 
+0100
--- src/xdiff/xprepare.h        2021-08-31 20:27:29.078489138 +0200
***************
*** 31,34 ****
  
  
  
! #endif // #if !defined(XPREPARE_H)
--- 31,34 ----
  
  
  
! #endif /* #if !defined(XPREPARE_H) */
*** ../vim-8.2.3389/src/xdiff/xtypes.h  2019-12-04 22:14:03.000000000 +0100
--- src/xdiff/xtypes.h  2021-08-31 20:27:29.078489138 +0200
***************
*** 64,67 ****
  
  
  
! #endif // #if !defined(XTYPES_H)
--- 64,67 ----
  
  
  
! #endif /* #if !defined(XTYPES_H) */
*** ../vim-8.2.3389/src/xdiff/xutils.c  2019-12-04 22:12:23.000000000 +0100
--- src/xdiff/xutils.c  2021-08-31 20:27:29.078489138 +0200
***************
*** 20,32 ****
   *
   */
  
- #include <limits.h>
- #include <assert.h>
  #include "xinclude.h"
  
  
- 
- 
  long xdl_bogosqrt(long n) {
        long i;
  
--- 20,28 ----
***************
*** 51,60 ****
        mb[1].size = size;
        if (size > 0 && rec[size - 1] != '\n') {
                mb[2].ptr = (char *) "\n\\ No newline at end of file\n";
!               mb[2].size = (long)strlen(mb[2].ptr);
                i++;
        }
!       if (ecb->outf(ecb->priv, mb, i) < 0) {
  
                return -1;
        }
--- 47,56 ----
        mb[1].size = size;
        if (size > 0 && rec[size - 1] != '\n') {
                mb[2].ptr = (char *) "\n\\ No newline at end of file\n";
!               mb[2].size = strlen(mb[2].ptr);
                i++;
        }
!       if (ecb->out_line(ecb->priv, mb, i) < 0) {
  
                return -1;
        }
***************
*** 168,174 ****
                s--;
        if (s == i)
                return 1;
!       // do not ignore CR at the end of an incomplete line
        if (complete && s == i + 1 && l[i] == '\r')
                return 1;
        return 0;
--- 164,170 ----
                s--;
        if (s == i)
                return 1;
!       /* do not ignore CR at the end of an incomplete line */
        if (complete && s == i + 1 && l[i] == '\r')
                return 1;
        return 0;
***************
*** 208,214 ****
        } else if (flags & XDF_IGNORE_WHITESPACE_CHANGE) {
                while (i1 < s1 && i2 < s2) {
                        if (XDL_ISSPACE(l1[i1]) && XDL_ISSPACE(l2[i2])) {
!                               // Skip matching spaces and try again
                                while (i1 < s1 && XDL_ISSPACE(l1[i1]))
                                        i1++;
                                while (i2 < s2 && XDL_ISSPACE(l2[i2]))
--- 204,210 ----
        } else if (flags & XDF_IGNORE_WHITESPACE_CHANGE) {
                while (i1 < s1 && i2 < s2) {
                        if (XDL_ISSPACE(l1[i1]) && XDL_ISSPACE(l2[i2])) {
!                               /* Skip matching spaces and try again */
                                while (i1 < s1 && XDL_ISSPACE(l1[i1]))
                                        i1++;
                                while (i2 < s2 && XDL_ISSPACE(l2[i2]))
***************
*** 224,230 ****
                        i2++;
                }
        } else if (flags & XDF_IGNORE_CR_AT_EOL) {
!               // Find the first difference and see how the line ends
                while (i1 < s1 && i2 < s2 && l1[i1] == l2[i2]) {
                        i1++;
                        i2++;
--- 220,226 ----
                        i2++;
                }
        } else if (flags & XDF_IGNORE_CR_AT_EOL) {
!               /* Find the first difference and see how the line ends */
                while (i1 < s1 && i2 < s2 && l1[i1] == l2[i2]) {
                        i1++;
                        i2++;
***************
*** 261,267 ****
  
        for (; ptr < top && *ptr != '\n'; ptr++) {
                if (cr_at_eol_only) {
!                       // do not ignore CR at the end of an incomplete line
                        if (*ptr == '\r' &&
                            (ptr + 1 < top && ptr[1] == '\n'))
                                continue;
--- 257,263 ----
  
        for (; ptr < top && *ptr != '\n'; ptr++) {
                if (cr_at_eol_only) {
!                       /* do not ignore CR at the end of an incomplete line */
                        if (*ptr == '\r' &&
                            (ptr + 1 < top && ptr[1] == '\n'))
                                continue;
***************
*** 274,280 ****
                                ptr++;
                        at_eol = (top <= ptr + 1 || ptr[1] == '\n');
                        if (flags & XDF_IGNORE_WHITESPACE)
!                               ; // already handled
                        else if (flags & XDF_IGNORE_WHITESPACE_CHANGE
                                 && !at_eol) {
                                ha += (ha << 5);
--- 270,276 ----
                                ptr++;
                        at_eol = (top <= ptr + 1 || ptr[1] == '\n');
                        if (flags & XDF_IGNORE_WHITESPACE)
!                               ; /* already handled */
                        else if (flags & XDF_IGNORE_WHITESPACE_CHANGE
                                 && !at_eol) {
                                ha += (ha << 5);
***************
*** 344,351 ****
        return str - out;
  }
  
! int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
!                     const char *func, long funclen, xdemitcb_t *ecb) {
        int nb = 0;
        mmbuffer_t mb;
        char buf[128];
--- 340,348 ----
        return str - out;
  }
  
! static int xdl_format_hunk_hdr(long s1, long c1, long s2, long c2,
!                              const char *func, long funclen,
!                              xdemitcb_t *ecb) {
        int nb = 0;
        mmbuffer_t mb;
        char buf[128];
***************
*** 387,395 ****
  
        mb.ptr = buf;
        mb.size = nb;
!       if (ecb->outf(ecb->priv, &mb, 1) < 0)
                return -1;
  
        return 0;
  }
  
--- 384,404 ----
  
        mb.ptr = buf;
        mb.size = nb;
!       if (ecb->out_line(ecb->priv, &mb, 1) < 0)
                return -1;
+       return 0;
+ }
  
+ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
+                     const char *func, long funclen,
+                     xdemitcb_t *ecb) {
+       if (!ecb->out_hunk)
+               return xdl_format_hunk_hdr(s1, c1, s2, c2, func, funclen, ecb);
+       if (ecb->out_hunk(ecb->priv,
+                         c1 ? s1 : s1 - 1, c1,
+                         c2 ? s2 : s2 - 1, c2,
+                         func, funclen) < 0)
+               return -1;
        return 0;
  }
  
*** ../vim-8.2.3389/src/xdiff/xutils.h  2019-12-04 22:14:23.000000000 +0100
--- src/xdiff/xutils.h  2021-08-31 20:27:29.078489138 +0200
***************
*** 44,47 ****
  
  
  
! #endif // #if !defined(XUTILS_H)
--- 44,47 ----
  
  
  
! #endif /* #if !defined(XUTILS_H) */
*** ../vim-8.2.3389/src/version.c       2021-08-31 19:12:47.757554157 +0200
--- src/version.c       2021-08-31 20:29:21.482296266 +0200
***************
*** 757,758 ****
--- 757,760 ----
  {   /* Add new patch number below this line */
+ /**/
+     3390,
  /**/

-- 
Never under any circumstances take a sleeping pill
and a laxative on the same night.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202108311847.17VIlJCT3951627%40masaka.moolenaar.net.

Raspunde prin e-mail lui