Fossil SCM

Provide a configuration option that can move the hash in a timeline before the comment, after the comment, or into the details, and can omit the details span.

drh 2017-11-24 20:10 trunk merge
Commit 4102f608461115ffbd829ad5dc5273c255ce8616c6d1a580a52691eb9922f20f
3 files changed +66 -38 +22 -1 +181 -97
+66 -38
--- src/finfo.c
+++ src/finfo.c
@@ -313,10 +313,15 @@
313313
int uBg = P("ubg")!=0;
314314
int fDebug = atoi(PD("debug","0"));
315315
int fShowId = P("showid")!=0;
316316
Stmt qparent;
317317
int iTableId = timeline_tableid();
318
+ int bHashBeforeComment = 0; /* Show hash before the comment */
319
+ int bHashAfterComment = 0; /* Show hash after the comment */
320
+ int bHashInDetail = 0; /* Show the hash inside the detail section */
321
+ int bShowDetail; /* Show the detail section */
322
+ int eCommentFormat; /* value for timeline-comment-format */
318323
319324
login_check_credentials();
320325
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
321326
style_header("File History");
322327
login_anonymous_available();
@@ -324,10 +329,17 @@
324329
if( brBg ) url_add_parameter(&url, "brbg", 0);
325330
if( uBg ) url_add_parameter(&url, "ubg", 0);
326331
baseCheckin = name_to_rid_www("ci");
327332
zPrevDate[0] = 0;
328333
zFilename = PD("name","");
334
+ eCommentFormat = db_get_int("timeline-comment-format", 0);
335
+ bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
336
+ switch( (eCommentFormat>>1)&3 ){
337
+ case 1: bHashAfterComment = 1; break;
338
+ case 2: bHashInDetail = 1; break;
339
+ default: bHashBeforeComment = 1; break;
340
+ }
329341
fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
330342
if( fnid==0 ){
331343
@ No such file: %h(zFilename)
332344
style_footer();
333345
return;
@@ -502,65 +514,78 @@
502514
if( zBgClr && zBgClr[0] ){
503515
@ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
504516
}else{
505517
@ <td class="timelineTableCell">
506518
}
507
- if( zUuid ){
508
- if( origCheckin==0 ){
519
+ if( bHashBeforeComment && zUuid ){
520
+ hyperlink_to_uuid(zUuid);
521
+ }
522
+ @ <span class="timelineComment timelineCheckinComment">%W(zCom)</span>
523
+ if( bHashAfterComment && zUuid ){
524
+ hyperlink_to_uuid(zUuid);
525
+ }
526
+ if( bShowDetail ){
527
+ cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
528
+ if( zUuid && bHashInDetail ){
529
+ @ file: %z(href("%R/artifact/%!S",zUuid))[%S(zUuid)]</a>
530
+ if( fShowId ){
531
+ int srcId = delta_source_rid(frid);
532
+ if( srcId>0 ){
533
+ @ id: %d(frid)&larr;%d(srcId)
534
+ }else{
535
+ @ id: %d(frid)
536
+ }
537
+ }
538
+ }
539
+ @ check-in:
540
+ hyperlink_to_uuid(zCkin);
541
+ if( fShowId ){
542
+ @ (%d(fmid))
543
+ }
544
+ @ user:
545
+ hyperlink_to_user(zUser, zDate, ",");
546
+ @ branch: %z(href("%R/timeline?t=%T&n=200",zBr))%h(zBr)</a>,
547
+ @ size: %d(szFile))
548
+ if( zUuid && origCheckin==0 ){
509549
if( nParent==0 ){
510550
@ <b>Added</b>
511551
}else if( pfnid ){
512552
char *zPrevName = db_text(0,"SELECT name FROM filename WHERE fnid=%d",
513553
pfnid);
514554
@ <b>Renamed</b> from
515555
@ %z(href("%R/finfo?name=%t", zPrevName))%h(zPrevName)</a>
516556
}
517557
}
518
- @ %z(href("%R/artifact/%!S",zUuid))[%S(zUuid)]</a>
519
- if( fShowId ){
520
- int srcId = delta_source_rid(frid);
521
- if( srcId>0 ){
522
- @ (%d(frid)&larr;%d(srcId))
523
- }else{
524
- @ (%d(frid))
525
- }
526
- }
527
- @ part of check-in
528
- }else{
529
- char *zNewName;
530
- zNewName = db_text(0,
531
- "SELECT name FROM filename WHERE fnid = "
532
- " (SELECT fnid FROM mlink"
533
- " WHERE mid=%d"
534
- " AND pfnid IN (SELECT fnid FROM filename WHERE name=%Q))",
535
- fmid, zFilename);
536
- if( zNewName ){
537
- @ <b>Renamed</b> to
538
- @ %z(href("%R/finfo?name=%t",zNewName))%h(zNewName)</a> by check-in
539
- fossil_free(zNewName);
540
- }else{
541
- @ <b>Deleted</b> by check-in
542
- }
543
- }
544
- hyperlink_to_uuid(zCkin);
545
- if( fShowId ){
546
- @ (%d(fmid))
547
- }
548
- @ %W(zCom) (user:
549
- hyperlink_to_user(zUser, zDate, ",");
550
- @ branch: %z(href("%R/timeline?t=%T&n=200",zBr))%h(zBr)</a>,
551
- @ size: %d(szFile))
552
- if( g.perm.Hyperlink && zUuid ){
553
- const char *z = zFilename;
558
+ if( zUuid==0 ){
559
+ char *zNewName;
560
+ zNewName = db_text(0,
561
+ "SELECT name FROM filename WHERE fnid = "
562
+ " (SELECT fnid FROM mlink"
563
+ " WHERE mid=%d"
564
+ " AND pfnid IN (SELECT fnid FROM filename WHERE name=%Q))",
565
+ fmid, zFilename);
566
+ if( zNewName ){
567
+ @ <b>Renamed</b> to
568
+ @ %z(href("%R/finfo?name=%t",zNewName))%h(zNewName)</a>
569
+ fossil_free(zNewName);
570
+ }else{
571
+ @ <b>Deleted</b>
572
+ }
573
+ }
574
+ }
575
+ if( g.perm.Hyperlink && zUuid ){
576
+ const char *z = zFilename;
577
+ @ <span class='timelineExtraLinks'>
554578
@ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
555579
@ [annotate]</a>
556580
@ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
557581
@ [blame]</a>
558582
@ %z(href("%R/timeline?n=200&uf=%!S",zUuid))[check-ins&nbsp;using]</a>
559583
if( fpid>0 ){
560584
@ %z(href("%R/fdiff?sbs=1&v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
561585
}
586
+ @ </span>
562587
}
563588
if( fDebug & FINFO_DEBUG_MLINK ){
564589
int ii;
565590
char *zAncLink;
566591
@ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
@@ -572,10 +597,13 @@
572597
}
573598
zAncLink = href("%R/finfo?name=%T&ci=%!S&debug=1",zFilename,zCkin);
574599
@ %z(zAncLink)[ancestry]</a>
575600
}
576601
tag_private_status(frid);
602
+ if( bShowDetail ){
603
+ @ </span>
604
+ }
577605
@ </td></tr>
578606
}
579607
db_finalize(&q);
580608
db_finalize(&qparent);
581609
if( pGraph ){
582610
--- src/finfo.c
+++ src/finfo.c
@@ -313,10 +313,15 @@
313 int uBg = P("ubg")!=0;
314 int fDebug = atoi(PD("debug","0"));
315 int fShowId = P("showid")!=0;
316 Stmt qparent;
317 int iTableId = timeline_tableid();
 
 
 
 
 
318
319 login_check_credentials();
320 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
321 style_header("File History");
322 login_anonymous_available();
@@ -324,10 +329,17 @@
324 if( brBg ) url_add_parameter(&url, "brbg", 0);
325 if( uBg ) url_add_parameter(&url, "ubg", 0);
326 baseCheckin = name_to_rid_www("ci");
327 zPrevDate[0] = 0;
328 zFilename = PD("name","");
 
 
 
 
 
 
 
329 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
330 if( fnid==0 ){
331 @ No such file: %h(zFilename)
332 style_footer();
333 return;
@@ -502,65 +514,78 @@
502 if( zBgClr && zBgClr[0] ){
503 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
504 }else{
505 @ <td class="timelineTableCell">
506 }
507 if( zUuid ){
508 if( origCheckin==0 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509 if( nParent==0 ){
510 @ <b>Added</b>
511 }else if( pfnid ){
512 char *zPrevName = db_text(0,"SELECT name FROM filename WHERE fnid=%d",
513 pfnid);
514 @ <b>Renamed</b> from
515 @ %z(href("%R/finfo?name=%t", zPrevName))%h(zPrevName)</a>
516 }
517 }
518 @ %z(href("%R/artifact/%!S",zUuid))[%S(zUuid)]</a>
519 if( fShowId ){
520 int srcId = delta_source_rid(frid);
521 if( srcId>0 ){
522 @ (%d(frid)&larr;%d(srcId))
523 }else{
524 @ (%d(frid))
525 }
526 }
527 @ part of check-in
528 }else{
529 char *zNewName;
530 zNewName = db_text(0,
531 "SELECT name FROM filename WHERE fnid = "
532 " (SELECT fnid FROM mlink"
533 " WHERE mid=%d"
534 " AND pfnid IN (SELECT fnid FROM filename WHERE name=%Q))",
535 fmid, zFilename);
536 if( zNewName ){
537 @ <b>Renamed</b> to
538 @ %z(href("%R/finfo?name=%t",zNewName))%h(zNewName)</a> by check-in
539 fossil_free(zNewName);
540 }else{
541 @ <b>Deleted</b> by check-in
542 }
543 }
544 hyperlink_to_uuid(zCkin);
545 if( fShowId ){
546 @ (%d(fmid))
547 }
548 @ %W(zCom) (user:
549 hyperlink_to_user(zUser, zDate, ",");
550 @ branch: %z(href("%R/timeline?t=%T&n=200",zBr))%h(zBr)</a>,
551 @ size: %d(szFile))
552 if( g.perm.Hyperlink && zUuid ){
553 const char *z = zFilename;
554 @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
555 @ [annotate]</a>
556 @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
557 @ [blame]</a>
558 @ %z(href("%R/timeline?n=200&uf=%!S",zUuid))[check-ins&nbsp;using]</a>
559 if( fpid>0 ){
560 @ %z(href("%R/fdiff?sbs=1&v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
561 }
 
562 }
563 if( fDebug & FINFO_DEBUG_MLINK ){
564 int ii;
565 char *zAncLink;
566 @ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
@@ -572,10 +597,13 @@
572 }
573 zAncLink = href("%R/finfo?name=%T&ci=%!S&debug=1",zFilename,zCkin);
574 @ %z(zAncLink)[ancestry]</a>
575 }
576 tag_private_status(frid);
 
 
 
577 @ </td></tr>
578 }
579 db_finalize(&q);
580 db_finalize(&qparent);
581 if( pGraph ){
582
--- src/finfo.c
+++ src/finfo.c
@@ -313,10 +313,15 @@
313 int uBg = P("ubg")!=0;
314 int fDebug = atoi(PD("debug","0"));
315 int fShowId = P("showid")!=0;
316 Stmt qparent;
317 int iTableId = timeline_tableid();
318 int bHashBeforeComment = 0; /* Show hash before the comment */
319 int bHashAfterComment = 0; /* Show hash after the comment */
320 int bHashInDetail = 0; /* Show the hash inside the detail section */
321 int bShowDetail; /* Show the detail section */
322 int eCommentFormat; /* value for timeline-comment-format */
323
324 login_check_credentials();
325 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
326 style_header("File History");
327 login_anonymous_available();
@@ -324,10 +329,17 @@
329 if( brBg ) url_add_parameter(&url, "brbg", 0);
330 if( uBg ) url_add_parameter(&url, "ubg", 0);
331 baseCheckin = name_to_rid_www("ci");
332 zPrevDate[0] = 0;
333 zFilename = PD("name","");
334 eCommentFormat = db_get_int("timeline-comment-format", 0);
335 bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
336 switch( (eCommentFormat>>1)&3 ){
337 case 1: bHashAfterComment = 1; break;
338 case 2: bHashInDetail = 1; break;
339 default: bHashBeforeComment = 1; break;
340 }
341 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
342 if( fnid==0 ){
343 @ No such file: %h(zFilename)
344 style_footer();
345 return;
@@ -502,65 +514,78 @@
514 if( zBgClr && zBgClr[0] ){
515 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
516 }else{
517 @ <td class="timelineTableCell">
518 }
519 if( bHashBeforeComment && zUuid ){
520 hyperlink_to_uuid(zUuid);
521 }
522 @ <span class="timelineComment timelineCheckinComment">%W(zCom)</span>
523 if( bHashAfterComment && zUuid ){
524 hyperlink_to_uuid(zUuid);
525 }
526 if( bShowDetail ){
527 cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
528 if( zUuid && bHashInDetail ){
529 @ file: %z(href("%R/artifact/%!S",zUuid))[%S(zUuid)]</a>
530 if( fShowId ){
531 int srcId = delta_source_rid(frid);
532 if( srcId>0 ){
533 @ id: %d(frid)&larr;%d(srcId)
534 }else{
535 @ id: %d(frid)
536 }
537 }
538 }
539 @ check-in:
540 hyperlink_to_uuid(zCkin);
541 if( fShowId ){
542 @ (%d(fmid))
543 }
544 @ user:
545 hyperlink_to_user(zUser, zDate, ",");
546 @ branch: %z(href("%R/timeline?t=%T&n=200",zBr))%h(zBr)</a>,
547 @ size: %d(szFile))
548 if( zUuid && origCheckin==0 ){
549 if( nParent==0 ){
550 @ <b>Added</b>
551 }else if( pfnid ){
552 char *zPrevName = db_text(0,"SELECT name FROM filename WHERE fnid=%d",
553 pfnid);
554 @ <b>Renamed</b> from
555 @ %z(href("%R/finfo?name=%t", zPrevName))%h(zPrevName)</a>
556 }
557 }
558 if( zUuid==0 ){
559 char *zNewName;
560 zNewName = db_text(0,
561 "SELECT name FROM filename WHERE fnid = "
562 " (SELECT fnid FROM mlink"
563 " WHERE mid=%d"
564 " AND pfnid IN (SELECT fnid FROM filename WHERE name=%Q))",
565 fmid, zFilename);
566 if( zNewName ){
567 @ <b>Renamed</b> to
568 @ %z(href("%R/finfo?name=%t",zNewName))%h(zNewName)</a>
569 fossil_free(zNewName);
570 }else{
571 @ <b>Deleted</b>
572 }
573 }
574 }
575 if( g.perm.Hyperlink && zUuid ){
576 const char *z = zFilename;
577 @ <span class='timelineExtraLinks'>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578 @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
579 @ [annotate]</a>
580 @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
581 @ [blame]</a>
582 @ %z(href("%R/timeline?n=200&uf=%!S",zUuid))[check-ins&nbsp;using]</a>
583 if( fpid>0 ){
584 @ %z(href("%R/fdiff?sbs=1&v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
585 }
586 @ </span>
587 }
588 if( fDebug & FINFO_DEBUG_MLINK ){
589 int ii;
590 char *zAncLink;
591 @ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
@@ -572,10 +597,13 @@
597 }
598 zAncLink = href("%R/finfo?name=%T&ci=%!S&debug=1",zFilename,zCkin);
599 @ %z(zAncLink)[ancestry]</a>
600 }
601 tag_private_status(frid);
602 if( bShowDetail ){
603 @ </span>
604 }
605 @ </td></tr>
606 }
607 db_finalize(&q);
608 db_finalize(&qparent);
609 if( pGraph ){
610
+22 -1
--- src/setup.c
+++ src/setup.c
@@ -1446,10 +1446,18 @@
14461446
"0", "HH:MM",
14471447
"1", "HH:MM:SS",
14481448
"2", "YYYY-MM-DD HH:MM",
14491449
"3", "YYMMDD HH:MM",
14501450
"4", "(off)"
1451
+ };
1452
+ static const char *const azCommentFormats[] = {
1453
+ "0", "[hash] comment (details)",
1454
+ "1", "[hash] comment",
1455
+ "2", "comment [hash] (details)",
1456
+ "3", "comment [hash]",
1457
+ "4", "comment (details)",
1458
+ "5", "comment-only",
14511459
};
14521460
login_check_credentials();
14531461
if( !g.perm.Setup ){
14541462
login_needed(0);
14551463
return;
@@ -1457,12 +1465,25 @@
14571465
14581466
style_header("Timeline Display Preferences");
14591467
db_begin_transaction();
14601468
@ <form action="%s(g.zTop)/setup_timeline" method="post"><div>
14611469
login_insert_csrf_secret();
1462
-
14631470
@ <p><input type="submit" name="submit" value="Apply Changes" /></p>
1471
+
1472
+ @ <hr />
1473
+ multiple_choice_attribute("Comment Format", "timeline-comment-format",
1474
+ "tcf", "0", count(azCommentFormats)/2, azCommentFormats);
1475
+ @ <p>Each timeline entry may contain the following subsections:
1476
+ @ <ol>
1477
+ @ <li> an artifact hash with a hyperlink to a detail page
1478
+ @ <li> the check-in comment or other text describing the item
1479
+ @ <li> details, such as the user, branch, tags, etc.
1480
+ @ </ol>
1481
+ @ This control selects which of the three items above are included on each
1482
+ @ timeline entry and the order in which they are displayed.
1483
+ @ (Preperty: "timeline-commit-format")</p>
1484
+
14641485
@ <hr />
14651486
onoff_attribute("Allow block-markup in timeline",
14661487
"timeline-block-markup", "tbm", 0, 0);
14671488
@ <p>In timeline displays, check-in comments can be displayed with or
14681489
@ without block markup such as paragraphs, tables, etc.
14691490
--- src/setup.c
+++ src/setup.c
@@ -1446,10 +1446,18 @@
1446 "0", "HH:MM",
1447 "1", "HH:MM:SS",
1448 "2", "YYYY-MM-DD HH:MM",
1449 "3", "YYMMDD HH:MM",
1450 "4", "(off)"
 
 
 
 
 
 
 
 
1451 };
1452 login_check_credentials();
1453 if( !g.perm.Setup ){
1454 login_needed(0);
1455 return;
@@ -1457,12 +1465,25 @@
1457
1458 style_header("Timeline Display Preferences");
1459 db_begin_transaction();
1460 @ <form action="%s(g.zTop)/setup_timeline" method="post"><div>
1461 login_insert_csrf_secret();
1462
1463 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1464 @ <hr />
1465 onoff_attribute("Allow block-markup in timeline",
1466 "timeline-block-markup", "tbm", 0, 0);
1467 @ <p>In timeline displays, check-in comments can be displayed with or
1468 @ without block markup such as paragraphs, tables, etc.
1469
--- src/setup.c
+++ src/setup.c
@@ -1446,10 +1446,18 @@
1446 "0", "HH:MM",
1447 "1", "HH:MM:SS",
1448 "2", "YYYY-MM-DD HH:MM",
1449 "3", "YYMMDD HH:MM",
1450 "4", "(off)"
1451 };
1452 static const char *const azCommentFormats[] = {
1453 "0", "[hash] comment (details)",
1454 "1", "[hash] comment",
1455 "2", "comment [hash] (details)",
1456 "3", "comment [hash]",
1457 "4", "comment (details)",
1458 "5", "comment-only",
1459 };
1460 login_check_credentials();
1461 if( !g.perm.Setup ){
1462 login_needed(0);
1463 return;
@@ -1457,12 +1465,25 @@
1465
1466 style_header("Timeline Display Preferences");
1467 db_begin_transaction();
1468 @ <form action="%s(g.zTop)/setup_timeline" method="post"><div>
1469 login_insert_csrf_secret();
 
1470 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
1471
1472 @ <hr />
1473 multiple_choice_attribute("Comment Format", "timeline-comment-format",
1474 "tcf", "0", count(azCommentFormats)/2, azCommentFormats);
1475 @ <p>Each timeline entry may contain the following subsections:
1476 @ <ol>
1477 @ <li> an artifact hash with a hyperlink to a detail page
1478 @ <li> the check-in comment or other text describing the item
1479 @ <li> details, such as the user, branch, tags, etc.
1480 @ </ol>
1481 @ This control selects which of the three items above are included on each
1482 @ timeline entry and the order in which they are displayed.
1483 @ (Preperty: "timeline-commit-format")</p>
1484
1485 @ <hr />
1486 onoff_attribute("Allow block-markup in timeline",
1487 "timeline-block-markup", "tbm", 0, 0);
1488 @ <p>In timeline displays, check-in comments can be displayed with or
1489 @ without block markup such as paragraphs, tables, etc.
1490
+181 -97
--- src/timeline.c
+++ src/timeline.c
@@ -248,10 +248,15 @@
248248
static Stmt qbranch;
249249
int pendingEndTr = 0; /* True if a </td></tr> is needed */
250250
int vid = 0; /* Current checkout version */
251251
int dateFormat = 0; /* 0: HH:MM (default) */
252252
int bCommentGitStyle = 0; /* Only show comments through first blank line */
253
+ int bHashBeforeComment = 0; /* Show hash before the comment */
254
+ int bHashAfterComment = 0; /* Show hash after the comment */
255
+ int bHashInDetail = 0; /* Show the hash inside the detail section */
256
+ int bShowDetail; /* Show the detail section */
257
+ int eCommentFormat; /* value for timeline-comment-format */
253258
const char *zDateFmt;
254259
int iTableId = timeline_tableid();
255260
256261
if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
257262
vid = db_lget_int("checkout", 0);
@@ -258,10 +263,17 @@
258263
}
259264
zPrevDate[0] = 0;
260265
mxWikiLen = db_get_int("timeline-max-comment", 0);
261266
dateFormat = db_get_int("timeline-date-format", 0);
262267
bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
268
+ eCommentFormat = db_get_int("timeline-comment-format", 0);
269
+ bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
270
+ switch( (eCommentFormat>>1)&3 ){
271
+ case 1: bHashAfterComment = 1; break;
272
+ case 2: bHashInDetail = 1; break;
273
+ default: bHashBeforeComment = 1; break;
274
+ }
263275
zDateFmt = P("datefmt");
264276
if( zDateFmt ) dateFormat = atoi(zDateFmt);
265277
if( tmFlags & TIMELINE_GRAPH ){
266278
pGraph = graph_init();
267279
}
@@ -420,118 +432,190 @@
420432
@ &bull;
421433
}
422434
if( modPending ){
423435
@ <span class="modpending">(Awaiting Moderator Approval)</span>
424436
}
425
- if( zType[0]=='c' ){
426
- if( tmFlags & TIMELINE_BISECT ){
427
- static Stmt bisectQuery;
428
- db_prepare(&bisectQuery, "SELECT seq, stat FROM bilog WHERE rid=:rid");
429
- db_bind_int(&bisectQuery, ":rid", rid);
430
- if( db_step(&bisectQuery)==SQLITE_ROW ){
431
- @ <b>%s(db_column_text(&bisectQuery,1))</b>
432
- @ (%d(db_column_int(&bisectQuery,0)))
433
- }
434
- db_reset(&bisectQuery);
435
- }
436
- hyperlink_to_uuid(zUuid);
437
- if( isLeaf ){
438
- if( db_exists("SELECT 1 FROM tagxref"
439
- " WHERE rid=%d AND tagid=%d AND tagtype>0",
440
- rid, TAG_CLOSED) ){
441
- @ <span class="timelineLeaf">Closed-Leaf:</span>
442
- }else{
443
- @ <span class="timelineLeaf">Leaf:</span>
444
- }
445
- }
446
- }else if( zType[0]=='e' && tagid ){
447
- hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
448
- }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
449
- hyperlink_to_uuid(zUuid);
450
- }
451
- if( tmFlags & TIMELINE_SHOWRID ){
452
- int srcId = delta_source_rid(rid);
453
- if( srcId ){
454
- @ (%d(rid)&larr;%d(srcId))
455
- }else{
456
- @ (%d(rid))
437
+ if( (tmFlags & TIMELINE_BISECT)!=0 && zType[0]=='c' ){
438
+ static Stmt bisectQuery;
439
+ db_prepare(&bisectQuery, "SELECT seq, stat FROM bilog WHERE rid=:rid");
440
+ db_bind_int(&bisectQuery, ":rid", rid);
441
+ if( db_step(&bisectQuery)==SQLITE_ROW ){
442
+ @ <b>%s(db_column_text(&bisectQuery,1))</b>
443
+ @ (%d(db_column_int(&bisectQuery,0)))
444
+ }
445
+ db_reset(&bisectQuery);
446
+ }
447
+ if( bHashBeforeComment ){
448
+ if( zType[0]=='c' ){
449
+ hyperlink_to_uuid(zUuid);
450
+ if( isLeaf ){
451
+ if( db_exists("SELECT 1 FROM tagxref"
452
+ " WHERE rid=%d AND tagid=%d AND tagtype>0",
453
+ rid, TAG_CLOSED) ){
454
+ @ <span class="timelineLeaf">Closed-Leaf:</span>
455
+ }else{
456
+ @ <span class="timelineLeaf">Leaf:</span>
457
+ }
458
+ }
459
+ }else if( zType[0]=='e' && tagid ){
460
+ hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
461
+ }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
462
+ hyperlink_to_uuid(zUuid);
463
+ }
464
+ if( tmFlags & TIMELINE_SHOWRID ){
465
+ int srcId = delta_source_rid(rid);
466
+ if( srcId ){
467
+ @ (%d(rid)&larr;%d(srcId))
468
+ }else{
469
+ @ (%d(rid))
470
+ }
457471
}
458472
}
459473
db_column_blob(pQuery, commentColumn, &comment);
460474
if( zType[0]!='c' ){
461475
/* Comments for anything other than a check-in are generated by
462476
** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
477
+ @ <span class='timelineComment'>
463478
wiki_convert(&comment, 0, WIKI_INLINE);
464
- }else if( bCommentGitStyle ){
465
- /* Truncate comment at first blank line */
466
- int ii, jj;
467
- int n = blob_size(&comment);
468
- char *z = blob_str(&comment);
469
- for(ii=0; ii<n; ii++){
470
- if( z[ii]=='\n' ){
471
- for(jj=ii+1; jj<n && z[jj]!='\n' && fossil_isspace(z[jj]); jj++){}
472
- if( z[jj]=='\n' ) break;
473
- }
474
- }
475
- z[ii] = 0;
476
- @ <span class="timelineComment">%W(z)</span>
477
- }else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
478
- Blob truncated;
479
- blob_zero(&truncated);
480
- blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
481
- blob_append(&truncated, "...", 3);
482
- @ <span class="timelineComment">%W(blob_str(&truncated))</span>
483
- blob_reset(&truncated);
479
+ @ </span>
484480
}else{
485
- @ <span class="timelineComment">%W(blob_str(&comment))</span>
481
+ @ <span class='timelineComment timelineCheckinComment'>
482
+ if( bCommentGitStyle ){
483
+ /* Truncate comment at first blank line */
484
+ int ii, jj;
485
+ int n = blob_size(&comment);
486
+ char *z = blob_str(&comment);
487
+ for(ii=0; ii<n; ii++){
488
+ if( z[ii]=='\n' ){
489
+ for(jj=ii+1; jj<n && z[jj]!='\n' && fossil_isspace(z[jj]); jj++){}
490
+ if( z[jj]=='\n' ) break;
491
+ }
492
+ }
493
+ z[ii] = 0;
494
+ @ %W(z)
495
+ }else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
496
+ Blob truncated;
497
+ blob_zero(&truncated);
498
+ blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
499
+ blob_append(&truncated, "...", 3);
500
+ @ %W(blob_str(&truncated))
501
+ blob_reset(&truncated);
502
+ }else{
503
+ @ %W(blob_str(&comment))
504
+ }
505
+ @ </span>
486506
}
487507
blob_reset(&comment);
488508
489
- /* Generate the "user: USERNAME" at the end of the comment, together
490
- ** with a hyperlink to another timeline for that user.
491
- */
492
- if( zTagList && zTagList[0]==0 ) zTagList = 0;
493
- if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){
494
- char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd&n=200", zDispUser, zDate);
495
- @ (user: %z(href("%z",zLink))%h(zDispUser)</a>%s(zTagList?",":"\051")
496
- }else{
497
- @ (user: %h(zDispUser)%s(zTagList?",":"\051")
498
- }
499
-
500
- /* Generate a "detail" link for tags. */
501
- if( (zType[0]=='g' || zType[0]=='w' || zType[0]=='t') && g.perm.Hyperlink ){
502
- @ [%z(href("%R/info/%!S",zUuid))details</a>]
503
- }
504
-
505
- /* Generate the "tags: TAGLIST" at the end of the comment, together
506
- ** with hyperlinks to the tag list.
507
- */
508
- if( zTagList ){
509
- if( g.perm.Hyperlink ){
510
- int i;
511
- const char *z = zTagList;
512
- Blob links;
513
- blob_zero(&links);
514
- while( z && z[0] ){
515
- for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
516
- if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
517
- blob_appendf(&links,
518
- "%z%#h</a>%.2s",
519
- href("%R/timeline?r=%#t&nd&c=%t&n=200",i,z,zDate), i,z, &z[i]
520
- );
521
- }else{
522
- blob_appendf(&links, "%#h", i+2, z);
523
- }
524
- if( z[i]==0 ) break;
525
- z += i+2;
526
- }
527
- @ tags: %s(blob_str(&links)))
528
- blob_reset(&links);
529
- }else{
530
- @ tags: %h(zTagList))
531
- }
532
- }
509
+ if( bHashAfterComment ){
510
+ if( zType[0]=='c' ){
511
+ hyperlink_to_uuid(zUuid);
512
+ if( isLeaf ){
513
+ if( db_exists("SELECT 1 FROM tagxref"
514
+ " WHERE rid=%d AND tagid=%d AND tagtype>0",
515
+ rid, TAG_CLOSED) ){
516
+ @ <span class="timelineLeaf">Closed-Leaf</span>
517
+ }else{
518
+ @ <span class="timelineLeaf">Leaf</span>
519
+ }
520
+ }
521
+ }else if( zType[0]=='e' && tagid ){
522
+ hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
523
+ }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
524
+ hyperlink_to_uuid(zUuid);
525
+ }
526
+ if( tmFlags & TIMELINE_SHOWRID ){
527
+ int srcId = delta_source_rid(rid);
528
+ if( srcId ){
529
+ @ (%d(rid)&larr;%d(srcId))
530
+ }else{
531
+ @ (%d(rid))
532
+ }
533
+ }
534
+ }
535
+
536
+
537
+ /* Generate extra information and hyperlinks to follow the comment.
538
+ ** Example: "(check-in: [abcdefg], user: drh, tags: trunk)"
539
+ */
540
+ if( bShowDetail ){
541
+ if( zType[0]=='c' ){
542
+ cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
543
+ }else{
544
+ cgi_printf("<span class='timelineDetail'>(");
545
+ }
546
+
547
+ if( bHashInDetail ){
548
+ if( zType[0]=='c' ){
549
+ if( isLeaf ){
550
+ if( db_exists("SELECT 1 FROM tagxref"
551
+ " WHERE rid=%d AND tagid=%d AND tagtype>0",
552
+ rid, TAG_CLOSED) ){
553
+ @ <span class='timelineLeaf'>Closed-Leaf</span>
554
+ }else{
555
+ @ <span class='timelineLeaf'>Leaf</span>
556
+ }
557
+ }
558
+ cgi_printf("check-in: ");
559
+ hyperlink_to_uuid(zUuid);
560
+ }else if( zType[0]=='e' && tagid ){
561
+ cgi_printf("technote: ");
562
+ hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
563
+ }else{
564
+ cgi_printf("artifact: ");
565
+ hyperlink_to_uuid(zUuid);
566
+ }
567
+ }
568
+
569
+ if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){
570
+ char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd&n=200", zDispUser, zDate);
571
+ cgi_printf("user: %z%h</a>", href("%z",zLink), zDispUser);
572
+ }else{
573
+ cgi_printf("user: %h", zDispUser);
574
+ }
575
+
576
+ /* Generate the "tags: TAGLIST" at the end of the comment, together
577
+ ** with hyperlinks to the tag list.
578
+ */
579
+ if( zTagList && zTagList[0]==0 ) zTagList = 0;
580
+ if( zTagList ){
581
+ if( g.perm.Hyperlink ){
582
+ int i;
583
+ const char *z = zTagList;
584
+ Blob links;
585
+ blob_zero(&links);
586
+ while( z && z[0] ){
587
+ for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
588
+ if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
589
+ blob_appendf(&links,
590
+ "%z%#h</a>%.2s",
591
+ href("%R/timeline?r=%#t&nd&c=%t&n=200",i,z,zDate), i,z, &z[i]
592
+ );
593
+ }else{
594
+ blob_appendf(&links, "%#h", i+2, z);
595
+ }
596
+ if( z[i]==0 ) break;
597
+ z += i+2;
598
+ }
599
+ cgi_printf(" tags: %s", blob_str(&links));
600
+ blob_reset(&links);
601
+ }else{
602
+ cgi_printf(" tags: %h", zTagList);
603
+ }
604
+ }
605
+
606
+ if( tmFlags & TIMELINE_SHOWRID ){
607
+ int srcId = delta_source_rid(rid);
608
+ if( srcId ){
609
+ cgi_printf(" id: %d&larr;%d", rid, srcId);
610
+ }else{
611
+ cgi_printf(" id: %d", rid);
612
+ }
613
+ }
614
+ cgi_printf(")</span>\n"); /* End of the details section */
615
+ }
616
+
533617
tag_private_status(rid);
534618
535619
/* Generate extra hyperlinks at the end of the comment */
536620
if( xExtra ){
537621
xExtra(rid);
538622
--- src/timeline.c
+++ src/timeline.c
@@ -248,10 +248,15 @@
248 static Stmt qbranch;
249 int pendingEndTr = 0; /* True if a </td></tr> is needed */
250 int vid = 0; /* Current checkout version */
251 int dateFormat = 0; /* 0: HH:MM (default) */
252 int bCommentGitStyle = 0; /* Only show comments through first blank line */
 
 
 
 
 
253 const char *zDateFmt;
254 int iTableId = timeline_tableid();
255
256 if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
257 vid = db_lget_int("checkout", 0);
@@ -258,10 +263,17 @@
258 }
259 zPrevDate[0] = 0;
260 mxWikiLen = db_get_int("timeline-max-comment", 0);
261 dateFormat = db_get_int("timeline-date-format", 0);
262 bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
 
 
 
 
 
 
 
263 zDateFmt = P("datefmt");
264 if( zDateFmt ) dateFormat = atoi(zDateFmt);
265 if( tmFlags & TIMELINE_GRAPH ){
266 pGraph = graph_init();
267 }
@@ -420,118 +432,190 @@
420 @ &bull;
421 }
422 if( modPending ){
423 @ <span class="modpending">(Awaiting Moderator Approval)</span>
424 }
425 if( zType[0]=='c' ){
426 if( tmFlags & TIMELINE_BISECT ){
427 static Stmt bisectQuery;
428 db_prepare(&bisectQuery, "SELECT seq, stat FROM bilog WHERE rid=:rid");
429 db_bind_int(&bisectQuery, ":rid", rid);
430 if( db_step(&bisectQuery)==SQLITE_ROW ){
431 @ <b>%s(db_column_text(&bisectQuery,1))</b>
432 @ (%d(db_column_int(&bisectQuery,0)))
433 }
434 db_reset(&bisectQuery);
435 }
436 hyperlink_to_uuid(zUuid);
437 if( isLeaf ){
438 if( db_exists("SELECT 1 FROM tagxref"
439 " WHERE rid=%d AND tagid=%d AND tagtype>0",
440 rid, TAG_CLOSED) ){
441 @ <span class="timelineLeaf">Closed-Leaf:</span>
442 }else{
443 @ <span class="timelineLeaf">Leaf:</span>
444 }
445 }
446 }else if( zType[0]=='e' && tagid ){
447 hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
448 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
449 hyperlink_to_uuid(zUuid);
450 }
451 if( tmFlags & TIMELINE_SHOWRID ){
452 int srcId = delta_source_rid(rid);
453 if( srcId ){
454 @ (%d(rid)&larr;%d(srcId))
455 }else{
456 @ (%d(rid))
 
 
457 }
458 }
459 db_column_blob(pQuery, commentColumn, &comment);
460 if( zType[0]!='c' ){
461 /* Comments for anything other than a check-in are generated by
462 ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
 
463 wiki_convert(&comment, 0, WIKI_INLINE);
464 }else if( bCommentGitStyle ){
465 /* Truncate comment at first blank line */
466 int ii, jj;
467 int n = blob_size(&comment);
468 char *z = blob_str(&comment);
469 for(ii=0; ii<n; ii++){
470 if( z[ii]=='\n' ){
471 for(jj=ii+1; jj<n && z[jj]!='\n' && fossil_isspace(z[jj]); jj++){}
472 if( z[jj]=='\n' ) break;
473 }
474 }
475 z[ii] = 0;
476 @ <span class="timelineComment">%W(z)</span>
477 }else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
478 Blob truncated;
479 blob_zero(&truncated);
480 blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
481 blob_append(&truncated, "...", 3);
482 @ <span class="timelineComment">%W(blob_str(&truncated))</span>
483 blob_reset(&truncated);
484 }else{
485 @ <span class="timelineComment">%W(blob_str(&comment))</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486 }
487 blob_reset(&comment);
488
489 /* Generate the "user: USERNAME" at the end of the comment, together
490 ** with a hyperlink to another timeline for that user.
491 */
492 if( zTagList && zTagList[0]==0 ) zTagList = 0;
493 if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){
494 char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd&n=200", zDispUser, zDate);
495 @ (user: %z(href("%z",zLink))%h(zDispUser)</a>%s(zTagList?",":"\051")
496 }else{
497 @ (user: %h(zDispUser)%s(zTagList?",":"\051")
498 }
499
500 /* Generate a "detail" link for tags. */
501 if( (zType[0]=='g' || zType[0]=='w' || zType[0]=='t') && g.perm.Hyperlink ){
502 @ [%z(href("%R/info/%!S",zUuid))details</a>]
503 }
504
505 /* Generate the "tags: TAGLIST" at the end of the comment, together
506 ** with hyperlinks to the tag list.
507 */
508 if( zTagList ){
509 if( g.perm.Hyperlink ){
510 int i;
511 const char *z = zTagList;
512 Blob links;
513 blob_zero(&links);
514 while( z && z[0] ){
515 for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
516 if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
517 blob_appendf(&links,
518 "%z%#h</a>%.2s",
519 href("%R/timeline?r=%#t&nd&c=%t&n=200",i,z,zDate), i,z, &z[i]
520 );
521 }else{
522 blob_appendf(&links, "%#h", i+2, z);
523 }
524 if( z[i]==0 ) break;
525 z += i+2;
526 }
527 @ tags: %s(blob_str(&links)))
528 blob_reset(&links);
529 }else{
530 @ tags: %h(zTagList))
531 }
532 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533 tag_private_status(rid);
534
535 /* Generate extra hyperlinks at the end of the comment */
536 if( xExtra ){
537 xExtra(rid);
538
--- src/timeline.c
+++ src/timeline.c
@@ -248,10 +248,15 @@
248 static Stmt qbranch;
249 int pendingEndTr = 0; /* True if a </td></tr> is needed */
250 int vid = 0; /* Current checkout version */
251 int dateFormat = 0; /* 0: HH:MM (default) */
252 int bCommentGitStyle = 0; /* Only show comments through first blank line */
253 int bHashBeforeComment = 0; /* Show hash before the comment */
254 int bHashAfterComment = 0; /* Show hash after the comment */
255 int bHashInDetail = 0; /* Show the hash inside the detail section */
256 int bShowDetail; /* Show the detail section */
257 int eCommentFormat; /* value for timeline-comment-format */
258 const char *zDateFmt;
259 int iTableId = timeline_tableid();
260
261 if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
262 vid = db_lget_int("checkout", 0);
@@ -258,10 +263,17 @@
263 }
264 zPrevDate[0] = 0;
265 mxWikiLen = db_get_int("timeline-max-comment", 0);
266 dateFormat = db_get_int("timeline-date-format", 0);
267 bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
268 eCommentFormat = db_get_int("timeline-comment-format", 0);
269 bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
270 switch( (eCommentFormat>>1)&3 ){
271 case 1: bHashAfterComment = 1; break;
272 case 2: bHashInDetail = 1; break;
273 default: bHashBeforeComment = 1; break;
274 }
275 zDateFmt = P("datefmt");
276 if( zDateFmt ) dateFormat = atoi(zDateFmt);
277 if( tmFlags & TIMELINE_GRAPH ){
278 pGraph = graph_init();
279 }
@@ -420,118 +432,190 @@
432 @ &bull;
433 }
434 if( modPending ){
435 @ <span class="modpending">(Awaiting Moderator Approval)</span>
436 }
437 if( (tmFlags & TIMELINE_BISECT)!=0 && zType[0]=='c' ){
438 static Stmt bisectQuery;
439 db_prepare(&bisectQuery, "SELECT seq, stat FROM bilog WHERE rid=:rid");
440 db_bind_int(&bisectQuery, ":rid", rid);
441 if( db_step(&bisectQuery)==SQLITE_ROW ){
442 @ <b>%s(db_column_text(&bisectQuery,1))</b>
443 @ (%d(db_column_int(&bisectQuery,0)))
444 }
445 db_reset(&bisectQuery);
446 }
447 if( bHashBeforeComment ){
448 if( zType[0]=='c' ){
449 hyperlink_to_uuid(zUuid);
450 if( isLeaf ){
451 if( db_exists("SELECT 1 FROM tagxref"
452 " WHERE rid=%d AND tagid=%d AND tagtype>0",
453 rid, TAG_CLOSED) ){
454 @ <span class="timelineLeaf">Closed-Leaf:</span>
455 }else{
456 @ <span class="timelineLeaf">Leaf:</span>
457 }
458 }
459 }else if( zType[0]=='e' && tagid ){
460 hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
461 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
462 hyperlink_to_uuid(zUuid);
463 }
464 if( tmFlags & TIMELINE_SHOWRID ){
465 int srcId = delta_source_rid(rid);
466 if( srcId ){
467 @ (%d(rid)&larr;%d(srcId))
468 }else{
469 @ (%d(rid))
470 }
471 }
472 }
473 db_column_blob(pQuery, commentColumn, &comment);
474 if( zType[0]!='c' ){
475 /* Comments for anything other than a check-in are generated by
476 ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
477 @ <span class='timelineComment'>
478 wiki_convert(&comment, 0, WIKI_INLINE);
479 @ </span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480 }else{
481 @ <span class='timelineComment timelineCheckinComment'>
482 if( bCommentGitStyle ){
483 /* Truncate comment at first blank line */
484 int ii, jj;
485 int n = blob_size(&comment);
486 char *z = blob_str(&comment);
487 for(ii=0; ii<n; ii++){
488 if( z[ii]=='\n' ){
489 for(jj=ii+1; jj<n && z[jj]!='\n' && fossil_isspace(z[jj]); jj++){}
490 if( z[jj]=='\n' ) break;
491 }
492 }
493 z[ii] = 0;
494 @ %W(z)
495 }else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
496 Blob truncated;
497 blob_zero(&truncated);
498 blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
499 blob_append(&truncated, "...", 3);
500 @ %W(blob_str(&truncated))
501 blob_reset(&truncated);
502 }else{
503 @ %W(blob_str(&comment))
504 }
505 @ </span>
506 }
507 blob_reset(&comment);
508
509 if( bHashAfterComment ){
510 if( zType[0]=='c' ){
511 hyperlink_to_uuid(zUuid);
512 if( isLeaf ){
513 if( db_exists("SELECT 1 FROM tagxref"
514 " WHERE rid=%d AND tagid=%d AND tagtype>0",
515 rid, TAG_CLOSED) ){
516 @ <span class="timelineLeaf">Closed-Leaf</span>
517 }else{
518 @ <span class="timelineLeaf">Leaf</span>
519 }
520 }
521 }else if( zType[0]=='e' && tagid ){
522 hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
523 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
524 hyperlink_to_uuid(zUuid);
525 }
526 if( tmFlags & TIMELINE_SHOWRID ){
527 int srcId = delta_source_rid(rid);
528 if( srcId ){
529 @ (%d(rid)&larr;%d(srcId))
530 }else{
531 @ (%d(rid))
532 }
533 }
534 }
535
536
537 /* Generate extra information and hyperlinks to follow the comment.
538 ** Example: "(check-in: [abcdefg], user: drh, tags: trunk)"
539 */
540 if( bShowDetail ){
541 if( zType[0]=='c' ){
542 cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
543 }else{
544 cgi_printf("<span class='timelineDetail'>(");
545 }
546
547 if( bHashInDetail ){
548 if( zType[0]=='c' ){
549 if( isLeaf ){
550 if( db_exists("SELECT 1 FROM tagxref"
551 " WHERE rid=%d AND tagid=%d AND tagtype>0",
552 rid, TAG_CLOSED) ){
553 @ <span class='timelineLeaf'>Closed-Leaf</span>
554 }else{
555 @ <span class='timelineLeaf'>Leaf</span>
556 }
557 }
558 cgi_printf("check-in: ");
559 hyperlink_to_uuid(zUuid);
560 }else if( zType[0]=='e' && tagid ){
561 cgi_printf("technote: ");
562 hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
563 }else{
564 cgi_printf("artifact: ");
565 hyperlink_to_uuid(zUuid);
566 }
567 }
568
569 if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){
570 char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd&n=200", zDispUser, zDate);
571 cgi_printf("user: %z%h</a>", href("%z",zLink), zDispUser);
572 }else{
573 cgi_printf("user: %h", zDispUser);
574 }
575
576 /* Generate the "tags: TAGLIST" at the end of the comment, together
577 ** with hyperlinks to the tag list.
578 */
579 if( zTagList && zTagList[0]==0 ) zTagList = 0;
580 if( zTagList ){
581 if( g.perm.Hyperlink ){
582 int i;
583 const char *z = zTagList;
584 Blob links;
585 blob_zero(&links);
586 while( z && z[0] ){
587 for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
588 if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
589 blob_appendf(&links,
590 "%z%#h</a>%.2s",
591 href("%R/timeline?r=%#t&nd&c=%t&n=200",i,z,zDate), i,z, &z[i]
592 );
593 }else{
594 blob_appendf(&links, "%#h", i+2, z);
595 }
596 if( z[i]==0 ) break;
597 z += i+2;
598 }
599 cgi_printf(" tags: %s", blob_str(&links));
600 blob_reset(&links);
601 }else{
602 cgi_printf(" tags: %h", zTagList);
603 }
604 }
605
606 if( tmFlags & TIMELINE_SHOWRID ){
607 int srcId = delta_source_rid(rid);
608 if( srcId ){
609 cgi_printf(" id: %d&larr;%d", rid, srcId);
610 }else{
611 cgi_printf(" id: %d", rid);
612 }
613 }
614 cgi_printf(")</span>\n"); /* End of the details section */
615 }
616
617 tag_private_status(rid);
618
619 /* Generate extra hyperlinks at the end of the comment */
620 if( xExtra ){
621 xExtra(rid);
622

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button