@@ -109,7 +109,7 @@ static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
109109 return 0 ;
110110}
111111
112- static int xdl_recs_copy_0 (int use_orig , xdfenv_t * xe , int i , int count , int add_nl , char * dest )
112+ static int xdl_recs_copy_0 (int use_orig , xdfenv_t * xe , int i , int count , int needs_cr , int add_nl , char * dest )
113113{
114114 xrecord_t * * recs ;
115115 int size = 0 ;
@@ -125,6 +125,12 @@ static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int add
125125 if (add_nl ) {
126126 i = recs [count - 1 ]-> size ;
127127 if (i == 0 || recs [count - 1 ]-> ptr [i - 1 ] != '\n' ) {
128+ if (needs_cr ) {
129+ if (dest )
130+ dest [size ] = '\r' ;
131+ size ++ ;
132+ }
133+
128134 if (dest )
129135 dest [size ] = '\n' ;
130136 size ++ ;
@@ -133,14 +139,58 @@ static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int add
133139 return size ;
134140}
135141
136- static int xdl_recs_copy (xdfenv_t * xe , int i , int count , int add_nl , char * dest )
142+ static int xdl_recs_copy (xdfenv_t * xe , int i , int count , int needs_cr , int add_nl , char * dest )
143+ {
144+ return xdl_recs_copy_0 (0 , xe , i , count , needs_cr , add_nl , dest );
145+ }
146+
147+ static int xdl_orig_copy (xdfenv_t * xe , int i , int count , int needs_cr , int add_nl , char * dest )
148+ {
149+ return xdl_recs_copy_0 (1 , xe , i , count , needs_cr , add_nl , dest );
150+ }
151+
152+ /*
153+ * Returns 1 if the i'th line ends in CR/LF (if it is the last line and
154+ * has no eol, the preceding line, if any), 0 if it ends in LF-only, and
155+ * -1 if the line ending cannot be determined.
156+ */
157+ static int is_eol_crlf (xdfile_t * file , int i )
137158{
138- return xdl_recs_copy_0 (0 , xe , i , count , add_nl , dest );
159+ long size ;
160+
161+ if (i < file -> nrec - 1 )
162+ /* All lines before the last *must* end in LF */
163+ return (size = file -> recs [i ]-> size ) > 1 &&
164+ file -> recs [i ]-> ptr [size - 2 ] == '\r' ;
165+ if (!file -> nrec )
166+ /* Cannot determine eol style from empty file */
167+ return -1 ;
168+ if ((size = file -> recs [i ]-> size ) &&
169+ file -> recs [i ]-> ptr [size - 1 ] == '\n' )
170+ /* Last line; ends in LF; Is it CR/LF? */
171+ return size > 1 &&
172+ file -> recs [i ]-> ptr [size - 2 ] == '\r' ;
173+ if (!i )
174+ /* The only line has no eol */
175+ return -1 ;
176+ /* Determine eol from second-to-last line */
177+ return (size = file -> recs [i - 1 ]-> size ) > 1 &&
178+ file -> recs [i - 1 ]-> ptr [size - 2 ] == '\r' ;
139179}
140180
141- static int xdl_orig_copy (xdfenv_t * xe , int i , int count , int add_nl , char * dest )
181+ static int is_cr_needed (xdfenv_t * xe1 , xdfenv_t * xe2 , xdmerge_t * m )
142182{
143- return xdl_recs_copy_0 (1 , xe , i , count , add_nl , dest );
183+ int needs_cr ;
184+
185+ /* Match post-images' preceding, or first, lines' end-of-line style */
186+ needs_cr = is_eol_crlf (& xe1 -> xdf2 , m -> i1 ? m -> i1 - 1 : 0 );
187+ if (needs_cr )
188+ needs_cr = is_eol_crlf (& xe2 -> xdf2 , m -> i2 ? m -> i2 - 1 : 0 );
189+ /* Look at pre-image's first line, unless we already settled on LF */
190+ if (needs_cr )
191+ needs_cr = is_eol_crlf (& xe1 -> xdf1 , 0 );
192+ /* If still undecided, use LF-only */
193+ return needs_cr < 0 ? 0 : needs_cr ;
144194}
145195
146196static int fill_conflict_hunk (xdfenv_t * xe1 , const char * name1 ,
@@ -152,16 +202,17 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
152202 int marker1_size = (name1 ? strlen (name1 ) + 1 : 0 );
153203 int marker2_size = (name2 ? strlen (name2 ) + 1 : 0 );
154204 int marker3_size = (name3 ? strlen (name3 ) + 1 : 0 );
205+ int needs_cr = is_cr_needed (xe1 , xe2 , m );
155206
156207 if (marker_size <= 0 )
157208 marker_size = DEFAULT_CONFLICT_MARKER_SIZE ;
158209
159210 /* Before conflicting part */
160- size += xdl_recs_copy (xe1 , i , m -> i1 - i , 0 ,
211+ size += xdl_recs_copy (xe1 , i , m -> i1 - i , 0 , 0 ,
161212 dest ? dest + size : NULL );
162213
163214 if (!dest ) {
164- size += marker_size + 1 + marker1_size ;
215+ size += marker_size + 1 + needs_cr + marker1_size ;
165216 } else {
166217 memset (dest + size , '<' , marker_size );
167218 size += marker_size ;
@@ -170,17 +221,19 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
170221 memcpy (dest + size + 1 , name1 , marker1_size - 1 );
171222 size += marker1_size ;
172223 }
224+ if (needs_cr )
225+ dest [size ++ ] = '\r' ;
173226 dest [size ++ ] = '\n' ;
174227 }
175228
176229 /* Postimage from side #1 */
177- size += xdl_recs_copy (xe1 , m -> i1 , m -> chg1 , 1 ,
230+ size += xdl_recs_copy (xe1 , m -> i1 , m -> chg1 , needs_cr , 1 ,
178231 dest ? dest + size : NULL );
179232
180233 if (style == XDL_MERGE_DIFF3 ) {
181234 /* Shared preimage */
182235 if (!dest ) {
183- size += marker_size + 1 + marker3_size ;
236+ size += marker_size + 1 + needs_cr + marker3_size ;
184237 } else {
185238 memset (dest + size , '|' , marker_size );
186239 size += marker_size ;
@@ -189,25 +242,29 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
189242 memcpy (dest + size + 1 , name3 , marker3_size - 1 );
190243 size += marker3_size ;
191244 }
245+ if (needs_cr )
246+ dest [size ++ ] = '\r' ;
192247 dest [size ++ ] = '\n' ;
193248 }
194- size += xdl_orig_copy (xe1 , m -> i0 , m -> chg0 , 1 ,
249+ size += xdl_orig_copy (xe1 , m -> i0 , m -> chg0 , needs_cr , 1 ,
195250 dest ? dest + size : NULL );
196251 }
197252
198253 if (!dest ) {
199- size += marker_size + 1 ;
254+ size += marker_size + 1 + needs_cr ;
200255 } else {
201256 memset (dest + size , '=' , marker_size );
202257 size += marker_size ;
258+ if (needs_cr )
259+ dest [size ++ ] = '\r' ;
203260 dest [size ++ ] = '\n' ;
204261 }
205262
206263 /* Postimage from side #2 */
207- size += xdl_recs_copy (xe2 , m -> i2 , m -> chg2 , 1 ,
264+ size += xdl_recs_copy (xe2 , m -> i2 , m -> chg2 , needs_cr , 1 ,
208265 dest ? dest + size : NULL );
209266 if (!dest ) {
210- size += marker_size + 1 + marker2_size ;
267+ size += marker_size + 1 + needs_cr + marker2_size ;
211268 } else {
212269 memset (dest + size , '>' , marker_size );
213270 size += marker_size ;
@@ -216,6 +273,8 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
216273 memcpy (dest + size + 1 , name2 , marker2_size - 1 );
217274 size += marker2_size ;
218275 }
276+ if (needs_cr )
277+ dest [size ++ ] = '\r' ;
219278 dest [size ++ ] = '\n' ;
220279 }
221280 return size ;
@@ -241,21 +300,24 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
241300 marker_size );
242301 else if (m -> mode & 3 ) {
243302 /* Before conflicting part */
244- size += xdl_recs_copy (xe1 , i , m -> i1 - i , 0 ,
303+ size += xdl_recs_copy (xe1 , i , m -> i1 - i , 0 , 0 ,
245304 dest ? dest + size : NULL );
246305 /* Postimage from side #1 */
247- if (m -> mode & 1 )
248- size += xdl_recs_copy (xe1 , m -> i1 , m -> chg1 , (m -> mode & 2 ),
306+ if (m -> mode & 1 ) {
307+ int needs_cr = is_cr_needed (xe1 , xe2 , m );
308+
309+ size += xdl_recs_copy (xe1 , m -> i1 , m -> chg1 , needs_cr , (m -> mode & 2 ),
249310 dest ? dest + size : NULL );
311+ }
250312 /* Postimage from side #2 */
251313 if (m -> mode & 2 )
252- size += xdl_recs_copy (xe2 , m -> i2 , m -> chg2 , 0 ,
314+ size += xdl_recs_copy (xe2 , m -> i2 , m -> chg2 , 0 , 0 ,
253315 dest ? dest + size : NULL );
254316 } else
255317 continue ;
256318 i = m -> i1 + m -> chg1 ;
257319 }
258- size += xdl_recs_copy (xe1 , i , xe1 -> xdf2 .nrec - i , 0 ,
320+ size += xdl_recs_copy (xe1 , i , xe1 -> xdf2 .nrec - i , 0 , 0 ,
259321 dest ? dest + size : NULL );
260322 return size ;
261323}
0 commit comments