@@ -100,14 +100,40 @@ static int xdl_emit_common(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
100100 return 0 ;
101101}
102102
103+ struct func_line {
104+ long len ;
105+ char buf [80 ];
106+ };
107+
108+ static long get_func_line (xdfenv_t * xe , xdemitconf_t const * xecfg ,
109+ struct func_line * func_line , long start , long limit )
110+ {
111+ find_func_t ff = xecfg -> find_func ? xecfg -> find_func : def_ff ;
112+ long l , size , step = (start > limit ) ? -1 : 1 ;
113+ char * buf , dummy [1 ];
114+
115+ buf = func_line ? func_line -> buf : dummy ;
116+ size = func_line ? sizeof (func_line -> buf ) : sizeof (dummy );
117+
118+ for (l = start ; l != limit && 0 <= l && l < xe -> xdf1 .nrec ; l += step ) {
119+ const char * rec ;
120+ long reclen = xdl_get_rec (& xe -> xdf1 , l , & rec );
121+ long len = ff (rec , reclen , buf , size , xecfg -> find_func_priv );
122+ if (len >= 0 ) {
123+ if (func_line )
124+ func_line -> len = len ;
125+ return l ;
126+ }
127+ }
128+ return -1 ;
129+ }
130+
103131int xdl_emit_diff (xdfenv_t * xe , xdchange_t * xscr , xdemitcb_t * ecb ,
104132 xdemitconf_t const * xecfg ) {
105133 long s1 , s2 , e1 , e2 , lctx ;
106134 xdchange_t * xch , * xche ;
107- char funcbuf [80 ];
108- long funclen = 0 ;
109135 long funclineprev = -1 ;
110- find_func_t ff = xecfg -> find_func ? xecfg -> find_func : def_ff ;
136+ struct func_line func_line = { 0 } ;
111137
112138 if (xecfg -> flags & XDL_EMIT_COMMON )
113139 return xdl_emit_common (xe , xscr , ecb , xecfg );
@@ -118,34 +144,61 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
118144 s1 = XDL_MAX (xch -> i1 - xecfg -> ctxlen , 0 );
119145 s2 = XDL_MAX (xch -> i2 - xecfg -> ctxlen , 0 );
120146
147+ if (xecfg -> flags & XDL_EMIT_FUNCCONTEXT ) {
148+ long fs1 = get_func_line (xe , xecfg , NULL , xch -> i1 , -1 );
149+ if (fs1 < 0 )
150+ fs1 = 0 ;
151+ if (fs1 < s1 ) {
152+ s2 -= s1 - fs1 ;
153+ s1 = fs1 ;
154+ }
155+ }
156+
157+ again :
121158 lctx = xecfg -> ctxlen ;
122159 lctx = XDL_MIN (lctx , xe -> xdf1 .nrec - (xche -> i1 + xche -> chg1 ));
123160 lctx = XDL_MIN (lctx , xe -> xdf2 .nrec - (xche -> i2 + xche -> chg2 ));
124161
125162 e1 = xche -> i1 + xche -> chg1 + lctx ;
126163 e2 = xche -> i2 + xche -> chg2 + lctx ;
127164
165+ if (xecfg -> flags & XDL_EMIT_FUNCCONTEXT ) {
166+ long fe1 = get_func_line (xe , xecfg , NULL ,
167+ xche -> i1 + xche -> chg1 ,
168+ xe -> xdf1 .nrec );
169+ if (fe1 < 0 )
170+ fe1 = xe -> xdf1 .nrec ;
171+ if (fe1 > e1 ) {
172+ e2 += fe1 - e1 ;
173+ e1 = fe1 ;
174+ }
175+
176+ /*
177+ * Overlap with next change? Then include it
178+ * in the current hunk and start over to find
179+ * its new end.
180+ */
181+ if (xche -> next ) {
182+ long l = xche -> next -> i1 ;
183+ if (l <= e1 ||
184+ get_func_line (xe , xecfg , NULL , l , e1 ) < 0 ) {
185+ xche = xche -> next ;
186+ goto again ;
187+ }
188+ }
189+ }
190+
128191 /*
129192 * Emit current hunk header.
130193 */
131194
132195 if (xecfg -> flags & XDL_EMIT_FUNCNAMES ) {
133- long l ;
134- for (l = s1 - 1 ; l >= 0 && l > funclineprev ; l -- ) {
135- const char * rec ;
136- long reclen = xdl_get_rec (& xe -> xdf1 , l , & rec );
137- long newfunclen = ff (rec , reclen , funcbuf ,
138- sizeof (funcbuf ),
139- xecfg -> find_func_priv );
140- if (newfunclen >= 0 ) {
141- funclen = newfunclen ;
142- break ;
143- }
144- }
196+ get_func_line (xe , xecfg , & func_line ,
197+ s1 - 1 , funclineprev );
145198 funclineprev = s1 - 1 ;
146199 }
147200 if (xdl_emit_hunk_hdr (s1 + 1 , e1 - s1 , s2 + 1 , e2 - s2 ,
148- funcbuf , funclen , ecb ) < 0 )
201+ func_line . buf , func_line . len , ecb ) < 0 )
149202 return -1 ;
150203
151204 /*
0 commit comments