Fossil SCM

Merge the side-by-side diff code into trunk.

drh 2011-10-17 01:19 UTC trunk merge
Commit 0bde74ea1e9229a48ca352ffe7af337722243781
4 files changed +184 +113 -22 +202 -1 +59
+184
--- src/diff.c
+++ src/diff.c
@@ -578,10 +578,194 @@
578578
free(c.aFrom);
579579
free(c.aTo);
580580
return c.aEdit;
581581
}
582582
}
583
+
584
+/*
585
+** Copy a line with a limit. Used for side-by-side diffs to enforce a maximum
586
+** line length limit.
587
+*/
588
+static char *copylimline(char *out, DLine *dl, int lim){
589
+ int len;
590
+ len = dl->h & LENGTH_MASK;
591
+ if( lim && len > lim ){
592
+ memcpy(out, dl->z, lim-3);
593
+ strcpy(&out[lim-3], "...");
594
+ }else{
595
+ memcpy(out, dl->z, len);
596
+ out[len] = '\0';
597
+ }
598
+ return out;
599
+}
600
+
601
+/*
602
+** Output table body of a side-by-side diff. Prior to the call, the caller
603
+** should have output:
604
+** <table class="sbsdiff">
605
+** <tr><th colspan="2" class="diffhdr">Old title</th><th/>
606
+** <th colspan="2" class="diffhdr">New title</th></tr>
607
+**
608
+** And after the call, it should output:
609
+** </table>
610
+**
611
+** Some good reference diffs in the fossil repository for testing:
612
+** /vdiff?from=080d27a&to=4b0f813&detail=1
613
+** /vdiff?from=636804745b&to=c1d78e0556&detail=1
614
+** /vdiff?from=c0b6c28d29&to=25169506b7&detail=1
615
+** /vdiff?from=e3d022dffa&to=48bcfbd47b&detail=1
616
+*/
617
+int html_sbsdiff(
618
+ Blob *pA_Blob, /* FROM file */
619
+ Blob *pB_Blob, /* TO file */
620
+ int nContext, /* Amount of context to unified diff */
621
+ int ignoreEolWs /* Ignore whitespace at the end of lines */
622
+){
623
+ DContext c;
624
+ int i;
625
+ int iFrom, iTo;
626
+ char *linebuf;
627
+ int collim=0; /* Currently not settable; allows a column limit for diffs */
628
+ int allowExp=0; /* Currently not settable; (dis)allow expansion of rows */
629
+
630
+ /* Prepare the input files */
631
+ memset(&c, 0, sizeof(c));
632
+ c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
633
+ &c.nFrom, ignoreEolWs);
634
+ c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
635
+ &c.nTo, ignoreEolWs);
636
+ if( c.aFrom==0 || c.aTo==0 ){
637
+ free(c.aFrom);
638
+ free(c.aTo);
639
+ /* Note: This would be generated within a table. */
640
+ @ <p class="generalError" style="white-space: nowrap">cannot compute
641
+ @ difference between binary files</p>
642
+ return 0;
643
+ }
644
+
645
+ collim = collim < 4 ? 0 : collim;
646
+
647
+ /* Compute the difference */
648
+ diff_all(&c);
649
+
650
+ linebuf = fossil_malloc(LENGTH_MASK+1);
651
+ if( !linebuf ){
652
+ free(c.aFrom);
653
+ free(c.aTo);
654
+ free(c.aEdit);
655
+ return 0;
656
+ }
657
+
658
+ iFrom=iTo=0;
659
+ i=0;
660
+ while( i<c.nEdit ){
661
+ int j;
662
+ /* Copied lines */
663
+ for( j=0; j<c.aEdit[i]; j++){
664
+ /* Hide lines which are copied and are further away from block boundaries
665
+ ** than nConext lines. For each block with hidden lines, show a row
666
+ ** notifying the user about the hidden rows.
667
+ */
668
+ if( j<nContext || j>c.aEdit[i]-nContext-1 ){
669
+ @ <tr>
670
+ }else if( j==nContext && j<c.aEdit[i]-nContext-1 ){
671
+ @ <tr>
672
+ @ <td class="meta" colspan="5" style="white-space: nowrap;">
673
+ @ %d(c.aEdit[i]-2*nContext) hidden lines</td>
674
+ @ </tr>
675
+ if( !allowExp )
676
+ continue;
677
+ @ <tr style="display:none;">
678
+ }else{
679
+ if( !allowExp )
680
+ continue;
681
+ @ <tr style="display:none;">
682
+ }
683
+
684
+ copylimline(linebuf, &c.aFrom[iFrom+j], collim);
685
+ @ <td class="lineno">%d(iFrom+j+1)</td>
686
+ @ <td class="srcline">%h(linebuf)</td>
687
+
688
+ @ <td> </td>
689
+
690
+ copylimline(linebuf, &c.aTo[iTo+j], collim);
691
+ @ <td class="lineno">%d(iTo+j+1)</td>
692
+ @ <td class="srcline">%h(linebuf)</td>
693
+
694
+ @ </tr>
695
+ }
696
+ iFrom+=c.aEdit[i];
697
+ iTo+=c.aEdit[i];
698
+
699
+ if( c.aEdit[i+1]!=0 && c.aEdit[i+2]!=0 ){
700
+ int lim;
701
+ lim = c.aEdit[i+1] > c.aEdit[i+2] ? c.aEdit[i+1] : c.aEdit[i+2];
702
+
703
+ /* Assume changed lines */
704
+ for( j=0; j<lim; j++ ){
705
+ @ <tr>
706
+
707
+ if( j<c.aEdit[i+1] ){
708
+ copylimline(linebuf, &c.aFrom[iFrom+j], collim);
709
+ @ <td class="changed lineno">%d(iFrom+j+1)</td>
710
+ @ <td class="changed srcline">%h(linebuf)</td>
711
+ }else{
712
+ @ <td colspan="2" class="changedvoid"/>
713
+ }
714
+
715
+ @ <td class="changed">|</td>
716
+
717
+ if( j<c.aEdit[i+2] ){
718
+ copylimline(linebuf, &c.aTo[iTo+j], collim);
719
+ @ <td class="changed lineno">%d(iTo+j+1)</td>
720
+ @ <td class="changed srcline">%h(linebuf)</td>
721
+ }else{
722
+ @ <td colspan="2" class="changedvoid"/>
723
+ }
724
+
725
+ @ </tr>
726
+ }
727
+ iFrom+=c.aEdit[i+1];
728
+ iTo+=c.aEdit[i+2];
729
+ }else{
730
+
731
+ /* Process deleted lines */
732
+ for( j=0; j<c.aEdit[i+1]; j++ ){
733
+ @ <tr>
734
+
735
+ copylimline(linebuf, &c.aFrom[iFrom+j], collim);
736
+ @ <td class="removed lineno">%d(iFrom+j+1)</td>
737
+ @ <td class="removed srcline">%h(linebuf)</td>
738
+ @ <td>&lt;</td>
739
+ @ <td colspan="2" class="removedvoid"/>
740
+ @ </tr>
741
+ }
742
+ iFrom+=c.aEdit[i+1];
743
+
744
+ /* Process inserted lines */
745
+ for( j=0; j<c.aEdit[i+2]; j++ ){
746
+ @ <tr>
747
+ @ <td colspan="2" class="addedvoid"/>
748
+ @ <td>&gt;</td>
749
+ copylimline(linebuf, &c.aTo[iTo+j], collim);
750
+ @ <td class="added lineno">%d(iTo+j+1)</td>
751
+ @ <td class="added srcline">%h(linebuf)</td>
752
+ @ </tr>
753
+ }
754
+ iTo+=c.aEdit[i+2];
755
+ }
756
+
757
+ i+=3;
758
+ }
759
+
760
+ free(linebuf);
761
+ free(c.aFrom);
762
+ free(c.aTo);
763
+ free(c.aEdit);
764
+ return 1;
765
+}
766
+
583767
584768
/*
585769
** COMMAND: test-rawdiff
586770
*/
587771
void test_rawdiff_cmd(void){
588772
--- src/diff.c
+++ src/diff.c
@@ -578,10 +578,194 @@
578 free(c.aFrom);
579 free(c.aTo);
580 return c.aEdit;
581 }
582 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
583
584 /*
585 ** COMMAND: test-rawdiff
586 */
587 void test_rawdiff_cmd(void){
588
--- src/diff.c
+++ src/diff.c
@@ -578,10 +578,194 @@
578 free(c.aFrom);
579 free(c.aTo);
580 return c.aEdit;
581 }
582 }
583
584 /*
585 ** Copy a line with a limit. Used for side-by-side diffs to enforce a maximum
586 ** line length limit.
587 */
588 static char *copylimline(char *out, DLine *dl, int lim){
589 int len;
590 len = dl->h & LENGTH_MASK;
591 if( lim && len > lim ){
592 memcpy(out, dl->z, lim-3);
593 strcpy(&out[lim-3], "...");
594 }else{
595 memcpy(out, dl->z, len);
596 out[len] = '\0';
597 }
598 return out;
599 }
600
601 /*
602 ** Output table body of a side-by-side diff. Prior to the call, the caller
603 ** should have output:
604 ** <table class="sbsdiff">
605 ** <tr><th colspan="2" class="diffhdr">Old title</th><th/>
606 ** <th colspan="2" class="diffhdr">New title</th></tr>
607 **
608 ** And after the call, it should output:
609 ** </table>
610 **
611 ** Some good reference diffs in the fossil repository for testing:
612 ** /vdiff?from=080d27a&to=4b0f813&detail=1
613 ** /vdiff?from=636804745b&to=c1d78e0556&detail=1
614 ** /vdiff?from=c0b6c28d29&to=25169506b7&detail=1
615 ** /vdiff?from=e3d022dffa&to=48bcfbd47b&detail=1
616 */
617 int html_sbsdiff(
618 Blob *pA_Blob, /* FROM file */
619 Blob *pB_Blob, /* TO file */
620 int nContext, /* Amount of context to unified diff */
621 int ignoreEolWs /* Ignore whitespace at the end of lines */
622 ){
623 DContext c;
624 int i;
625 int iFrom, iTo;
626 char *linebuf;
627 int collim=0; /* Currently not settable; allows a column limit for diffs */
628 int allowExp=0; /* Currently not settable; (dis)allow expansion of rows */
629
630 /* Prepare the input files */
631 memset(&c, 0, sizeof(c));
632 c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
633 &c.nFrom, ignoreEolWs);
634 c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
635 &c.nTo, ignoreEolWs);
636 if( c.aFrom==0 || c.aTo==0 ){
637 free(c.aFrom);
638 free(c.aTo);
639 /* Note: This would be generated within a table. */
640 @ <p class="generalError" style="white-space: nowrap">cannot compute
641 @ difference between binary files</p>
642 return 0;
643 }
644
645 collim = collim < 4 ? 0 : collim;
646
647 /* Compute the difference */
648 diff_all(&c);
649
650 linebuf = fossil_malloc(LENGTH_MASK+1);
651 if( !linebuf ){
652 free(c.aFrom);
653 free(c.aTo);
654 free(c.aEdit);
655 return 0;
656 }
657
658 iFrom=iTo=0;
659 i=0;
660 while( i<c.nEdit ){
661 int j;
662 /* Copied lines */
663 for( j=0; j<c.aEdit[i]; j++){
664 /* Hide lines which are copied and are further away from block boundaries
665 ** than nConext lines. For each block with hidden lines, show a row
666 ** notifying the user about the hidden rows.
667 */
668 if( j<nContext || j>c.aEdit[i]-nContext-1 ){
669 @ <tr>
670 }else if( j==nContext && j<c.aEdit[i]-nContext-1 ){
671 @ <tr>
672 @ <td class="meta" colspan="5" style="white-space: nowrap;">
673 @ %d(c.aEdit[i]-2*nContext) hidden lines</td>
674 @ </tr>
675 if( !allowExp )
676 continue;
677 @ <tr style="display:none;">
678 }else{
679 if( !allowExp )
680 continue;
681 @ <tr style="display:none;">
682 }
683
684 copylimline(linebuf, &c.aFrom[iFrom+j], collim);
685 @ <td class="lineno">%d(iFrom+j+1)</td>
686 @ <td class="srcline">%h(linebuf)</td>
687
688 @ <td> </td>
689
690 copylimline(linebuf, &c.aTo[iTo+j], collim);
691 @ <td class="lineno">%d(iTo+j+1)</td>
692 @ <td class="srcline">%h(linebuf)</td>
693
694 @ </tr>
695 }
696 iFrom+=c.aEdit[i];
697 iTo+=c.aEdit[i];
698
699 if( c.aEdit[i+1]!=0 && c.aEdit[i+2]!=0 ){
700 int lim;
701 lim = c.aEdit[i+1] > c.aEdit[i+2] ? c.aEdit[i+1] : c.aEdit[i+2];
702
703 /* Assume changed lines */
704 for( j=0; j<lim; j++ ){
705 @ <tr>
706
707 if( j<c.aEdit[i+1] ){
708 copylimline(linebuf, &c.aFrom[iFrom+j], collim);
709 @ <td class="changed lineno">%d(iFrom+j+1)</td>
710 @ <td class="changed srcline">%h(linebuf)</td>
711 }else{
712 @ <td colspan="2" class="changedvoid"/>
713 }
714
715 @ <td class="changed">|</td>
716
717 if( j<c.aEdit[i+2] ){
718 copylimline(linebuf, &c.aTo[iTo+j], collim);
719 @ <td class="changed lineno">%d(iTo+j+1)</td>
720 @ <td class="changed srcline">%h(linebuf)</td>
721 }else{
722 @ <td colspan="2" class="changedvoid"/>
723 }
724
725 @ </tr>
726 }
727 iFrom+=c.aEdit[i+1];
728 iTo+=c.aEdit[i+2];
729 }else{
730
731 /* Process deleted lines */
732 for( j=0; j<c.aEdit[i+1]; j++ ){
733 @ <tr>
734
735 copylimline(linebuf, &c.aFrom[iFrom+j], collim);
736 @ <td class="removed lineno">%d(iFrom+j+1)</td>
737 @ <td class="removed srcline">%h(linebuf)</td>
738 @ <td>&lt;</td>
739 @ <td colspan="2" class="removedvoid"/>
740 @ </tr>
741 }
742 iFrom+=c.aEdit[i+1];
743
744 /* Process inserted lines */
745 for( j=0; j<c.aEdit[i+2]; j++ ){
746 @ <tr>
747 @ <td colspan="2" class="addedvoid"/>
748 @ <td>&gt;</td>
749 copylimline(linebuf, &c.aTo[iTo+j], collim);
750 @ <td class="added lineno">%d(iTo+j+1)</td>
751 @ <td class="added srcline">%h(linebuf)</td>
752 @ </tr>
753 }
754 iTo+=c.aEdit[i+2];
755 }
756
757 i+=3;
758 }
759
760 free(linebuf);
761 free(c.aFrom);
762 free(c.aTo);
763 free(c.aEdit);
764 return 1;
765 }
766
767
768 /*
769 ** COMMAND: test-rawdiff
770 */
771 void test_rawdiff_cmd(void){
772
+113 -22
--- src/info.c
+++ src/info.c
@@ -276,10 +276,40 @@
276276
@ %h(blob_str(&out))
277277
blob_reset(&from);
278278
blob_reset(&to);
279279
blob_reset(&out);
280280
}
281
+
282
+
283
+/*
284
+** Write the difference between two RIDs to the output
285
+*/
286
+static void generate_sbsdiff(const char *zFrom, const char *zTo){
287
+ int fromid;
288
+ int toid;
289
+ Blob from, to;
290
+ if( zFrom ){
291
+ fromid = uuid_to_rid(zFrom, 0);
292
+ content_get(fromid, &from);
293
+ }else{
294
+ blob_zero(&from);
295
+ }
296
+ if( zTo ){
297
+ toid = uuid_to_rid(zTo, 0);
298
+ content_get(toid, &to);
299
+ }else{
300
+ blob_zero(&to);
301
+ }
302
+ @ <table class="sbsdiff">
303
+ @ <tr><th colspan="2" class="diffhdr">Old (%S(zFrom))</th><th/>
304
+ @ <th colspan="2" class="diffhdr">New (%S(zTo))</th></tr>
305
+ html_sbsdiff(&from, &to, 5, 1);
306
+ @ </table>
307
+ blob_reset(&from);
308
+ blob_reset(&to);
309
+}
310
+
281311
282312
/*
283313
** Write a line of web-page output that shows changes that have occurred
284314
** to a file between two check-ins.
285315
*/
@@ -287,10 +317,11 @@
287317
const char *zName, /* Name of the file that has changed */
288318
const char *zOld, /* blob.uuid before change. NULL for added files */
289319
const char *zNew, /* blob.uuid after change. NULL for deletes */
290320
const char *zOldName, /* Prior name. NULL if no name change. */
291321
int showDiff, /* Show edit diffs if true */
322
+ int sideBySide, /* Show diffs side-by-side */
292323
int mperm /* executable or symlink permission for zNew */
293324
){
294325
if( !g.perm.History ){
295326
if( zNew==0 ){
296327
@ <p>Deleted %h(zName)</p>
@@ -329,13 +360,17 @@
329360
}else{
330361
@ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
331362
@ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a>
332363
}
333364
if( showDiff ){
334
- @ <blockquote><pre>
335
- append_diff(zOld, zNew);
336
- @ </pre></blockquote>
365
+ if( sideBySide ){
366
+ generate_sbsdiff(zOld, zNew);
367
+ }else{
368
+ @ <blockquote><pre>
369
+ append_diff(zOld, zNew);
370
+ @ </pre></blockquote>
371
+ }
337372
}else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
338373
@ &nbsp;&nbsp;
339374
@ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
340375
}
341376
@ </p>
@@ -361,10 +396,11 @@
361396
void ci_page(void){
362397
Stmt q;
363398
int rid;
364399
int isLeaf;
365400
int showDiff;
401
+ int sideBySide;
366402
const char *zName; /* Name of the checkin to be displayed */
367403
const char *zUuid; /* UUID of zName */
368404
const char *zParent; /* UUID of the parent checkin (if any) */
369405
370406
login_check_credentials();
@@ -390,10 +426,11 @@
390426
" FROM blob, event"
391427
" WHERE blob.rid=%d"
392428
" AND event.objid=%d",
393429
rid, rid
394430
);
431
+ sideBySide = atoi(PD("sbs","1"));
395432
if( db_step(&q)==SQLITE_ROW ){
396433
const char *zUuid = db_column_text(&q, 0);
397434
char *zTitle = mprintf("Check-in [%.10s]", zUuid);
398435
char *zEUser, *zEComment;
399436
const char *zUser;
@@ -511,18 +548,42 @@
511548
showDiff = g.zPath[0]!='c';
512549
if( db_get_boolean("show-version-diffs", 0)==0 ){
513550
showDiff = !showDiff;
514551
if( showDiff ){
515552
@ <a href="%s(g.zTop)/vinfo/%T(zName)">[hide&nbsp;diffs]</a>
553
+ @ &nbsp;&nbsp;
554
+ if( sideBySide ){
555
+ @ <a href="%s(g.zTop)/ci/%T(zName)?sbs=0">
556
+ @ [unified&nbsp;diffs]</a>
557
+ }else{
558
+ @ <a href="%s(g.zTop)/ci/%T(zName)?sbs=1">
559
+ @ [side-by-side&nbsp;diffs]</a>
560
+ }
516561
}else{
517
- @ <a href="%s(g.zTop)/ci/%T(zName)">[show&nbsp;diffs]</a>
562
+ @ <a href="%s(g.zTop)/ci/%T(zName)?sbs=0">
563
+ @ [show&nbsp;unified&nbsp;diffs]</a>
564
+ @ &nbsp;&nbsp;
565
+ @ <a href="%s(g.zTop)/ci/%T(zName)?sbs=1">
566
+ @ [show&nbsp;side-by-side&nbsp;diffs]</a>
518567
}
519568
}else{
520569
if( showDiff ){
521570
@ <a href="%s(g.zTop)/ci/%T(zName)">[hide&nbsp;diffs]</a>
571
+ @ &nbsp;&nbsp;
572
+ if( sideBySide ){
573
+ @ <a href="%s(g.zTop)/info/%T(zName)?sbs=0">
574
+ @ [unified&nbsp;diffs]</a>
575
+ }else{
576
+ @ <a href="%s(g.zTop)/info/%T(zName)?sbs=1">
577
+ @ [side-by-side&nbsp;diffs]</a>
578
+ }
522579
}else{
523
- @ <a href="%s(g.zTop)/vinfo/%T(zName)">[show&nbsp;diffs]</a>
580
+ @ <a href="%s(g.zTop)/vinfo/%T(zName)?sbs=0">
581
+ @ [show&nbsp;unified&nbsp;diffs]</a>
582
+ @ &nbsp;&nbsp;
583
+ @ <a href="%s(g.zTop)/vinfo/%T(zName)?sbs=1">
584
+ @ [show&nbsp;side-by-side&nbsp;diffs]</a>
524585
}
525586
}
526587
@ &nbsp;&nbsp;
527588
@ <a href="%s(g.zTop)/vpatch?from=%S(zParent)&to=%S(zUuid)">[patch]</a><br/>
528589
db_prepare(&q,
@@ -540,11 +601,12 @@
540601
const char *zName = db_column_text(&q,0);
541602
int mperm = db_column_int(&q, 1);
542603
const char *zOld = db_column_text(&q,2);
543604
const char *zNew = db_column_text(&q,3);
544605
const char *zOldName = db_column_text(&q, 4);
545
- append_file_change_line(zName, zOld, zNew, zOldName, showDiff, mperm);
606
+ append_file_change_line(zName, zOld, zNew, zOldName, showDiff,
607
+ sideBySide, mperm);
546608
}
547609
db_finalize(&q);
548610
}
549611
style_footer();
550612
}
@@ -690,17 +752,18 @@
690752
}
691753
692754
693755
/*
694756
** WEBPAGE: vdiff
695
-** URL: /vdiff?from=UUID&amp;to=UUID&amp;detail=BOOLEAN
757
+** URL: /vdiff?from=UUID&amp;to=UUID&amp;detail=BOOLEAN;sbs=BOOLEAN
696758
**
697759
** Show all differences between two checkins.
698760
*/
699761
void vdiff_page(void){
700762
int ridFrom, ridTo;
701763
int showDetail = 0;
764
+ int sideBySide = 0;
702765
Manifest *pFrom, *pTo;
703766
ManifestFile *pFileFrom, *pFileTo;
704767
705768
login_check_credentials();
706769
if( !g.perm.Read ){ login_needed(); return; }
@@ -709,10 +772,20 @@
709772
pFrom = vdiff_parse_manifest("from", &ridFrom);
710773
if( pFrom==0 ) return;
711774
pTo = vdiff_parse_manifest("to", &ridTo);
712775
if( pTo==0 ) return;
713776
showDetail = atoi(PD("detail","0"));
777
+ sideBySide = atoi(PD("sbs","1"));
778
+ if( !sideBySide ){
779
+ style_submenu_element("Side-by-side Diff", "sbsdiff",
780
+ "%s/vdiff?from=%T&to=%T&detail=%d&sbs=1",
781
+ g.zTop, P("from"), P("to"), showDetail);
782
+ }else{
783
+ style_submenu_element("Unified Diff", "udiff",
784
+ "%s/vdiff?from=%T&to=%T&detail=%d&sbs=0",
785
+ g.zTop, P("from"), P("to"), showDetail);
786
+ }
714787
style_header("Check-in Differences");
715788
@ <h2>Difference From:</h2><blockquote>
716789
checkin_description(ridFrom);
717790
@ </blockquote><h2>To:</h2><blockquote>
718791
checkin_description(ridTo);
@@ -731,25 +804,25 @@
731804
}else{
732805
cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
733806
}
734807
if( cmp<0 ){
735808
append_file_change_line(pFileFrom->zName,
736
- pFileFrom->zUuid, 0, 0, 0, 0);
809
+ pFileFrom->zUuid, 0, 0, 0, 0, 0);
737810
pFileFrom = manifest_file_next(pFrom, 0);
738811
}else if( cmp>0 ){
739812
append_file_change_line(pFileTo->zName,
740
- 0, pFileTo->zUuid, 0, 0,
813
+ 0, pFileTo->zUuid, 0, 0, 0,
741814
manifest_file_mperm(pFileTo));
742815
pFileTo = manifest_file_next(pTo, 0);
743816
}else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
744817
/* No changes */
745818
pFileFrom = manifest_file_next(pFrom, 0);
746819
pFileTo = manifest_file_next(pTo, 0);
747820
}else{
748821
append_file_change_line(pFileFrom->zName,
749822
pFileFrom->zUuid,
750
- pFileTo->zUuid, 0, showDetail,
823
+ pFileTo->zUuid, 0, showDetail, sideBySide,
751824
manifest_file_mperm(pFileTo));
752825
pFileFrom = manifest_file_next(pFrom, 0);
753826
pFileTo = manifest_file_next(pTo, 0);
754827
}
755828
}
@@ -983,28 +1056,30 @@
9831056
}
9841057
9851058
9861059
/*
9871060
** WEBPAGE: fdiff
988
-** URL: fdiff?v1=UUID&v2=UUID&patch
1061
+** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN
9891062
**
990
-** Two arguments, v1 and v2, identify the files to be diffed. Show the
991
-** difference between the two artifacts. Generate plaintext if "patch"
992
-** is present.
1063
+** Two arguments, v1 and v2, identify the files to be diffed. Show the
1064
+** difference between the two artifacts. Show diff side by side unless sbs
1065
+** is 0. Generate plaintext if "patch" is present.
9931066
*/
9941067
void diff_page(void){
9951068
int v1, v2;
9961069
int isPatch;
1070
+ int sideBySide;
9971071
Blob c1, c2, diff, *pOut;
9981072
char *zV1;
9991073
char *zV2;
10001074
10011075
login_check_credentials();
10021076
if( !g.perm.Read ){ login_needed(); return; }
10031077
v1 = name_to_rid_www("v1");
10041078
v2 = name_to_rid_www("v2");
10051079
if( v1==0 || v2==0 ) fossil_redirect_home();
1080
+ sideBySide = atoi(PD("sbs","1"));
10061081
zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
10071082
zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
10081083
isPatch = P("patch")!=0;
10091084
if( isPatch ){
10101085
pOut = cgi_output_blob();
@@ -1011,28 +1086,44 @@
10111086
cgi_set_content_type("text/plain");
10121087
}else{
10131088
blob_zero(&diff);
10141089
pOut = &diff;
10151090
}
1016
- content_get(v1, &c1);
1017
- content_get(v2, &c2);
1018
- text_diff(&c1, &c2, pOut, 4, 1);
1019
- blob_reset(&c1);
1020
- blob_reset(&c2);
1091
+ if( !sideBySide || isPatch ){
1092
+ content_get(v1, &c1);
1093
+ content_get(v2, &c2);
1094
+ text_diff(&c1, &c2, pOut, 4, 1);
1095
+ blob_reset(&c1);
1096
+ blob_reset(&c2);
1097
+ }
10211098
if( !isPatch ){
10221099
style_header("Diff");
10231100
style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
10241101
g.zTop, P("v1"), P("v2"));
1102
+ if( !sideBySide ){
1103
+ style_submenu_element("Side-by-side Diff", "sbsdiff",
1104
+ "%s/fdiff?v1=%T&v2=%T&sbs=1",
1105
+ g.zTop, P("v1"), P("v2"));
1106
+ }else{
1107
+ style_submenu_element("Unified Diff", "udiff",
1108
+ "%s/fdiff?v1=%T&v2=%T&sbs=0",
1109
+ g.zTop, P("v1"), P("v2"));
1110
+ }
1111
+
10251112
@ <h2>Differences From
10261113
@ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
10271114
object_description(v1, 0, 0);
10281115
@ <h2>To Artifact <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
10291116
object_description(v2, 0, 0);
10301117
@ <hr />
1031
- @ <blockquote><pre>
1032
- @ %h(blob_str(&diff))
1033
- @ </pre></blockquote>
1118
+ if( sideBySide ){
1119
+ generate_sbsdiff(zV1, zV2);
1120
+ }else{
1121
+ @ <blockquote><pre>
1122
+ @ %h(blob_str(&diff))
1123
+ @ </pre></blockquote>
1124
+ }
10341125
blob_reset(&diff);
10351126
style_footer();
10361127
}
10371128
}
10381129
10391130
--- src/info.c
+++ src/info.c
@@ -276,10 +276,40 @@
276 @ %h(blob_str(&out))
277 blob_reset(&from);
278 blob_reset(&to);
279 blob_reset(&out);
280 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
282 /*
283 ** Write a line of web-page output that shows changes that have occurred
284 ** to a file between two check-ins.
285 */
@@ -287,10 +317,11 @@
287 const char *zName, /* Name of the file that has changed */
288 const char *zOld, /* blob.uuid before change. NULL for added files */
289 const char *zNew, /* blob.uuid after change. NULL for deletes */
290 const char *zOldName, /* Prior name. NULL if no name change. */
291 int showDiff, /* Show edit diffs if true */
 
292 int mperm /* executable or symlink permission for zNew */
293 ){
294 if( !g.perm.History ){
295 if( zNew==0 ){
296 @ <p>Deleted %h(zName)</p>
@@ -329,13 +360,17 @@
329 }else{
330 @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
331 @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a>
332 }
333 if( showDiff ){
334 @ <blockquote><pre>
335 append_diff(zOld, zNew);
336 @ </pre></blockquote>
 
 
 
 
337 }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
338 @ &nbsp;&nbsp;
339 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
340 }
341 @ </p>
@@ -361,10 +396,11 @@
361 void ci_page(void){
362 Stmt q;
363 int rid;
364 int isLeaf;
365 int showDiff;
 
366 const char *zName; /* Name of the checkin to be displayed */
367 const char *zUuid; /* UUID of zName */
368 const char *zParent; /* UUID of the parent checkin (if any) */
369
370 login_check_credentials();
@@ -390,10 +426,11 @@
390 " FROM blob, event"
391 " WHERE blob.rid=%d"
392 " AND event.objid=%d",
393 rid, rid
394 );
 
395 if( db_step(&q)==SQLITE_ROW ){
396 const char *zUuid = db_column_text(&q, 0);
397 char *zTitle = mprintf("Check-in [%.10s]", zUuid);
398 char *zEUser, *zEComment;
399 const char *zUser;
@@ -511,18 +548,42 @@
511 showDiff = g.zPath[0]!='c';
512 if( db_get_boolean("show-version-diffs", 0)==0 ){
513 showDiff = !showDiff;
514 if( showDiff ){
515 @ <a href="%s(g.zTop)/vinfo/%T(zName)">[hide&nbsp;diffs]</a>
 
 
 
 
 
 
 
 
516 }else{
517 @ <a href="%s(g.zTop)/ci/%T(zName)">[show&nbsp;diffs]</a>
 
 
 
 
518 }
519 }else{
520 if( showDiff ){
521 @ <a href="%s(g.zTop)/ci/%T(zName)">[hide&nbsp;diffs]</a>
 
 
 
 
 
 
 
 
522 }else{
523 @ <a href="%s(g.zTop)/vinfo/%T(zName)">[show&nbsp;diffs]</a>
 
 
 
 
524 }
525 }
526 @ &nbsp;&nbsp;
527 @ <a href="%s(g.zTop)/vpatch?from=%S(zParent)&to=%S(zUuid)">[patch]</a><br/>
528 db_prepare(&q,
@@ -540,11 +601,12 @@
540 const char *zName = db_column_text(&q,0);
541 int mperm = db_column_int(&q, 1);
542 const char *zOld = db_column_text(&q,2);
543 const char *zNew = db_column_text(&q,3);
544 const char *zOldName = db_column_text(&q, 4);
545 append_file_change_line(zName, zOld, zNew, zOldName, showDiff, mperm);
 
546 }
547 db_finalize(&q);
548 }
549 style_footer();
550 }
@@ -690,17 +752,18 @@
690 }
691
692
693 /*
694 ** WEBPAGE: vdiff
695 ** URL: /vdiff?from=UUID&amp;to=UUID&amp;detail=BOOLEAN
696 **
697 ** Show all differences between two checkins.
698 */
699 void vdiff_page(void){
700 int ridFrom, ridTo;
701 int showDetail = 0;
 
702 Manifest *pFrom, *pTo;
703 ManifestFile *pFileFrom, *pFileTo;
704
705 login_check_credentials();
706 if( !g.perm.Read ){ login_needed(); return; }
@@ -709,10 +772,20 @@
709 pFrom = vdiff_parse_manifest("from", &ridFrom);
710 if( pFrom==0 ) return;
711 pTo = vdiff_parse_manifest("to", &ridTo);
712 if( pTo==0 ) return;
713 showDetail = atoi(PD("detail","0"));
 
 
 
 
 
 
 
 
 
 
714 style_header("Check-in Differences");
715 @ <h2>Difference From:</h2><blockquote>
716 checkin_description(ridFrom);
717 @ </blockquote><h2>To:</h2><blockquote>
718 checkin_description(ridTo);
@@ -731,25 +804,25 @@
731 }else{
732 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
733 }
734 if( cmp<0 ){
735 append_file_change_line(pFileFrom->zName,
736 pFileFrom->zUuid, 0, 0, 0, 0);
737 pFileFrom = manifest_file_next(pFrom, 0);
738 }else if( cmp>0 ){
739 append_file_change_line(pFileTo->zName,
740 0, pFileTo->zUuid, 0, 0,
741 manifest_file_mperm(pFileTo));
742 pFileTo = manifest_file_next(pTo, 0);
743 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
744 /* No changes */
745 pFileFrom = manifest_file_next(pFrom, 0);
746 pFileTo = manifest_file_next(pTo, 0);
747 }else{
748 append_file_change_line(pFileFrom->zName,
749 pFileFrom->zUuid,
750 pFileTo->zUuid, 0, showDetail,
751 manifest_file_mperm(pFileTo));
752 pFileFrom = manifest_file_next(pFrom, 0);
753 pFileTo = manifest_file_next(pTo, 0);
754 }
755 }
@@ -983,28 +1056,30 @@
983 }
984
985
986 /*
987 ** WEBPAGE: fdiff
988 ** URL: fdiff?v1=UUID&v2=UUID&patch
989 **
990 ** Two arguments, v1 and v2, identify the files to be diffed. Show the
991 ** difference between the two artifacts. Generate plaintext if "patch"
992 ** is present.
993 */
994 void diff_page(void){
995 int v1, v2;
996 int isPatch;
 
997 Blob c1, c2, diff, *pOut;
998 char *zV1;
999 char *zV2;
1000
1001 login_check_credentials();
1002 if( !g.perm.Read ){ login_needed(); return; }
1003 v1 = name_to_rid_www("v1");
1004 v2 = name_to_rid_www("v2");
1005 if( v1==0 || v2==0 ) fossil_redirect_home();
 
1006 zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
1007 zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
1008 isPatch = P("patch")!=0;
1009 if( isPatch ){
1010 pOut = cgi_output_blob();
@@ -1011,28 +1086,44 @@
1011 cgi_set_content_type("text/plain");
1012 }else{
1013 blob_zero(&diff);
1014 pOut = &diff;
1015 }
1016 content_get(v1, &c1);
1017 content_get(v2, &c2);
1018 text_diff(&c1, &c2, pOut, 4, 1);
1019 blob_reset(&c1);
1020 blob_reset(&c2);
 
 
1021 if( !isPatch ){
1022 style_header("Diff");
1023 style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
1024 g.zTop, P("v1"), P("v2"));
 
 
 
 
 
 
 
 
 
 
1025 @ <h2>Differences From
1026 @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
1027 object_description(v1, 0, 0);
1028 @ <h2>To Artifact <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
1029 object_description(v2, 0, 0);
1030 @ <hr />
1031 @ <blockquote><pre>
1032 @ %h(blob_str(&diff))
1033 @ </pre></blockquote>
 
 
 
 
1034 blob_reset(&diff);
1035 style_footer();
1036 }
1037 }
1038
1039
--- src/info.c
+++ src/info.c
@@ -276,10 +276,40 @@
276 @ %h(blob_str(&out))
277 blob_reset(&from);
278 blob_reset(&to);
279 blob_reset(&out);
280 }
281
282
283 /*
284 ** Write the difference between two RIDs to the output
285 */
286 static void generate_sbsdiff(const char *zFrom, const char *zTo){
287 int fromid;
288 int toid;
289 Blob from, to;
290 if( zFrom ){
291 fromid = uuid_to_rid(zFrom, 0);
292 content_get(fromid, &from);
293 }else{
294 blob_zero(&from);
295 }
296 if( zTo ){
297 toid = uuid_to_rid(zTo, 0);
298 content_get(toid, &to);
299 }else{
300 blob_zero(&to);
301 }
302 @ <table class="sbsdiff">
303 @ <tr><th colspan="2" class="diffhdr">Old (%S(zFrom))</th><th/>
304 @ <th colspan="2" class="diffhdr">New (%S(zTo))</th></tr>
305 html_sbsdiff(&from, &to, 5, 1);
306 @ </table>
307 blob_reset(&from);
308 blob_reset(&to);
309 }
310
311
312 /*
313 ** Write a line of web-page output that shows changes that have occurred
314 ** to a file between two check-ins.
315 */
@@ -287,10 +317,11 @@
317 const char *zName, /* Name of the file that has changed */
318 const char *zOld, /* blob.uuid before change. NULL for added files */
319 const char *zNew, /* blob.uuid after change. NULL for deletes */
320 const char *zOldName, /* Prior name. NULL if no name change. */
321 int showDiff, /* Show edit diffs if true */
322 int sideBySide, /* Show diffs side-by-side */
323 int mperm /* executable or symlink permission for zNew */
324 ){
325 if( !g.perm.History ){
326 if( zNew==0 ){
327 @ <p>Deleted %h(zName)</p>
@@ -329,13 +360,17 @@
360 }else{
361 @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
362 @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a>
363 }
364 if( showDiff ){
365 if( sideBySide ){
366 generate_sbsdiff(zOld, zNew);
367 }else{
368 @ <blockquote><pre>
369 append_diff(zOld, zNew);
370 @ </pre></blockquote>
371 }
372 }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
373 @ &nbsp;&nbsp;
374 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
375 }
376 @ </p>
@@ -361,10 +396,11 @@
396 void ci_page(void){
397 Stmt q;
398 int rid;
399 int isLeaf;
400 int showDiff;
401 int sideBySide;
402 const char *zName; /* Name of the checkin to be displayed */
403 const char *zUuid; /* UUID of zName */
404 const char *zParent; /* UUID of the parent checkin (if any) */
405
406 login_check_credentials();
@@ -390,10 +426,11 @@
426 " FROM blob, event"
427 " WHERE blob.rid=%d"
428 " AND event.objid=%d",
429 rid, rid
430 );
431 sideBySide = atoi(PD("sbs","1"));
432 if( db_step(&q)==SQLITE_ROW ){
433 const char *zUuid = db_column_text(&q, 0);
434 char *zTitle = mprintf("Check-in [%.10s]", zUuid);
435 char *zEUser, *zEComment;
436 const char *zUser;
@@ -511,18 +548,42 @@
548 showDiff = g.zPath[0]!='c';
549 if( db_get_boolean("show-version-diffs", 0)==0 ){
550 showDiff = !showDiff;
551 if( showDiff ){
552 @ <a href="%s(g.zTop)/vinfo/%T(zName)">[hide&nbsp;diffs]</a>
553 @ &nbsp;&nbsp;
554 if( sideBySide ){
555 @ <a href="%s(g.zTop)/ci/%T(zName)?sbs=0">
556 @ [unified&nbsp;diffs]</a>
557 }else{
558 @ <a href="%s(g.zTop)/ci/%T(zName)?sbs=1">
559 @ [side-by-side&nbsp;diffs]</a>
560 }
561 }else{
562 @ <a href="%s(g.zTop)/ci/%T(zName)?sbs=0">
563 @ [show&nbsp;unified&nbsp;diffs]</a>
564 @ &nbsp;&nbsp;
565 @ <a href="%s(g.zTop)/ci/%T(zName)?sbs=1">
566 @ [show&nbsp;side-by-side&nbsp;diffs]</a>
567 }
568 }else{
569 if( showDiff ){
570 @ <a href="%s(g.zTop)/ci/%T(zName)">[hide&nbsp;diffs]</a>
571 @ &nbsp;&nbsp;
572 if( sideBySide ){
573 @ <a href="%s(g.zTop)/info/%T(zName)?sbs=0">
574 @ [unified&nbsp;diffs]</a>
575 }else{
576 @ <a href="%s(g.zTop)/info/%T(zName)?sbs=1">
577 @ [side-by-side&nbsp;diffs]</a>
578 }
579 }else{
580 @ <a href="%s(g.zTop)/vinfo/%T(zName)?sbs=0">
581 @ [show&nbsp;unified&nbsp;diffs]</a>
582 @ &nbsp;&nbsp;
583 @ <a href="%s(g.zTop)/vinfo/%T(zName)?sbs=1">
584 @ [show&nbsp;side-by-side&nbsp;diffs]</a>
585 }
586 }
587 @ &nbsp;&nbsp;
588 @ <a href="%s(g.zTop)/vpatch?from=%S(zParent)&to=%S(zUuid)">[patch]</a><br/>
589 db_prepare(&q,
@@ -540,11 +601,12 @@
601 const char *zName = db_column_text(&q,0);
602 int mperm = db_column_int(&q, 1);
603 const char *zOld = db_column_text(&q,2);
604 const char *zNew = db_column_text(&q,3);
605 const char *zOldName = db_column_text(&q, 4);
606 append_file_change_line(zName, zOld, zNew, zOldName, showDiff,
607 sideBySide, mperm);
608 }
609 db_finalize(&q);
610 }
611 style_footer();
612 }
@@ -690,17 +752,18 @@
752 }
753
754
755 /*
756 ** WEBPAGE: vdiff
757 ** URL: /vdiff?from=UUID&amp;to=UUID&amp;detail=BOOLEAN;sbs=BOOLEAN
758 **
759 ** Show all differences between two checkins.
760 */
761 void vdiff_page(void){
762 int ridFrom, ridTo;
763 int showDetail = 0;
764 int sideBySide = 0;
765 Manifest *pFrom, *pTo;
766 ManifestFile *pFileFrom, *pFileTo;
767
768 login_check_credentials();
769 if( !g.perm.Read ){ login_needed(); return; }
@@ -709,10 +772,20 @@
772 pFrom = vdiff_parse_manifest("from", &ridFrom);
773 if( pFrom==0 ) return;
774 pTo = vdiff_parse_manifest("to", &ridTo);
775 if( pTo==0 ) return;
776 showDetail = atoi(PD("detail","0"));
777 sideBySide = atoi(PD("sbs","1"));
778 if( !sideBySide ){
779 style_submenu_element("Side-by-side Diff", "sbsdiff",
780 "%s/vdiff?from=%T&to=%T&detail=%d&sbs=1",
781 g.zTop, P("from"), P("to"), showDetail);
782 }else{
783 style_submenu_element("Unified Diff", "udiff",
784 "%s/vdiff?from=%T&to=%T&detail=%d&sbs=0",
785 g.zTop, P("from"), P("to"), showDetail);
786 }
787 style_header("Check-in Differences");
788 @ <h2>Difference From:</h2><blockquote>
789 checkin_description(ridFrom);
790 @ </blockquote><h2>To:</h2><blockquote>
791 checkin_description(ridTo);
@@ -731,25 +804,25 @@
804 }else{
805 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
806 }
807 if( cmp<0 ){
808 append_file_change_line(pFileFrom->zName,
809 pFileFrom->zUuid, 0, 0, 0, 0, 0);
810 pFileFrom = manifest_file_next(pFrom, 0);
811 }else if( cmp>0 ){
812 append_file_change_line(pFileTo->zName,
813 0, pFileTo->zUuid, 0, 0, 0,
814 manifest_file_mperm(pFileTo));
815 pFileTo = manifest_file_next(pTo, 0);
816 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
817 /* No changes */
818 pFileFrom = manifest_file_next(pFrom, 0);
819 pFileTo = manifest_file_next(pTo, 0);
820 }else{
821 append_file_change_line(pFileFrom->zName,
822 pFileFrom->zUuid,
823 pFileTo->zUuid, 0, showDetail, sideBySide,
824 manifest_file_mperm(pFileTo));
825 pFileFrom = manifest_file_next(pFrom, 0);
826 pFileTo = manifest_file_next(pTo, 0);
827 }
828 }
@@ -983,28 +1056,30 @@
1056 }
1057
1058
1059 /*
1060 ** WEBPAGE: fdiff
1061 ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN
1062 **
1063 ** Two arguments, v1 and v2, identify the files to be diffed. Show the
1064 ** difference between the two artifacts. Show diff side by side unless sbs
1065 ** is 0. Generate plaintext if "patch" is present.
1066 */
1067 void diff_page(void){
1068 int v1, v2;
1069 int isPatch;
1070 int sideBySide;
1071 Blob c1, c2, diff, *pOut;
1072 char *zV1;
1073 char *zV2;
1074
1075 login_check_credentials();
1076 if( !g.perm.Read ){ login_needed(); return; }
1077 v1 = name_to_rid_www("v1");
1078 v2 = name_to_rid_www("v2");
1079 if( v1==0 || v2==0 ) fossil_redirect_home();
1080 sideBySide = atoi(PD("sbs","1"));
1081 zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
1082 zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
1083 isPatch = P("patch")!=0;
1084 if( isPatch ){
1085 pOut = cgi_output_blob();
@@ -1011,28 +1086,44 @@
1086 cgi_set_content_type("text/plain");
1087 }else{
1088 blob_zero(&diff);
1089 pOut = &diff;
1090 }
1091 if( !sideBySide || isPatch ){
1092 content_get(v1, &c1);
1093 content_get(v2, &c2);
1094 text_diff(&c1, &c2, pOut, 4, 1);
1095 blob_reset(&c1);
1096 blob_reset(&c2);
1097 }
1098 if( !isPatch ){
1099 style_header("Diff");
1100 style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
1101 g.zTop, P("v1"), P("v2"));
1102 if( !sideBySide ){
1103 style_submenu_element("Side-by-side Diff", "sbsdiff",
1104 "%s/fdiff?v1=%T&v2=%T&sbs=1",
1105 g.zTop, P("v1"), P("v2"));
1106 }else{
1107 style_submenu_element("Unified Diff", "udiff",
1108 "%s/fdiff?v1=%T&v2=%T&sbs=0",
1109 g.zTop, P("v1"), P("v2"));
1110 }
1111
1112 @ <h2>Differences From
1113 @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
1114 object_description(v1, 0, 0);
1115 @ <h2>To Artifact <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
1116 object_description(v2, 0, 0);
1117 @ <hr />
1118 if( sideBySide ){
1119 generate_sbsdiff(zV1, zV2);
1120 }else{
1121 @ <blockquote><pre>
1122 @ %h(blob_str(&diff))
1123 @ </pre></blockquote>
1124 }
1125 blob_reset(&diff);
1126 style_footer();
1127 }
1128 }
1129
1130
+202 -1
--- src/skins.c
+++ src/skins.c
@@ -152,10 +152,55 @@
152152
@ /* The label/value pairs on (for example) the vinfo page */
153153
@ table.label-value th {
154154
@ vertical-align: top;
155155
@ text-align: right;
156156
@ padding: 0.2ex 2ex;
157
+@ }
158
+@
159
+@ /* Side-by-side diff */
160
+@ table.sbsdiff {
161
+@ background-color: white;
162
+@ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
163
+@ font-size: 10pt;
164
+@ border-collapse:collapse;
165
+@ white-space: pre;
166
+@ width: 98%;
167
+@ border: 1px #000 dashed;
168
+@ }
169
+@
170
+@ table.sbsdiff th.diffhdr {
171
+@ border-bottom: dotted;
172
+@ border-width: 1px;
173
+@ }
174
+@
175
+@ table.sbsdiff tr td {
176
+@ white-space: pre;
177
+@ padding-left: 3px;
178
+@ padding-right: 3px;
179
+@ margin: 0px;
180
+@ }
181
+@
182
+@ table.sbsdiff tr td.lineno {
183
+@ text-align: right;
184
+@ }
185
+@
186
+@ table.sbsdiff tr td.meta {
187
+@ color: white;
188
+@ background-color: rgb(20, 20, 20);
189
+@ text-align: center;
190
+@ }
191
+@
192
+@ table.sbsdiff tr td.added {
193
+@ background-color: rgb(230, 230, 230);
194
+@ }
195
+@
196
+@ table.sbsdiff tr td.removed {
197
+@ background-color: rgb(200, 200, 200);
198
+@ }
199
+@
200
+@ table.sbsdiff tr td.changed {
201
+@ background-color: rgb(220, 220, 220);
157202
@ }');
158203
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
159204
@ <head>
160205
@ <title>$<project_name>: $<title></title>
161206
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@@ -356,11 +401,54 @@
356401
@ table.label-value th {
357402
@ vertical-align: top;
358403
@ text-align: right;
359404
@ padding: 0.2ex 2ex;
360405
@ }
361
-@ ');
406
+@
407
+@ /* Side-by-side diff */
408
+@ table.sbsdiff {
409
+@ background-color: #ffffc5;
410
+@ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
411
+@ font-size: 10pt;
412
+@ border-collapse:collapse;
413
+@ white-space: pre;
414
+@ width: 98%;
415
+@ border: 1px #000 dashed;
416
+@ }
417
+@
418
+@ table.sbsdiff th.diffhdr {
419
+@ border-bottom: dotted;
420
+@ border-width: 1px;
421
+@ }
422
+@
423
+@ table.sbsdiff tr td {
424
+@ white-space: pre;
425
+@ padding-left: 3px;
426
+@ padding-right: 3px;
427
+@ margin: 0px;
428
+@ }
429
+@
430
+@ table.sbsdiff tr td.lineno {
431
+@ text-align: right;
432
+@ }
433
+@
434
+@ table.sbsdiff tr td.meta {
435
+@ background-color: #a09048;
436
+@ text-align: center;
437
+@ }
438
+@
439
+@ table.sbsdiff tr td.added {
440
+@ background-color: rgb(210, 210, 100);
441
+@ }
442
+@
443
+@ table.sbsdiff tr td.removed {
444
+@ background-color: rgb(190, 200, 110);
445
+@ }
446
+@
447
+@ table.sbsdiff tr td.changed {
448
+@ background-color: rgb(200, 210, 120);
449
+@ }');
362450
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
363451
@ <head>
364452
@ <title>$<project_name>: $<title></title>
365453
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
366454
@ href="$home/timeline.rss">
@@ -590,10 +678,56 @@
590678
@ /* The label/value pairs on (for example) the ci page */
591679
@ table.label-value th {
592680
@ vertical-align: top;
593681
@ text-align: right;
594682
@ padding: 0.2ex 2ex;
683
+@ }
684
+@
685
+@ /* Side-by-side diff */
686
+@ table.sbsdiff {
687
+@ background-color: white;
688
+@ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
689
+@ font-size: 10pt;
690
+@ border-collapse:collapse;
691
+@ white-space: pre;
692
+@ width: 98%;
693
+@ border: 1px #000 dashed;
694
+@ }
695
+@
696
+@ table.sbsdiff th.diffhdr {
697
+@ border-bottom: dotted;
698
+@ border-width: 1px;
699
+@ }
700
+@
701
+@ table.sbsdiff tr td {
702
+@ white-space: pre;
703
+@ padding-left: 3px;
704
+@ padding-right: 3px;
705
+@ margin: 0px;
706
+@ }
707
+@
708
+@ table.sbsdiff tr td.lineno {
709
+@ text-align: right;
710
+@ }
711
+@
712
+@ table.sbsdiff tr td.meta {
713
+@ color: white;
714
+@ background-color: black;
715
+@ text-align: center;
716
+@ }
717
+@
718
+@ table.sbsdiff tr td.added {
719
+@ background-color: white;
720
+@ }
721
+@
722
+@ table.sbsdiff tr td.removed {
723
+@ background-color: white;
724
+@ text-decoration: line-through;
725
+@ }
726
+@
727
+@ table.sbsdiff tr td.changed {
728
+@ background-color: white;
595729
@ }');
596730
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
597731
@ <head>
598732
@ <title>$<project_name>: $<title></title>
599733
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@@ -885,10 +1019,77 @@
8851019
@ padding: 3px 5px;
8861020
@ }
8871021
@
8881022
@ textarea {
8891023
@ font-size: 1em;
1024
+@ }
1025
+@
1026
+@ /* Side-by-side diff */
1027
+@ table.sbsdiff {
1028
+@ background-color: white;
1029
+@ font-family: Dejavu Sans Mono, Monaco, Lucida Console, monospace;
1030
+@ font-size: 8pt;
1031
+@ border-collapse:collapse;
1032
+@ width: 98%;
1033
+@ border: 1px #000 dashed;
1034
+@ margin-left: auto;
1035
+@ margin-right: auto;
1036
+@ }
1037
+@
1038
+@ table.sbsdiff th.diffhdr {
1039
+@ border-bottom: dotted;
1040
+@ border-width: 1px;
1041
+@ }
1042
+@
1043
+@ table.sbsdiff tr td {
1044
+@ padding-left: 3px;
1045
+@ padding-right: 3px;
1046
+@ margin: 0px;
1047
+@ vertical-align: top;
1048
+@ white-space: pre-wrap;
1049
+@ }
1050
+@
1051
+@ table.sbsdiff tr td.lineno {
1052
+@ text-align: right;
1053
+@ /* border-bottom: 1px solid rgb(220, 220, 220); */
1054
+@ }
1055
+@
1056
+@ table.sbsdiff tr td.srcline {
1057
+@ max-width: 400px;
1058
+@ /* Note: May partially hide long lines without whitespaces */
1059
+@ overflow: hidden;
1060
+@ /* border-bottom: 1px solid rgb(220, 220, 220); */
1061
+@ }
1062
+@
1063
+@ table.sbsdiff tr td.meta {
1064
+@ background-color: rgb(170, 160, 255);
1065
+@ padding-top: 0.25em;
1066
+@ padding-bottom: 0.25em;
1067
+@ text-align: center;
1068
+@ -moz-border-radius: 5px;
1069
+@ -moz-border-radius: 5px;
1070
+@ -webkit-border-radius: 5px;
1071
+@ -webkit-border-radius: 5px;
1072
+@ -border-radius: 5px;
1073
+@ -border-radius: 5px;
1074
+@ border-radius: 5px;
1075
+@ border-radius: 5px;
1076
+@ }
1077
+@
1078
+@ table.sbsdiff tr td.added {
1079
+@ background-color: rgb(180, 250, 180);
1080
+@ /* border-bottom: 1px solid rgb(160, 230, 160); */
1081
+@ }
1082
+@
1083
+@ table.sbsdiff tr td.removed {
1084
+@ background-color: rgb(250, 130, 130);
1085
+@ /* border-bottom: 1px solid rgb(230, 110, 110); */
1086
+@ }
1087
+@
1088
+@ table.sbsdiff tr td.changed {
1089
+@ background-color: rgb(210, 210, 200);
1090
+@ /* border-bottom: 1px solid rgb(190, 190, 180); */
8901091
@ }');
8911092
@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
8921093
@ <head>
8931094
@ <title>$<project_name>: $<title></title>
8941095
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
8951096
--- src/skins.c
+++ src/skins.c
@@ -152,10 +152,55 @@
152 @ /* The label/value pairs on (for example) the vinfo page */
153 @ table.label-value th {
154 @ vertical-align: top;
155 @ text-align: right;
156 @ padding: 0.2ex 2ex;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157 @ }');
158 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
159 @ <head>
160 @ <title>$<project_name>: $<title></title>
161 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@@ -356,11 +401,54 @@
356 @ table.label-value th {
357 @ vertical-align: top;
358 @ text-align: right;
359 @ padding: 0.2ex 2ex;
360 @ }
361 @ ');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
363 @ <head>
364 @ <title>$<project_name>: $<title></title>
365 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
366 @ href="$home/timeline.rss">
@@ -590,10 +678,56 @@
590 @ /* The label/value pairs on (for example) the ci page */
591 @ table.label-value th {
592 @ vertical-align: top;
593 @ text-align: right;
594 @ padding: 0.2ex 2ex;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
595 @ }');
596 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
597 @ <head>
598 @ <title>$<project_name>: $<title></title>
599 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@@ -885,10 +1019,77 @@
885 @ padding: 3px 5px;
886 @ }
887 @
888 @ textarea {
889 @ font-size: 1em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
890 @ }');
891 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
892 @ <head>
893 @ <title>$<project_name>: $<title></title>
894 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
895
--- src/skins.c
+++ src/skins.c
@@ -152,10 +152,55 @@
152 @ /* The label/value pairs on (for example) the vinfo page */
153 @ table.label-value th {
154 @ vertical-align: top;
155 @ text-align: right;
156 @ padding: 0.2ex 2ex;
157 @ }
158 @
159 @ /* Side-by-side diff */
160 @ table.sbsdiff {
161 @ background-color: white;
162 @ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
163 @ font-size: 10pt;
164 @ border-collapse:collapse;
165 @ white-space: pre;
166 @ width: 98%;
167 @ border: 1px #000 dashed;
168 @ }
169 @
170 @ table.sbsdiff th.diffhdr {
171 @ border-bottom: dotted;
172 @ border-width: 1px;
173 @ }
174 @
175 @ table.sbsdiff tr td {
176 @ white-space: pre;
177 @ padding-left: 3px;
178 @ padding-right: 3px;
179 @ margin: 0px;
180 @ }
181 @
182 @ table.sbsdiff tr td.lineno {
183 @ text-align: right;
184 @ }
185 @
186 @ table.sbsdiff tr td.meta {
187 @ color: white;
188 @ background-color: rgb(20, 20, 20);
189 @ text-align: center;
190 @ }
191 @
192 @ table.sbsdiff tr td.added {
193 @ background-color: rgb(230, 230, 230);
194 @ }
195 @
196 @ table.sbsdiff tr td.removed {
197 @ background-color: rgb(200, 200, 200);
198 @ }
199 @
200 @ table.sbsdiff tr td.changed {
201 @ background-color: rgb(220, 220, 220);
202 @ }');
203 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
204 @ <head>
205 @ <title>$<project_name>: $<title></title>
206 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@@ -356,11 +401,54 @@
401 @ table.label-value th {
402 @ vertical-align: top;
403 @ text-align: right;
404 @ padding: 0.2ex 2ex;
405 @ }
406 @
407 @ /* Side-by-side diff */
408 @ table.sbsdiff {
409 @ background-color: #ffffc5;
410 @ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
411 @ font-size: 10pt;
412 @ border-collapse:collapse;
413 @ white-space: pre;
414 @ width: 98%;
415 @ border: 1px #000 dashed;
416 @ }
417 @
418 @ table.sbsdiff th.diffhdr {
419 @ border-bottom: dotted;
420 @ border-width: 1px;
421 @ }
422 @
423 @ table.sbsdiff tr td {
424 @ white-space: pre;
425 @ padding-left: 3px;
426 @ padding-right: 3px;
427 @ margin: 0px;
428 @ }
429 @
430 @ table.sbsdiff tr td.lineno {
431 @ text-align: right;
432 @ }
433 @
434 @ table.sbsdiff tr td.meta {
435 @ background-color: #a09048;
436 @ text-align: center;
437 @ }
438 @
439 @ table.sbsdiff tr td.added {
440 @ background-color: rgb(210, 210, 100);
441 @ }
442 @
443 @ table.sbsdiff tr td.removed {
444 @ background-color: rgb(190, 200, 110);
445 @ }
446 @
447 @ table.sbsdiff tr td.changed {
448 @ background-color: rgb(200, 210, 120);
449 @ }');
450 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
451 @ <head>
452 @ <title>$<project_name>: $<title></title>
453 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
454 @ href="$home/timeline.rss">
@@ -590,10 +678,56 @@
678 @ /* The label/value pairs on (for example) the ci page */
679 @ table.label-value th {
680 @ vertical-align: top;
681 @ text-align: right;
682 @ padding: 0.2ex 2ex;
683 @ }
684 @
685 @ /* Side-by-side diff */
686 @ table.sbsdiff {
687 @ background-color: white;
688 @ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
689 @ font-size: 10pt;
690 @ border-collapse:collapse;
691 @ white-space: pre;
692 @ width: 98%;
693 @ border: 1px #000 dashed;
694 @ }
695 @
696 @ table.sbsdiff th.diffhdr {
697 @ border-bottom: dotted;
698 @ border-width: 1px;
699 @ }
700 @
701 @ table.sbsdiff tr td {
702 @ white-space: pre;
703 @ padding-left: 3px;
704 @ padding-right: 3px;
705 @ margin: 0px;
706 @ }
707 @
708 @ table.sbsdiff tr td.lineno {
709 @ text-align: right;
710 @ }
711 @
712 @ table.sbsdiff tr td.meta {
713 @ color: white;
714 @ background-color: black;
715 @ text-align: center;
716 @ }
717 @
718 @ table.sbsdiff tr td.added {
719 @ background-color: white;
720 @ }
721 @
722 @ table.sbsdiff tr td.removed {
723 @ background-color: white;
724 @ text-decoration: line-through;
725 @ }
726 @
727 @ table.sbsdiff tr td.changed {
728 @ background-color: white;
729 @ }');
730 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
731 @ <head>
732 @ <title>$<project_name>: $<title></title>
733 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
@@ -885,10 +1019,77 @@
1019 @ padding: 3px 5px;
1020 @ }
1021 @
1022 @ textarea {
1023 @ font-size: 1em;
1024 @ }
1025 @
1026 @ /* Side-by-side diff */
1027 @ table.sbsdiff {
1028 @ background-color: white;
1029 @ font-family: Dejavu Sans Mono, Monaco, Lucida Console, monospace;
1030 @ font-size: 8pt;
1031 @ border-collapse:collapse;
1032 @ width: 98%;
1033 @ border: 1px #000 dashed;
1034 @ margin-left: auto;
1035 @ margin-right: auto;
1036 @ }
1037 @
1038 @ table.sbsdiff th.diffhdr {
1039 @ border-bottom: dotted;
1040 @ border-width: 1px;
1041 @ }
1042 @
1043 @ table.sbsdiff tr td {
1044 @ padding-left: 3px;
1045 @ padding-right: 3px;
1046 @ margin: 0px;
1047 @ vertical-align: top;
1048 @ white-space: pre-wrap;
1049 @ }
1050 @
1051 @ table.sbsdiff tr td.lineno {
1052 @ text-align: right;
1053 @ /* border-bottom: 1px solid rgb(220, 220, 220); */
1054 @ }
1055 @
1056 @ table.sbsdiff tr td.srcline {
1057 @ max-width: 400px;
1058 @ /* Note: May partially hide long lines without whitespaces */
1059 @ overflow: hidden;
1060 @ /* border-bottom: 1px solid rgb(220, 220, 220); */
1061 @ }
1062 @
1063 @ table.sbsdiff tr td.meta {
1064 @ background-color: rgb(170, 160, 255);
1065 @ padding-top: 0.25em;
1066 @ padding-bottom: 0.25em;
1067 @ text-align: center;
1068 @ -moz-border-radius: 5px;
1069 @ -moz-border-radius: 5px;
1070 @ -webkit-border-radius: 5px;
1071 @ -webkit-border-radius: 5px;
1072 @ -border-radius: 5px;
1073 @ -border-radius: 5px;
1074 @ border-radius: 5px;
1075 @ border-radius: 5px;
1076 @ }
1077 @
1078 @ table.sbsdiff tr td.added {
1079 @ background-color: rgb(180, 250, 180);
1080 @ /* border-bottom: 1px solid rgb(160, 230, 160); */
1081 @ }
1082 @
1083 @ table.sbsdiff tr td.removed {
1084 @ background-color: rgb(250, 130, 130);
1085 @ /* border-bottom: 1px solid rgb(230, 110, 110); */
1086 @ }
1087 @
1088 @ table.sbsdiff tr td.changed {
1089 @ background-color: rgb(210, 210, 200);
1090 @ /* border-bottom: 1px solid rgb(190, 190, 180); */
1091 @ }');
1092 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
1093 @ <head>
1094 @ <title>$<project_name>: $<title></title>
1095 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
1096
+59
--- src/style.c
+++ src/style.c
@@ -396,10 +396,69 @@
396396
@ table.label-value th {
397397
@ vertical-align: top;
398398
@ text-align: right;
399399
@ padding: 0.2ex 2ex;
400400
@ }
401
+@
402
+@ /* Side-by-side diff */
403
+@ table.sbsdiff {
404
+@ background-color: white;
405
+@ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
406
+@ font-size: 10pt;
407
+@ border-collapse:collapse;
408
+@ white-space: pre;
409
+@ width: 98%;
410
+@ border: 1px #000 dashed;
411
+@ margin-left: auto;
412
+@ margin-right: auto;
413
+@ }
414
+@
415
+@ table.sbsdiff th.diffhdr {
416
+@ border-bottom: dotted;
417
+@ border-width: 1px;
418
+@ }
419
+@
420
+@ table.sbsdiff tr td {
421
+@ white-space: pre;
422
+@ padding-left: 3px;
423
+@ padding-right: 3px;
424
+@ margin: 0px;
425
+@ vertical-align: top;
426
+@ }
427
+@
428
+@ table.sbsdiff tr td.lineno {
429
+@ text-align: right;
430
+@ }
431
+@
432
+@ table.sbsdiff tr td.srcline {
433
+@ }
434
+@
435
+@ table.sbsdiff tr td.meta {
436
+@ background-color: rgb(170, 160, 255);
437
+@ text-align: center;
438
+@ }
439
+@
440
+@ table.sbsdiff tr td.added {
441
+@ background-color: rgb(180, 250, 180);
442
+@ }
443
+@ table.sbsdiff tr td.addedvoid {
444
+@ background-color: rgb(190, 190, 180);
445
+@ }
446
+@
447
+@ table.sbsdiff tr td.removed {
448
+@ background-color: rgb(250, 130, 130);
449
+@ }
450
+@ table.sbsdiff tr td.removedvoid {
451
+@ background-color: rgb(190, 190, 180);
452
+@ }
453
+@
454
+@ table.sbsdiff tr td.changed {
455
+@ background-color: rgb(210, 210, 200);
456
+@ }
457
+@ table.sbsdiff tr td.changedvoid {
458
+@ background-color: rgb(190, 190, 180);
459
+@ }
401460
@
402461
;
403462
404463
405464
/* The following table contains bits of default CSS that must
406465
--- src/style.c
+++ src/style.c
@@ -396,10 +396,69 @@
396 @ table.label-value th {
397 @ vertical-align: top;
398 @ text-align: right;
399 @ padding: 0.2ex 2ex;
400 @ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401 @
402 ;
403
404
405 /* The following table contains bits of default CSS that must
406
--- src/style.c
+++ src/style.c
@@ -396,10 +396,69 @@
396 @ table.label-value th {
397 @ vertical-align: top;
398 @ text-align: right;
399 @ padding: 0.2ex 2ex;
400 @ }
401 @
402 @ /* Side-by-side diff */
403 @ table.sbsdiff {
404 @ background-color: white;
405 @ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
406 @ font-size: 10pt;
407 @ border-collapse:collapse;
408 @ white-space: pre;
409 @ width: 98%;
410 @ border: 1px #000 dashed;
411 @ margin-left: auto;
412 @ margin-right: auto;
413 @ }
414 @
415 @ table.sbsdiff th.diffhdr {
416 @ border-bottom: dotted;
417 @ border-width: 1px;
418 @ }
419 @
420 @ table.sbsdiff tr td {
421 @ white-space: pre;
422 @ padding-left: 3px;
423 @ padding-right: 3px;
424 @ margin: 0px;
425 @ vertical-align: top;
426 @ }
427 @
428 @ table.sbsdiff tr td.lineno {
429 @ text-align: right;
430 @ }
431 @
432 @ table.sbsdiff tr td.srcline {
433 @ }
434 @
435 @ table.sbsdiff tr td.meta {
436 @ background-color: rgb(170, 160, 255);
437 @ text-align: center;
438 @ }
439 @
440 @ table.sbsdiff tr td.added {
441 @ background-color: rgb(180, 250, 180);
442 @ }
443 @ table.sbsdiff tr td.addedvoid {
444 @ background-color: rgb(190, 190, 180);
445 @ }
446 @
447 @ table.sbsdiff tr td.removed {
448 @ background-color: rgb(250, 130, 130);
449 @ }
450 @ table.sbsdiff tr td.removedvoid {
451 @ background-color: rgb(190, 190, 180);
452 @ }
453 @
454 @ table.sbsdiff tr td.changed {
455 @ background-color: rgb(210, 210, 200);
456 @ }
457 @ table.sbsdiff tr td.changedvoid {
458 @ background-color: rgb(190, 190, 180);
459 @ }
460 @
461 ;
462
463
464 /* The following table contains bits of default CSS that must
465

Keyboard Shortcuts

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