]>
git.cameronkatri.com Git - cgit.git/blob - ui-ssdiff.c
7 static int current_old_line
, current_new_line
;
9 struct deferred_lines
{
12 struct deferred_lines
*next
;
15 static struct deferred_lines
*deferred_old
, *deferred_old_last
;
16 static struct deferred_lines
*deferred_new
, *deferred_new_last
;
18 static char *longest_common_subsequence(char *A
, char *B
)
28 for (i
= m
; i
>= 0; i
--) {
29 for (j
= n
; j
>= 0; j
--) {
30 if (A
[i
] == '\0' || B
[j
] == '\0') {
32 } else if (A
[i
] == B
[j
]) {
33 L
[i
][j
] = 1 + L
[i
+ 1][j
+ 1];
37 L
[i
][j
] = (tmp1
> tmp2
? tmp1
: tmp2
);
43 result
= xmalloc(lcs_length
+ 2);
44 memset(result
, 0, sizeof(*result
) * (lcs_length
+ 2));
49 while (i
< m
&& j
< n
) {
55 } else if (L
[i
+ 1][j
] >= L
[i
][j
+ 1]) {
64 static int line_from_hunk(char *line
, char type
)
69 buf1
= strchr(line
, type
);
73 buf2
= strchr(buf1
, ',');
77 buf2
= xmalloc(len
+ 1);
78 strncpy(buf2
, buf1
, len
);
85 static char *replace_tabs(char *line
)
87 char *prev_buf
= line
;
89 int linelen
= strlen(line
);
101 for (i
= 0; i
< linelen
; i
++)
104 result
= xmalloc(linelen
+ n_tabs
* 8 + 1);
108 cur_buf
= strchr(prev_buf
, '\t');
110 strcat(result
, prev_buf
);
114 strncat(result
, spaces
, 8 - (strlen(result
) % 8));
115 strncat(result
, prev_buf
, cur_buf
- prev_buf
);
117 prev_buf
= cur_buf
+ 1;
122 static int calc_deferred_lines(struct deferred_lines
*start
)
124 struct deferred_lines
*item
= start
;
133 static void deferred_old_add(char *line
, int line_no
)
135 struct deferred_lines
*item
= xmalloc(sizeof(struct deferred_lines
));
136 item
->line
= xstrdup(line
);
137 item
->line_no
= line_no
;
140 deferred_old_last
->next
= item
;
141 deferred_old_last
= item
;
143 deferred_old
= deferred_old_last
= item
;
147 static void deferred_new_add(char *line
, int line_no
)
149 struct deferred_lines
*item
= xmalloc(sizeof(struct deferred_lines
));
150 item
->line
= xstrdup(line
);
151 item
->line_no
= line_no
;
154 deferred_new_last
->next
= item
;
155 deferred_new_last
= item
;
157 deferred_new
= deferred_new_last
= item
;
161 static void print_part_with_lcs(char *class, char *line
, char *lcs
)
163 int line_len
= strlen(line
);
169 for (i
= 0; i
< line_len
; i
++) {
172 if (line
[i
] == lcs
[j
])
176 htmlf("<span class='%s'>", class);
178 } else if (line
[i
] == lcs
[j
]) {
187 static void print_ssdiff_line(char *class,
191 char *new_line
, int individual_chars
)
195 old_line
= replace_tabs(old_line
+ 1);
197 new_line
= replace_tabs(new_line
+ 1);
198 if (individual_chars
&& old_line
&& new_line
)
199 lcs
= longest_common_subsequence(old_line
, new_line
);
202 htmlf("<td class='lineno'>%d</td><td class='%s'>",
205 htmlf("<td class='lineno'></td><td class='%s'>", class);
207 htmlf("<td class='lineno'></td><td class='%s_dark'>", class);
210 print_part_with_lcs("del", old_line
, lcs
);
217 htmlf("<td class='lineno'>%d</td><td class='%s'>",
220 htmlf("<td class='lineno'></td><td class='%s'>", class);
222 htmlf("<td class='lineno'></td><td class='%s_dark'>", class);
225 print_part_with_lcs("add", new_line
, lcs
);
239 static void print_deferred_old_lines()
241 struct deferred_lines
*iter_old
, *tmp
;
242 iter_old
= deferred_old
;
244 print_ssdiff_line("del", iter_old
->line_no
,
245 iter_old
->line
, -1, NULL
, 0);
246 tmp
= iter_old
->next
;
252 static void print_deferred_new_lines()
254 struct deferred_lines
*iter_new
, *tmp
;
255 iter_new
= deferred_new
;
257 print_ssdiff_line("add", -1, NULL
,
258 iter_new
->line_no
, iter_new
->line
, 0);
259 tmp
= iter_new
->next
;
265 static void print_deferred_changed_lines()
267 struct deferred_lines
*iter_old
, *iter_new
, *tmp
;
268 int n_old_lines
= calc_deferred_lines(deferred_old
);
269 int n_new_lines
= calc_deferred_lines(deferred_new
);
270 int individual_chars
= (n_old_lines
== n_new_lines
? 1 : 0);
272 iter_old
= deferred_old
;
273 iter_new
= deferred_new
;
274 while (iter_old
|| iter_new
) {
275 if (iter_old
&& iter_new
)
276 print_ssdiff_line("changed", iter_old
->line_no
,
278 iter_new
->line_no
, iter_new
->line
,
281 print_ssdiff_line("changed", iter_old
->line_no
,
282 iter_old
->line
, -1, NULL
, 0);
284 print_ssdiff_line("changed", -1, NULL
,
285 iter_new
->line_no
, iter_new
->line
, 0);
287 tmp
= iter_old
->next
;
293 tmp
= iter_new
->next
;
300 void cgit_ssdiff_print_deferred_lines()
302 if (!deferred_old
&& !deferred_new
)
304 if (deferred_old
&& !deferred_new
)
305 print_deferred_old_lines();
306 else if (!deferred_old
&& deferred_new
)
307 print_deferred_new_lines();
309 print_deferred_changed_lines();
310 deferred_old
= deferred_old_last
= NULL
;
311 deferred_new
= deferred_new_last
= NULL
;
315 * print a single line returned from xdiff
317 void cgit_ssdiff_line_cb(char *line
, int len
)
319 char c
= line
[len
- 1];
320 line
[len
- 1] = '\0';
321 if (line
[0] == '@') {
322 current_old_line
= line_from_hunk(line
, '-');
323 current_new_line
= line_from_hunk(line
, '+');
326 if (line
[0] == ' ') {
327 if (deferred_old
|| deferred_new
)
328 cgit_ssdiff_print_deferred_lines();
329 print_ssdiff_line("ctx", current_old_line
, line
,
330 current_new_line
, line
, 0);
331 current_old_line
+= 1;
332 current_new_line
+= 1;
333 } else if (line
[0] == '+') {
334 deferred_new_add(line
, current_new_line
);
335 current_new_line
+= 1;
336 } else if (line
[0] == '-') {
337 deferred_old_add(line
, current_old_line
);
338 current_old_line
+= 1;
339 } else if (line
[0] == '@') {
340 html("<tr><td colspan='4' class='hunk'>");
344 html("<tr><td colspan='4' class='ctx'>");
351 void cgit_ssdiff_header_begin()
353 current_old_line
= -1;
354 current_new_line
= -1;
355 html("<tr><td class='space' colspan='4'><div></div></td></tr>");
356 html("<tr><td class='head' colspan='4'>");
359 void cgit_ssdiff_header_end()
364 void cgit_ssdiff_footer()
366 if (deferred_old
|| deferred_new
)
367 cgit_ssdiff_print_deferred_lines();
368 html("<tr><td class='foot' colspan='4'></td></tr>");