2121
2222#if defined(FEAT_DIFF ) || defined(PROTO )
2323
24- static int diff_busy = FALSE; /* ex_diffgetput() is busy */
24+ static int diff_busy = FALSE; // using diff structs, don't change them
25+ static int diff_need_update = FALSE; // ex_diffupdate needs to be called
2526
2627/* flags obtained from the 'diffopt' option */
27- #define DIFF_FILLER 1 // display filler lines
28- #define DIFF_ICASE 2 // ignore case
29- #define DIFF_IWHITE 4 // ignore change in white space
30- #define DIFF_HORIZONTAL 8 // horizontal splits
31- #define DIFF_VERTICAL 16 // vertical splits
32- #define DIFF_HIDDEN_OFF 32 // diffoff when hidden
33- #define DIFF_INTERNAL 64 // use internal xdiff algorithm
28+ #define DIFF_FILLER 0x001 // display filler lines
29+ #define DIFF_IBLANK 0x002 // ignore empty lines
30+ #define DIFF_ICASE 0x004 // ignore case
31+ #define DIFF_IWHITE 0x008 // ignore change in white space
32+ #define DIFF_IWHITEALL 0x010 // ignore all white space changes
33+ #define DIFF_IWHITEEOL 0x020 // ignore change in white space at EOL
34+ #define DIFF_HORIZONTAL 0x040 // horizontal splits
35+ #define DIFF_VERTICAL 0x080 // vertical splits
36+ #define DIFF_HIDDEN_OFF 0x100 // diffoff when hidden
37+ #define DIFF_INTERNAL 0x200 // use internal xdiff algorithm
38+ #define ALL_WHITE_DIFF (DIFF_IWHITE | DIFF_IWHITEALL | DIFF_IWHITEEOL)
3439static int diff_flags = DIFF_INTERNAL | DIFF_FILLER ;
3540
3641static long diff_algorithm = 0 ;
@@ -288,6 +293,16 @@ diff_mark_adjust_tp(
288293 linenr_T lnum_deleted = line1 ; /* lnum of remaining deletion */
289294 int check_unchanged ;
290295
296+ if (diff_internal ())
297+ {
298+ // Will udpate diffs before redrawing. Set _invalid to update the
299+ // diffs themselves, set _update to also update folds properly just
300+ // before redrawing.
301+ tp -> tp_diff_invalid = TRUE;
302+ tp -> tp_diff_update = TRUE;
303+ return ;
304+ }
305+
291306 if (line2 == MAXLNUM )
292307 {
293308 /* mark_adjust(99, MAXLNUM, 9, 0): insert lines */
@@ -636,7 +651,7 @@ diff_check_sanity(tabpage_T *tp, diff_T *dp)
636651 */
637652 static void
638653diff_redraw (
639- int dofold ) /* also recompute the folds */
654+ int dofold ) // also recompute the folds
640655{
641656 win_T * wp ;
642657 int n ;
@@ -698,7 +713,7 @@ diff_write_buffer(buf_T *buf, diffin_T *din)
698713
699714 // xdiff requires one big block of memory with all the text.
700715 for (lnum = 1 ; lnum <= buf -> b_ml .ml_line_count ; ++ lnum )
701- len += STRLEN (ml_get_buf (buf , lnum , FALSE)) + 1 ;
716+ len += ( long ) STRLEN (ml_get_buf (buf , lnum , FALSE)) + 1 ;
702717 ptr = lalloc (len , TRUE);
703718 if (ptr == NULL )
704719 {
@@ -859,7 +874,7 @@ diff_try_update(
859874 * Note that if the internal diff failed for one of the buffers, the external
860875 * diff will be used anyway.
861876 */
862- static int
877+ int
863878diff_internal (void )
864879{
865880 return (diff_flags & DIFF_INTERNAL ) != 0 && * p_dex == NUL ;
@@ -883,9 +898,9 @@ diff_internal_failed(void)
883898
884899/*
885900 * Completely update the diffs for the buffers involved.
886- * This uses the ordinary "diff" command.
887- * The buffers are written to a file, also for unmodified buffers (the file
888- * could have been produced by autocommands, e.g. the netrw plugin).
901+ * When using the external "diff" command the buffers are written to a file,
902+ * also for unmodified buffers (the file could have been produced by
903+ * autocommands, e.g. the netrw plugin).
889904 */
890905 void
891906ex_diffupdate (exarg_T * eap ) // "eap" can be NULL
@@ -894,6 +909,12 @@ ex_diffupdate(exarg_T *eap) // "eap" can be NULL
894909 int idx_new ;
895910 diffio_T diffio ;
896911
912+ if (diff_busy )
913+ {
914+ diff_need_update = TRUE;
915+ return ;
916+ }
917+
897918 // Delete all diffblocks.
898919 diff_clear (curtab );
899920 curtab -> tp_diff_invalid = FALSE;
@@ -928,6 +949,8 @@ ex_diffupdate(exarg_T *eap) // "eap" can be NULL
928949 curwin -> w_valid_cursor .lnum = 0 ;
929950
930951 diff_redraw (TRUE);
952+
953+ apply_autocmds (EVENT_DIFFUPDATED , NULL , NULL , FALSE, curbuf );
931954}
932955
933956/*
@@ -1050,6 +1073,12 @@ diff_file_internal(diffio_T *diffio)
10501073
10511074 if (diff_flags & DIFF_IWHITE )
10521075 param .flags |= XDF_IGNORE_WHITESPACE_CHANGE ;
1076+ if (diff_flags & DIFF_IWHITEALL )
1077+ param .flags |= XDF_IGNORE_WHITESPACE ;
1078+ if (diff_flags & DIFF_IWHITEEOL )
1079+ param .flags |= XDF_IGNORE_WHITESPACE_AT_EOL ;
1080+ if (diff_flags & DIFF_IBLANK )
1081+ param .flags |= XDF_IGNORE_BLANK_LINES ;
10531082
10541083 emit_cfg .ctxlen = 0 ; // don't need any diff_context here
10551084 emit_cb .priv = & diffio -> dio_diff ;
@@ -1106,14 +1135,17 @@ diff_file(diffio_T *dio)
11061135 // Build the diff command and execute it. Always use -a, binary
11071136 // differences are of no use. Ignore errors, diff returns
11081137 // non-zero when differences have been found.
1109- vim_snprintf ((char * )cmd , len , "diff %s%s%s%s%s %s" ,
1138+ vim_snprintf ((char * )cmd , len , "diff %s%s%s%s%s%s%s%s %s" ,
11101139 diff_a_works == FALSE ? "" : "-a " ,
11111140#if defined(MSWIN )
11121141 diff_bin_works == TRUE ? "--binary " : "" ,
11131142#else
11141143 "" ,
11151144#endif
11161145 (diff_flags & DIFF_IWHITE ) ? "-b " : "" ,
1146+ (diff_flags & DIFF_IWHITEALL ) ? "-w " : "" ,
1147+ (diff_flags & DIFF_IWHITEEOL ) ? "-Z " : "" ,
1148+ (diff_flags & DIFF_IBLANK ) ? "-B " : "" ,
11171149 (diff_flags & DIFF_ICASE ) ? "-i " : "" ,
11181150 tmp_orig , tmp_new );
11191151 append_redir (cmd , (int )len , p_srr , tmp_diff );
@@ -1946,17 +1978,25 @@ diff_cmp(char_u *s1, char_u *s2)
19461978 char_u * p1 , * p2 ;
19471979 int l ;
19481980
1949- if ((diff_flags & (DIFF_ICASE | DIFF_IWHITE )) == 0 )
1981+ if ((diff_flags & DIFF_IBLANK )
1982+ && (* skipwhite (s1 ) == NUL || * skipwhite (s2 ) == NUL ))
1983+ return 0 ;
1984+
1985+ if ((diff_flags & (DIFF_ICASE | ALL_WHITE_DIFF )) == 0 )
19501986 return STRCMP (s1 , s2 );
1951- if ((diff_flags & DIFF_ICASE ) && !(diff_flags & DIFF_IWHITE ))
1987+ if ((diff_flags & DIFF_ICASE ) && !(diff_flags & ALL_WHITE_DIFF ))
19521988 return MB_STRICMP (s1 , s2 );
19531989
1954- /* Ignore white space changes and possibly ignore case. */
19551990 p1 = s1 ;
19561991 p2 = s2 ;
1992+
1993+ // Ignore white space changes and possibly ignore case.
19571994 while (* p1 != NUL && * p2 != NUL )
19581995 {
1959- if (VIM_ISWHITE (* p1 ) && VIM_ISWHITE (* p2 ))
1996+ if (((diff_flags & DIFF_IWHITE )
1997+ && VIM_ISWHITE (* p1 ) && VIM_ISWHITE (* p2 ))
1998+ || ((diff_flags & DIFF_IWHITEALL )
1999+ && (VIM_ISWHITE (* p1 ) || VIM_ISWHITE (* p2 ))))
19602000 {
19612001 p1 = skipwhite (p1 );
19622002 p2 = skipwhite (p2 );
@@ -1970,7 +2010,7 @@ diff_cmp(char_u *s1, char_u *s2)
19702010 }
19712011 }
19722012
1973- /* Ignore trailing white space. */
2013+ // Ignore trailing white space.
19742014 p1 = skipwhite (p1 );
19752015 p2 = skipwhite (p2 );
19762016 if (* p1 != NUL || * p2 != NUL )
@@ -2142,11 +2182,26 @@ diffopt_changed(void)
21422182 p += 8 ;
21432183 diff_context_new = getdigits (& p );
21442184 }
2185+ else if (STRNCMP (p , "iblank" , 6 ) == 0 )
2186+ {
2187+ p += 6 ;
2188+ diff_flags_new |= DIFF_IBLANK ;
2189+ }
21452190 else if (STRNCMP (p , "icase" , 5 ) == 0 )
21462191 {
21472192 p += 5 ;
21482193 diff_flags_new |= DIFF_ICASE ;
21492194 }
2195+ else if (STRNCMP (p , "iwhiteall" , 9 ) == 0 )
2196+ {
2197+ p += 9 ;
2198+ diff_flags_new |= DIFF_IWHITEALL ;
2199+ }
2200+ else if (STRNCMP (p , "iwhiteeol" , 9 ) == 0 )
2201+ {
2202+ p += 9 ;
2203+ diff_flags_new |= DIFF_IWHITEEOL ;
2204+ }
21502205 else if (STRNCMP (p , "iwhite" , 6 ) == 0 )
21512206 {
21522207 p += 6 ;
@@ -2315,9 +2370,12 @@ diff_find_change(
23152370 si_org = si_new = 0 ;
23162371 while (line_org [si_org ] != NUL )
23172372 {
2318- if ((diff_flags & DIFF_IWHITE )
2319- && VIM_ISWHITE (line_org [si_org ])
2320- && VIM_ISWHITE (line_new [si_new ]))
2373+ if (((diff_flags & DIFF_IWHITE )
2374+ && VIM_ISWHITE (line_org [si_org ])
2375+ && VIM_ISWHITE (line_new [si_new ]))
2376+ || ((diff_flags & DIFF_IWHITEALL )
2377+ && (VIM_ISWHITE (line_org [si_org ])
2378+ || VIM_ISWHITE (line_new [si_new ]))))
23212379 {
23222380 si_org = (int )(skipwhite (line_org + si_org ) - line_org );
23232381 si_new = (int )(skipwhite (line_new + si_new ) - line_new );
@@ -2351,9 +2409,12 @@ diff_find_change(
23512409 while (ei_org >= * startp && ei_new >= si_new
23522410 && ei_org >= 0 && ei_new >= 0 )
23532411 {
2354- if ((diff_flags & DIFF_IWHITE )
2355- && VIM_ISWHITE (line_org [ei_org ])
2356- && VIM_ISWHITE (line_new [ei_new ]))
2412+ if (((diff_flags & DIFF_IWHITE )
2413+ && VIM_ISWHITE (line_org [ei_org ])
2414+ && VIM_ISWHITE (line_new [ei_new ]))
2415+ || ((diff_flags & DIFF_IWHITEALL )
2416+ && (VIM_ISWHITE (line_org [ei_org ])
2417+ || VIM_ISWHITE (line_new [ei_new ]))))
23572418 {
23582419 while (ei_org >= * startp
23592420 && VIM_ISWHITE (line_org [ei_org ]))
@@ -2606,7 +2667,7 @@ ex_diffgetput(exarg_T *eap)
26062667 if (diff_buf_idx (curbuf ) != idx_to )
26072668 {
26082669 EMSG (_ ("E787: Buffer changed unexpectedly" ));
2609- return ;
2670+ goto theend ;
26102671 }
26112672 }
26122673
@@ -2777,7 +2838,13 @@ ex_diffgetput(exarg_T *eap)
27772838 aucmd_restbuf (& aco );
27782839 }
27792840
2841+ theend :
27802842 diff_busy = FALSE;
2843+ if (diff_need_update )
2844+ {
2845+ diff_need_update = FALSE;
2846+ ex_diffupdate (NULL );
2847+ }
27812848
27822849 /* Check that the cursor is on a valid character and update it's position.
27832850 * When there were filler lines the topline has become invalid. */
0 commit comments