author | Ragnar Ouchterlony <ragnar@lysator.liu.se> | 2009-09-15 17:44:37 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2009-09-16 18:17:56 (UTC) |
commit | 207cc34711039329b41345f716bf421a88a6fd0a (patch) (unidiff) | |
tree | 5fb56c7e5c105c9045e52abd971013270db23368 | |
parent | c358aa3dfebf4fc1f3005dd960aa5c1c020eed76 (diff) | |
download | cgit-207cc34711039329b41345f716bf421a88a6fd0a.zip cgit-207cc34711039329b41345f716bf421a88a6fd0a.tar.gz cgit-207cc34711039329b41345f716bf421a88a6fd0a.tar.bz2 |
Polishing of how the side-by-side diff looks.
Aligned all different files, so that all side-by-side tables look
the same. Also made sure that the tables take up the whole browser
width.
Also various changes to the css to make things easier on the eye.
Signed-off-by: Ragnar Ouchterlony <ragnar@lysator.liu.se>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | cgit.css | 66 | ||||
-rw-r--r-- | ui-diff.c | 27 | ||||
-rw-r--r-- | ui-ssdiff.c | 30 | ||||
-rw-r--r-- | ui-ssdiff.h | 3 |
4 files changed, 96 insertions, 30 deletions
@@ -1,638 +1,692 @@ | |||
1 | body, table, form { | 1 | body, table, form { |
2 | padding: 0em; | 2 | padding: 0em; |
3 | margin: 0em; | 3 | margin: 0em; |
4 | } | 4 | } |
5 | 5 | ||
6 | body { | 6 | body { |
7 | font-family: sans-serif; | 7 | font-family: sans-serif; |
8 | font-size: 10pt; | 8 | font-size: 10pt; |
9 | color: #333; | 9 | color: #333; |
10 | background: white; | 10 | background: white; |
11 | padding: 4px; | 11 | padding: 4px; |
12 | } | 12 | } |
13 | 13 | ||
14 | a { | 14 | a { |
15 | color: blue; | 15 | color: blue; |
16 | text-decoration: none; | 16 | text-decoration: none; |
17 | } | 17 | } |
18 | 18 | ||
19 | a:hover { | 19 | a:hover { |
20 | text-decoration: underline; | 20 | text-decoration: underline; |
21 | } | 21 | } |
22 | 22 | ||
23 | table { | 23 | table { |
24 | border-collapse: collapse; | 24 | border-collapse: collapse; |
25 | } | 25 | } |
26 | 26 | ||
27 | table#header { | 27 | table#header { |
28 | width: 100%; | 28 | width: 100%; |
29 | margin-bottom: 1em; | 29 | margin-bottom: 1em; |
30 | } | 30 | } |
31 | 31 | ||
32 | table#header td.logo { | 32 | table#header td.logo { |
33 | width: 96px; | 33 | width: 96px; |
34 | } | 34 | } |
35 | 35 | ||
36 | table#header td.main { | 36 | table#header td.main { |
37 | font-size: 250%; | 37 | font-size: 250%; |
38 | padding-left: 10px; | 38 | padding-left: 10px; |
39 | white-space: nowrap; | 39 | white-space: nowrap; |
40 | } | 40 | } |
41 | 41 | ||
42 | table#header td.main a { | 42 | table#header td.main a { |
43 | color: #000; | 43 | color: #000; |
44 | } | 44 | } |
45 | 45 | ||
46 | table#header td.form { | 46 | table#header td.form { |
47 | text-align: right; | 47 | text-align: right; |
48 | vertical-align: bottom; | 48 | vertical-align: bottom; |
49 | padding-right: 1em; | 49 | padding-right: 1em; |
50 | padding-bottom: 2px; | 50 | padding-bottom: 2px; |
51 | white-space: nowrap; | 51 | white-space: nowrap; |
52 | } | 52 | } |
53 | 53 | ||
54 | table#header td.form form, | 54 | table#header td.form form, |
55 | table#header td.form input, | 55 | table#header td.form input, |
56 | table#header td.form select { | 56 | table#header td.form select { |
57 | font-size: 90%; | 57 | font-size: 90%; |
58 | } | 58 | } |
59 | 59 | ||
60 | table#header td.sub { | 60 | table#header td.sub { |
61 | color: #777; | 61 | color: #777; |
62 | border-top: solid 1px #ccc; | 62 | border-top: solid 1px #ccc; |
63 | padding-left: 10px; | 63 | padding-left: 10px; |
64 | } | 64 | } |
65 | 65 | ||
66 | table.tabs { | 66 | table.tabs { |
67 | /* border-bottom: solid 2px #ccc; */ | 67 | /* border-bottom: solid 2px #ccc; */ |
68 | border-collapse: collapse; | 68 | border-collapse: collapse; |
69 | margin-top: 2em; | 69 | margin-top: 2em; |
70 | margin-bottom: 0px; | 70 | margin-bottom: 0px; |
71 | width: 100%; | 71 | width: 100%; |
72 | } | 72 | } |
73 | 73 | ||
74 | table.tabs td { | 74 | table.tabs td { |
75 | padding: 0px 1em; | 75 | padding: 0px 1em; |
76 | vertical-align: bottom; | 76 | vertical-align: bottom; |
77 | } | 77 | } |
78 | 78 | ||
79 | table.tabs td a { | 79 | table.tabs td a { |
80 | padding: 2px 0.75em; | 80 | padding: 2px 0.75em; |
81 | color: #777; | 81 | color: #777; |
82 | font-size: 110%; | 82 | font-size: 110%; |
83 | } | 83 | } |
84 | 84 | ||
85 | table.tabs td a.active { | 85 | table.tabs td a.active { |
86 | color: #000; | 86 | color: #000; |
87 | background-color: #ccc; | 87 | background-color: #ccc; |
88 | } | 88 | } |
89 | 89 | ||
90 | table.tabs td.form { | 90 | table.tabs td.form { |
91 | text-align: right; | 91 | text-align: right; |
92 | } | 92 | } |
93 | 93 | ||
94 | table.tabs td.form form { | 94 | table.tabs td.form form { |
95 | padding-bottom: 2px; | 95 | padding-bottom: 2px; |
96 | font-size: 90%; | 96 | font-size: 90%; |
97 | white-space: nowrap; | 97 | white-space: nowrap; |
98 | } | 98 | } |
99 | 99 | ||
100 | table.tabs td.form input, | 100 | table.tabs td.form input, |
101 | table.tabs td.form select { | 101 | table.tabs td.form select { |
102 | font-size: 90%; | 102 | font-size: 90%; |
103 | } | 103 | } |
104 | 104 | ||
105 | div.content { | 105 | div.content { |
106 | margin: 0px; | 106 | margin: 0px; |
107 | padding: 2em; | 107 | padding: 2em; |
108 | border-top: solid 3px #ccc; | 108 | border-top: solid 3px #ccc; |
109 | border-bottom: solid 3px #ccc; | 109 | border-bottom: solid 3px #ccc; |
110 | } | 110 | } |
111 | 111 | ||
112 | 112 | ||
113 | table.list { | 113 | table.list { |
114 | width: 100%; | 114 | width: 100%; |
115 | border: none; | 115 | border: none; |
116 | border-collapse: collapse; | 116 | border-collapse: collapse; |
117 | } | 117 | } |
118 | 118 | ||
119 | table.list tr { | 119 | table.list tr { |
120 | background: white; | 120 | background: white; |
121 | } | 121 | } |
122 | 122 | ||
123 | table.list tr.logheader { | 123 | table.list tr.logheader { |
124 | background: #eee; | 124 | background: #eee; |
125 | } | 125 | } |
126 | 126 | ||
127 | table.list tr:hover { | 127 | table.list tr:hover { |
128 | background: #eee; | 128 | background: #eee; |
129 | } | 129 | } |
130 | 130 | ||
131 | table.list tr.nohover:hover { | 131 | table.list tr.nohover:hover { |
132 | background: white; | 132 | background: white; |
133 | } | 133 | } |
134 | 134 | ||
135 | table.list th { | 135 | table.list th { |
136 | font-weight: bold; | 136 | font-weight: bold; |
137 | /* color: #888; | 137 | /* color: #888; |
138 | border-top: dashed 1px #888; | 138 | border-top: dashed 1px #888; |
139 | border-bottom: dashed 1px #888; | 139 | border-bottom: dashed 1px #888; |
140 | */ | 140 | */ |
141 | padding: 0.1em 0.5em 0.05em 0.5em; | 141 | padding: 0.1em 0.5em 0.05em 0.5em; |
142 | vertical-align: baseline; | 142 | vertical-align: baseline; |
143 | } | 143 | } |
144 | 144 | ||
145 | table.list td { | 145 | table.list td { |
146 | border: none; | 146 | border: none; |
147 | padding: 0.1em 0.5em 0.1em 0.5em; | 147 | padding: 0.1em 0.5em 0.1em 0.5em; |
148 | } | 148 | } |
149 | 149 | ||
150 | table.list td.logsubject { | 150 | table.list td.logsubject { |
151 | font-family: monospace; | 151 | font-family: monospace; |
152 | font-weight: bold; | 152 | font-weight: bold; |
153 | } | 153 | } |
154 | 154 | ||
155 | table.list td.logmsg { | 155 | table.list td.logmsg { |
156 | font-family: monospace; | 156 | font-family: monospace; |
157 | white-space: pre; | 157 | white-space: pre; |
158 | padding: 1em 0.5em 2em 0.5em; | 158 | padding: 1em 0.5em 2em 0.5em; |
159 | } | 159 | } |
160 | 160 | ||
161 | table.list td a { | 161 | table.list td a { |
162 | color: black; | 162 | color: black; |
163 | } | 163 | } |
164 | 164 | ||
165 | table.list td a:hover { | 165 | table.list td a:hover { |
166 | color: #00f; | 166 | color: #00f; |
167 | } | 167 | } |
168 | 168 | ||
169 | img { | 169 | img { |
170 | border: none; | 170 | border: none; |
171 | } | 171 | } |
172 | 172 | ||
173 | input#switch-btn { | 173 | input#switch-btn { |
174 | margin: 2px 0px 0px 0px; | 174 | margin: 2px 0px 0px 0px; |
175 | } | 175 | } |
176 | 176 | ||
177 | td#sidebar input.txt { | 177 | td#sidebar input.txt { |
178 | width: 100%; | 178 | width: 100%; |
179 | margin: 2px 0px 0px 0px; | 179 | margin: 2px 0px 0px 0px; |
180 | } | 180 | } |
181 | 181 | ||
182 | table#grid { | 182 | table#grid { |
183 | margin: 0px; | 183 | margin: 0px; |
184 | } | 184 | } |
185 | 185 | ||
186 | td#content { | 186 | td#content { |
187 | vertical-align: top; | 187 | vertical-align: top; |
188 | padding: 1em 2em 1em 1em; | 188 | padding: 1em 2em 1em 1em; |
189 | border: none; | 189 | border: none; |
190 | } | 190 | } |
191 | 191 | ||
192 | div#summary { | 192 | div#summary { |
193 | vertical-align: top; | 193 | vertical-align: top; |
194 | margin-bottom: 1em; | 194 | margin-bottom: 1em; |
195 | } | 195 | } |
196 | 196 | ||
197 | table#downloads { | 197 | table#downloads { |
198 | float: right; | 198 | float: right; |
199 | border-collapse: collapse; | 199 | border-collapse: collapse; |
200 | border: solid 1px #777; | 200 | border: solid 1px #777; |
201 | margin-left: 0.5em; | 201 | margin-left: 0.5em; |
202 | margin-bottom: 0.5em; | 202 | margin-bottom: 0.5em; |
203 | } | 203 | } |
204 | 204 | ||
205 | table#downloads th { | 205 | table#downloads th { |
206 | background-color: #ccc; | 206 | background-color: #ccc; |
207 | } | 207 | } |
208 | 208 | ||
209 | div#blob { | 209 | div#blob { |
210 | border: solid 1px black; | 210 | border: solid 1px black; |
211 | } | 211 | } |
212 | 212 | ||
213 | div.error { | 213 | div.error { |
214 | color: red; | 214 | color: red; |
215 | font-weight: bold; | 215 | font-weight: bold; |
216 | margin: 1em 2em; | 216 | margin: 1em 2em; |
217 | } | 217 | } |
218 | 218 | ||
219 | a.ls-blob, a.ls-dir, a.ls-mod { | 219 | a.ls-blob, a.ls-dir, a.ls-mod { |
220 | font-family: monospace; | 220 | font-family: monospace; |
221 | } | 221 | } |
222 | 222 | ||
223 | td.ls-size { | 223 | td.ls-size { |
224 | text-align: right; | 224 | text-align: right; |
225 | font-family: monospace; | 225 | font-family: monospace; |
226 | width: 10em; | 226 | width: 10em; |
227 | } | 227 | } |
228 | 228 | ||
229 | td.ls-mode { | 229 | td.ls-mode { |
230 | font-family: monospace; | 230 | font-family: monospace; |
231 | width: 10em; | 231 | width: 10em; |
232 | } | 232 | } |
233 | 233 | ||
234 | table.blob { | 234 | table.blob { |
235 | margin-top: 0.5em; | 235 | margin-top: 0.5em; |
236 | border-top: solid 1px black; | 236 | border-top: solid 1px black; |
237 | } | 237 | } |
238 | 238 | ||
239 | table.blob td.lines { | 239 | table.blob td.lines { |
240 | margin: 0; padding: 0 0 0 0.5em; | 240 | margin: 0; padding: 0 0 0 0.5em; |
241 | vertical-align: top; | 241 | vertical-align: top; |
242 | color: black; | 242 | color: black; |
243 | } | 243 | } |
244 | 244 | ||
245 | table.blob td.linenumbers { | 245 | table.blob td.linenumbers { |
246 | margin: 0; padding: 0 0.5em 0 0.5em; | 246 | margin: 0; padding: 0 0.5em 0 0.5em; |
247 | vertical-align: top; | 247 | vertical-align: top; |
248 | text-align: right; | 248 | text-align: right; |
249 | border-right: 1px solid gray; | 249 | border-right: 1px solid gray; |
250 | } | 250 | } |
251 | 251 | ||
252 | table.blob pre { | 252 | table.blob pre { |
253 | padding: 0; margin: 0; | 253 | padding: 0; margin: 0; |
254 | } | 254 | } |
255 | 255 | ||
256 | table.blob a.no { | 256 | table.blob a.no { |
257 | color: gray; | 257 | color: gray; |
258 | text-align: right; | 258 | text-align: right; |
259 | text-decoration: none; | 259 | text-decoration: none; |
260 | } | 260 | } |
261 | 261 | ||
262 | table.blob a.no a:hover { | 262 | table.blob a.no a:hover { |
263 | color: black; | 263 | color: black; |
264 | } | 264 | } |
265 | 265 | ||
266 | table.bin-blob { | 266 | table.bin-blob { |
267 | margin-top: 0.5em; | 267 | margin-top: 0.5em; |
268 | border: solid 1px black; | 268 | border: solid 1px black; |
269 | } | 269 | } |
270 | 270 | ||
271 | table.bin-blob th { | 271 | table.bin-blob th { |
272 | font-family: monospace; | 272 | font-family: monospace; |
273 | white-space: pre; | 273 | white-space: pre; |
274 | border: solid 1px #777; | 274 | border: solid 1px #777; |
275 | padding: 0.5em 1em; | 275 | padding: 0.5em 1em; |
276 | } | 276 | } |
277 | 277 | ||
278 | table.bin-blob td { | 278 | table.bin-blob td { |
279 | font-family: monospace; | 279 | font-family: monospace; |
280 | white-space: pre; | 280 | white-space: pre; |
281 | border-left: solid 1px #777; | 281 | border-left: solid 1px #777; |
282 | padding: 0em 1em; | 282 | padding: 0em 1em; |
283 | } | 283 | } |
284 | 284 | ||
285 | table.nowrap td { | 285 | table.nowrap td { |
286 | white-space: nowrap; | 286 | white-space: nowrap; |
287 | } | 287 | } |
288 | 288 | ||
289 | table.commit-info { | 289 | table.commit-info { |
290 | border-collapse: collapse; | 290 | border-collapse: collapse; |
291 | margin-top: 1.5em; | 291 | margin-top: 1.5em; |
292 | } | 292 | } |
293 | 293 | ||
294 | table.commit-info th { | 294 | table.commit-info th { |
295 | text-align: left; | 295 | text-align: left; |
296 | font-weight: normal; | 296 | font-weight: normal; |
297 | padding: 0.1em 1em 0.1em 0.1em; | 297 | padding: 0.1em 1em 0.1em 0.1em; |
298 | vertical-align: top; | 298 | vertical-align: top; |
299 | } | 299 | } |
300 | 300 | ||
301 | table.commit-info td { | 301 | table.commit-info td { |
302 | font-weight: normal; | 302 | font-weight: normal; |
303 | padding: 0.1em 1em 0.1em 0.1em; | 303 | padding: 0.1em 1em 0.1em 0.1em; |
304 | } | 304 | } |
305 | 305 | ||
306 | div.commit-subject { | 306 | div.commit-subject { |
307 | font-weight: bold; | 307 | font-weight: bold; |
308 | font-size: 125%; | 308 | font-size: 125%; |
309 | margin: 1.5em 0em 0.5em 0em; | 309 | margin: 1.5em 0em 0.5em 0em; |
310 | padding: 0em; | 310 | padding: 0em; |
311 | } | 311 | } |
312 | 312 | ||
313 | div.commit-msg { | 313 | div.commit-msg { |
314 | white-space: pre; | 314 | white-space: pre; |
315 | font-family: monospace; | 315 | font-family: monospace; |
316 | } | 316 | } |
317 | 317 | ||
318 | div.diffstat-header { | 318 | div.diffstat-header { |
319 | font-weight: bold; | 319 | font-weight: bold; |
320 | padding-top: 1.5em; | 320 | padding-top: 1.5em; |
321 | } | 321 | } |
322 | 322 | ||
323 | table.diffstat { | 323 | table.diffstat { |
324 | border-collapse: collapse; | 324 | border-collapse: collapse; |
325 | border: solid 1px #aaa; | 325 | border: solid 1px #aaa; |
326 | background-color: #eee; | 326 | background-color: #eee; |
327 | } | 327 | } |
328 | 328 | ||
329 | table.diffstat th { | 329 | table.diffstat th { |
330 | font-weight: normal; | 330 | font-weight: normal; |
331 | text-align: left; | 331 | text-align: left; |
332 | text-decoration: underline; | 332 | text-decoration: underline; |
333 | padding: 0.1em 1em 0.1em 0.1em; | 333 | padding: 0.1em 1em 0.1em 0.1em; |
334 | font-size: 100%; | 334 | font-size: 100%; |
335 | } | 335 | } |
336 | 336 | ||
337 | table.diffstat td { | 337 | table.diffstat td { |
338 | padding: 0.2em 0.2em 0.1em 0.1em; | 338 | padding: 0.2em 0.2em 0.1em 0.1em; |
339 | font-size: 100%; | 339 | font-size: 100%; |
340 | border: none; | 340 | border: none; |
341 | } | 341 | } |
342 | 342 | ||
343 | table.diffstat td.mode { | 343 | table.diffstat td.mode { |
344 | white-space: nowrap; | 344 | white-space: nowrap; |
345 | } | 345 | } |
346 | 346 | ||
347 | table.diffstat td span.modechange { | 347 | table.diffstat td span.modechange { |
348 | padding-left: 1em; | 348 | padding-left: 1em; |
349 | color: red; | 349 | color: red; |
350 | } | 350 | } |
351 | 351 | ||
352 | table.diffstat td.add a { | 352 | table.diffstat td.add a { |
353 | color: green; | 353 | color: green; |
354 | } | 354 | } |
355 | 355 | ||
356 | table.diffstat td.del a { | 356 | table.diffstat td.del a { |
357 | color: red; | 357 | color: red; |
358 | } | 358 | } |
359 | 359 | ||
360 | table.diffstat td.upd a { | 360 | table.diffstat td.upd a { |
361 | color: blue; | 361 | color: blue; |
362 | } | 362 | } |
363 | 363 | ||
364 | table.diffstat td.graph { | 364 | table.diffstat td.graph { |
365 | width: 500px; | 365 | width: 500px; |
366 | vertical-align: middle; | 366 | vertical-align: middle; |
367 | } | 367 | } |
368 | 368 | ||
369 | table.diffstat td.graph table { | 369 | table.diffstat td.graph table { |
370 | border: none; | 370 | border: none; |
371 | } | 371 | } |
372 | 372 | ||
373 | table.diffstat td.graph td { | 373 | table.diffstat td.graph td { |
374 | padding: 0px; | 374 | padding: 0px; |
375 | border: 0px; | 375 | border: 0px; |
376 | height: 7pt; | 376 | height: 7pt; |
377 | } | 377 | } |
378 | 378 | ||
379 | table.diffstat td.graph td.add { | 379 | table.diffstat td.graph td.add { |
380 | background-color: #5c5; | 380 | background-color: #5c5; |
381 | } | 381 | } |
382 | 382 | ||
383 | table.diffstat td.graph td.rem { | 383 | table.diffstat td.graph td.rem { |
384 | background-color: #c55; | 384 | background-color: #c55; |
385 | } | 385 | } |
386 | 386 | ||
387 | div.diffstat-summary { | 387 | div.diffstat-summary { |
388 | color: #888; | 388 | color: #888; |
389 | padding-top: 0.5em; | 389 | padding-top: 0.5em; |
390 | } | 390 | } |
391 | 391 | ||
392 | table.diff { | 392 | table.diff { |
393 | width: 100%; | 393 | width: 100%; |
394 | } | 394 | } |
395 | 395 | ||
396 | table.diff td { | 396 | table.diff td { |
397 | font-family: monospace; | 397 | font-family: monospace; |
398 | white-space: pre; | 398 | white-space: pre; |
399 | } | 399 | } |
400 | 400 | ||
401 | table.diff td div.head { | 401 | table.diff td div.head { |
402 | font-weight: bold; | 402 | font-weight: bold; |
403 | margin-top: 1em; | 403 | margin-top: 1em; |
404 | color: black; | 404 | color: black; |
405 | } | 405 | } |
406 | 406 | ||
407 | table.diff td div.hunk { | 407 | table.diff td div.hunk { |
408 | color: #009; | 408 | color: #009; |
409 | } | 409 | } |
410 | 410 | ||
411 | table.diff td div.add { | 411 | table.diff td div.add { |
412 | color: green; | 412 | color: green; |
413 | } | 413 | } |
414 | 414 | ||
415 | table.diff td div.del { | 415 | table.diff td div.del { |
416 | color: red; | 416 | color: red; |
417 | } | 417 | } |
418 | 418 | ||
419 | .sha1 { | 419 | .sha1 { |
420 | font-family: monospace; | 420 | font-family: monospace; |
421 | font-size: 90%; | 421 | font-size: 90%; |
422 | } | 422 | } |
423 | 423 | ||
424 | .left { | 424 | .left { |
425 | text-align: left; | 425 | text-align: left; |
426 | } | 426 | } |
427 | 427 | ||
428 | .right { | 428 | .right { |
429 | text-align: right; | 429 | text-align: right; |
430 | } | 430 | } |
431 | 431 | ||
432 | table.list td.reposection { | 432 | table.list td.reposection { |
433 | font-style: italic; | 433 | font-style: italic; |
434 | color: #888; | 434 | color: #888; |
435 | } | 435 | } |
436 | 436 | ||
437 | a.button { | 437 | a.button { |
438 | font-size: 80%; | 438 | font-size: 80%; |
439 | padding: 0em 0.5em; | 439 | padding: 0em 0.5em; |
440 | } | 440 | } |
441 | 441 | ||
442 | a.primary { | 442 | a.primary { |
443 | font-size: 100%; | 443 | font-size: 100%; |
444 | } | 444 | } |
445 | 445 | ||
446 | a.secondary { | 446 | a.secondary { |
447 | font-size: 90%; | 447 | font-size: 90%; |
448 | } | 448 | } |
449 | 449 | ||
450 | td.toplevel-repo { | 450 | td.toplevel-repo { |
451 | 451 | ||
452 | } | 452 | } |
453 | 453 | ||
454 | table.list td.sublevel-repo { | 454 | table.list td.sublevel-repo { |
455 | padding-left: 1.5em; | 455 | padding-left: 1.5em; |
456 | } | 456 | } |
457 | 457 | ||
458 | div.pager { | 458 | div.pager { |
459 | text-align: center; | 459 | text-align: center; |
460 | margin: 1em 0em 0em 0em; | 460 | margin: 1em 0em 0em 0em; |
461 | } | 461 | } |
462 | 462 | ||
463 | div.pager a { | 463 | div.pager a { |
464 | color: #777; | 464 | color: #777; |
465 | margin: 0em 0.5em; | 465 | margin: 0em 0.5em; |
466 | } | 466 | } |
467 | 467 | ||
468 | span.age-mins { | 468 | span.age-mins { |
469 | font-weight: bold; | 469 | font-weight: bold; |
470 | color: #080; | 470 | color: #080; |
471 | } | 471 | } |
472 | 472 | ||
473 | span.age-hours { | 473 | span.age-hours { |
474 | color: #080; | 474 | color: #080; |
475 | } | 475 | } |
476 | 476 | ||
477 | span.age-days { | 477 | span.age-days { |
478 | color: #040; | 478 | color: #040; |
479 | } | 479 | } |
480 | 480 | ||
481 | span.age-weeks { | 481 | span.age-weeks { |
482 | color: #444; | 482 | color: #444; |
483 | } | 483 | } |
484 | 484 | ||
485 | span.age-months { | 485 | span.age-months { |
486 | color: #888; | 486 | color: #888; |
487 | } | 487 | } |
488 | 488 | ||
489 | span.age-years { | 489 | span.age-years { |
490 | color: #bbb; | 490 | color: #bbb; |
491 | } | 491 | } |
492 | div.footer { | 492 | div.footer { |
493 | margin-top: 0.5em; | 493 | margin-top: 0.5em; |
494 | text-align: center; | 494 | text-align: center; |
495 | font-size: 80%; | 495 | font-size: 80%; |
496 | color: #ccc; | 496 | color: #ccc; |
497 | } | 497 | } |
498 | a.branch-deco { | 498 | a.branch-deco { |
499 | margin: 0px 0.5em; | 499 | margin: 0px 0.5em; |
500 | padding: 0px 0.25em; | 500 | padding: 0px 0.25em; |
501 | background-color: #88ff88; | 501 | background-color: #88ff88; |
502 | border: solid 1px #007700; | 502 | border: solid 1px #007700; |
503 | } | 503 | } |
504 | a.tag-deco { | 504 | a.tag-deco { |
505 | margin: 0px 0.5em; | 505 | margin: 0px 0.5em; |
506 | padding: 0px 0.25em; | 506 | padding: 0px 0.25em; |
507 | background-color: #ffff88; | 507 | background-color: #ffff88; |
508 | border: solid 1px #777700; | 508 | border: solid 1px #777700; |
509 | } | 509 | } |
510 | a.remote-deco { | 510 | a.remote-deco { |
511 | margin: 0px 0.5em; | 511 | margin: 0px 0.5em; |
512 | padding: 0px 0.25em; | 512 | padding: 0px 0.25em; |
513 | background-color: #ccccff; | 513 | background-color: #ccccff; |
514 | border: solid 1px #000077; | 514 | border: solid 1px #000077; |
515 | } | 515 | } |
516 | a.deco { | 516 | a.deco { |
517 | margin: 0px 0.5em; | 517 | margin: 0px 0.5em; |
518 | padding: 0px 0.25em; | 518 | padding: 0px 0.25em; |
519 | background-color: #ff8888; | 519 | background-color: #ff8888; |
520 | border: solid 1px #770000; | 520 | border: solid 1px #770000; |
521 | } | 521 | } |
522 | 522 | ||
523 | div.commit-subject a { | 523 | div.commit-subject a { |
524 | margin-left: 1em; | 524 | margin-left: 1em; |
525 | font-size: 75%; | 525 | font-size: 75%; |
526 | } | 526 | } |
527 | 527 | ||
528 | table.stats { | 528 | table.stats { |
529 | border: solid 1px black; | 529 | border: solid 1px black; |
530 | border-collapse: collapse; | 530 | border-collapse: collapse; |
531 | } | 531 | } |
532 | 532 | ||
533 | table.stats th { | 533 | table.stats th { |
534 | text-align: left; | 534 | text-align: left; |
535 | padding: 1px 0.5em; | 535 | padding: 1px 0.5em; |
536 | background-color: #eee; | 536 | background-color: #eee; |
537 | border: solid 1px black; | 537 | border: solid 1px black; |
538 | } | 538 | } |
539 | 539 | ||
540 | table.stats td { | 540 | table.stats td { |
541 | text-align: right; | 541 | text-align: right; |
542 | padding: 1px 0.5em; | 542 | padding: 1px 0.5em; |
543 | border: solid 1px black; | 543 | border: solid 1px black; |
544 | } | 544 | } |
545 | 545 | ||
546 | table.stats td.total { | 546 | table.stats td.total { |
547 | font-weight: bold; | 547 | font-weight: bold; |
548 | text-align: left; | 548 | text-align: left; |
549 | } | 549 | } |
550 | 550 | ||
551 | table.stats td.sum { | 551 | table.stats td.sum { |
552 | color: #c00; | 552 | color: #c00; |
553 | font-weight: bold; | 553 | font-weight: bold; |
554 | /*background-color: #eee; */ | 554 | /*background-color: #eee; */ |
555 | } | 555 | } |
556 | 556 | ||
557 | table.stats td.left { | 557 | table.stats td.left { |
558 | text-align: left; | 558 | text-align: left; |
559 | } | 559 | } |
560 | 560 | ||
561 | table.vgraph { | 561 | table.vgraph { |
562 | border-collapse: separate; | 562 | border-collapse: separate; |
563 | border: solid 1px black; | 563 | border: solid 1px black; |
564 | height: 200px; | 564 | height: 200px; |
565 | } | 565 | } |
566 | 566 | ||
567 | table.vgraph th { | 567 | table.vgraph th { |
568 | background-color: #eee; | 568 | background-color: #eee; |
569 | font-weight: bold; | 569 | font-weight: bold; |
570 | border: solid 1px white; | 570 | border: solid 1px white; |
571 | padding: 1px 0.5em; | 571 | padding: 1px 0.5em; |
572 | } | 572 | } |
573 | 573 | ||
574 | table.vgraph td { | 574 | table.vgraph td { |
575 | vertical-align: bottom; | 575 | vertical-align: bottom; |
576 | padding: 0px 10px; | 576 | padding: 0px 10px; |
577 | } | 577 | } |
578 | 578 | ||
579 | table.vgraph div.bar { | 579 | table.vgraph div.bar { |
580 | background-color: #eee; | 580 | background-color: #eee; |
581 | } | 581 | } |
582 | 582 | ||
583 | table.hgraph { | 583 | table.hgraph { |
584 | border: solid 1px black; | 584 | border: solid 1px black; |
585 | width: 800px; | 585 | width: 800px; |
586 | } | 586 | } |
587 | 587 | ||
588 | table.hgraph th { | 588 | table.hgraph th { |
589 | background-color: #eee; | 589 | background-color: #eee; |
590 | font-weight: bold; | 590 | font-weight: bold; |
591 | border: solid 1px black; | 591 | border: solid 1px black; |
592 | padding: 1px 0.5em; | 592 | padding: 1px 0.5em; |
593 | } | 593 | } |
594 | 594 | ||
595 | table.hgraph td { | 595 | table.hgraph td { |
596 | vertical-align: center; | 596 | vertical-align: center; |
597 | padding: 2px 2px; | 597 | padding: 2px 2px; |
598 | } | 598 | } |
599 | 599 | ||
600 | table.hgraph div.bar { | 600 | table.hgraph div.bar { |
601 | background-color: #eee; | 601 | background-color: #eee; |
602 | height: 1em; | 602 | height: 1em; |
603 | } | 603 | } |
604 | 604 | ||
605 | table.ssdiff { | ||
606 | width: 100%; | ||
607 | } | ||
608 | |||
609 | table.ssdiff td { | ||
610 | font-size: 75%; | ||
611 | font-family: monospace; | ||
612 | white-space: pre; | ||
613 | padding: 1px 4px 1px 4px; | ||
614 | border-left: solid 1px #aaa; | ||
615 | border-right: solid 1px #aaa; | ||
616 | } | ||
617 | |||
605 | table.ssdiff td.add { | 618 | table.ssdiff td.add { |
606 | color: black; | 619 | color: black; |
607 | background: #afa; | 620 | background: #cfc; |
621 | min-width: 50%; | ||
608 | } | 622 | } |
609 | 623 | ||
610 | table.ssdiff td.add_dark { | 624 | table.ssdiff td.add_dark { |
611 | color: black; | 625 | color: black; |
612 | background: #9c9; | 626 | background: #aca; |
627 | min-width: 50%; | ||
613 | } | 628 | } |
614 | 629 | ||
615 | table.ssdiff td.del { | 630 | table.ssdiff td.del { |
616 | color: black; | 631 | color: black; |
617 | background: #faa; | 632 | background: #fcc; |
633 | min-width: 50%; | ||
618 | } | 634 | } |
619 | 635 | ||
620 | table.ssdiff td.del_dark { | 636 | table.ssdiff td.del_dark { |
621 | color: black; | 637 | color: black; |
622 | background: #c99; | 638 | background: #caa; |
639 | min-width: 50%; | ||
623 | } | 640 | } |
624 | 641 | ||
625 | table.ssdiff td.changed { | 642 | table.ssdiff td.changed { |
626 | color: black; | 643 | color: black; |
627 | background: #ffa; | 644 | background: #ffc; |
645 | min-width: 50%; | ||
628 | } | 646 | } |
629 | 647 | ||
630 | table.ssdiff td.changed_dark { | 648 | table.ssdiff td.changed_dark { |
631 | color: black; | 649 | color: black; |
632 | background: #cc9; | 650 | background: #cca; |
651 | min-width: 50%; | ||
652 | } | ||
653 | |||
654 | table.ssdiff td.lineno { | ||
655 | color: black; | ||
656 | background: #eee; | ||
657 | text-align: right; | ||
658 | width: 3em; | ||
659 | min-width: 3em; | ||
633 | } | 660 | } |
634 | 661 | ||
635 | table.ssdiff td.hunk { | 662 | table.ssdiff td.hunk { |
636 | color: #black; | 663 | color: #black; |
637 | background: #ccf; | 664 | background: #ccf; |
665 | border-top: solid 1px #aaa; | ||
666 | border-bottom: solid 1px #aaa; | ||
638 | } | 667 | } |
668 | |||
669 | table.ssdiff td.head { | ||
670 | border-top: solid 1px #aaa; | ||
671 | border-bottom: solid 1px #aaa; | ||
672 | } | ||
673 | |||
674 | table.ssdiff td.head div.head { | ||
675 | font-weight: bold; | ||
676 | color: black; | ||
677 | } | ||
678 | |||
679 | table.ssdiff td.foot { | ||
680 | border-top: solid 1px #aaa; | ||
681 | border-left: none; | ||
682 | border-right: none; | ||
683 | border-bottom: none; | ||
684 | } | ||
685 | |||
686 | table.ssdiff td.space { | ||
687 | border: none; | ||
688 | } | ||
689 | |||
690 | table.ssdiff td.space div { | ||
691 | min-height: 3em; | ||
692 | } \ No newline at end of file | ||
@@ -1,342 +1,347 @@ | |||
1 | /* ui-diff.c: show diff between two blobs | 1 | /* ui-diff.c: show diff between two blobs |
2 | * | 2 | * |
3 | * Copyright (C) 2006 Lars Hjemli | 3 | * Copyright (C) 2006 Lars Hjemli |
4 | * | 4 | * |
5 | * Licensed under GNU General Public License v2 | 5 | * Licensed under GNU General Public License v2 |
6 | * (see COPYING for full license text) | 6 | * (see COPYING for full license text) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | 11 | #include "ui-shared.h" |
12 | #include "ui-ssdiff.h" | 12 | #include "ui-ssdiff.h" |
13 | 13 | ||
14 | unsigned char old_rev_sha1[20]; | 14 | unsigned char old_rev_sha1[20]; |
15 | unsigned char new_rev_sha1[20]; | 15 | unsigned char new_rev_sha1[20]; |
16 | 16 | ||
17 | static int files, slots; | 17 | static int files, slots; |
18 | static int total_adds, total_rems, max_changes; | 18 | static int total_adds, total_rems, max_changes; |
19 | static int lines_added, lines_removed; | 19 | static int lines_added, lines_removed; |
20 | 20 | ||
21 | static struct fileinfo { | 21 | static struct fileinfo { |
22 | char status; | 22 | char status; |
23 | unsigned char old_sha1[20]; | 23 | unsigned char old_sha1[20]; |
24 | unsigned char new_sha1[20]; | 24 | unsigned char new_sha1[20]; |
25 | unsigned short old_mode; | 25 | unsigned short old_mode; |
26 | unsigned short new_mode; | 26 | unsigned short new_mode; |
27 | char *old_path; | 27 | char *old_path; |
28 | char *new_path; | 28 | char *new_path; |
29 | unsigned int added; | 29 | unsigned int added; |
30 | unsigned int removed; | 30 | unsigned int removed; |
31 | unsigned long old_size; | 31 | unsigned long old_size; |
32 | unsigned long new_size; | 32 | unsigned long new_size; |
33 | int binary:1; | 33 | int binary:1; |
34 | } *items; | 34 | } *items; |
35 | 35 | ||
36 | static int use_ssdiff = 0; | 36 | static int use_ssdiff = 0; |
37 | 37 | ||
38 | static void print_fileinfo(struct fileinfo *info) | 38 | static void print_fileinfo(struct fileinfo *info) |
39 | { | 39 | { |
40 | char *class; | 40 | char *class; |
41 | 41 | ||
42 | switch (info->status) { | 42 | switch (info->status) { |
43 | case DIFF_STATUS_ADDED: | 43 | case DIFF_STATUS_ADDED: |
44 | class = "add"; | 44 | class = "add"; |
45 | break; | 45 | break; |
46 | case DIFF_STATUS_COPIED: | 46 | case DIFF_STATUS_COPIED: |
47 | class = "cpy"; | 47 | class = "cpy"; |
48 | break; | 48 | break; |
49 | case DIFF_STATUS_DELETED: | 49 | case DIFF_STATUS_DELETED: |
50 | class = "del"; | 50 | class = "del"; |
51 | break; | 51 | break; |
52 | case DIFF_STATUS_MODIFIED: | 52 | case DIFF_STATUS_MODIFIED: |
53 | class = "upd"; | 53 | class = "upd"; |
54 | break; | 54 | break; |
55 | case DIFF_STATUS_RENAMED: | 55 | case DIFF_STATUS_RENAMED: |
56 | class = "mov"; | 56 | class = "mov"; |
57 | break; | 57 | break; |
58 | case DIFF_STATUS_TYPE_CHANGED: | 58 | case DIFF_STATUS_TYPE_CHANGED: |
59 | class = "typ"; | 59 | class = "typ"; |
60 | break; | 60 | break; |
61 | case DIFF_STATUS_UNKNOWN: | 61 | case DIFF_STATUS_UNKNOWN: |
62 | class = "unk"; | 62 | class = "unk"; |
63 | break; | 63 | break; |
64 | case DIFF_STATUS_UNMERGED: | 64 | case DIFF_STATUS_UNMERGED: |
65 | class = "stg"; | 65 | class = "stg"; |
66 | break; | 66 | break; |
67 | default: | 67 | default: |
68 | die("bug: unhandled diff status %c", info->status); | 68 | die("bug: unhandled diff status %c", info->status); |
69 | } | 69 | } |
70 | 70 | ||
71 | html("<tr>"); | 71 | html("<tr>"); |
72 | htmlf("<td class='mode'>"); | 72 | htmlf("<td class='mode'>"); |
73 | if (is_null_sha1(info->new_sha1)) { | 73 | if (is_null_sha1(info->new_sha1)) { |
74 | cgit_print_filemode(info->old_mode); | 74 | cgit_print_filemode(info->old_mode); |
75 | } else { | 75 | } else { |
76 | cgit_print_filemode(info->new_mode); | 76 | cgit_print_filemode(info->new_mode); |
77 | } | 77 | } |
78 | 78 | ||
79 | if (info->old_mode != info->new_mode && | 79 | if (info->old_mode != info->new_mode && |
80 | !is_null_sha1(info->old_sha1) && | 80 | !is_null_sha1(info->old_sha1) && |
81 | !is_null_sha1(info->new_sha1)) { | 81 | !is_null_sha1(info->new_sha1)) { |
82 | html("<span class='modechange'>["); | 82 | html("<span class='modechange'>["); |
83 | cgit_print_filemode(info->old_mode); | 83 | cgit_print_filemode(info->old_mode); |
84 | html("]</span>"); | 84 | html("]</span>"); |
85 | } | 85 | } |
86 | htmlf("</td><td class='%s'>", class); | 86 | htmlf("</td><td class='%s'>", class); |
87 | cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, ctx.qry.sha1, | 87 | cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, ctx.qry.sha1, |
88 | ctx.qry.sha2, info->new_path, 0); | 88 | ctx.qry.sha2, info->new_path, 0); |
89 | if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) | 89 | if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) |
90 | htmlf(" (%s from %s)", | 90 | htmlf(" (%s from %s)", |
91 | info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", | 91 | info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", |
92 | info->old_path); | 92 | info->old_path); |
93 | html("</td><td class='right'>"); | 93 | html("</td><td class='right'>"); |
94 | if (info->binary) { | 94 | if (info->binary) { |
95 | htmlf("bin</td><td class='graph'>%d -> %d bytes", | 95 | htmlf("bin</td><td class='graph'>%d -> %d bytes", |
96 | info->old_size, info->new_size); | 96 | info->old_size, info->new_size); |
97 | return; | 97 | return; |
98 | } | 98 | } |
99 | htmlf("%d", info->added + info->removed); | 99 | htmlf("%d", info->added + info->removed); |
100 | html("</td><td class='graph'>"); | 100 | html("</td><td class='graph'>"); |
101 | htmlf("<table summary='file diffstat' width='%d%%'><tr>", (max_changes > 100 ? 100 : max_changes)); | 101 | htmlf("<table summary='file diffstat' width='%d%%'><tr>", (max_changes > 100 ? 100 : max_changes)); |
102 | htmlf("<td class='add' style='width: %.1f%%;'/>", | 102 | htmlf("<td class='add' style='width: %.1f%%;'/>", |
103 | info->added * 100.0 / max_changes); | 103 | info->added * 100.0 / max_changes); |
104 | htmlf("<td class='rem' style='width: %.1f%%;'/>", | 104 | htmlf("<td class='rem' style='width: %.1f%%;'/>", |
105 | info->removed * 100.0 / max_changes); | 105 | info->removed * 100.0 / max_changes); |
106 | htmlf("<td class='none' style='width: %.1f%%;'/>", | 106 | htmlf("<td class='none' style='width: %.1f%%;'/>", |
107 | (max_changes - info->removed - info->added) * 100.0 / max_changes); | 107 | (max_changes - info->removed - info->added) * 100.0 / max_changes); |
108 | html("</tr></table></td></tr>\n"); | 108 | html("</tr></table></td></tr>\n"); |
109 | } | 109 | } |
110 | 110 | ||
111 | static void count_diff_lines(char *line, int len) | 111 | static void count_diff_lines(char *line, int len) |
112 | { | 112 | { |
113 | if (line && (len > 0)) { | 113 | if (line && (len > 0)) { |
114 | if (line[0] == '+') | 114 | if (line[0] == '+') |
115 | lines_added++; | 115 | lines_added++; |
116 | else if (line[0] == '-') | 116 | else if (line[0] == '-') |
117 | lines_removed++; | 117 | lines_removed++; |
118 | } | 118 | } |
119 | } | 119 | } |
120 | 120 | ||
121 | static void inspect_filepair(struct diff_filepair *pair) | 121 | static void inspect_filepair(struct diff_filepair *pair) |
122 | { | 122 | { |
123 | int binary = 0; | 123 | int binary = 0; |
124 | unsigned long old_size = 0; | 124 | unsigned long old_size = 0; |
125 | unsigned long new_size = 0; | 125 | unsigned long new_size = 0; |
126 | files++; | 126 | files++; |
127 | lines_added = 0; | 127 | lines_added = 0; |
128 | lines_removed = 0; | 128 | lines_removed = 0; |
129 | cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, &new_size, | 129 | cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, &new_size, |
130 | &binary, count_diff_lines); | 130 | &binary, count_diff_lines); |
131 | if (files >= slots) { | 131 | if (files >= slots) { |
132 | if (slots == 0) | 132 | if (slots == 0) |
133 | slots = 4; | 133 | slots = 4; |
134 | else | 134 | else |
135 | slots = slots * 2; | 135 | slots = slots * 2; |
136 | items = xrealloc(items, slots * sizeof(struct fileinfo)); | 136 | items = xrealloc(items, slots * sizeof(struct fileinfo)); |
137 | } | 137 | } |
138 | items[files-1].status = pair->status; | 138 | items[files-1].status = pair->status; |
139 | hashcpy(items[files-1].old_sha1, pair->one->sha1); | 139 | hashcpy(items[files-1].old_sha1, pair->one->sha1); |
140 | hashcpy(items[files-1].new_sha1, pair->two->sha1); | 140 | hashcpy(items[files-1].new_sha1, pair->two->sha1); |
141 | items[files-1].old_mode = pair->one->mode; | 141 | items[files-1].old_mode = pair->one->mode; |
142 | items[files-1].new_mode = pair->two->mode; | 142 | items[files-1].new_mode = pair->two->mode; |
143 | items[files-1].old_path = xstrdup(pair->one->path); | 143 | items[files-1].old_path = xstrdup(pair->one->path); |
144 | items[files-1].new_path = xstrdup(pair->two->path); | 144 | items[files-1].new_path = xstrdup(pair->two->path); |
145 | items[files-1].added = lines_added; | 145 | items[files-1].added = lines_added; |
146 | items[files-1].removed = lines_removed; | 146 | items[files-1].removed = lines_removed; |
147 | items[files-1].old_size = old_size; | 147 | items[files-1].old_size = old_size; |
148 | items[files-1].new_size = new_size; | 148 | items[files-1].new_size = new_size; |
149 | items[files-1].binary = binary; | 149 | items[files-1].binary = binary; |
150 | if (lines_added + lines_removed > max_changes) | 150 | if (lines_added + lines_removed > max_changes) |
151 | max_changes = lines_added + lines_removed; | 151 | max_changes = lines_added + lines_removed; |
152 | total_adds += lines_added; | 152 | total_adds += lines_added; |
153 | total_rems += lines_removed; | 153 | total_rems += lines_removed; |
154 | } | 154 | } |
155 | 155 | ||
156 | void cgit_print_diffstat(const unsigned char *old_sha1, | 156 | void cgit_print_diffstat(const unsigned char *old_sha1, |
157 | const unsigned char *new_sha1) | 157 | const unsigned char *new_sha1) |
158 | { | 158 | { |
159 | int i; | 159 | int i; |
160 | 160 | ||
161 | html("<div class='diffstat-header'>"); | 161 | html("<div class='diffstat-header'>"); |
162 | cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1, | 162 | cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1, |
163 | ctx.qry.sha2, NULL, 0); | 163 | ctx.qry.sha2, NULL, 0); |
164 | html("</div>"); | 164 | html("</div>"); |
165 | html("<table summary='diffstat' class='diffstat'>"); | 165 | html("<table summary='diffstat' class='diffstat'>"); |
166 | max_changes = 0; | 166 | max_changes = 0; |
167 | cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, NULL); | 167 | cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, NULL); |
168 | for(i = 0; i<files; i++) | 168 | for(i = 0; i<files; i++) |
169 | print_fileinfo(&items[i]); | 169 | print_fileinfo(&items[i]); |
170 | html("</table>"); | 170 | html("</table>"); |
171 | html("<div class='diffstat-summary'>"); | 171 | html("<div class='diffstat-summary'>"); |
172 | htmlf("%d files changed, %d insertions, %d deletions", | 172 | htmlf("%d files changed, %d insertions, %d deletions", |
173 | files, total_adds, total_rems); | 173 | files, total_adds, total_rems); |
174 | html("</div>"); | 174 | html("</div>"); |
175 | } | 175 | } |
176 | 176 | ||
177 | 177 | ||
178 | /* | 178 | /* |
179 | * print a single line returned from xdiff | 179 | * print a single line returned from xdiff |
180 | */ | 180 | */ |
181 | static void print_line(char *line, int len) | 181 | static void print_line(char *line, int len) |
182 | { | 182 | { |
183 | char *class = "ctx"; | 183 | char *class = "ctx"; |
184 | char c = line[len-1]; | 184 | char c = line[len-1]; |
185 | 185 | ||
186 | if (line[0] == '+') | 186 | if (line[0] == '+') |
187 | class = "add"; | 187 | class = "add"; |
188 | else if (line[0] == '-') | 188 | else if (line[0] == '-') |
189 | class = "del"; | 189 | class = "del"; |
190 | else if (line[0] == '@') | 190 | else if (line[0] == '@') |
191 | class = "hunk"; | 191 | class = "hunk"; |
192 | 192 | ||
193 | htmlf("<div class='%s'>", class); | 193 | htmlf("<div class='%s'>", class); |
194 | line[len-1] = '\0'; | 194 | line[len-1] = '\0'; |
195 | html_txt(line); | 195 | html_txt(line); |
196 | html("</div>"); | 196 | html("</div>"); |
197 | line[len-1] = c; | 197 | line[len-1] = c; |
198 | } | 198 | } |
199 | 199 | ||
200 | static void header(unsigned char *sha1, char *path1, int mode1, | 200 | static void header(unsigned char *sha1, char *path1, int mode1, |
201 | unsigned char *sha2, char *path2, int mode2) | 201 | unsigned char *sha2, char *path2, int mode2) |
202 | { | 202 | { |
203 | char *abbrev1, *abbrev2; | 203 | char *abbrev1, *abbrev2; |
204 | int subproject; | 204 | int subproject; |
205 | 205 | ||
206 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); | 206 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); |
207 | html("<div class='head'>"); | 207 | html("<div class='head'>"); |
208 | html("diff --git a/"); | 208 | html("diff --git a/"); |
209 | html_txt(path1); | 209 | html_txt(path1); |
210 | html(" b/"); | 210 | html(" b/"); |
211 | html_txt(path2); | 211 | html_txt(path2); |
212 | 212 | ||
213 | if (is_null_sha1(sha1)) | 213 | if (is_null_sha1(sha1)) |
214 | path1 = "dev/null"; | 214 | path1 = "dev/null"; |
215 | if (is_null_sha1(sha2)) | 215 | if (is_null_sha1(sha2)) |
216 | path2 = "dev/null"; | 216 | path2 = "dev/null"; |
217 | 217 | ||
218 | if (mode1 == 0) | 218 | if (mode1 == 0) |
219 | htmlf("<br/>new file mode %.6o", mode2); | 219 | htmlf("<br/>new file mode %.6o", mode2); |
220 | 220 | ||
221 | if (mode2 == 0) | 221 | if (mode2 == 0) |
222 | htmlf("<br/>deleted file mode %.6o", mode1); | 222 | htmlf("<br/>deleted file mode %.6o", mode1); |
223 | 223 | ||
224 | if (!subproject) { | 224 | if (!subproject) { |
225 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); | 225 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); |
226 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); | 226 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); |
227 | htmlf("<br/>index %s..%s", abbrev1, abbrev2); | 227 | htmlf("<br/>index %s..%s", abbrev1, abbrev2); |
228 | free(abbrev1); | 228 | free(abbrev1); |
229 | free(abbrev2); | 229 | free(abbrev2); |
230 | if (mode1 != 0 && mode2 != 0) { | 230 | if (mode1 != 0 && mode2 != 0) { |
231 | htmlf(" %.6o", mode1); | 231 | htmlf(" %.6o", mode1); |
232 | if (mode2 != mode1) | 232 | if (mode2 != mode1) |
233 | htmlf("..%.6o", mode2); | 233 | htmlf("..%.6o", mode2); |
234 | } | 234 | } |
235 | html("<br/>--- a/"); | 235 | html("<br/>--- a/"); |
236 | if (mode1 != 0) | 236 | if (mode1 != 0) |
237 | cgit_tree_link(path1, NULL, NULL, ctx.qry.head, | 237 | cgit_tree_link(path1, NULL, NULL, ctx.qry.head, |
238 | sha1_to_hex(old_rev_sha1), path1); | 238 | sha1_to_hex(old_rev_sha1), path1); |
239 | else | 239 | else |
240 | html_txt(path1); | 240 | html_txt(path1); |
241 | html("<br/>+++ b/"); | 241 | html("<br/>+++ b/"); |
242 | if (mode2 != 0) | 242 | if (mode2 != 0) |
243 | cgit_tree_link(path2, NULL, NULL, ctx.qry.head, | 243 | cgit_tree_link(path2, NULL, NULL, ctx.qry.head, |
244 | sha1_to_hex(new_rev_sha1), path2); | 244 | sha1_to_hex(new_rev_sha1), path2); |
245 | else | 245 | else |
246 | html_txt(path2); | 246 | html_txt(path2); |
247 | } | 247 | } |
248 | html("</div>"); | 248 | html("</div>"); |
249 | if (use_ssdiff) | ||
250 | cgit_ssdiff_header(); | ||
251 | } | 249 | } |
252 | 250 | ||
253 | static void print_ssdiff_link() | 251 | static void print_ssdiff_link() |
254 | { | 252 | { |
255 | if (!strcmp(ctx.qry.page, "diff")) { | 253 | if (!strcmp(ctx.qry.page, "diff")) { |
256 | if (use_ssdiff) | 254 | if (use_ssdiff) |
257 | cgit_diff_link("Unidiff", NULL, NULL, ctx.qry.head, | 255 | cgit_diff_link("Unidiff", NULL, NULL, ctx.qry.head, |
258 | ctx.qry.sha1, ctx.qry.sha2, NULL, 1); | 256 | ctx.qry.sha1, ctx.qry.sha2, NULL, 1); |
259 | else | 257 | else |
260 | cgit_diff_link("Side-by-side diff", NULL, NULL, | 258 | cgit_diff_link("Side-by-side diff", NULL, NULL, |
261 | ctx.qry.head, ctx.qry.sha1, | 259 | ctx.qry.head, ctx.qry.sha1, |
262 | ctx.qry.sha2, NULL, 1); | 260 | ctx.qry.sha2, NULL, 1); |
263 | } | 261 | } |
264 | } | 262 | } |
265 | 263 | ||
266 | static void filepair_cb(struct diff_filepair *pair) | 264 | static void filepair_cb(struct diff_filepair *pair) |
267 | { | 265 | { |
268 | unsigned long old_size = 0; | 266 | unsigned long old_size = 0; |
269 | unsigned long new_size = 0; | 267 | unsigned long new_size = 0; |
270 | int binary = 0; | 268 | int binary = 0; |
271 | linediff_fn print_line_fn = print_line; | 269 | linediff_fn print_line_fn = print_line; |
272 | 270 | ||
273 | header(pair->one->sha1, pair->one->path, pair->one->mode, | ||
274 | pair->two->sha1, pair->two->path, pair->two->mode); | ||
275 | if (use_ssdiff) { | 271 | if (use_ssdiff) { |
276 | cgit_ssdiff_header(); | 272 | cgit_ssdiff_header_begin(); |
277 | print_line_fn = cgit_ssdiff_line_cb; | 273 | print_line_fn = cgit_ssdiff_line_cb; |
278 | } | 274 | } |
275 | header(pair->one->sha1, pair->one->path, pair->one->mode, | ||
276 | pair->two->sha1, pair->two->path, pair->two->mode); | ||
277 | if (use_ssdiff) | ||
278 | cgit_ssdiff_header_end(); | ||
279 | if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { | 279 | if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { |
280 | if (S_ISGITLINK(pair->one->mode)) | 280 | if (S_ISGITLINK(pair->one->mode)) |
281 | print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); | 281 | print_line_fn(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); |
282 | if (S_ISGITLINK(pair->two->mode)) | 282 | if (S_ISGITLINK(pair->two->mode)) |
283 | print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); | 283 | print_line_fn(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); |
284 | return; | 284 | return; |
285 | } | 285 | } |
286 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, | 286 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, |
287 | &new_size, &binary, print_line_fn)) | 287 | &new_size, &binary, print_line_fn)) |
288 | cgit_print_error("Error running diff"); | 288 | cgit_print_error("Error running diff"); |
289 | if (binary) | 289 | if (binary) |
290 | html("Binary files differ"); | 290 | print_line_fn(" Binary files differ", 20); |
291 | if (use_ssdiff) | 291 | if (use_ssdiff) |
292 | cgit_ssdiff_footer(); | 292 | cgit_ssdiff_footer(); |
293 | } | 293 | } |
294 | 294 | ||
295 | void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix) | 295 | void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix) |
296 | { | 296 | { |
297 | enum object_type type; | 297 | enum object_type type; |
298 | unsigned long size; | 298 | unsigned long size; |
299 | struct commit *commit, *commit2; | 299 | struct commit *commit, *commit2; |
300 | 300 | ||
301 | if (!new_rev) | 301 | if (!new_rev) |
302 | new_rev = ctx.qry.head; | 302 | new_rev = ctx.qry.head; |
303 | get_sha1(new_rev, new_rev_sha1); | 303 | get_sha1(new_rev, new_rev_sha1); |
304 | type = sha1_object_info(new_rev_sha1, &size); | 304 | type = sha1_object_info(new_rev_sha1, &size); |
305 | if (type == OBJ_BAD) { | 305 | if (type == OBJ_BAD) { |
306 | cgit_print_error(fmt("Bad object name: %s", new_rev)); | 306 | cgit_print_error(fmt("Bad object name: %s", new_rev)); |
307 | return; | 307 | return; |
308 | } | 308 | } |
309 | commit = lookup_commit_reference(new_rev_sha1); | 309 | commit = lookup_commit_reference(new_rev_sha1); |
310 | if (!commit || parse_commit(commit)) | 310 | if (!commit || parse_commit(commit)) |
311 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(new_rev_sha1))); | 311 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(new_rev_sha1))); |
312 | 312 | ||
313 | if (old_rev) | 313 | if (old_rev) |
314 | get_sha1(old_rev, old_rev_sha1); | 314 | get_sha1(old_rev, old_rev_sha1); |
315 | else if (commit->parents && commit->parents->item) | 315 | else if (commit->parents && commit->parents->item) |
316 | hashcpy(old_rev_sha1, commit->parents->item->object.sha1); | 316 | hashcpy(old_rev_sha1, commit->parents->item->object.sha1); |
317 | else | 317 | else |
318 | hashclr(old_rev_sha1); | 318 | hashclr(old_rev_sha1); |
319 | 319 | ||
320 | if (!is_null_sha1(old_rev_sha1)) { | 320 | if (!is_null_sha1(old_rev_sha1)) { |
321 | type = sha1_object_info(old_rev_sha1, &size); | 321 | type = sha1_object_info(old_rev_sha1, &size); |
322 | if (type == OBJ_BAD) { | 322 | if (type == OBJ_BAD) { |
323 | cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(old_rev_sha1))); | 323 | cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(old_rev_sha1))); |
324 | return; | 324 | return; |
325 | } | 325 | } |
326 | commit2 = lookup_commit_reference(old_rev_sha1); | 326 | commit2 = lookup_commit_reference(old_rev_sha1); |
327 | if (!commit2 || parse_commit(commit2)) | 327 | if (!commit2 || parse_commit(commit2)) |
328 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(old_rev_sha1))); | 328 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(old_rev_sha1))); |
329 | } | 329 | } |
330 | 330 | ||
331 | if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff)) | 331 | if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff)) |
332 | use_ssdiff = 1; | 332 | use_ssdiff = 1; |
333 | 333 | ||
334 | print_ssdiff_link(); | 334 | print_ssdiff_link(); |
335 | cgit_print_diffstat(old_rev_sha1, new_rev_sha1); | 335 | cgit_print_diffstat(old_rev_sha1, new_rev_sha1); |
336 | 336 | ||
337 | html("<table summary='diff' class='diff'>"); | 337 | if (use_ssdiff) { |
338 | html("<tr><td>"); | 338 | html("<table summary='ssdiff' class='ssdiff'>"); |
339 | } else { | ||
340 | html("<table summary='diff' class='diff'>"); | ||
341 | html("<tr><td>"); | ||
342 | } | ||
339 | cgit_diff_tree(old_rev_sha1, new_rev_sha1, filepair_cb, prefix); | 343 | cgit_diff_tree(old_rev_sha1, new_rev_sha1, filepair_cb, prefix); |
340 | html("</td></tr>"); | 344 | if (!use_ssdiff) |
345 | html("</td></tr>"); | ||
341 | html("</table>"); | 346 | html("</table>"); |
342 | } | 347 | } |
diff --git a/ui-ssdiff.c b/ui-ssdiff.c index 3591ab4..8215051 100644 --- a/ui-ssdiff.c +++ b/ui-ssdiff.c | |||
@@ -1,264 +1,270 @@ | |||
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 | 4 | ||
5 | extern int use_ssdiff; | 5 | extern int use_ssdiff; |
6 | 6 | ||
7 | static int current_old_line, current_new_line; | 7 | static int current_old_line, current_new_line; |
8 | 8 | ||
9 | struct deferred_lines { | 9 | struct deferred_lines { |
10 | int line_no; | 10 | int line_no; |
11 | char *line; | 11 | char *line; |
12 | struct deferred_lines *next; | 12 | struct deferred_lines *next; |
13 | }; | 13 | }; |
14 | 14 | ||
15 | static struct deferred_lines *deferred_old, *deferred_old_last; | 15 | static struct deferred_lines *deferred_old, *deferred_old_last; |
16 | static struct deferred_lines *deferred_new, *deferred_new_last; | 16 | static struct deferred_lines *deferred_new, *deferred_new_last; |
17 | 17 | ||
18 | static int line_from_hunk(char *line, char type) | 18 | static int line_from_hunk(char *line, char type) |
19 | { | 19 | { |
20 | char *buf1, *buf2; | 20 | char *buf1, *buf2; |
21 | int len; | 21 | int len; |
22 | 22 | ||
23 | buf1 = strchr(line, type); | 23 | buf1 = strchr(line, type); |
24 | if (buf1 == NULL) | 24 | if (buf1 == NULL) |
25 | return 0; | 25 | return 0; |
26 | buf1 += 1; | 26 | buf1 += 1; |
27 | buf2 = strchr(buf1, ','); | 27 | buf2 = strchr(buf1, ','); |
28 | if (buf2 == NULL) | 28 | if (buf2 == NULL) |
29 | return 0; | 29 | return 0; |
30 | len = buf2 - buf1; | 30 | len = buf2 - buf1; |
31 | buf2 = xmalloc(len + 1); | 31 | buf2 = xmalloc(len + 1); |
32 | strncpy(buf2, buf1, len); | 32 | strncpy(buf2, buf1, len); |
33 | buf2[len] = '\0'; | 33 | buf2[len] = '\0'; |
34 | int res = atoi(buf2); | 34 | int res = atoi(buf2); |
35 | free(buf2); | 35 | free(buf2); |
36 | return res; | 36 | return res; |
37 | } | 37 | } |
38 | 38 | ||
39 | static char *replace_tabs(char *line) | 39 | static char *replace_tabs(char *line) |
40 | { | 40 | { |
41 | char *prev_buf = line; | 41 | char *prev_buf = line; |
42 | char *cur_buf; | 42 | char *cur_buf; |
43 | int linelen = strlen(line); | 43 | int linelen = strlen(line); |
44 | int n_tabs = 0; | 44 | int n_tabs = 0; |
45 | int i; | 45 | int i; |
46 | char *result; | 46 | char *result; |
47 | char *spaces = " "; | 47 | char *spaces = " "; |
48 | 48 | ||
49 | if (linelen == 0) { | 49 | if (linelen == 0) { |
50 | result = xmalloc(1); | 50 | result = xmalloc(1); |
51 | result[0] = '\0'; | 51 | result[0] = '\0'; |
52 | return result; | 52 | return result; |
53 | } | 53 | } |
54 | 54 | ||
55 | for (i = 0; i < linelen; i++) | 55 | for (i = 0; i < linelen; i++) |
56 | if (line[i] == '\t') | 56 | if (line[i] == '\t') |
57 | n_tabs += 1; | 57 | n_tabs += 1; |
58 | result = xmalloc(linelen + n_tabs * 8 + 1); | 58 | result = xmalloc(linelen + n_tabs * 8 + 1); |
59 | result[0] = '\0'; | 59 | result[0] = '\0'; |
60 | 60 | ||
61 | while (1) { | 61 | while (1) { |
62 | cur_buf = strchr(prev_buf, '\t'); | 62 | cur_buf = strchr(prev_buf, '\t'); |
63 | if (!cur_buf) { | 63 | if (!cur_buf) { |
64 | strcat(result, prev_buf); | 64 | strcat(result, prev_buf); |
65 | break; | 65 | break; |
66 | } else { | 66 | } else { |
67 | strcat(result, " "); | 67 | strcat(result, " "); |
68 | strncat(result, spaces, 8 - (strlen(result) % 8)); | 68 | strncat(result, spaces, 8 - (strlen(result) % 8)); |
69 | strncat(result, prev_buf, cur_buf - prev_buf); | 69 | strncat(result, prev_buf, cur_buf - prev_buf); |
70 | } | 70 | } |
71 | prev_buf = cur_buf + 1; | 71 | prev_buf = cur_buf + 1; |
72 | } | 72 | } |
73 | return result; | 73 | return result; |
74 | } | 74 | } |
75 | 75 | ||
76 | static void deferred_old_add(char *line, int line_no) | 76 | static void deferred_old_add(char *line, int line_no) |
77 | { | 77 | { |
78 | struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines)); | 78 | struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines)); |
79 | item->line = xstrdup(line); | 79 | item->line = xstrdup(line); |
80 | item->line_no = line_no; | 80 | item->line_no = line_no; |
81 | item->next = NULL; | 81 | item->next = NULL; |
82 | if (deferred_old) { | 82 | if (deferred_old) { |
83 | deferred_old_last->next = item; | 83 | deferred_old_last->next = item; |
84 | deferred_old_last = item; | 84 | deferred_old_last = item; |
85 | } else { | 85 | } else { |
86 | deferred_old = deferred_old_last = item; | 86 | deferred_old = deferred_old_last = item; |
87 | } | 87 | } |
88 | } | 88 | } |
89 | 89 | ||
90 | static void deferred_new_add(char *line, int line_no) | 90 | static void deferred_new_add(char *line, int line_no) |
91 | { | 91 | { |
92 | struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines)); | 92 | struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines)); |
93 | item->line = xstrdup(line); | 93 | item->line = xstrdup(line); |
94 | item->line_no = line_no; | 94 | item->line_no = line_no; |
95 | item->next = NULL; | 95 | item->next = NULL; |
96 | if (deferred_new) { | 96 | if (deferred_new) { |
97 | deferred_new_last->next = item; | 97 | deferred_new_last->next = item; |
98 | deferred_new_last = item; | 98 | deferred_new_last = item; |
99 | } else { | 99 | } else { |
100 | deferred_new = deferred_new_last = item; | 100 | deferred_new = deferred_new_last = item; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | static void print_ssdiff_line(char *class, int old_line_no, char *old_line, | 104 | static void print_ssdiff_line(char *class, int old_line_no, char *old_line, |
105 | int new_line_no, char *new_line) | 105 | int new_line_no, char *new_line) |
106 | { | 106 | { |
107 | html("<tr>"); | 107 | html("<tr>"); |
108 | if (old_line_no > 0) | 108 | if (old_line_no > 0) |
109 | htmlf("<td class='%s'>%d </td><td class='%s'>", class, | 109 | htmlf("<td class='lineno'>%d</td><td class='%s'>", |
110 | old_line_no, class); | 110 | old_line_no, class); |
111 | else | 111 | else |
112 | htmlf("<td class='%s_dark'> </td><td class='%s_dark'>", class, class); | 112 | htmlf("<td class='lineno'></td><td class='%s_dark'>", class); |
113 | 113 | ||
114 | if (old_line) { | 114 | if (old_line) { |
115 | old_line = replace_tabs(old_line + 1); | 115 | old_line = replace_tabs(old_line + 1); |
116 | html_txt(old_line); | 116 | html_txt(old_line); |
117 | free(old_line); | 117 | free(old_line); |
118 | } | 118 | } |
119 | 119 | ||
120 | html(" </td>"); | 120 | html("</td>"); |
121 | 121 | ||
122 | if (new_line_no > 0) | 122 | if (new_line_no > 0) |
123 | htmlf("<td class='%s'> %d </td><td class='%s'>", class, | 123 | htmlf("<td class='lineno'>%d</td><td class='%s'>", |
124 | new_line_no, class); | 124 | new_line_no, class); |
125 | else | 125 | else |
126 | htmlf("<td class='%s_dark'> </td><td class='%s_dark'>", class, class); | 126 | htmlf("<td class='lineno'></td><td class='%s_dark'>", class); |
127 | 127 | ||
128 | if (new_line) { | 128 | if (new_line) { |
129 | new_line = replace_tabs(new_line + 1); | 129 | new_line = replace_tabs(new_line + 1); |
130 | html_txt(new_line); | 130 | html_txt(new_line); |
131 | free(new_line); | 131 | free(new_line); |
132 | } | 132 | } |
133 | 133 | ||
134 | html("</td></tr>"); | 134 | html("</td></tr>"); |
135 | } | 135 | } |
136 | 136 | ||
137 | static void print_deferred_old_lines() | 137 | static void print_deferred_old_lines() |
138 | { | 138 | { |
139 | struct deferred_lines *iter_old, *tmp; | 139 | struct deferred_lines *iter_old, *tmp; |
140 | 140 | ||
141 | iter_old = deferred_old; | 141 | iter_old = deferred_old; |
142 | while (iter_old) { | 142 | while (iter_old) { |
143 | print_ssdiff_line("del", iter_old->line_no, | 143 | print_ssdiff_line("del", iter_old->line_no, |
144 | iter_old->line, -1, NULL); | 144 | iter_old->line, -1, NULL); |
145 | tmp = iter_old->next; | 145 | tmp = iter_old->next; |
146 | free(iter_old); | 146 | free(iter_old); |
147 | iter_old = tmp; | 147 | iter_old = tmp; |
148 | } | 148 | } |
149 | } | 149 | } |
150 | 150 | ||
151 | static void print_deferred_new_lines() | 151 | static void print_deferred_new_lines() |
152 | { | 152 | { |
153 | struct deferred_lines *iter_new, *tmp; | 153 | struct deferred_lines *iter_new, *tmp; |
154 | 154 | ||
155 | iter_new = deferred_new; | 155 | iter_new = deferred_new; |
156 | while (iter_new) { | 156 | while (iter_new) { |
157 | print_ssdiff_line("add", -1, NULL, iter_new->line_no, | 157 | print_ssdiff_line("add", -1, NULL, iter_new->line_no, |
158 | iter_new->line); | 158 | iter_new->line); |
159 | tmp = iter_new->next; | 159 | tmp = iter_new->next; |
160 | free(iter_new); | 160 | free(iter_new); |
161 | iter_new = tmp; | 161 | iter_new = tmp; |
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | static void print_deferred_changed_lines() | 165 | static void print_deferred_changed_lines() |
166 | { | 166 | { |
167 | struct deferred_lines *iter_old, *iter_new, *tmp; | 167 | struct deferred_lines *iter_old, *iter_new, *tmp; |
168 | 168 | ||
169 | iter_old = deferred_old; | 169 | iter_old = deferred_old; |
170 | iter_new = deferred_new; | 170 | iter_new = deferred_new; |
171 | while (iter_old || iter_new) { | 171 | while (iter_old || iter_new) { |
172 | if (iter_old && iter_new) | 172 | if (iter_old && iter_new) |
173 | print_ssdiff_line("changed", iter_old->line_no, | 173 | print_ssdiff_line("changed", iter_old->line_no, |
174 | iter_old->line, | 174 | iter_old->line, |
175 | iter_new->line_no, iter_new->line); | 175 | iter_new->line_no, iter_new->line); |
176 | else if (iter_old) | 176 | else if (iter_old) |
177 | print_ssdiff_line("changed", iter_old->line_no, | 177 | print_ssdiff_line("changed", iter_old->line_no, |
178 | iter_old->line, -1, NULL); | 178 | iter_old->line, -1, NULL); |
179 | else if (iter_new) | 179 | else if (iter_new) |
180 | print_ssdiff_line("changed", -1, NULL, | 180 | print_ssdiff_line("changed", -1, NULL, |
181 | iter_new->line_no, iter_new->line); | 181 | iter_new->line_no, iter_new->line); |
182 | 182 | ||
183 | if (iter_old) { | 183 | if (iter_old) { |
184 | tmp = iter_old->next; | 184 | tmp = iter_old->next; |
185 | free(iter_old); | 185 | free(iter_old); |
186 | iter_old = tmp; | 186 | iter_old = tmp; |
187 | } | 187 | } |
188 | 188 | ||
189 | if (iter_new) { | 189 | if (iter_new) { |
190 | tmp = iter_new->next; | 190 | tmp = iter_new->next; |
191 | free(iter_new); | 191 | free(iter_new); |
192 | iter_new = tmp; | 192 | iter_new = tmp; |
193 | } | 193 | } |
194 | } | 194 | } |
195 | } | 195 | } |
196 | 196 | ||
197 | void cgit_ssdiff_print_deferred_lines() | 197 | void cgit_ssdiff_print_deferred_lines() |
198 | { | 198 | { |
199 | if (!deferred_old && !deferred_new) | 199 | if (!deferred_old && !deferred_new) |
200 | return; | 200 | return; |
201 | 201 | ||
202 | if (deferred_old && !deferred_new) | 202 | if (deferred_old && !deferred_new) |
203 | print_deferred_old_lines(); | 203 | print_deferred_old_lines(); |
204 | else if (!deferred_old && deferred_new) | 204 | else if (!deferred_old && deferred_new) |
205 | print_deferred_new_lines(); | 205 | print_deferred_new_lines(); |
206 | else | 206 | else |
207 | print_deferred_changed_lines(); | 207 | print_deferred_changed_lines(); |
208 | 208 | ||
209 | deferred_old = deferred_old_last = NULL; | 209 | deferred_old = deferred_old_last = NULL; |
210 | deferred_new = deferred_new_last = NULL; | 210 | deferred_new = deferred_new_last = NULL; |
211 | } | 211 | } |
212 | 212 | ||
213 | /* | 213 | /* |
214 | * print a single line returned from xdiff | 214 | * print a single line returned from xdiff |
215 | */ | 215 | */ |
216 | void cgit_ssdiff_line_cb(char *line, int len) | 216 | void cgit_ssdiff_line_cb(char *line, int len) |
217 | { | 217 | { |
218 | char c = line[len - 1]; | 218 | char c = line[len - 1]; |
219 | 219 | ||
220 | line[len - 1] = '\0'; | 220 | line[len - 1] = '\0'; |
221 | 221 | ||
222 | if (line[0] == '@') { | 222 | if (line[0] == '@') { |
223 | current_old_line = line_from_hunk(line, '-'); | 223 | current_old_line = line_from_hunk(line, '-'); |
224 | current_new_line = line_from_hunk(line, '+'); | 224 | current_new_line = line_from_hunk(line, '+'); |
225 | } | 225 | } |
226 | 226 | ||
227 | if (line[0] == ' ') { | 227 | if (line[0] == ' ') { |
228 | if (deferred_old || deferred_new) | 228 | if (deferred_old || deferred_new) |
229 | cgit_ssdiff_print_deferred_lines(); | 229 | cgit_ssdiff_print_deferred_lines(); |
230 | print_ssdiff_line("ctx", current_old_line, line, | 230 | print_ssdiff_line("ctx", current_old_line, line, |
231 | current_new_line, line); | 231 | current_new_line, line); |
232 | current_old_line += 1; | 232 | current_old_line += 1; |
233 | current_new_line += 1; | 233 | current_new_line += 1; |
234 | } else if (line[0] == '+') { | 234 | } else if (line[0] == '+') { |
235 | deferred_new_add(line, current_new_line); | 235 | deferred_new_add(line, current_new_line); |
236 | current_new_line += 1; | 236 | current_new_line += 1; |
237 | } else if (line[0] == '-') { | 237 | } else if (line[0] == '-') { |
238 | deferred_old_add(line, current_old_line); | 238 | deferred_old_add(line, current_old_line); |
239 | current_old_line += 1; | 239 | current_old_line += 1; |
240 | } else if (line[0] == '@') { | 240 | } else if (line[0] == '@') { |
241 | html("<tr><td colspan='4' class='hunk'>"); | 241 | html("<tr><td colspan='4' class='hunk'>"); |
242 | html_txt(line); | 242 | html_txt(line); |
243 | html("</td></tr>"); | 243 | html("</td></tr>"); |
244 | } else { | 244 | } else { |
245 | html("<tr><td colspan='4' class='ctx'>"); | 245 | html("<tr><td colspan='4' class='ctx'>"); |
246 | html_txt(line); | 246 | html_txt(line); |
247 | html("</td></tr>"); | 247 | html("</td></tr>"); |
248 | } | 248 | } |
249 | line[len - 1] = c; | 249 | line[len - 1] = c; |
250 | } | 250 | } |
251 | 251 | ||
252 | void cgit_ssdiff_header() | 252 | void cgit_ssdiff_header_begin() |
253 | { | 253 | { |
254 | current_old_line = 0; | 254 | current_old_line = 0; |
255 | current_new_line = 0; | 255 | current_new_line = 0; |
256 | html("<table class='ssdiff'>"); | 256 | html("<tr><td class='space' colspan='4'><div></div></td></tr>"); |
257 | html("<tr><td class='head' colspan='4'>"); | ||
258 | } | ||
259 | |||
260 | void cgit_ssdiff_header_end() | ||
261 | { | ||
262 | html("</td><tr>"); | ||
257 | } | 263 | } |
258 | 264 | ||
259 | void cgit_ssdiff_footer() | 265 | void cgit_ssdiff_footer() |
260 | { | 266 | { |
261 | if (deferred_old || deferred_new) | 267 | if (deferred_old || deferred_new) |
262 | cgit_ssdiff_print_deferred_lines(); | 268 | cgit_ssdiff_print_deferred_lines(); |
263 | html("</table>"); | 269 | html("<tr><td class='foot' colspan='4'></td></tr>"); |
264 | } | 270 | } |
diff --git a/ui-ssdiff.h b/ui-ssdiff.h index a0b1efe..64b4b12 100644 --- a/ui-ssdiff.h +++ b/ui-ssdiff.h | |||
@@ -1,12 +1,13 @@ | |||
1 | #ifndef UI_SSDIFF_H | 1 | #ifndef UI_SSDIFF_H |
2 | #define UI_SSDIFF_H | 2 | #define UI_SSDIFF_H |
3 | 3 | ||
4 | extern void cgit_ssdiff_print_deferred_lines(); | 4 | extern void cgit_ssdiff_print_deferred_lines(); |
5 | 5 | ||
6 | extern void cgit_ssdiff_line_cb(char *line, int len); | 6 | extern void cgit_ssdiff_line_cb(char *line, int len); |
7 | 7 | ||
8 | extern void cgit_ssdiff_header(); | 8 | extern void cgit_ssdiff_header_begin(); |
9 | extern void cgit_ssdiff_header_end(); | ||
9 | 10 | ||
10 | extern void cgit_ssdiff_footer(); | 11 | extern void cgit_ssdiff_footer(); |
11 | 12 | ||
12 | #endif /* UI_SSDIFF_H */ | 13 | #endif /* UI_SSDIFF_H */ |