Diff options
Diffstat (limited to '')
| -rw-r--r-- | source/ui-ssdiff.c | 113 |
1 file changed, 43 insertions, 70 deletions
diff --git a/source/ui-ssdiff.c b/source/ui-ssdiff.c index afa25ea..90498b7 100644 --- a/source/ui-ssdiff.c +++ b/source/ui-ssdiff.c @@ -14,6 +14,14 @@ #include "ui-shared.h" #include "ui-ssdiff.h" +// The longest old line and the longest new line the view will compare +// character by character. The comparison fills a cell for every pair of +// characters, so its cost is the product of the two, and a line past the limit +// is shown whole instead. +#define MAX_SSDIFF_M 128 +#define MAX_SSDIFF_N 128 +#define MAX_SSDIFF_SIZE (MAX_SSDIFF_M * MAX_SSDIFF_N) + // One line held back until its run ends, owning the copy taken of it. struct deferred_line { int line_no; @@ -21,6 +29,8 @@ struct deferred_line { struct deferred_line *next; }; +// The pair being rendered, whose two sides the line number links lead into. +static struct diff_filepair *current_filepair; static int current_old_line, current_new_line; static int **lcs_table; static struct deferred_line *deferred_old, *deferred_old_last; @@ -182,6 +192,27 @@ static void print_lineno_cell(struct diff_filespec *file, const struct object_id strbuf_release(&path); } +/* + * mark is the class for the characters this side of the row does not share + * with the other. + */ +static void print_side(const char *class, struct diff_filespec *file, const struct object_id *rev, + int line_no, const char *line, const char *lcs, const char *mark) +{ + if (line_no > 0) + print_lineno_cell(file, rev, line_no); + else + html("<td class='lineno'></td>"); + htmlf("<td class='%s%s'>", class, line ? "" : "-dark"); + if (line) { + if (lcs) + print_line_with_lcs(mark, line, lcs); + else + html_txt(line); + } + html("</td>"); +} + static void print_row(const char *class, int old_line_no, char *old_line, int new_line_no, char *new_line, int highlight_chars) { @@ -195,38 +226,10 @@ static void print_row(const char *class, int old_line_no, char *old_line, if (highlight_chars && old_line && new_line) lcs = longest_common_subsequence(old_line, new_line); html("<tr>\n"); - if (old_line_no > 0) { - print_lineno_cell(cgit_get_current_old_file(), old_rev_oid, old_line_no); - htmlf("<td class='%s'>", class); - } else if (old_line) { - htmlf("<td class='lineno'></td><td class='%s'>", class); - } else { - htmlf("<td class='lineno'></td><td class='%s-dark'>", class); - } - if (old_line) { - if (lcs) - print_line_with_lcs("del", old_line, lcs); - else - html_txt(old_line); - } - - html("</td>\n"); - if (new_line_no > 0) { - print_lineno_cell(cgit_get_current_new_file(), new_rev_oid, new_line_no); - htmlf("<td class='%s'>", class); - } else if (new_line) { - htmlf("<td class='lineno'></td><td class='%s'>", class); - } else { - htmlf("<td class='lineno'></td><td class='%s-dark'>", class); - } - if (new_line) { - if (lcs) - print_line_with_lcs("add", new_line, lcs); - else - html_txt(new_line); - } - - html("</td></tr>\n"); + print_side(class, current_filepair->one, old_rev_oid, old_line_no, old_line, lcs, "del"); + html("\n"); + print_side(class, current_filepair->two, new_rev_oid, new_line_no, new_line, lcs, "add"); + html("</tr>\n"); free(lcs); free(new_line); free(old_line); @@ -268,38 +271,12 @@ static int count_deferred(struct deferred_line *item) return count; } -static void print_deferred_old_lines(void) -{ - struct deferred_line *item = deferred_old; - struct deferred_line *next; - - while (item) { - print_row("del", item->line_no, item->line, -1, NULL, 0); - next = item->next; - free_deferred(item); - item = next; - } -} - -static void print_deferred_new_lines(void) -{ - struct deferred_line *item = deferred_new; - struct deferred_line *next; - - while (item) { - print_row("add", -1, NULL, item->line_no, item->line, 0); - next = item->next; - free_deferred(item); - item = next; - } -} - /* * Pairing a removal with an addition only stands for anything when the two * runs are the same length, which is why the character marking is offered only * then. */ -static void print_deferred_changed_lines(void) +static void print_deferred_run(const char *class) { struct deferred_line *old_item = deferred_old; struct deferred_line *new_item = deferred_new; @@ -309,12 +286,12 @@ static void print_deferred_changed_lines(void) highlight_chars = count_deferred(old_item) == count_deferred(new_item); while (old_item || new_item) { if (old_item && new_item) - print_row("changed", old_item->line_no, old_item->line, + print_row(class, old_item->line_no, old_item->line, new_item->line_no, new_item->line, highlight_chars); else if (old_item) - print_row("changed", old_item->line_no, old_item->line, -1, NULL, 0); + print_row(class, old_item->line_no, old_item->line, -1, NULL, 0); else if (new_item) - print_row("changed", -1, NULL, new_item->line_no, new_item->line, 0); + print_row(class, -1, NULL, new_item->line_no, new_item->line, 0); if (old_item) { next = old_item->next; free_deferred(old_item); @@ -353,12 +330,7 @@ static void print_deferred_lines(void) { if (!deferred_old && !deferred_new) return; - if (deferred_old && !deferred_new) - print_deferred_old_lines(); - else if (!deferred_old && deferred_new) - print_deferred_new_lines(); - else - print_deferred_changed_lines(); + print_deferred_run(!deferred_new ? "del" : !deferred_old ? "add" : "changed"); deferred_old = deferred_old_last = NULL; deferred_new = deferred_new_last = NULL; } @@ -401,12 +373,13 @@ void cgit_ssdiff_line_cb(char *line, int len) line[len - 1] = terminator; } -void cgit_ssdiff_header_begin(const char *path) +void cgit_ssdiff_header_begin(struct diff_filepair *pair) { + current_filepair = pair; current_old_line = -1; current_new_line = -1; html("<tbody class='file' data-path='"); - html_attr(path); + html_attr(pair->two->path); html("'>\n"); html("<tr><td class='space' colspan='4'></td></tr>\n"); html("<tr><td class='head' colspan='4'>"); |
