Diff options
Diffstat (limited to '')
-rw-r--r--source/ui-ssdiff.c113
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'>");