summaryrefslogtreecommitdiffabout
path: root/ui-ssdiff.c
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2010-12-23 11:47:55 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2011-02-19 13:41:39 (UTC)
commite52040bf90b034aebbfa32756638a24d6b1b3712 (patch) (unidiff)
treeba2db3037cb486fb40a8c85a62b5a393d5035924 /ui-ssdiff.c
parent808c685ebb7cd2d24d3881b74e3be2439bd1393b (diff)
downloadcgit-e52040bf90b034aebbfa32756638a24d6b1b3712.zip
cgit-e52040bf90b034aebbfa32756638a24d6b1b3712.tar.gz
cgit-e52040bf90b034aebbfa32756638a24d6b1b3712.tar.bz2
ssdiff: anchors for ssdiff
Emit anchors to the respective revisions in side-by-side diff view Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'ui-ssdiff.c') (more/less context) (show whitespace changes)
-rw-r--r--ui-ssdiff.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/ui-ssdiff.c b/ui-ssdiff.c
index 408e620..2481585 100644
--- a/ui-ssdiff.c
+++ b/ui-ssdiff.c
@@ -1,51 +1,52 @@
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#include "ui-diff.h"
4 5
5extern int use_ssdiff; 6extern int use_ssdiff;
6 7
7static int current_old_line, current_new_line; 8static int current_old_line, current_new_line;
8 9
9struct deferred_lines { 10struct deferred_lines {
10 int line_no; 11 int line_no;
11 char *line; 12 char *line;
12 struct deferred_lines *next; 13 struct deferred_lines *next;
13}; 14};
14 15
15static struct deferred_lines *deferred_old, *deferred_old_last; 16static struct deferred_lines *deferred_old, *deferred_old_last;
16static struct deferred_lines *deferred_new, *deferred_new_last; 17static struct deferred_lines *deferred_new, *deferred_new_last;
17 18
18static char *longest_common_subsequence(char *A, char *B) 19static char *longest_common_subsequence(char *A, char *B)
19{ 20{
20 int i, j, ri; 21 int i, j, ri;
21 int m = strlen(A); 22 int m = strlen(A);
22 int n = strlen(B); 23 int n = strlen(B);
23 int L[m + 1][n + 1]; 24 int L[m + 1][n + 1];
24 int tmp1, tmp2; 25 int tmp1, tmp2;
25 int lcs_length; 26 int lcs_length;
26 char *result; 27 char *result;
27 28
28 for (i = m; i >= 0; i--) { 29 for (i = m; i >= 0; i--) {
29 for (j = n; j >= 0; j--) { 30 for (j = n; j >= 0; j--) {
30 if (A[i] == '\0' || B[j] == '\0') { 31 if (A[i] == '\0' || B[j] == '\0') {
31 L[i][j] = 0; 32 L[i][j] = 0;
32 } else if (A[i] == B[j]) { 33 } else if (A[i] == B[j]) {
33 L[i][j] = 1 + L[i + 1][j + 1]; 34 L[i][j] = 1 + L[i + 1][j + 1];
34 } else { 35 } else {
35 tmp1 = L[i + 1][j]; 36 tmp1 = L[i + 1][j];
36 tmp2 = L[i][j + 1]; 37 tmp2 = L[i][j + 1];
37 L[i][j] = (tmp1 > tmp2 ? tmp1 : tmp2); 38 L[i][j] = (tmp1 > tmp2 ? tmp1 : tmp2);
38 } 39 }
39 } 40 }
40 } 41 }
41 42
42 lcs_length = L[0][0]; 43 lcs_length = L[0][0];
43 result = xmalloc(lcs_length + 2); 44 result = xmalloc(lcs_length + 2);
44 memset(result, 0, sizeof(*result) * (lcs_length + 2)); 45 memset(result, 0, sizeof(*result) * (lcs_length + 2));
45 46
46 ri = 0; 47 ri = 0;
47 i = 0; 48 i = 0;
48 j = 0; 49 j = 0;
49 while (i < m && j < n) { 50 while (i < m && j < n) {
50 if (A[i] == B[j]) { 51 if (A[i] == B[j]) {
51 result[ri] = A[i]; 52 result[ri] = A[i];
@@ -146,122 +147,135 @@ static void deferred_old_add(char *line, int line_no)
146 147
147static void deferred_new_add(char *line, int line_no) 148static void deferred_new_add(char *line, int line_no)
148{ 149{
149 struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines)); 150 struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines));
150 item->line = xstrdup(line); 151 item->line = xstrdup(line);
151 item->line_no = line_no; 152 item->line_no = line_no;
152 item->next = NULL; 153 item->next = NULL;
153 if (deferred_new) { 154 if (deferred_new) {
154 deferred_new_last->next = item; 155 deferred_new_last->next = item;
155 deferred_new_last = item; 156 deferred_new_last = item;
156 } else { 157 } else {
157 deferred_new = deferred_new_last = item; 158 deferred_new = deferred_new_last = item;
158 } 159 }
159} 160}
160 161
161static void print_part_with_lcs(char *class, char *line, char *lcs) 162static void print_part_with_lcs(char *class, char *line, char *lcs)
162{ 163{
163 int line_len = strlen(line); 164 int line_len = strlen(line);
164 int i, j; 165 int i, j;
165 char c[2] = " "; 166 char c[2] = " ";
166 int same = 1; 167 int same = 1;
167 168
168 j = 0; 169 j = 0;
169 for (i = 0; i < line_len; i++) { 170 for (i = 0; i < line_len; i++) {
170 c[0] = line[i]; 171 c[0] = line[i];
171 if (same) { 172 if (same) {
172 if (line[i] == lcs[j]) 173 if (line[i] == lcs[j])
173 j += 1; 174 j += 1;
174 else { 175 else {
175 same = 0; 176 same = 0;
176 htmlf("<span class='%s'>", class); 177 htmlf("<span class='%s'>", class);
177 } 178 }
178 } else if (line[i] == lcs[j]) { 179 } else if (line[i] == lcs[j]) {
179 same = 1; 180 same = 1;
180 htmlf("</span>"); 181 htmlf("</span>");
181 j += 1; 182 j += 1;
182 } 183 }
183 html_txt(c); 184 html_txt(c);
184 } 185 }
185} 186}
186 187
187static void print_ssdiff_line(char *class, 188static void print_ssdiff_line(char *class,
188 int old_line_no, 189 int old_line_no,
189 char *old_line, 190 char *old_line,
190 int new_line_no, 191 int new_line_no,
191 char *new_line, int individual_chars) 192 char *new_line, int individual_chars)
192{ 193{
193 char *lcs = NULL; 194 char *lcs = NULL;
195
194 if (old_line) 196 if (old_line)
195 old_line = replace_tabs(old_line + 1); 197 old_line = replace_tabs(old_line + 1);
196 if (new_line) 198 if (new_line)
197 new_line = replace_tabs(new_line + 1); 199 new_line = replace_tabs(new_line + 1);
198 if (individual_chars && old_line && new_line) 200 if (individual_chars && old_line && new_line)
199 lcs = longest_common_subsequence(old_line, new_line); 201 lcs = longest_common_subsequence(old_line, new_line);
200 html("<tr>"); 202 html("<tr>\n");
201 if (old_line_no > 0) 203 if (old_line_no > 0) {
202 htmlf("<td class='lineno'>%d</td><td class='%s'>", 204 struct diff_filespec *old_file = cgit_get_current_old_file();
203 old_line_no, class); 205 char *lineno_str = fmt("n%d", old_line_no);
204 else if (old_line) 206 char *id_str = fmt("%s#%s", is_null_sha1(old_file->sha1)?"HEAD":sha1_to_hex(old_rev_sha1), lineno_str);
207 html("<td class='lineno'><a class='no' href='");
208 html(cgit_fileurl(ctx.repo->url, "tree", old_file->path, id_str));
209 htmlf("' id='%s' name='%s'>%s</a>", lineno_str, lineno_str, lineno_str + 1);
210 html("</td>");
211 htmlf("<td class='%s'>", class);
212 } else if (old_line)
205 htmlf("<td class='lineno'></td><td class='%s'>", class); 213 htmlf("<td class='lineno'></td><td class='%s'>", class);
206 else 214 else
207 htmlf("<td class='lineno'></td><td class='%s_dark'>", class); 215 htmlf("<td class='lineno'></td><td class='%s_dark'>", class);
208 if (old_line) { 216 if (old_line) {
209 if (lcs) 217 if (lcs)
210 print_part_with_lcs("del", old_line, lcs); 218 print_part_with_lcs("del", old_line, lcs);
211 else 219 else
212 html_txt(old_line); 220 html_txt(old_line);
213 } 221 }
214 222
223 html("</td>\n");
224 if (new_line_no > 0) {
225 struct diff_filespec *new_file = cgit_get_current_new_file();
226 char *lineno_str = fmt("n%d", new_line_no);
227 char *id_str = fmt("%s#%s", is_null_sha1(new_file->sha1)?"HEAD":sha1_to_hex(new_rev_sha1), lineno_str);
228 html("<td class='lineno'><a class='no' href='");
229 html(cgit_fileurl(ctx.repo->url, "tree", new_file->path, id_str));
230 htmlf("' id='%s' name='%s'>%s</a>", lineno_str, lineno_str, lineno_str + 1);
215 html("</td>"); 231 html("</td>");
216 if (new_line_no > 0) 232 htmlf("<td class='%s'>", class);
217 htmlf("<td class='lineno'>%d</td><td class='%s'>", 233 } else if (new_line)
218 new_line_no, class);
219 else if (new_line)
220 htmlf("<td class='lineno'></td><td class='%s'>", class); 234 htmlf("<td class='lineno'></td><td class='%s'>", class);
221 else 235 else
222 htmlf("<td class='lineno'></td><td class='%s_dark'>", class); 236 htmlf("<td class='lineno'></td><td class='%s_dark'>", class);
223 if (new_line) { 237 if (new_line) {
224 if (lcs) 238 if (lcs)
225 print_part_with_lcs("add", new_line, lcs); 239 print_part_with_lcs("add", new_line, lcs);
226 else 240 else
227 html_txt(new_line); 241 html_txt(new_line);
228 } 242 }
229 243
230 html("</td></tr>"); 244 html("</td></tr>");
231 if (lcs) 245 if (lcs)
232 free(lcs); 246 free(lcs);
233 if (new_line) 247 if (new_line)
234 free(new_line); 248 free(new_line);
235 if (old_line) 249 if (old_line)
236 free(old_line); 250 free(old_line);
237} 251}
238 252
239static void print_deferred_old_lines() 253static void print_deferred_old_lines()
240{ 254{
241 struct deferred_lines *iter_old, *tmp; 255 struct deferred_lines *iter_old, *tmp;
242 iter_old = deferred_old; 256 iter_old = deferred_old;
243 while (iter_old) { 257 while (iter_old) {
244 print_ssdiff_line("del", iter_old->line_no, 258 print_ssdiff_line("del", iter_old->line_no,
245 iter_old->line, -1, NULL, 0); 259 iter_old->line, -1, NULL, 0);
246 tmp = iter_old->next; 260 tmp = iter_old->next;
247 free(iter_old); 261 free(iter_old);
248 iter_old = tmp; 262 iter_old = tmp;
249 } 263 }
250} 264}
251 265
252static void print_deferred_new_lines() 266static void print_deferred_new_lines()
253{ 267{
254 struct deferred_lines *iter_new, *tmp; 268 struct deferred_lines *iter_new, *tmp;
255 iter_new = deferred_new; 269 iter_new = deferred_new;
256 while (iter_new) { 270 while (iter_new) {
257 print_ssdiff_line("add", -1, NULL, 271 print_ssdiff_line("add", -1, NULL,
258 iter_new->line_no, iter_new->line, 0); 272 iter_new->line_no, iter_new->line, 0);
259 tmp = iter_new->next; 273 tmp = iter_new->next;
260 free(iter_new); 274 free(iter_new);
261 iter_new = tmp; 275 iter_new = tmp;
262 } 276 }
263} 277}
264 278
265static void print_deferred_changed_lines() 279static void print_deferred_changed_lines()
266{ 280{
267 struct deferred_lines *iter_old, *iter_new, *tmp; 281 struct deferred_lines *iter_old, *iter_new, *tmp;