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 int line_from_hunk(char *line, char type)
23 buf1 = strchr(line, type);
27 buf2 = strchr(buf1, ',');
31 buf2 = xmalloc(len + 1);
32 strncpy(buf2, buf1, len);
39 static char *replace_tabs(char *line)
41 char *prev_buf = line;
43 int linelen = strlen(line);
55 for (i = 0; i < linelen; i++)
58 result = xmalloc(linelen + n_tabs * 8 + 1);
62 cur_buf = strchr(prev_buf, '\t');
64 strcat(result, prev_buf);
68 strncat(result, spaces, 8 - (strlen(result) % 8));
69 strncat(result, prev_buf, cur_buf - prev_buf);
71 prev_buf = cur_buf + 1;
76 static void deferred_old_add(char *line, int line_no)
78 struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines));
79 item->line = xstrdup(line);
80 item->line_no = line_no;
83 deferred_old_last->next = item;
84 deferred_old_last = item;
86 deferred_old = deferred_old_last = item;
90 static void deferred_new_add(char *line, int line_no)
92 struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines));
93 item->line = xstrdup(line);
94 item->line_no = line_no;
97 deferred_new_last->next = item;
98 deferred_new_last = item;
100 deferred_new = deferred_new_last = item;
104 static void print_ssdiff_line(char *class, int old_line_no, char *old_line,
105 int new_line_no, char *new_line)
109 htmlf("<td class='lineno'>%d</td><td class='%s'>",
112 htmlf("<td class='lineno'></td><td class='%s_dark'>", class);
115 old_line = replace_tabs(old_line + 1);
123 htmlf("<td class='lineno'>%d</td><td class='%s'>",
126 htmlf("<td class='lineno'></td><td class='%s_dark'>", class);
129 new_line = replace_tabs(new_line + 1);
137 static void print_deferred_old_lines()
139 struct deferred_lines *iter_old, *tmp;
141 iter_old = deferred_old;
143 print_ssdiff_line("del", iter_old->line_no,
144 iter_old->line, -1, NULL);
145 tmp = iter_old->next;
151 static void print_deferred_new_lines()
153 struct deferred_lines *iter_new, *tmp;
155 iter_new = deferred_new;
157 print_ssdiff_line("add", -1, NULL, iter_new->line_no,
159 tmp = iter_new->next;
165 static void print_deferred_changed_lines()
167 struct deferred_lines *iter_old, *iter_new, *tmp;
169 iter_old = deferred_old;
170 iter_new = deferred_new;
171 while (iter_old || iter_new) {
172 if (iter_old && iter_new)
173 print_ssdiff_line("changed", iter_old->line_no,
175 iter_new->line_no, iter_new->line);
177 print_ssdiff_line("changed", iter_old->line_no,
178 iter_old->line, -1, NULL);
180 print_ssdiff_line("changed", -1, NULL,
181 iter_new->line_no, iter_new->line);
184 tmp = iter_old->next;
190 tmp = iter_new->next;
197 void cgit_ssdiff_print_deferred_lines()
199 if (!deferred_old && !deferred_new)
202 if (deferred_old && !deferred_new)
203 print_deferred_old_lines();
204 else if (!deferred_old && deferred_new)
205 print_deferred_new_lines();
207 print_deferred_changed_lines();
209 deferred_old = deferred_old_last = NULL;
210 deferred_new = deferred_new_last = NULL;
214 * print a single line returned from xdiff
216 void cgit_ssdiff_line_cb(char *line, int len)
218 char c = line[len - 1];
220 line[len - 1] = '\0';
222 if (line[0] == '@') {
223 current_old_line = line_from_hunk(line, '-');
224 current_new_line = line_from_hunk(line, '+');
227 if (line[0] == ' ') {
228 if (deferred_old || deferred_new)
229 cgit_ssdiff_print_deferred_lines();
230 print_ssdiff_line("ctx", current_old_line, line,
231 current_new_line, line);
232 current_old_line += 1;
233 current_new_line += 1;
234 } else if (line[0] == '+') {
235 deferred_new_add(line, current_new_line);
236 current_new_line += 1;
237 } else if (line[0] == '-') {
238 deferred_old_add(line, current_old_line);
239 current_old_line += 1;
240 } else if (line[0] == '@') {
241 html("<tr><td colspan='4' class='hunk'>");
245 html("<tr><td colspan='4' class='ctx'>");
252 void cgit_ssdiff_header_begin()
254 current_old_line = 0;
255 current_new_line = 0;
256 html("<tr><td class='space' colspan='4'><div></div></td></tr>");
257 html("<tr><td class='head' colspan='4'>");
260 void cgit_ssdiff_header_end()
265 void cgit_ssdiff_footer()
267 if (deferred_old || deferred_new)
268 cgit_ssdiff_print_deferred_lines();
269 html("<tr><td class='foot' colspan='4'></td></tr>");