summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.css19
-rw-r--r--ui-tree.c71
2 files changed, 67 insertions, 23 deletions
diff --git a/cgit.css b/cgit.css
index 957d5aa..adfc8ae 100644
--- a/cgit.css
+++ b/cgit.css
@@ -170,192 +170,211 @@ img {
170 border: none; 170 border: none;
171} 171}
172 172
173input#switch-btn { 173input#switch-btn {
174 margin: 2px 0px 0px 0px; 174 margin: 2px 0px 0px 0px;
175} 175}
176 176
177td#sidebar input.txt { 177td#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
182table#grid { 182table#grid {
183 margin: 0px; 183 margin: 0px;
184} 184}
185 185
186td#content { 186td#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
192div#summary { 192div#summary {
193 vertical-align: top; 193 vertical-align: top;
194 margin-bottom: 1em; 194 margin-bottom: 1em;
195} 195}
196 196
197table#downloads { 197table#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
205table#downloads th { 205table#downloads th {
206 background-color: #ccc; 206 background-color: #ccc;
207} 207}
208 208
209div#blob { 209div#blob {
210 border: solid 1px black; 210 border: solid 1px black;
211} 211}
212 212
213div.error { 213div.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
219a.ls-blob, a.ls-dir, a.ls-mod { 219a.ls-blob, a.ls-dir, a.ls-mod {
220 font-family: monospace; 220 font-family: monospace;
221} 221}
222 222
223td.ls-size { 223td.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
229td.ls-mode { 229td.ls-mode {
230 font-family: monospace; 230 font-family: monospace;
231 width: 10em; 231 width: 10em;
232} 232}
233 233
234table.blob { 234table.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
239table.blob td.lines { 239table.blob td.lines {
240 margin: 0; padding: 0; 240 margin: 0; padding: 0;
241 vertical-align: top; 241 vertical-align: top;
242 color: black; 242 color: black;
243} 243}
244 244
245table.blob td.linenumbers { 245table.blob td.linenumbers {
246 margin: 0; padding: 0; 246 margin: 0; padding: 0;
247 vertical-align: top; 247 vertical-align: top;
248 border-right: 1px solid gray; 248 border-right: 1px solid gray;
249 background-color: #eee; 249 background-color: #eee;
250} 250}
251 251
252table.blob pre { 252table.blob pre {
253 padding: 0; margin: 0; 253 padding: 0; margin: 0;
254} 254}
255 255
256table.blob a.no { 256table.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
262table.blob a.no a:hover { 262table.blob a.no a:hover {
263 color: black; 263 color: black;
264} 264}
265 265
266table.bin-blob {
267 margin-top: 0.5em;
268 border: solid 1px black;
269}
270
271table.bin-blob th {
272 font-family: monospace;
273 white-space: pre;
274 border: solid 1px #777;
275 padding: 0.5em 1em;
276}
277
278table.bin-blob td {
279 font-family: monospace;
280 white-space: pre;
281 border-left: solid 1px #777;
282 padding: 0em 1em;
283}
284
266table.nowrap td { 285table.nowrap td {
267 white-space: nowrap; 286 white-space: nowrap;
268} 287}
269 288
270table.commit-info { 289table.commit-info {
271 border-collapse: collapse; 290 border-collapse: collapse;
272 margin-top: 1.5em; 291 margin-top: 1.5em;
273} 292}
274 293
275table.commit-info th { 294table.commit-info th {
276 text-align: left; 295 text-align: left;
277 font-weight: normal; 296 font-weight: normal;
278 padding: 0.1em 1em 0.1em 0.1em; 297 padding: 0.1em 1em 0.1em 0.1em;
279 vertical-align: top; 298 vertical-align: top;
280} 299}
281 300
282table.commit-info td { 301table.commit-info td {
283 font-weight: normal; 302 font-weight: normal;
284 padding: 0.1em 1em 0.1em 0.1em; 303 padding: 0.1em 1em 0.1em 0.1em;
285} 304}
286 305
287div.commit-subject { 306div.commit-subject {
288 font-weight: bold; 307 font-weight: bold;
289 font-size: 125%; 308 font-size: 125%;
290 margin: 1.5em 0em 0.5em 0em; 309 margin: 1.5em 0em 0.5em 0em;
291 padding: 0em; 310 padding: 0em;
292} 311}
293 312
294div.commit-msg { 313div.commit-msg {
295 white-space: pre; 314 white-space: pre;
296 font-family: monospace; 315 font-family: monospace;
297} 316}
298 317
299div.diffstat-header { 318div.diffstat-header {
300 font-weight: bold; 319 font-weight: bold;
301 padding-top: 1.5em; 320 padding-top: 1.5em;
302} 321}
303 322
304table.diffstat { 323table.diffstat {
305 border-collapse: collapse; 324 border-collapse: collapse;
306 border: solid 1px #aaa; 325 border: solid 1px #aaa;
307 background-color: #eee; 326 background-color: #eee;
308} 327}
309 328
310table.diffstat th { 329table.diffstat th {
311 font-weight: normal; 330 font-weight: normal;
312 text-align: left; 331 text-align: left;
313 text-decoration: underline; 332 text-decoration: underline;
314 padding: 0.1em 1em 0.1em 0.1em; 333 padding: 0.1em 1em 0.1em 0.1em;
315 font-size: 100%; 334 font-size: 100%;
316} 335}
317 336
318table.diffstat td { 337table.diffstat td {
319 padding: 0.2em 0.2em 0.1em 0.1em; 338 padding: 0.2em 0.2em 0.1em 0.1em;
320 font-size: 100%; 339 font-size: 100%;
321 border: none; 340 border: none;
322} 341}
323 342
324table.diffstat td.mode { 343table.diffstat td.mode {
325 white-space: nowrap; 344 white-space: nowrap;
326} 345}
327 346
328table.diffstat td span.modechange { 347table.diffstat td span.modechange {
329 padding-left: 1em; 348 padding-left: 1em;
330 color: red; 349 color: red;
331} 350}
332 351
333table.diffstat td.add a { 352table.diffstat td.add a {
334 color: green; 353 color: green;
335} 354}
336 355
337table.diffstat td.del a { 356table.diffstat td.del a {
338 color: red; 357 color: red;
339} 358}
340 359
341table.diffstat td.upd a { 360table.diffstat td.upd a {
342 color: blue; 361 color: blue;
343} 362}
344 363
345table.diffstat td.graph { 364table.diffstat td.graph {
346 width: 500px; 365 width: 500px;
347 vertical-align: middle; 366 vertical-align: middle;
348} 367}
349 368
350table.diffstat td.graph table { 369table.diffstat td.graph table {
351 border: none; 370 border: none;
352} 371}
353 372
354table.diffstat td.graph td { 373table.diffstat td.graph td {
355 padding: 0px; 374 padding: 0px;
356 border: 0px; 375 border: 0px;
357 height: 7pt; 376 height: 7pt;
358} 377}
359 378
360table.diffstat td.graph td.add { 379table.diffstat td.graph td.add {
361 background-color: #5c5; 380 background-color: #5c5;
diff --git a/ui-tree.c b/ui-tree.c
index c26ba4c..a37a4e5 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -1,159 +1,184 @@
1/* ui-tree.c: functions for tree output 1/* ui-tree.c: functions for tree output
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 <ctype.h>
9#include "cgit.h" 10#include "cgit.h"
10#include "html.h" 11#include "html.h"
11#include "ui-shared.h" 12#include "ui-shared.h"
12 13
13char *curr_rev; 14char *curr_rev;
14char *match_path; 15char *match_path;
15int header = 0; 16int header = 0;
16 17
18static void print_text_buffer(char *buf, unsigned long size)
19{
20 unsigned long lineno, idx;
21 const char *numberfmt =
22 "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
23
24 html("<table summary='blob content' class='blob'>\n");
25 html("<tr><td class='linenumbers'><pre>");
26 idx = 0;
27 lineno = 0;
28 htmlf(numberfmt, ++lineno);
29 while(idx < size - 1) { // skip absolute last newline
30 if (buf[idx] == '\n')
31 htmlf(numberfmt, ++lineno);
32 idx++;
33 }
34 html("</pre></td>\n");
35 html("<td class='lines'><pre><code>");
36 html_txt(buf);
37 html("</code></pre></td></tr></table>\n");
38}
39
40static void print_binary_buffer(char *buf, unsigned long size)
41{
42 unsigned long ofs, idx;
43
44 html("<table summary='blob content' class='bin-blob'>\n");
45 html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>");
46 for (ofs = 0; ofs < size; ofs += 32, buf += 32) {
47 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs);
48 for (idx = 0; idx < 32 && ofs + idx < size; idx++)
49 htmlf("%*s%02x",
50 idx == 16 ? 4 : 1, "",
51 buf[idx] & 0xff);
52 html(" </td><td class='hex'>");
53 for (idx = 0; idx < 32 && ofs + idx < size; idx++)
54 htmlf("%c", isgraph(buf[idx]) ? buf[idx] : '.');
55 html("</td></tr>\n");
56 }
57 html("</table>\n");
58}
59
17static void print_object(const unsigned char *sha1, char *path) 60static void print_object(const unsigned char *sha1, char *path)
18{ 61{
19 enum object_type type; 62 enum object_type type;
20 char *buf; 63 char *buf;
21 unsigned long size, lineno, idx; 64 unsigned long size;
22 const char *numberfmt = "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
23 65
24 type = sha1_object_info(sha1, &size); 66 type = sha1_object_info(sha1, &size);
25 if (type == OBJ_BAD) { 67 if (type == OBJ_BAD) {
26 cgit_print_error(fmt("Bad object name: %s", 68 cgit_print_error(fmt("Bad object name: %s",
27 sha1_to_hex(sha1))); 69 sha1_to_hex(sha1)));
28 return; 70 return;
29 } 71 }
30 72
31 buf = read_sha1_file(sha1, &type, &size); 73 buf = read_sha1_file(sha1, &type, &size);
32 if (!buf) { 74 if (!buf) {
33 cgit_print_error(fmt("Error reading object %s", 75 cgit_print_error(fmt("Error reading object %s",
34 sha1_to_hex(sha1))); 76 sha1_to_hex(sha1)));
35 return; 77 return;
36 } 78 }
37 79
38 html(" ("); 80 html(" (");
39 cgit_plain_link("plain", NULL, NULL, ctx.qry.head, 81 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
40 curr_rev, path); 82 curr_rev, path);
41 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); 83 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
42 84
43 html("<table summary='blob content' class='blob'>\n"); 85 if (buffer_is_binary(buf, size))
44 html("<tr>\n"); 86 print_binary_buffer(buf, size);
45 87 else
46 html("<td class='linenumbers'><pre>"); 88 print_text_buffer(buf, size);
47 idx = 0;
48 lineno = 0;
49 htmlf(numberfmt, ++lineno);
50 while(idx < size - 1) { // skip absolute last newline
51 if (buf[idx] == '\n') {
52 htmlf(numberfmt, ++lineno);
53 }
54 idx++;
55 }
56 html("</pre></td>\n");
57
58 html("<td class='lines'><pre><code>");
59 html_txt(buf);
60 html("</code></pre></td>\n");
61
62 html("</tr>\n");
63 html("</table>\n");
64} 89}
65 90
66 91
67static int ls_item(const unsigned char *sha1, const char *base, int baselen, 92static int ls_item(const unsigned char *sha1, const char *base, int baselen,
68 const char *pathname, unsigned int mode, int stage, 93 const char *pathname, unsigned int mode, int stage,
69 void *cbdata) 94 void *cbdata)
70{ 95{
71 char *name; 96 char *name;
72 char *fullpath; 97 char *fullpath;
73 enum object_type type; 98 enum object_type type;
74 unsigned long size = 0; 99 unsigned long size = 0;
75 100
76 name = xstrdup(pathname); 101 name = xstrdup(pathname);
77 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", 102 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "",
78 ctx.qry.path ? "/" : "", name); 103 ctx.qry.path ? "/" : "", name);
79 104
80 if (!S_ISGITLINK(mode)) { 105 if (!S_ISGITLINK(mode)) {
81 type = sha1_object_info(sha1, &size); 106 type = sha1_object_info(sha1, &size);
82 if (type == OBJ_BAD) { 107 if (type == OBJ_BAD) {
83 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 108 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
84 name, 109 name,
85 sha1_to_hex(sha1)); 110 sha1_to_hex(sha1));
86 return 0; 111 return 0;
87 } 112 }
88 } 113 }
89 114
90 html("<tr><td class='ls-mode'>"); 115 html("<tr><td class='ls-mode'>");
91 cgit_print_filemode(mode); 116 cgit_print_filemode(mode);
92 html("</td><td>"); 117 html("</td><td>");
93 if (S_ISGITLINK(mode)) { 118 if (S_ISGITLINK(mode)) {
94 htmlf("<a class='ls-mod' href='"); 119 htmlf("<a class='ls-mod' href='");
95 html_attr(fmt(ctx.repo->module_link, 120 html_attr(fmt(ctx.repo->module_link,
96 name, 121 name,
97 sha1_to_hex(sha1))); 122 sha1_to_hex(sha1)));
98 html("'>"); 123 html("'>");
99 html_txt(name); 124 html_txt(name);
100 html("</a>"); 125 html("</a>");
101 } else if (S_ISDIR(mode)) { 126 } else if (S_ISDIR(mode)) {
102 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, 127 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
103 curr_rev, fullpath); 128 curr_rev, fullpath);
104 } else { 129 } else {
105 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, 130 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head,
106 curr_rev, fullpath); 131 curr_rev, fullpath);
107 } 132 }
108 htmlf("</td><td class='ls-size'>%li</td>", size); 133 htmlf("</td><td class='ls-size'>%li</td>", size);
109 134
110 html("<td>"); 135 html("<td>");
111 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, 136 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev,
112 fullpath, 0, NULL, NULL, ctx.qry.showmsg); 137 fullpath, 0, NULL, NULL, ctx.qry.showmsg);
113 if (ctx.repo->max_stats) 138 if (ctx.repo->max_stats)
114 cgit_stats_link("stats", NULL, "button", ctx.qry.head, 139 cgit_stats_link("stats", NULL, "button", ctx.qry.head,
115 fullpath); 140 fullpath);
116 html("</td></tr>\n"); 141 html("</td></tr>\n");
117 free(name); 142 free(name);
118 return 0; 143 return 0;
119} 144}
120 145
121static void ls_head() 146static void ls_head()
122{ 147{
123 html("<table summary='tree listing' class='list'>\n"); 148 html("<table summary='tree listing' class='list'>\n");
124 html("<tr class='nohover'>"); 149 html("<tr class='nohover'>");
125 html("<th class='left'>Mode</th>"); 150 html("<th class='left'>Mode</th>");
126 html("<th class='left'>Name</th>"); 151 html("<th class='left'>Name</th>");
127 html("<th class='right'>Size</th>"); 152 html("<th class='right'>Size</th>");
128 html("<th/>"); 153 html("<th/>");
129 html("</tr>\n"); 154 html("</tr>\n");
130 header = 1; 155 header = 1;
131} 156}
132 157
133static void ls_tail() 158static void ls_tail()
134{ 159{
135 if (!header) 160 if (!header)
136 return; 161 return;
137 html("</table>\n"); 162 html("</table>\n");
138 header = 0; 163 header = 0;
139} 164}
140 165
141static void ls_tree(const unsigned char *sha1, char *path) 166static void ls_tree(const unsigned char *sha1, char *path)
142{ 167{
143 struct tree *tree; 168 struct tree *tree;
144 169
145 tree = parse_tree_indirect(sha1); 170 tree = parse_tree_indirect(sha1);
146 if (!tree) { 171 if (!tree) {
147 cgit_print_error(fmt("Not a tree object: %s", 172 cgit_print_error(fmt("Not a tree object: %s",
148 sha1_to_hex(sha1))); 173 sha1_to_hex(sha1)));
149 return; 174 return;
150 } 175 }
151 176
152 ls_head(); 177 ls_head();
153 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL); 178 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL);
154 ls_tail(); 179 ls_tail();
155} 180}
156 181
157 182
158static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 183static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
159 const char *pathname, unsigned mode, int stage, 184 const char *pathname, unsigned mode, int stage,