-rw-r--r-- | cgit.css | 66 | ||||
-rw-r--r-- | ui-diff.c | 27 | ||||
-rw-r--r-- | ui-ssdiff.c | 30 | ||||
-rw-r--r-- | ui-ssdiff.h | 3 |
4 files changed, 96 insertions, 30 deletions
@@ -541,98 +541,152 @@ table.stats td { | |||
541 | text-align: right; | 541 | text-align: right; |
542 | padding: 1px 0.5em; | 542 | padding: 1px 0.5em; |
543 | border: solid 1px black; | 543 | border: solid 1px black; |
544 | } | 544 | } |
545 | 545 | ||
546 | table.stats td.total { | 546 | table.stats td.total { |
547 | font-weight: bold; | 547 | font-weight: bold; |
548 | text-align: left; | 548 | text-align: left; |
549 | } | 549 | } |
550 | 550 | ||
551 | table.stats td.sum { | 551 | table.stats td.sum { |
552 | color: #c00; | 552 | color: #c00; |
553 | font-weight: bold; | 553 | font-weight: bold; |
554 | /*background-color: #eee; */ | 554 | /*background-color: #eee; */ |
555 | } | 555 | } |
556 | 556 | ||
557 | table.stats td.left { | 557 | table.stats td.left { |
558 | text-align: left; | 558 | text-align: left; |
559 | } | 559 | } |
560 | 560 | ||
561 | table.vgraph { | 561 | table.vgraph { |
562 | border-collapse: separate; | 562 | border-collapse: separate; |
563 | border: solid 1px black; | 563 | border: solid 1px black; |
564 | height: 200px; | 564 | height: 200px; |
565 | } | 565 | } |
566 | 566 | ||
567 | table.vgraph th { | 567 | table.vgraph th { |
568 | background-color: #eee; | 568 | background-color: #eee; |
569 | font-weight: bold; | 569 | font-weight: bold; |
570 | border: solid 1px white; | 570 | border: solid 1px white; |
571 | padding: 1px 0.5em; | 571 | padding: 1px 0.5em; |
572 | } | 572 | } |
573 | 573 | ||
574 | table.vgraph td { | 574 | table.vgraph td { |
575 | vertical-align: bottom; | 575 | vertical-align: bottom; |
576 | padding: 0px 10px; | 576 | padding: 0px 10px; |
577 | } | 577 | } |
578 | 578 | ||
579 | table.vgraph div.bar { | 579 | table.vgraph div.bar { |
580 | background-color: #eee; | 580 | background-color: #eee; |
581 | } | 581 | } |
582 | 582 | ||
583 | table.hgraph { | 583 | table.hgraph { |
584 | border: solid 1px black; | 584 | border: solid 1px black; |
585 | width: 800px; | 585 | width: 800px; |
586 | } | 586 | } |
587 | 587 | ||
588 | table.hgraph th { | 588 | table.hgraph th { |
589 | background-color: #eee; | 589 | background-color: #eee; |
590 | font-weight: bold; | 590 | font-weight: bold; |
591 | border: solid 1px black; | 591 | border: solid 1px black; |
592 | padding: 1px 0.5em; | 592 | padding: 1px 0.5em; |
593 | } | 593 | } |
594 | 594 | ||
595 | table.hgraph td { | 595 | table.hgraph td { |
596 | vertical-align: center; | 596 | vertical-align: center; |
597 | padding: 2px 2px; | 597 | padding: 2px 2px; |
598 | } | 598 | } |
599 | 599 | ||
600 | table.hgraph div.bar { | 600 | table.hgraph div.bar { |
601 | background-color: #eee; | 601 | background-color: #eee; |
602 | height: 1em; | 602 | height: 1em; |
603 | } | 603 | } |
604 | 604 | ||
605 | table.ssdiff { | ||
606 | width: 100%; | ||
607 | } | ||
608 | |||
609 | table.ssdiff td { | ||
610 | font-size: 75%; | ||
611 | font-family: monospace; | ||
612 | white-space: pre; | ||
613 | padding: 1px 4px 1px 4px; | ||
614 | border-left: solid 1px #aaa; | ||
615 | border-right: solid 1px #aaa; | ||
616 | } | ||
617 | |||
605 | table.ssdiff td.add { | 618 | table.ssdiff td.add { |
606 | color: black; | 619 | color: black; |
607 | background: #afa; | 620 | background: #cfc; |
621 | min-width: 50%; | ||
608 | } | 622 | } |
609 | 623 | ||
610 | table.ssdiff td.add_dark { | 624 | table.ssdiff td.add_dark { |
611 | color: black; | 625 | color: black; |
612 | background: #9c9; | 626 | background: #aca; |
627 | min-width: 50%; | ||
613 | } | 628 | } |
614 | 629 | ||
615 | table.ssdiff td.del { | 630 | table.ssdiff td.del { |
616 | color: black; | 631 | color: black; |
617 | background: #faa; | 632 | background: #fcc; |
633 | min-width: 50%; | ||
618 | } | 634 | } |
619 | 635 | ||
620 | table.ssdiff td.del_dark { | 636 | table.ssdiff td.del_dark { |
621 | color: black; | 637 | color: black; |
622 | background: #c99; | 638 | background: #caa; |
639 | min-width: 50%; | ||
623 | } | 640 | } |
624 | 641 | ||
625 | table.ssdiff td.changed { | 642 | table.ssdiff td.changed { |
626 | color: black; | 643 | color: black; |
627 | background: #ffa; | 644 | background: #ffc; |
645 | min-width: 50%; | ||
628 | } | 646 | } |
629 | 647 | ||
630 | table.ssdiff td.changed_dark { | 648 | table.ssdiff td.changed_dark { |
631 | color: black; | 649 | color: black; |
632 | background: #cc9; | 650 | background: #cca; |
651 | min-width: 50%; | ||
652 | } | ||
653 | |||
654 | table.ssdiff td.lineno { | ||
655 | color: black; | ||
656 | background: #eee; | ||
657 | text-align: right; | ||
658 | width: 3em; | ||
659 | min-width: 3em; | ||
633 | } | 660 | } |
634 | 661 | ||
635 | table.ssdiff td.hunk { | 662 | table.ssdiff td.hunk { |
636 | color: #black; | 663 | color: #black; |
637 | background: #ccf; | 664 | background: #ccf; |
665 | border-top: solid 1px #aaa; | ||
666 | border-bottom: solid 1px #aaa; | ||
638 | } | 667 | } |
668 | |||
669 | table.ssdiff td.head { | ||
670 | border-top: solid 1px #aaa; | ||
671 | border-bottom: solid 1px #aaa; | ||
672 | } | ||
673 | |||
674 | table.ssdiff td.head div.head { | ||
675 | font-weight: bold; | ||
676 | color: black; | ||
677 | } | ||
678 | |||
679 | table.ssdiff td.foot { | ||
680 | border-top: solid 1px #aaa; | ||
681 | border-left: none; | ||
682 | border-right: none; | ||
683 | border-bottom: none; | ||
684 | } | ||
685 | |||
686 | table.ssdiff td.space { | ||
687 | border: none; | ||
688 | } | ||
689 | |||
690 | table.ssdiff td.space div { | ||
691 | min-height: 3em; | ||
692 | } \ No newline at end of file | ||
@@ -185,158 +185,163 @@ static void print_line(char *line, int len) | |||
185 | 185 | ||
186 | if (line[0] == '+') | 186 | if (line[0] == '+') |
187 | class = "add"; | 187 | class = "add"; |
188 | else if (line[0] == '-') | 188 | else if (line[0] == '-') |
189 | class = "del"; | 189 | class = "del"; |
190 | else if (line[0] == '@') | 190 | else if (line[0] == '@') |
191 | class = "hunk"; | 191 | class = "hunk"; |
192 | 192 | ||
193 | htmlf("<div class='%s'>", class); | 193 | htmlf("<div class='%s'>", class); |
194 | line[len-1] = '\0'; | 194 | line[len-1] = '\0'; |
195 | html_txt(line); | 195 | html_txt(line); |
196 | html("</div>"); | 196 | html("</div>"); |
197 | line[len-1] = c; | 197 | line[len-1] = c; |
198 | } | 198 | } |
199 | 199 | ||
200 | static void header(unsigned char *sha1, char *path1, int mode1, | 200 | static void header(unsigned char *sha1, char *path1, int mode1, |
201 | unsigned char *sha2, char *path2, int mode2) | 201 | unsigned char *sha2, char *path2, int mode2) |
202 | { | 202 | { |
203 | char *abbrev1, *abbrev2; | 203 | char *abbrev1, *abbrev2; |
204 | int subproject; | 204 | int subproject; |
205 | 205 | ||
206 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); | 206 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); |
207 | html("<div class='head'>"); | 207 | html("<div class='head'>"); |
208 | html("diff --git a/"); | 208 | html("diff --git a/"); |
209 | html_txt(path1); | 209 | html_txt(path1); |
210 | html(" b/"); | 210 | html(" b/"); |
211 | html_txt(path2); | 211 | html_txt(path2); |
212 | 212 | ||
213 | if (is_null_sha1(sha1)) | 213 | if (is_null_sha1(sha1)) |
214 | path1 = "dev/null"; | 214 | path1 = "dev/null"; |
215 | if (is_null_sha1(sha2)) | 215 | if (is_null_sha1(sha2)) |
216 | path2 = "dev/null"; | 216 | path2 = "dev/null"; |
217 | 217 | ||
218 | if (mode1 == 0) | 218 | if (mode1 == 0) |
219 | htmlf("<br/>new file mode %.6o", mode2); | 219 | htmlf("<br/>new file mode %.6o", mode2); |
220 | 220 | ||
221 | if (mode2 == 0) | 221 | if (mode2 == 0) |
222 | htmlf("<br/>deleted file mode %.6o", mode1); | 222 | htmlf("<br/>deleted file mode %.6o", mode1); |
223 | 223 | ||
224 | if (!subproject) { | 224 | if (!subproject) { |
225 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); | 225 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); |
226 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); | 226 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); |
227 | htmlf("<br/>index %s..%s", abbrev1, abbrev2); | 227 | htmlf("<br/>index %s..%s", abbrev1, abbrev2); |
228 | free(abbrev1); | 228 | free(abbrev1); |
229 | free(abbrev2); | 229 | free(abbrev2); |
230 | if (mode1 != 0 && mode2 != 0) { | 230 | if (mode1 != 0 && mode2 != 0) { |
231 | htmlf(" %.6o", mode1); | 231 | htmlf(" %.6o", mode1); |
232 | if (mode2 != mode1) | 232 | if (mode2 != mode1) |
233 | htmlf("..%.6o", mode2); | 233 | htmlf("..%.6o", mode2); |
234 | } | 234 | } |
235 | html("<br/>--- a/"); | 235 | html("<br/>--- a/"); |
236 | if (mode1 != 0) | 236 | if (mode1 != 0) |
237 | cgit_tree_link(path1, NULL, NULL, ctx.qry.head, | 237 | cgit_tree_link(path1, NULL, NULL, ctx.qry.head, |
238 | sha1_to_hex(old_rev_sha1), path1); | 238 | sha1_to_hex(old_rev_sha1), path1); |
239 | else | 239 | else |
240 | html_txt(path1); | 240 | html_txt(path1); |
241 | html("<br/>+++ b/"); | 241 | html("<br/>+++ b/"); |
242 | if (mode2 != 0) | 242 | if (mode2 != 0) |
243 | cgit_tree_link(path2, NULL, NULL, ctx.qry.head, | 243 | cgit_tree_link(path2, NULL, NULL, ctx.qry.head, |
244 | sha1_to_hex(new_rev_sha1), path2); | 244 | sha1_to_hex(new_rev_sha1), path2); |
245 | else | 245 | else |
246 | html_txt(path2); | 246 | html_txt(path2); |
247 | } | 247 | } |
248 | html("</div>"); | 248 | html("</div>"); |
249 | if (use_ssdiff) | ||
250 | cgit_ssdiff_header(); | ||
251 | } | 249 | } |
252 | 250 | ||
253 | static void print_ssdiff_link() | 251 | static void print_ssdiff_link() |
254 | { | 252 | { |
255 | if (!strcmp(ctx.qry.page, "diff")) { | 253 | if (!strcmp(ctx.qry.page, "diff")) { |
256 | if (use_ssdiff) | 254 | if (use_ssdiff) |
257 | cgit_diff_link("Unidiff", NULL, NULL, ctx.qry.head, | 255 | cgit_diff_link("Unidiff", NULL, NULL, ctx.qry.head, |
258 | ctx.qry.sha1, ctx.qry.sha2, NULL, 1); | 256 | ctx.qry.sha1, ctx.qry.sha2, NULL, 1); |
259 | else | 257 | else |
260 | cgit_diff_link("Side-by-side diff", NULL, NULL, | 258 | cgit_diff_link("Side-by-side diff", NULL, NULL, |
261 | ctx.qry.head, ctx.qry.sha1, | 259 | ctx.qry.head, ctx.qry.sha1, |
262 | ctx.qry.sha2, NULL, 1); | 260 | ctx.qry.sha2, NULL, 1); |
263 | } | 261 | } |
264 | } | 262 | } |
265 | 263 | ||
266 | static void filepair_cb(struct diff_filepair *pair) | 264 | static void filepair_cb(struct diff_filepair *pair) |
267 | { | 265 | { |
268 | unsigned long old_size = 0; | 266 | unsigned long old_size = 0; |
269 | unsigned long new_size = 0; | 267 | unsigned long new_size = 0; |
270 | int binary = 0; | 268 | int binary = 0; |
271 | linediff_fn print_line_fn = print_line; | 269 | linediff_fn print_line_fn = print_line; |
272 | 270 | ||
273 | header(pair->one->sha1, pair->one->path, pair->one->mode, | ||
274 | pair->two->sha1, pair->two->path, pair->two->mode); | ||
275 | if (use_ssdiff) { | 271 | if (use_ssdiff) { |
276 | cgit_ssdiff_header(); | 272 | cgit_ssdiff_header_begin(); |
277 | print_line_fn = cgit_ssdiff_line_cb; | 273 | print_line_fn = cgit_ssdiff_line_cb; |
278 | } | 274 | } |
275 | header(pair->one->sha1, pair->one->path, pair->one->mode, | ||
276 | pair->two->sha1, pair->two->path, pair->two->mode); | ||
277 | if (use_ssdiff) | ||
278 | cgit_ssdiff_header_end(); | ||
279 | if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { | 279 | if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { |
280 | if (S_ISGITLINK(pair->one->mode)) | 280 | if (S_ISGITLINK(pair->one->mode)) |
281 | print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); | 281 | print_line_fn(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); |
282 | if (S_ISGITLINK(pair->two->mode)) | 282 | if (S_ISGITLINK(pair->two->mode)) |
283 | print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); | 283 | print_line_fn(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); |
284 | return; | 284 | return; |
285 | } | 285 | } |
286 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, | 286 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, |
287 | &new_size, &binary, print_line_fn)) | 287 | &new_size, &binary, print_line_fn)) |
288 | cgit_print_error("Error running diff"); | 288 | cgit_print_error("Error running diff"); |
289 | if (binary) | 289 | if (binary) |
290 | html("Binary files differ"); | 290 | print_line_fn(" Binary files differ", 20); |
291 | if (use_ssdiff) | 291 | if (use_ssdiff) |
292 | cgit_ssdiff_footer(); | 292 | cgit_ssdiff_footer(); |
293 | } | 293 | } |
294 | 294 | ||
295 | void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix) | 295 | void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix) |
296 | { | 296 | { |
297 | enum object_type type; | 297 | enum object_type type; |
298 | unsigned long size; | 298 | unsigned long size; |
299 | struct commit *commit, *commit2; | 299 | struct commit *commit, *commit2; |
300 | 300 | ||
301 | if (!new_rev) | 301 | if (!new_rev) |
302 | new_rev = ctx.qry.head; | 302 | new_rev = ctx.qry.head; |
303 | get_sha1(new_rev, new_rev_sha1); | 303 | get_sha1(new_rev, new_rev_sha1); |
304 | type = sha1_object_info(new_rev_sha1, &size); | 304 | type = sha1_object_info(new_rev_sha1, &size); |
305 | if (type == OBJ_BAD) { | 305 | if (type == OBJ_BAD) { |
306 | cgit_print_error(fmt("Bad object name: %s", new_rev)); | 306 | cgit_print_error(fmt("Bad object name: %s", new_rev)); |
307 | return; | 307 | return; |
308 | } | 308 | } |
309 | commit = lookup_commit_reference(new_rev_sha1); | 309 | commit = lookup_commit_reference(new_rev_sha1); |
310 | if (!commit || parse_commit(commit)) | 310 | if (!commit || parse_commit(commit)) |
311 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(new_rev_sha1))); | 311 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(new_rev_sha1))); |
312 | 312 | ||
313 | if (old_rev) | 313 | if (old_rev) |
314 | get_sha1(old_rev, old_rev_sha1); | 314 | get_sha1(old_rev, old_rev_sha1); |
315 | else if (commit->parents && commit->parents->item) | 315 | else if (commit->parents && commit->parents->item) |
316 | hashcpy(old_rev_sha1, commit->parents->item->object.sha1); | 316 | hashcpy(old_rev_sha1, commit->parents->item->object.sha1); |
317 | else | 317 | else |
318 | hashclr(old_rev_sha1); | 318 | hashclr(old_rev_sha1); |
319 | 319 | ||
320 | if (!is_null_sha1(old_rev_sha1)) { | 320 | if (!is_null_sha1(old_rev_sha1)) { |
321 | type = sha1_object_info(old_rev_sha1, &size); | 321 | type = sha1_object_info(old_rev_sha1, &size); |
322 | if (type == OBJ_BAD) { | 322 | if (type == OBJ_BAD) { |
323 | cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(old_rev_sha1))); | 323 | cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(old_rev_sha1))); |
324 | return; | 324 | return; |
325 | } | 325 | } |
326 | commit2 = lookup_commit_reference(old_rev_sha1); | 326 | commit2 = lookup_commit_reference(old_rev_sha1); |
327 | if (!commit2 || parse_commit(commit2)) | 327 | if (!commit2 || parse_commit(commit2)) |
328 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(old_rev_sha1))); | 328 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(old_rev_sha1))); |
329 | } | 329 | } |
330 | 330 | ||
331 | if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff)) | 331 | if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff)) |
332 | use_ssdiff = 1; | 332 | use_ssdiff = 1; |
333 | 333 | ||
334 | print_ssdiff_link(); | 334 | print_ssdiff_link(); |
335 | cgit_print_diffstat(old_rev_sha1, new_rev_sha1); | 335 | cgit_print_diffstat(old_rev_sha1, new_rev_sha1); |
336 | 336 | ||
337 | html("<table summary='diff' class='diff'>"); | 337 | if (use_ssdiff) { |
338 | html("<tr><td>"); | 338 | html("<table summary='ssdiff' class='ssdiff'>"); |
339 | } else { | ||
340 | html("<table summary='diff' class='diff'>"); | ||
341 | html("<tr><td>"); | ||
342 | } | ||
339 | cgit_diff_tree(old_rev_sha1, new_rev_sha1, filepair_cb, prefix); | 343 | cgit_diff_tree(old_rev_sha1, new_rev_sha1, filepair_cb, prefix); |
340 | html("</td></tr>"); | 344 | if (!use_ssdiff) |
345 | html("</td></tr>"); | ||
341 | html("</table>"); | 346 | html("</table>"); |
342 | } | 347 | } |
diff --git a/ui-ssdiff.c b/ui-ssdiff.c index 3591ab4..8215051 100644 --- a/ui-ssdiff.c +++ b/ui-ssdiff.c | |||
@@ -1,264 +1,270 @@ | |||
1 | #include "cgit.h" | 1 | #include "cgit.h" |
2 | #include "html.h" | 2 | #include "html.h" |
3 | #include "ui-shared.h" | 3 | #include "ui-shared.h" |
4 | 4 | ||
5 | extern int use_ssdiff; | 5 | extern int use_ssdiff; |
6 | 6 | ||
7 | static int current_old_line, current_new_line; | 7 | static int current_old_line, current_new_line; |
8 | 8 | ||
9 | struct deferred_lines { | 9 | struct deferred_lines { |
10 | int line_no; | 10 | int line_no; |
11 | char *line; | 11 | char *line; |
12 | struct deferred_lines *next; | 12 | struct deferred_lines *next; |
13 | }; | 13 | }; |
14 | 14 | ||
15 | static struct deferred_lines *deferred_old, *deferred_old_last; | 15 | static struct deferred_lines *deferred_old, *deferred_old_last; |
16 | static struct deferred_lines *deferred_new, *deferred_new_last; | 16 | static struct deferred_lines *deferred_new, *deferred_new_last; |
17 | 17 | ||
18 | static int line_from_hunk(char *line, char type) | 18 | static int line_from_hunk(char *line, char type) |
19 | { | 19 | { |
20 | char *buf1, *buf2; | 20 | char *buf1, *buf2; |
21 | int len; | 21 | int len; |
22 | 22 | ||
23 | buf1 = strchr(line, type); | 23 | buf1 = strchr(line, type); |
24 | if (buf1 == NULL) | 24 | if (buf1 == NULL) |
25 | return 0; | 25 | return 0; |
26 | buf1 += 1; | 26 | buf1 += 1; |
27 | buf2 = strchr(buf1, ','); | 27 | buf2 = strchr(buf1, ','); |
28 | if (buf2 == NULL) | 28 | if (buf2 == NULL) |
29 | return 0; | 29 | return 0; |
30 | len = buf2 - buf1; | 30 | len = buf2 - buf1; |
31 | buf2 = xmalloc(len + 1); | 31 | buf2 = xmalloc(len + 1); |
32 | strncpy(buf2, buf1, len); | 32 | strncpy(buf2, buf1, len); |
33 | buf2[len] = '\0'; | 33 | buf2[len] = '\0'; |
34 | int res = atoi(buf2); | 34 | int res = atoi(buf2); |
35 | free(buf2); | 35 | free(buf2); |
36 | return res; | 36 | return res; |
37 | } | 37 | } |
38 | 38 | ||
39 | static char *replace_tabs(char *line) | 39 | static char *replace_tabs(char *line) |
40 | { | 40 | { |
41 | char *prev_buf = line; | 41 | char *prev_buf = line; |
42 | char *cur_buf; | 42 | char *cur_buf; |
43 | int linelen = strlen(line); | 43 | int linelen = strlen(line); |
44 | int n_tabs = 0; | 44 | int n_tabs = 0; |
45 | int i; | 45 | int i; |
46 | char *result; | 46 | char *result; |
47 | char *spaces = " "; | 47 | char *spaces = " "; |
48 | 48 | ||
49 | if (linelen == 0) { | 49 | if (linelen == 0) { |
50 | result = xmalloc(1); | 50 | result = xmalloc(1); |
51 | result[0] = '\0'; | 51 | result[0] = '\0'; |
52 | return result; | 52 | return result; |
53 | } | 53 | } |
54 | 54 | ||
55 | for (i = 0; i < linelen; i++) | 55 | for (i = 0; i < linelen; i++) |
56 | if (line[i] == '\t') | 56 | if (line[i] == '\t') |
57 | n_tabs += 1; | 57 | n_tabs += 1; |
58 | result = xmalloc(linelen + n_tabs * 8 + 1); | 58 | result = xmalloc(linelen + n_tabs * 8 + 1); |
59 | result[0] = '\0'; | 59 | result[0] = '\0'; |
60 | 60 | ||
61 | while (1) { | 61 | while (1) { |
62 | cur_buf = strchr(prev_buf, '\t'); | 62 | cur_buf = strchr(prev_buf, '\t'); |
63 | if (!cur_buf) { | 63 | if (!cur_buf) { |
64 | strcat(result, prev_buf); | 64 | strcat(result, prev_buf); |
65 | break; | 65 | break; |
66 | } else { | 66 | } else { |
67 | strcat(result, " "); | 67 | strcat(result, " "); |
68 | strncat(result, spaces, 8 - (strlen(result) % 8)); | 68 | strncat(result, spaces, 8 - (strlen(result) % 8)); |
69 | strncat(result, prev_buf, cur_buf - prev_buf); | 69 | strncat(result, prev_buf, cur_buf - prev_buf); |
70 | } | 70 | } |
71 | prev_buf = cur_buf + 1; | 71 | prev_buf = cur_buf + 1; |
72 | } | 72 | } |
73 | return result; | 73 | return result; |
74 | } | 74 | } |
75 | 75 | ||
76 | static void deferred_old_add(char *line, int line_no) | 76 | static void deferred_old_add(char *line, int line_no) |
77 | { | 77 | { |
78 | struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines)); | 78 | struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines)); |
79 | item->line = xstrdup(line); | 79 | item->line = xstrdup(line); |
80 | item->line_no = line_no; | 80 | item->line_no = line_no; |
81 | item->next = NULL; | 81 | item->next = NULL; |
82 | if (deferred_old) { | 82 | if (deferred_old) { |
83 | deferred_old_last->next = item; | 83 | deferred_old_last->next = item; |
84 | deferred_old_last = item; | 84 | deferred_old_last = item; |
85 | } else { | 85 | } else { |
86 | deferred_old = deferred_old_last = item; | 86 | deferred_old = deferred_old_last = item; |
87 | } | 87 | } |
88 | } | 88 | } |
89 | 89 | ||
90 | static void deferred_new_add(char *line, int line_no) | 90 | static void deferred_new_add(char *line, int line_no) |
91 | { | 91 | { |
92 | struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines)); | 92 | struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines)); |
93 | item->line = xstrdup(line); | 93 | item->line = xstrdup(line); |
94 | item->line_no = line_no; | 94 | item->line_no = line_no; |
95 | item->next = NULL; | 95 | item->next = NULL; |
96 | if (deferred_new) { | 96 | if (deferred_new) { |
97 | deferred_new_last->next = item; | 97 | deferred_new_last->next = item; |
98 | deferred_new_last = item; | 98 | deferred_new_last = item; |
99 | } else { | 99 | } else { |
100 | deferred_new = deferred_new_last = item; | 100 | deferred_new = deferred_new_last = item; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | static void print_ssdiff_line(char *class, int old_line_no, char *old_line, | 104 | static void print_ssdiff_line(char *class, int old_line_no, char *old_line, |
105 | int new_line_no, char *new_line) | 105 | int new_line_no, char *new_line) |
106 | { | 106 | { |
107 | html("<tr>"); | 107 | html("<tr>"); |
108 | if (old_line_no > 0) | 108 | if (old_line_no > 0) |
109 | htmlf("<td class='%s'>%d </td><td class='%s'>", class, | 109 | htmlf("<td class='lineno'>%d</td><td class='%s'>", |
110 | old_line_no, class); | 110 | old_line_no, class); |
111 | else | 111 | else |
112 | htmlf("<td class='%s_dark'> </td><td class='%s_dark'>", class, class); | 112 | htmlf("<td class='lineno'></td><td class='%s_dark'>", class); |
113 | 113 | ||
114 | if (old_line) { | 114 | if (old_line) { |
115 | old_line = replace_tabs(old_line + 1); | 115 | old_line = replace_tabs(old_line + 1); |
116 | html_txt(old_line); | 116 | html_txt(old_line); |
117 | free(old_line); | 117 | free(old_line); |
118 | } | 118 | } |
119 | 119 | ||
120 | html(" </td>"); | 120 | html("</td>"); |
121 | 121 | ||
122 | if (new_line_no > 0) | 122 | if (new_line_no > 0) |
123 | htmlf("<td class='%s'> %d </td><td class='%s'>", class, | 123 | htmlf("<td class='lineno'>%d</td><td class='%s'>", |
124 | new_line_no, class); | 124 | new_line_no, class); |
125 | else | 125 | else |
126 | htmlf("<td class='%s_dark'> </td><td class='%s_dark'>", class, class); | 126 | htmlf("<td class='lineno'></td><td class='%s_dark'>", class); |
127 | 127 | ||
128 | if (new_line) { | 128 | if (new_line) { |
129 | new_line = replace_tabs(new_line + 1); | 129 | new_line = replace_tabs(new_line + 1); |
130 | html_txt(new_line); | 130 | html_txt(new_line); |
131 | free(new_line); | 131 | free(new_line); |
132 | } | 132 | } |
133 | 133 | ||
134 | html("</td></tr>"); | 134 | html("</td></tr>"); |
135 | } | 135 | } |
136 | 136 | ||
137 | static void print_deferred_old_lines() | 137 | static void print_deferred_old_lines() |
138 | { | 138 | { |
139 | struct deferred_lines *iter_old, *tmp; | 139 | struct deferred_lines *iter_old, *tmp; |
140 | 140 | ||
141 | iter_old = deferred_old; | 141 | iter_old = deferred_old; |
142 | while (iter_old) { | 142 | while (iter_old) { |
143 | print_ssdiff_line("del", iter_old->line_no, | 143 | print_ssdiff_line("del", iter_old->line_no, |
144 | iter_old->line, -1, NULL); | 144 | iter_old->line, -1, NULL); |
145 | tmp = iter_old->next; | 145 | tmp = iter_old->next; |
146 | free(iter_old); | 146 | free(iter_old); |
147 | iter_old = tmp; | 147 | iter_old = tmp; |
148 | } | 148 | } |
149 | } | 149 | } |
150 | 150 | ||
151 | static void print_deferred_new_lines() | 151 | static void print_deferred_new_lines() |
152 | { | 152 | { |
153 | struct deferred_lines *iter_new, *tmp; | 153 | struct deferred_lines *iter_new, *tmp; |
154 | 154 | ||
155 | iter_new = deferred_new; | 155 | iter_new = deferred_new; |
156 | while (iter_new) { | 156 | while (iter_new) { |
157 | print_ssdiff_line("add", -1, NULL, iter_new->line_no, | 157 | print_ssdiff_line("add", -1, NULL, iter_new->line_no, |
158 | iter_new->line); | 158 | iter_new->line); |
159 | tmp = iter_new->next; | 159 | tmp = iter_new->next; |
160 | free(iter_new); | 160 | free(iter_new); |
161 | iter_new = tmp; | 161 | iter_new = tmp; |
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | static void print_deferred_changed_lines() | 165 | static void print_deferred_changed_lines() |
166 | { | 166 | { |
167 | struct deferred_lines *iter_old, *iter_new, *tmp; | 167 | struct deferred_lines *iter_old, *iter_new, *tmp; |
168 | 168 | ||
169 | iter_old = deferred_old; | 169 | iter_old = deferred_old; |
170 | iter_new = deferred_new; | 170 | iter_new = deferred_new; |
171 | while (iter_old || iter_new) { | 171 | while (iter_old || iter_new) { |
172 | if (iter_old && iter_new) | 172 | if (iter_old && iter_new) |
173 | print_ssdiff_line("changed", iter_old->line_no, | 173 | print_ssdiff_line("changed", iter_old->line_no, |
174 | iter_old->line, | 174 | iter_old->line, |
175 | iter_new->line_no, iter_new->line); | 175 | iter_new->line_no, iter_new->line); |
176 | else if (iter_old) | 176 | else if (iter_old) |
177 | print_ssdiff_line("changed", iter_old->line_no, | 177 | print_ssdiff_line("changed", iter_old->line_no, |
178 | iter_old->line, -1, NULL); | 178 | iter_old->line, -1, NULL); |
179 | else if (iter_new) | 179 | else if (iter_new) |
180 | print_ssdiff_line("changed", -1, NULL, | 180 | print_ssdiff_line("changed", -1, NULL, |
181 | iter_new->line_no, iter_new->line); | 181 | iter_new->line_no, iter_new->line); |
182 | 182 | ||
183 | if (iter_old) { | 183 | if (iter_old) { |
184 | tmp = iter_old->next; | 184 | tmp = iter_old->next; |
185 | free(iter_old); | 185 | free(iter_old); |
186 | iter_old = tmp; | 186 | iter_old = tmp; |
187 | } | 187 | } |
188 | 188 | ||
189 | if (iter_new) { | 189 | if (iter_new) { |
190 | tmp = iter_new->next; | 190 | tmp = iter_new->next; |
191 | free(iter_new); | 191 | free(iter_new); |
192 | iter_new = tmp; | 192 | iter_new = tmp; |
193 | } | 193 | } |
194 | } | 194 | } |
195 | } | 195 | } |
196 | 196 | ||
197 | void cgit_ssdiff_print_deferred_lines() | 197 | void cgit_ssdiff_print_deferred_lines() |
198 | { | 198 | { |
199 | if (!deferred_old && !deferred_new) | 199 | if (!deferred_old && !deferred_new) |
200 | return; | 200 | return; |
201 | 201 | ||
202 | if (deferred_old && !deferred_new) | 202 | if (deferred_old && !deferred_new) |
203 | print_deferred_old_lines(); | 203 | print_deferred_old_lines(); |
204 | else if (!deferred_old && deferred_new) | 204 | else if (!deferred_old && deferred_new) |
205 | print_deferred_new_lines(); | 205 | print_deferred_new_lines(); |
206 | else | 206 | else |
207 | print_deferred_changed_lines(); | 207 | print_deferred_changed_lines(); |
208 | 208 | ||
209 | deferred_old = deferred_old_last = NULL; | 209 | deferred_old = deferred_old_last = NULL; |
210 | deferred_new = deferred_new_last = NULL; | 210 | deferred_new = deferred_new_last = NULL; |
211 | } | 211 | } |
212 | 212 | ||
213 | /* | 213 | /* |
214 | * print a single line returned from xdiff | 214 | * print a single line returned from xdiff |
215 | */ | 215 | */ |
216 | void cgit_ssdiff_line_cb(char *line, int len) | 216 | void cgit_ssdiff_line_cb(char *line, int len) |
217 | { | 217 | { |
218 | char c = line[len - 1]; | 218 | char c = line[len - 1]; |
219 | 219 | ||
220 | line[len - 1] = '\0'; | 220 | line[len - 1] = '\0'; |
221 | 221 | ||
222 | if (line[0] == '@') { | 222 | if (line[0] == '@') { |
223 | current_old_line = line_from_hunk(line, '-'); | 223 | current_old_line = line_from_hunk(line, '-'); |
224 | current_new_line = line_from_hunk(line, '+'); | 224 | current_new_line = line_from_hunk(line, '+'); |
225 | } | 225 | } |
226 | 226 | ||
227 | if (line[0] == ' ') { | 227 | if (line[0] == ' ') { |
228 | if (deferred_old || deferred_new) | 228 | if (deferred_old || deferred_new) |
229 | cgit_ssdiff_print_deferred_lines(); | 229 | cgit_ssdiff_print_deferred_lines(); |
230 | print_ssdiff_line("ctx", current_old_line, line, | 230 | print_ssdiff_line("ctx", current_old_line, line, |
231 | current_new_line, line); | 231 | current_new_line, line); |
232 | current_old_line += 1; | 232 | current_old_line += 1; |
233 | current_new_line += 1; | 233 | current_new_line += 1; |
234 | } else if (line[0] == '+') { | 234 | } else if (line[0] == '+') { |
235 | deferred_new_add(line, current_new_line); | 235 | deferred_new_add(line, current_new_line); |
236 | current_new_line += 1; | 236 | current_new_line += 1; |
237 | } else if (line[0] == '-') { | 237 | } else if (line[0] == '-') { |
238 | deferred_old_add(line, current_old_line); | 238 | deferred_old_add(line, current_old_line); |
239 | current_old_line += 1; | 239 | current_old_line += 1; |
240 | } else if (line[0] == '@') { | 240 | } else if (line[0] == '@') { |
241 | html("<tr><td colspan='4' class='hunk'>"); | 241 | html("<tr><td colspan='4' class='hunk'>"); |
242 | html_txt(line); | 242 | html_txt(line); |
243 | html("</td></tr>"); | 243 | html("</td></tr>"); |
244 | } else { | 244 | } else { |
245 | html("<tr><td colspan='4' class='ctx'>"); | 245 | html("<tr><td colspan='4' class='ctx'>"); |
246 | html_txt(line); | 246 | html_txt(line); |
247 | html("</td></tr>"); | 247 | html("</td></tr>"); |
248 | } | 248 | } |
249 | line[len - 1] = c; | 249 | line[len - 1] = c; |
250 | } | 250 | } |
251 | 251 | ||
252 | void cgit_ssdiff_header() | 252 | void cgit_ssdiff_header_begin() |
253 | { | 253 | { |
254 | current_old_line = 0; | 254 | current_old_line = 0; |
255 | current_new_line = 0; | 255 | current_new_line = 0; |
256 | html("<table class='ssdiff'>"); | 256 | html("<tr><td class='space' colspan='4'><div></div></td></tr>"); |
257 | html("<tr><td class='head' colspan='4'>"); | ||
258 | } | ||
259 | |||
260 | void cgit_ssdiff_header_end() | ||
261 | { | ||
262 | html("</td><tr>"); | ||
257 | } | 263 | } |
258 | 264 | ||
259 | void cgit_ssdiff_footer() | 265 | void cgit_ssdiff_footer() |
260 | { | 266 | { |
261 | if (deferred_old || deferred_new) | 267 | if (deferred_old || deferred_new) |
262 | cgit_ssdiff_print_deferred_lines(); | 268 | cgit_ssdiff_print_deferred_lines(); |
263 | html("</table>"); | 269 | html("<tr><td class='foot' colspan='4'></td></tr>"); |
264 | } | 270 | } |
diff --git a/ui-ssdiff.h b/ui-ssdiff.h index a0b1efe..64b4b12 100644 --- a/ui-ssdiff.h +++ b/ui-ssdiff.h | |||
@@ -1,12 +1,13 @@ | |||
1 | #ifndef UI_SSDIFF_H | 1 | #ifndef UI_SSDIFF_H |
2 | #define UI_SSDIFF_H | 2 | #define UI_SSDIFF_H |
3 | 3 | ||
4 | extern void cgit_ssdiff_print_deferred_lines(); | 4 | extern void cgit_ssdiff_print_deferred_lines(); |
5 | 5 | ||
6 | extern void cgit_ssdiff_line_cb(char *line, int len); | 6 | extern void cgit_ssdiff_line_cb(char *line, int len); |
7 | 7 | ||
8 | extern void cgit_ssdiff_header(); | 8 | extern void cgit_ssdiff_header_begin(); |
9 | extern void cgit_ssdiff_header_end(); | ||
9 | 10 | ||
10 | extern void cgit_ssdiff_footer(); | 11 | extern void cgit_ssdiff_footer(); |
11 | 12 | ||
12 | #endif /* UI_SSDIFF_H */ | 13 | #endif /* UI_SSDIFF_H */ |