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'>", class);
114 htmlf("<td class='lineno'></td><td class='%s_dark'>", class);
117 old_line = replace_tabs(old_line + 1);
125 htmlf("<td class='lineno'>%d</td><td class='%s'>",
128 htmlf("<td class='lineno'></td><td class='%s'>", class);
130 htmlf("<td class='lineno'></td><td class='%s_dark'>", class);
133 new_line = replace_tabs(new_line + 1);
141 static void print_deferred_old_lines()
143 struct deferred_lines *iter_old, *tmp;
145 iter_old = deferred_old;
147 print_ssdiff_line("del", iter_old->line_no,
148 iter_old->line, -1, NULL);
149 tmp = iter_old->next;
155 static void print_deferred_new_lines()
157 struct deferred_lines *iter_new, *tmp;
159 iter_new = deferred_new;
161 print_ssdiff_line("add", -1, NULL, iter_new->line_no,
163 tmp = iter_new->next;
169 static void print_deferred_changed_lines()
171 struct deferred_lines *iter_old, *iter_new, *tmp;
173 iter_old = deferred_old;
174 iter_new = deferred_new;
175 while (iter_old || iter_new) {
176 if (iter_old && iter_new)
177 print_ssdiff_line("changed", iter_old->line_no,
179 iter_new->line_no, iter_new->line);
181 print_ssdiff_line("changed", iter_old->line_no,
182 iter_old->line, -1, NULL);
184 print_ssdiff_line("changed", -1, NULL,
185 iter_new->line_no, iter_new->line);
188 tmp = iter_old->next;
194 tmp = iter_new->next;
201 void cgit_ssdiff_print_deferred_lines()
203 if (!deferred_old && !deferred_new)
206 if (deferred_old && !deferred_new)
207 print_deferred_old_lines();
208 else if (!deferred_old && deferred_new)
209 print_deferred_new_lines();
211 print_deferred_changed_lines();
213 deferred_old = deferred_old_last = NULL;
214 deferred_new = deferred_new_last = NULL;
218 * print a single line returned from xdiff
220 void cgit_ssdiff_line_cb(char *line, int len)
222 char c = line[len - 1];
224 line[len - 1] = '\0';
226 if (line[0] == '@') {
227 current_old_line = line_from_hunk(line, '-');
228 current_new_line = line_from_hunk(line, '+');
231 if (line[0] == ' ') {
232 if (deferred_old || deferred_new)
233 cgit_ssdiff_print_deferred_lines();
234 print_ssdiff_line("ctx", current_old_line, line,
235 current_new_line, line);
236 current_old_line += 1;
237 current_new_line += 1;
238 } else if (line[0] == '+') {
239 deferred_new_add(line, current_new_line);
240 current_new_line += 1;
241 } else if (line[0] == '-') {
242 deferred_old_add(line, current_old_line);
243 current_old_line += 1;
244 } else if (line[0] == '@') {
245 html("<tr><td colspan='4' class='hunk'>");
249 html("<tr><td colspan='4' class='ctx'>");
256 void cgit_ssdiff_header_begin()
258 current_old_line = -1;
259 current_new_line = -1;
260 html("<tr><td class='space' colspan='4'><div></div></td></tr>");
261 html("<tr><td class='head' colspan='4'>");
264 void cgit_ssdiff_header_end()
269 void cgit_ssdiff_footer()
271 if (deferred_old || deferred_new)
272 cgit_ssdiff_print_deferred_lines();
273 html("<tr><td class='foot' colspan='4'></td></tr>");