@@ -30,17 +30,32 @@ typedef struct s_xdmerge {
3030 * 2 = no conflict, take second.
3131 */
3232 int mode ;
33+ /*
34+ * These point at the respective postimages. E.g. <i1,chg1> is
35+ * how side #1 wants to change the common ancestor; if there is no
36+ * overlap, lines before i1 in the postimage of side #1 appear
37+ * in the merge result as a region touched by neither side.
38+ */
3339 long i1 , i2 ;
3440 long chg1 , chg2 ;
41+ /*
42+ * These point at the preimage; of course there is just one
43+ * preimage, that is from the shared common ancestor.
44+ */
45+ long i0 ;
46+ long chg0 ;
3547} xdmerge_t ;
3648
3749static int xdl_append_merge (xdmerge_t * * merge , int mode ,
38- long i1 , long chg1 , long i2 , long chg2 )
50+ long i0 , long chg0 ,
51+ long i1 , long chg1 ,
52+ long i2 , long chg2 )
3953{
4054 xdmerge_t * m = * merge ;
4155 if (m && (i1 <= m -> i1 + m -> chg1 || i2 <= m -> i2 + m -> chg2 )) {
4256 if (mode != m -> mode )
4357 m -> mode = 0 ;
58+ m -> chg0 = i0 + chg0 - m -> i0 ;
4459 m -> chg1 = i1 + chg1 - m -> i1 ;
4560 m -> chg2 = i2 + chg2 - m -> i2 ;
4661 } else {
@@ -49,6 +64,8 @@ static int xdl_append_merge(xdmerge_t **merge, int mode,
4964 return -1 ;
5065 m -> next = NULL ;
5166 m -> mode = mode ;
67+ m -> i0 = i0 ;
68+ m -> chg0 = chg0 ;
5269 m -> i1 = i1 ;
5370 m -> chg1 = chg1 ;
5471 m -> i2 = i2 ;
@@ -91,11 +108,13 @@ static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
91108 return 0 ;
92109}
93110
94- static int xdl_recs_copy ( xdfenv_t * xe , int i , int count , int add_nl , char * dest )
111+ static int xdl_recs_copy_0 ( int use_orig , xdfenv_t * xe , int i , int count , int add_nl , char * dest )
95112{
96- xrecord_t * * recs = xe -> xdf2 . recs + i ;
113+ xrecord_t * * recs ;
97114 int size = 0 ;
98115
116+ recs = (use_orig ? xe -> xdf1 .recs : xe -> xdf2 .recs ) + i ;
117+
99118 if (count < 1 )
100119 return 0 ;
101120
@@ -113,9 +132,19 @@ static int xdl_recs_copy(xdfenv_t *xe, int i, int count, int add_nl, char *dest)
113132 return size ;
114133}
115134
135+ static int xdl_recs_copy (xdfenv_t * xe , int i , int count , int add_nl , char * dest )
136+ {
137+ return xdl_recs_copy_0 (0 , xe , i , count , add_nl , dest );
138+ }
139+
140+ static int xdl_orig_copy (xdfenv_t * xe , int i , int count , int add_nl , char * dest )
141+ {
142+ return xdl_recs_copy_0 (1 , xe , i , count , add_nl , dest );
143+ }
144+
116145static int fill_conflict_hunk (xdfenv_t * xe1 , const char * name1 ,
117146 xdfenv_t * xe2 , const char * name2 ,
118- int size , int i ,
147+ int size , int i , int style ,
119148 xdmerge_t * m , char * dest )
120149{
121150 const int marker_size = 7 ;
@@ -143,6 +172,20 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
143172 /* Postimage from side #1 */
144173 size += xdl_recs_copy (xe1 , m -> i1 , m -> chg1 , 1 ,
145174 dest ? dest + size : NULL );
175+
176+ if (style == XDL_MERGE_DIFF3 ) {
177+ /* Shared preimage */
178+ if (!dest ) {
179+ size += marker_size + 1 ;
180+ } else {
181+ for (j = 0 ; j < marker_size ; j ++ )
182+ dest [size ++ ] = '|' ;
183+ dest [size ++ ] = '\n' ;
184+ }
185+ size += xdl_orig_copy (xe1 , m -> i0 , m -> chg0 , 1 ,
186+ dest ? dest + size : NULL );
187+ }
188+
146189 if (!dest ) {
147190 size += marker_size + 1 ;
148191 } else {
@@ -170,14 +213,15 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
170213}
171214
172215static int xdl_fill_merge_buffer (xdfenv_t * xe1 , const char * name1 ,
173- xdfenv_t * xe2 , const char * name2 , xdmerge_t * m , char * dest )
216+ xdfenv_t * xe2 , const char * name2 ,
217+ xdmerge_t * m , char * dest , int style )
174218{
175219 int size , i ;
176220
177221 for (size = i = 0 ; m ; m = m -> next ) {
178222 if (m -> mode == 0 )
179223 size = fill_conflict_hunk (xe1 , name1 , xe2 , name2 ,
180- size , i , m , dest );
224+ size , i , style , m , dest );
181225 else if (m -> mode == 1 )
182226 size += xdl_recs_copy (xe1 , i , m -> i1 + m -> chg1 - i , 0 ,
183227 dest ? dest + size : NULL );
@@ -342,33 +386,41 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m,
342386 */
343387static int xdl_do_merge (xdfenv_t * xe1 , xdchange_t * xscr1 , const char * name1 ,
344388 xdfenv_t * xe2 , xdchange_t * xscr2 , const char * name2 ,
345- int level , xpparam_t const * xpp , mmbuffer_t * result ) {
389+ int flags , xpparam_t const * xpp , mmbuffer_t * result ) {
346390 xdmerge_t * changes , * c ;
347- int i1 , i2 , chg1 , chg2 ;
391+ int i0 , i1 , i2 , chg0 , chg1 , chg2 ;
392+ int level = flags & XDL_MERGE_LEVEL_MASK ;
393+ int style = flags & XDL_MERGE_STYLE_MASK ;
348394
349395 c = changes = NULL ;
350396
351397 while (xscr1 && xscr2 ) {
352398 if (!changes )
353399 changes = c ;
354400 if (xscr1 -> i1 + xscr1 -> chg1 < xscr2 -> i1 ) {
401+ i0 = xscr1 -> i1 ;
355402 i1 = xscr1 -> i2 ;
356403 i2 = xscr2 -> i2 - xscr2 -> i1 + xscr1 -> i1 ;
404+ chg0 = xscr1 -> chg1 ;
357405 chg1 = xscr1 -> chg2 ;
358406 chg2 = xscr1 -> chg1 ;
359- if (xdl_append_merge (& c , 1 , i1 , chg1 , i2 , chg2 )) {
407+ if (xdl_append_merge (& c , 1 ,
408+ i0 , chg0 , i1 , chg1 , i2 , chg2 )) {
360409 xdl_cleanup_merge (changes );
361410 return -1 ;
362411 }
363412 xscr1 = xscr1 -> next ;
364413 continue ;
365414 }
366415 if (xscr2 -> i1 + xscr2 -> chg1 < xscr1 -> i1 ) {
416+ i0 = xscr2 -> i1 ;
367417 i1 = xscr1 -> i2 - xscr1 -> i1 + xscr2 -> i1 ;
368418 i2 = xscr2 -> i2 ;
419+ chg0 = xscr2 -> chg1 ;
369420 chg1 = xscr2 -> chg1 ;
370421 chg2 = xscr2 -> chg2 ;
371- if (xdl_append_merge (& c , 2 , i1 , chg1 , i2 , chg2 )) {
422+ if (xdl_append_merge (& c , 2 ,
423+ i0 , chg0 , i1 , chg1 , i2 , chg2 )) {
372424 xdl_cleanup_merge (changes );
373425 return -1 ;
374426 }
@@ -385,19 +437,26 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
385437 int off = xscr1 -> i1 - xscr2 -> i1 ;
386438 int ffo = off + xscr1 -> chg1 - xscr2 -> chg1 ;
387439
440+ i0 = xscr1 -> i1 ;
388441 i1 = xscr1 -> i2 ;
389442 i2 = xscr2 -> i2 ;
390- if (off > 0 )
443+ if (off > 0 ) {
444+ i0 -= off ;
391445 i1 -= off ;
446+ }
392447 else
393448 i2 += off ;
449+ chg0 = xscr1 -> i1 + xscr1 -> chg1 - i0 ;
394450 chg1 = xscr1 -> i2 + xscr1 -> chg2 - i1 ;
395451 chg2 = xscr2 -> i2 + xscr2 -> chg2 - i2 ;
396452 if (ffo > 0 )
397453 chg2 += ffo ;
398- else
454+ else {
455+ chg0 -= ffo ;
399456 chg1 -= ffo ;
400- if (xdl_append_merge (& c , 0 , i1 , chg1 , i2 , chg2 )) {
457+ }
458+ if (xdl_append_merge (& c , 0 ,
459+ i0 , chg0 , i1 , chg1 , i2 , chg2 )) {
401460 xdl_cleanup_merge (changes );
402461 return -1 ;
403462 }
@@ -414,11 +473,14 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
414473 while (xscr1 ) {
415474 if (!changes )
416475 changes = c ;
476+ i0 = xscr1 -> i1 ;
417477 i1 = xscr1 -> i2 ;
418478 i2 = xscr1 -> i1 + xe2 -> xdf2 .nrec - xe2 -> xdf1 .nrec ;
479+ chg0 = xscr1 -> chg1 ;
419480 chg1 = xscr1 -> chg2 ;
420481 chg2 = xscr1 -> chg1 ;
421- if (xdl_append_merge (& c , 1 , i1 , chg1 , i2 , chg2 )) {
482+ if (xdl_append_merge (& c , 1 ,
483+ i0 , chg0 , i1 , chg1 , i2 , chg2 )) {
422484 xdl_cleanup_merge (changes );
423485 return -1 ;
424486 }
@@ -427,11 +489,14 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
427489 while (xscr2 ) {
428490 if (!changes )
429491 changes = c ;
492+ i0 = xscr2 -> i1 ;
430493 i1 = xscr2 -> i1 + xe1 -> xdf2 .nrec - xe1 -> xdf1 .nrec ;
431494 i2 = xscr2 -> i2 ;
495+ chg0 = xscr2 -> chg1 ;
432496 chg1 = xscr2 -> chg1 ;
433497 chg2 = xscr2 -> chg2 ;
434- if (xdl_append_merge (& c , 2 , i1 , chg1 , i2 , chg2 )) {
498+ if (xdl_append_merge (& c , 2 ,
499+ i0 , chg0 , i1 , chg1 , i2 , chg2 )) {
435500 xdl_cleanup_merge (changes );
436501 return -1 ;
437502 }
@@ -449,22 +514,22 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
449514 /* output */
450515 if (result ) {
451516 int size = xdl_fill_merge_buffer (xe1 , name1 , xe2 , name2 ,
452- changes , NULL );
517+ changes , NULL , style );
453518 result -> ptr = xdl_malloc (size );
454519 if (!result -> ptr ) {
455520 xdl_cleanup_merge (changes );
456521 return -1 ;
457522 }
458523 result -> size = size ;
459524 xdl_fill_merge_buffer (xe1 , name1 , xe2 , name2 , changes ,
460- result -> ptr );
525+ result -> ptr , style );
461526 }
462527 return xdl_cleanup_merge (changes );
463528}
464529
465530int xdl_merge (mmfile_t * orig , mmfile_t * mf1 , const char * name1 ,
466531 mmfile_t * mf2 , const char * name2 ,
467- xpparam_t const * xpp , int level , mmbuffer_t * result ) {
532+ xpparam_t const * xpp , int flags , mmbuffer_t * result ) {
468533 xdchange_t * xscr1 , * xscr2 ;
469534 xdfenv_t xe1 , xe2 ;
470535 int status ;
@@ -501,7 +566,7 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
501566 } else {
502567 status = xdl_do_merge (& xe1 , xscr1 , name1 ,
503568 & xe2 , xscr2 , name2 ,
504- level , xpp , result );
569+ flags , xpp , result );
505570 }
506571 xdl_free_script (xscr1 );
507572 xdl_free_script (xscr2 );
0 commit comments