Fossil SCM

Refactor the name of the sub-line change detection object.

drh 2021-09-03 18:45 diff-color-enhancements
Commit 3e08b15858b770fff871b60b60ae4ca66cf34aa04da58b01b3d0b2a308cfb72c
1 file changed +69 -75
+69 -75
--- src/diff.c
+++ src/diff.c
@@ -124,16 +124,10 @@
124124
DLine *aTo; /* File on right side of the diff */
125125
int nTo; /* Number of lines in aTo[] */
126126
int (*xDiffer)(const DLine*,const DLine*); /* comparison function */
127127
};
128128
129
-/* <span> text for change coloration
130
-*/
131
-static const char zClassRm[] = "<span class=\"diffrm\">";
132
-static const char zClassAdd[] = "<span class=\"diffadd\">";
133
-static const char zClassChng[] = "<span class=\"diffchng\">";
134
-
135129
/*
136130
** Count the number of lines in the input string. Include the last line
137131
** in the count even if it lacks the \n terminator. If an empty string
138132
** is specified, the number of lines is zero. For the purposes of this
139133
** function, a string is considered empty if it contains no characters
@@ -461,26 +455,26 @@
461455
appendDiffLine(pOut, ' ', &A[a+j]);
462456
}
463457
}
464458
}
465459
466
-#define SBS_CSN 8 /* Maximum number of change spans across a change region */
460
+#define MX_CSN 8 /* Maximum number of change spans across a change region */
467461
468462
/*
469463
** A description of zero or more (up to SBS_CSN) areas of commonality
470464
** between two lines of text.
471465
*/
472
-typedef struct ChangeSpan ChangeSpan;
473
-struct ChangeSpan {
466
+typedef struct LineChange LineChange;
467
+struct LineChange {
474468
int n; /* Number of change spans */
475469
struct Span {
476
- int iStart1; /* Byte offset to start of change on the left */
477
- int iLen1; /* Length of left change span in bytes */
478
- int iStart2; /* Byte offset to start of change span on the right */
479
- int iLen2; /* Length of right change span in bytes */
480
- int isMin; /* True if this span is known to have no useful subdivs */
481
- } a[SBS_CSN]; /* Array of change spans, sorted order */
470
+ int iStart1; /* Byte offset to start of a change on the left */
471
+ int iLen1; /* Length of the left change in bytes */
472
+ int iStart2; /* Byte offset to start of a change on the right */
473
+ int iLen2; /* Length of the change on the right in bytes */
474
+ int isMin; /* True if this change is known to have no useful subdivs */
475
+ } a[MX_CSN]; /* Array of change spans, sorted order */
482476
};
483477
484478
/*
485479
** The two text segments zLeft and zRight are known to be different on
486480
** both ends, but they might have a common segment in the middle. If
@@ -527,22 +521,22 @@
527521
528522
/*
529523
** Find the smallest spans that are different between two text strings that
530524
** are known to be different on both ends.
531525
*/
532
-static int textChangeSpans(
526
+static int textLineChanges(
533527
const char *zLeft, int nA, /* String on the left */
534528
const char *zRight, int nB, /* String on the right */
535
- ChangeSpan *p /* Write results here */
529
+ LineChange *p /* Write results here */
536530
){
537531
p->n = 1;
538532
p->a[0].iStart1 = 0;
539533
p->a[0].iLen1 = nA;
540534
p->a[0].iStart2 = 0;
541535
p->a[0].iLen2 = nB;
542536
p->a[0].isMin = 0;
543
- while( p->n<SBS_CSN ){
537
+ while( p->n<MX_CSN ){
544538
int mxi = -1;
545539
int mxLen = -1;
546540
int x, i;
547541
int aLCS[4];
548542
struct Span *a, *b;
@@ -581,17 +575,17 @@
581575
582576
/*
583577
** Given two lines of text, pFrom and pTo, compute a set of changes
584578
** between those two lines, for enhanced display purposes.
585579
**
586
-** The result is written into the ChangeSpan object given by the
580
+** The result is written into the LineChange object given by the
587581
** third parameter.
588582
*/
589583
static void oneLineChange(
590584
const DLine *pLeft, /* Left line of the change */
591585
const DLine *pRight, /* Right line of the change */
592
- ChangeSpan *p /* OUTPUT: Write the results here */
586
+ LineChange *p /* OUTPUT: Write the results here */
593587
){
594588
int nLeft; /* Length of left line in bytes */
595589
int nRight; /* Length of right line in bytes */
596590
int nShort; /* Shortest of left and right */
597591
int nPrefix; /* Length of common prefix */
@@ -689,11 +683,11 @@
689683
*/
690684
nLeftDiff = nLeft - nCommon;
691685
nRightDiff = nRight - nCommon;
692686
if( nLeftDiff >= 4
693687
&& nRightDiff >= 4
694
- && textChangeSpans(&zLeft[nPrefix], nLeftDiff,
688
+ && textLineChanges(&zLeft[nPrefix], nLeftDiff,
695689
&zRight[nPrefix], nRightDiff, p)>1
696690
){
697691
int i;
698692
for(i=0; i<p->n; i++){
699693
p->a[i].iStart1 += nPrefix;
@@ -717,22 +711,22 @@
717711
** Show the differences between the two strings. Used for testing
718712
** the oneLineChange() routine in the diff logic.
719713
*/
720714
void test_line_diff(void){
721715
DLine a, b;
722
- ChangeSpan span;
716
+ LineChange chng;
723717
int i, j, x;
724718
if( g.argc!=4 ) usage("STRING1 STRING2");
725719
a.z = g.argv[2];
726720
a.n = (int)strlen(a.z);
727721
b.z = g.argv[3];
728722
b.n = (int)strlen(b.z);
729
- oneLineChange(&a, &b, &span);
723
+ oneLineChange(&a, &b, &chng);
730724
fossil_print("left: [%s]\n", a.z);
731
- for(i=x=0; i<span.n; i++){
732
- int ofst = span.a[i].iStart1;
733
- int len = span.a[i].iLen1;
725
+ for(i=x=0; i<chng.n; i++){
726
+ int ofst = chng.a[i].iStart1;
727
+ int len = chng.a[i].iLen1;
734728
if( len ){
735729
if( x==0 ){ fossil_print("%*s", 8, ""); }
736730
while( ofst > x ){
737731
if( (a.z[x]&0xc0)!=0x80 ) fossil_print(" ");
738732
x++;
@@ -742,13 +736,13 @@
742736
}
743737
}
744738
}
745739
if( x ) fossil_print("\n");
746740
fossil_print("right: [%s]\n", b.z);
747
- for(i=x=0; i<span.n; i++){
748
- int ofst = span.a[i].iStart2;
749
- int len = span.a[i].iLen2;
741
+ for(i=x=0; i<chng.n; i++){
742
+ int ofst = chng.a[i].iStart2;
743
+ int len = chng.a[i].iLen2;
750744
if( len ){
751745
if( x==0 ){ fossil_print("%*s", 8, ""); }
752746
while( ofst > x ){
753747
if( (b.z[x]&0xc0)!=0x80 ) fossil_print(" ");
754748
x++;
@@ -1042,19 +1036,19 @@
10421036
p->lnRight, (int)pY->n, pY->z);
10431037
}
10441038
static void dfdebugEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
10451039
int i, j;
10461040
int x;
1047
- ChangeSpan span;
1041
+ LineChange chng;
10481042
p->lnLeft++;
10491043
p->lnRight++;
10501044
blob_appendf(p->pOut, "EDIT %8u %.*s\n",
10511045
p->lnLeft, (int)pX->n, pX->z);
1052
- oneLineChange(pX, pY, &span);
1053
- for(i=x=0; i<span.n; i++){
1054
- int ofst = span.a[i].iStart1;
1055
- int len = span.a[i].iLen1;
1046
+ oneLineChange(pX, pY, &chng);
1047
+ for(i=x=0; i<chng.n; i++){
1048
+ int ofst = chng.a[i].iStart1;
1049
+ int len = chng.a[i].iLen1;
10561050
if( len ){
10571051
if( x==0 ){ blob_appendf(p->pOut, "%*s", 25, ""); }
10581052
while( ofst > x ){
10591053
if( (pX->z[x]&0xc0)!=0x80 ) blob_append_char(p->pOut, ' ');
10601054
x++;
@@ -1065,13 +1059,13 @@
10651059
}
10661060
}
10671061
if( x ) blob_append_char(p->pOut, '\n');
10681062
blob_appendf(p->pOut, " %8u %.*s\n",
10691063
p->lnRight, (int)pY->n, pY->z);
1070
- for(i=x=0; i<span.n; i++){
1071
- int ofst = span.a[i].iStart2;
1072
- int len = span.a[i].iLen2;
1064
+ for(i=x=0; i<chng.n; i++){
1065
+ int ofst = chng.a[i].iStart2;
1066
+ int len = chng.a[i].iLen2;
10731067
if( len ){
10741068
if( x==0 ){ blob_appendf(p->pOut, "%*s", 25, ""); }
10751069
while( ofst > x ){
10761070
if( (pY->z[x]&0xc0)!=0x80 ) blob_append_char(p->pOut, ' ');
10771071
x++;
@@ -1153,23 +1147,23 @@
11531147
blob_append_tcl_literal(p->pOut, pY->z, pY->n);
11541148
blob_append_char(p->pOut, '\n');
11551149
}
11561150
static void dftclEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
11571151
int i, x;
1158
- ChangeSpan span;
1159
- blob_append(p->pOut, "EDIT", 4);
1160
- oneLineChange(pX, pY, &span);
1161
- for(i=x=0; i<span.n; i++){
1162
- blob_append_char(p->pOut, ' ');
1163
- blob_append_tcl_literal(p->pOut, pX->z + x, span.a[i].iStart1 - x);
1164
- x = span.a[i].iStart1;
1165
- blob_append_char(p->pOut, ' ');
1166
- blob_append_tcl_literal(p->pOut, pX->z + x, span.a[i].iLen1);
1167
- x += span.a[i].iLen1;
1152
+ LineChange chng;
1153
+ blob_append(p->pOut, "EDIT", 4);
1154
+ oneLineChange(pX, pY, &chng);
1155
+ for(i=x=0; i<chng.n; i++){
1156
+ blob_append_char(p->pOut, ' ');
1157
+ blob_append_tcl_literal(p->pOut, pX->z + x, chng.a[i].iStart1 - x);
1158
+ x = chng.a[i].iStart1;
1159
+ blob_append_char(p->pOut, ' ');
1160
+ blob_append_tcl_literal(p->pOut, pX->z + x, chng.a[i].iLen1);
1161
+ x += chng.a[i].iLen1;
11681162
blob_append_char(p->pOut, ' ');
11691163
blob_append_tcl_literal(p->pOut,
1170
- pY->z + span.a[i].iStart2, span.a[i].iLen2);
1164
+ pY->z + chng.a[i].iStart2, chng.a[i].iLen2);
11711165
}
11721166
if( x<pX->n ){
11731167
blob_append_char(p->pOut, ' ');
11741168
blob_append_tcl_literal(p->pOut, pX->z + x, pX->n - x);
11751169
}
@@ -1237,22 +1231,22 @@
12371231
blob_append_json_literal(p->pOut, pY->z, (int)pY->n);
12381232
blob_append(p->pOut, ",\"\"],\n",-1);
12391233
}
12401234
static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
12411235
int i, x;
1242
- ChangeSpan span;
1236
+ LineChange chng;
12431237
blob_append(p->pOut, "5,[", 3);
1244
- oneLineChange(pX, pY, &span);
1245
- for(i=x=0; i<span.n; i++){
1246
- blob_append_json_literal(p->pOut, pX->z + x, span.a[i].iStart1 - x);
1247
- x = span.a[i].iStart1;
1238
+ oneLineChange(pX, pY, &chng);
1239
+ for(i=x=0; i<chng.n; i++){
1240
+ blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iStart1 - x);
1241
+ x = chng.a[i].iStart1;
12481242
blob_append_char(p->pOut, ',');
1249
- blob_append_json_literal(p->pOut, pX->z + x, span.a[i].iLen1);
1250
- x += span.a[i].iLen1;
1243
+ blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iLen1);
1244
+ x += chng.a[i].iLen1;
12511245
blob_append_char(p->pOut, ',');
12521246
blob_append_json_literal(p->pOut,
1253
- pY->z + span.a[i].iStart2, span.a[i].iLen2);
1247
+ pY->z + chng.a[i].iStart2, chng.a[i].iLen2);
12541248
}
12551249
blob_append_char(p->pOut, ',');
12561250
blob_append_json_literal(p->pOut, pX->z + x, pX->n - x);
12571251
blob_append(p->pOut, "],\n",3);
12581252
}
@@ -1423,12 +1417,12 @@
14231417
p->nPending++;
14241418
}
14251419
static void dfunifiedEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
14261420
int i;
14271421
int x;
1428
- ChangeSpan span;
1429
- oneLineChange(pX, pY, &span);
1422
+ LineChange chng;
1423
+ oneLineChange(pX, pY, &chng);
14301424
dfunifiedStartRow(p);
14311425
if( p->eState==0 ){
14321426
dfunifiedFinishInsert(p);
14331427
blob_append(p->pOut, "<del>", 5);
14341428
blob_append(&p->aCol[2], "<del>", 5);
@@ -1438,13 +1432,13 @@
14381432
p->lnRight++;
14391433
blob_appendf(p->pOut,"%d\n", p->lnLeft);
14401434
blob_append_char(&p->aCol[0], '\n');
14411435
blob_append(&p->aCol[1], "-\n", 2);
14421436
1443
- for(i=x=0; i<span.n; i++){
1444
- int ofst = span.a[i].iStart1;
1445
- int len = span.a[i].iLen1;
1437
+ for(i=x=0; i<chng.n; i++){
1438
+ int ofst = chng.a[i].iStart1;
1439
+ int len = chng.a[i].iLen1;
14461440
if( len ){
14471441
htmlize_to_blob(&p->aCol[2], pX->z+x, ofst - x);
14481442
x = ofst;
14491443
blob_append(&p->aCol[2], "<del>", 5);
14501444
htmlize_to_blob(&p->aCol[2], pX->z+x, len);
@@ -1454,13 +1448,13 @@
14541448
}
14551449
htmlize_to_blob(&p->aCol[2], pX->z+x, pX->n - x);
14561450
blob_append_char(&p->aCol[2], '\n');
14571451
14581452
blob_appendf(&p->aCol[3],"%d\n", p->lnRight);
1459
- for(i=x=0; i<span.n; i++){
1460
- int ofst = span.a[i].iStart2;
1461
- int len = span.a[i].iLen2;
1453
+ for(i=x=0; i<chng.n; i++){
1454
+ int ofst = chng.a[i].iStart2;
1455
+ int len = chng.a[i].iLen2;
14621456
if( len ){
14631457
htmlize_to_blob(&p->aCol[4], pY->z+x, ofst - x);
14641458
x = ofst;
14651459
blob_append(&p->aCol[4], "<ins>", 5);
14661460
htmlize_to_blob(&p->aCol[4], pY->z+x, len);
@@ -1631,24 +1625,24 @@
16311625
blob_append_char(&p->aCol[3], '\n');
16321626
}
16331627
static void dfsplitEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
16341628
int i;
16351629
int x;
1636
- ChangeSpan span;
1637
- oneLineChange(pX, pY, &span);
1630
+ LineChange chng;
1631
+ oneLineChange(pX, pY, &chng);
16381632
dfsplitStartRow(p);
16391633
dfsplitChangeState(p, 3);
16401634
p->lnLeft++;
16411635
p->lnRight++;
16421636
blob_appendf(p->pOut,"%d\n", p->lnLeft);
1643
- for(i=x=0; i<span.n; i++){
1644
- int ofst = span.a[i].iStart1;
1645
- int len = span.a[i].iLen1;
1637
+ for(i=x=0; i<chng.n; i++){
1638
+ int ofst = chng.a[i].iStart1;
1639
+ int len = chng.a[i].iLen1;
16461640
if( len ){
16471641
htmlize_to_blob(&p->aCol[0], pX->z+x, ofst - x);
16481642
x = ofst;
1649
- if( span.a[i].iLen2 ){
1643
+ if( chng.a[i].iLen2 ){
16501644
blob_append(&p->aCol[0], "<del class='edit'>", -1);
16511645
}else{
16521646
blob_append(&p->aCol[0], "<del>", 5);
16531647
}
16541648
htmlize_to_blob(&p->aCol[0], pX->z+x, len);
@@ -1660,17 +1654,17 @@
16601654
blob_append_char(&p->aCol[0], '\n');
16611655
16621656
blob_append(&p->aCol[1], "|\n", 2);
16631657
16641658
blob_appendf(&p->aCol[2],"%d\n", p->lnRight);
1665
- for(i=x=0; i<span.n; i++){
1666
- int ofst = span.a[i].iStart2;
1667
- int len = span.a[i].iLen2;
1659
+ for(i=x=0; i<chng.n; i++){
1660
+ int ofst = chng.a[i].iStart2;
1661
+ int len = chng.a[i].iLen2;
16681662
if( len ){
16691663
htmlize_to_blob(&p->aCol[3], pY->z+x, ofst - x);
16701664
x = ofst;
1671
- if( span.a[i].iLen1 ){
1665
+ if( chng.a[i].iLen1 ){
16721666
blob_append(&p->aCol[3], "<ins class='edit'>", -1);
16731667
}else{
16741668
blob_append(&p->aCol[3], "<ins>", 5);
16751669
}
16761670
htmlize_to_blob(&p->aCol[3], pY->z+x, len);
@@ -2030,11 +2024,11 @@
20302024
int n; /* Loop limit */
20312025
DLine *pA, *pB; /* Pointers to lines */
20322026
int iSX, iSY, iEX, iEY; /* Current match */
20332027
int skew = 0; /* How lopsided is the match */
20342028
int dist = 0; /* Distance of match from center */
2035
- int mid; /* Center of the span */
2029
+ int mid; /* Center of the chng */
20362030
int iSXb, iSYb, iEXb, iEYb; /* Best match so far */
20372031
int iSXp, iSYp, iEXp, iEYp; /* Previous match */
20382032
sqlite3_int64 bestScore; /* Best score so far */
20392033
sqlite3_int64 score; /* Score for current candidate LCS */
20402034
int span; /* combined width of the input sequences */
20412035
--- src/diff.c
+++ src/diff.c
@@ -124,16 +124,10 @@
124 DLine *aTo; /* File on right side of the diff */
125 int nTo; /* Number of lines in aTo[] */
126 int (*xDiffer)(const DLine*,const DLine*); /* comparison function */
127 };
128
129 /* <span> text for change coloration
130 */
131 static const char zClassRm[] = "<span class=\"diffrm\">";
132 static const char zClassAdd[] = "<span class=\"diffadd\">";
133 static const char zClassChng[] = "<span class=\"diffchng\">";
134
135 /*
136 ** Count the number of lines in the input string. Include the last line
137 ** in the count even if it lacks the \n terminator. If an empty string
138 ** is specified, the number of lines is zero. For the purposes of this
139 ** function, a string is considered empty if it contains no characters
@@ -461,26 +455,26 @@
461 appendDiffLine(pOut, ' ', &A[a+j]);
462 }
463 }
464 }
465
466 #define SBS_CSN 8 /* Maximum number of change spans across a change region */
467
468 /*
469 ** A description of zero or more (up to SBS_CSN) areas of commonality
470 ** between two lines of text.
471 */
472 typedef struct ChangeSpan ChangeSpan;
473 struct ChangeSpan {
474 int n; /* Number of change spans */
475 struct Span {
476 int iStart1; /* Byte offset to start of change on the left */
477 int iLen1; /* Length of left change span in bytes */
478 int iStart2; /* Byte offset to start of change span on the right */
479 int iLen2; /* Length of right change span in bytes */
480 int isMin; /* True if this span is known to have no useful subdivs */
481 } a[SBS_CSN]; /* Array of change spans, sorted order */
482 };
483
484 /*
485 ** The two text segments zLeft and zRight are known to be different on
486 ** both ends, but they might have a common segment in the middle. If
@@ -527,22 +521,22 @@
527
528 /*
529 ** Find the smallest spans that are different between two text strings that
530 ** are known to be different on both ends.
531 */
532 static int textChangeSpans(
533 const char *zLeft, int nA, /* String on the left */
534 const char *zRight, int nB, /* String on the right */
535 ChangeSpan *p /* Write results here */
536 ){
537 p->n = 1;
538 p->a[0].iStart1 = 0;
539 p->a[0].iLen1 = nA;
540 p->a[0].iStart2 = 0;
541 p->a[0].iLen2 = nB;
542 p->a[0].isMin = 0;
543 while( p->n<SBS_CSN ){
544 int mxi = -1;
545 int mxLen = -1;
546 int x, i;
547 int aLCS[4];
548 struct Span *a, *b;
@@ -581,17 +575,17 @@
581
582 /*
583 ** Given two lines of text, pFrom and pTo, compute a set of changes
584 ** between those two lines, for enhanced display purposes.
585 **
586 ** The result is written into the ChangeSpan object given by the
587 ** third parameter.
588 */
589 static void oneLineChange(
590 const DLine *pLeft, /* Left line of the change */
591 const DLine *pRight, /* Right line of the change */
592 ChangeSpan *p /* OUTPUT: Write the results here */
593 ){
594 int nLeft; /* Length of left line in bytes */
595 int nRight; /* Length of right line in bytes */
596 int nShort; /* Shortest of left and right */
597 int nPrefix; /* Length of common prefix */
@@ -689,11 +683,11 @@
689 */
690 nLeftDiff = nLeft - nCommon;
691 nRightDiff = nRight - nCommon;
692 if( nLeftDiff >= 4
693 && nRightDiff >= 4
694 && textChangeSpans(&zLeft[nPrefix], nLeftDiff,
695 &zRight[nPrefix], nRightDiff, p)>1
696 ){
697 int i;
698 for(i=0; i<p->n; i++){
699 p->a[i].iStart1 += nPrefix;
@@ -717,22 +711,22 @@
717 ** Show the differences between the two strings. Used for testing
718 ** the oneLineChange() routine in the diff logic.
719 */
720 void test_line_diff(void){
721 DLine a, b;
722 ChangeSpan span;
723 int i, j, x;
724 if( g.argc!=4 ) usage("STRING1 STRING2");
725 a.z = g.argv[2];
726 a.n = (int)strlen(a.z);
727 b.z = g.argv[3];
728 b.n = (int)strlen(b.z);
729 oneLineChange(&a, &b, &span);
730 fossil_print("left: [%s]\n", a.z);
731 for(i=x=0; i<span.n; i++){
732 int ofst = span.a[i].iStart1;
733 int len = span.a[i].iLen1;
734 if( len ){
735 if( x==0 ){ fossil_print("%*s", 8, ""); }
736 while( ofst > x ){
737 if( (a.z[x]&0xc0)!=0x80 ) fossil_print(" ");
738 x++;
@@ -742,13 +736,13 @@
742 }
743 }
744 }
745 if( x ) fossil_print("\n");
746 fossil_print("right: [%s]\n", b.z);
747 for(i=x=0; i<span.n; i++){
748 int ofst = span.a[i].iStart2;
749 int len = span.a[i].iLen2;
750 if( len ){
751 if( x==0 ){ fossil_print("%*s", 8, ""); }
752 while( ofst > x ){
753 if( (b.z[x]&0xc0)!=0x80 ) fossil_print(" ");
754 x++;
@@ -1042,19 +1036,19 @@
1042 p->lnRight, (int)pY->n, pY->z);
1043 }
1044 static void dfdebugEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1045 int i, j;
1046 int x;
1047 ChangeSpan span;
1048 p->lnLeft++;
1049 p->lnRight++;
1050 blob_appendf(p->pOut, "EDIT %8u %.*s\n",
1051 p->lnLeft, (int)pX->n, pX->z);
1052 oneLineChange(pX, pY, &span);
1053 for(i=x=0; i<span.n; i++){
1054 int ofst = span.a[i].iStart1;
1055 int len = span.a[i].iLen1;
1056 if( len ){
1057 if( x==0 ){ blob_appendf(p->pOut, "%*s", 25, ""); }
1058 while( ofst > x ){
1059 if( (pX->z[x]&0xc0)!=0x80 ) blob_append_char(p->pOut, ' ');
1060 x++;
@@ -1065,13 +1059,13 @@
1065 }
1066 }
1067 if( x ) blob_append_char(p->pOut, '\n');
1068 blob_appendf(p->pOut, " %8u %.*s\n",
1069 p->lnRight, (int)pY->n, pY->z);
1070 for(i=x=0; i<span.n; i++){
1071 int ofst = span.a[i].iStart2;
1072 int len = span.a[i].iLen2;
1073 if( len ){
1074 if( x==0 ){ blob_appendf(p->pOut, "%*s", 25, ""); }
1075 while( ofst > x ){
1076 if( (pY->z[x]&0xc0)!=0x80 ) blob_append_char(p->pOut, ' ');
1077 x++;
@@ -1153,23 +1147,23 @@
1153 blob_append_tcl_literal(p->pOut, pY->z, pY->n);
1154 blob_append_char(p->pOut, '\n');
1155 }
1156 static void dftclEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1157 int i, x;
1158 ChangeSpan span;
1159 blob_append(p->pOut, "EDIT", 4);
1160 oneLineChange(pX, pY, &span);
1161 for(i=x=0; i<span.n; i++){
1162 blob_append_char(p->pOut, ' ');
1163 blob_append_tcl_literal(p->pOut, pX->z + x, span.a[i].iStart1 - x);
1164 x = span.a[i].iStart1;
1165 blob_append_char(p->pOut, ' ');
1166 blob_append_tcl_literal(p->pOut, pX->z + x, span.a[i].iLen1);
1167 x += span.a[i].iLen1;
1168 blob_append_char(p->pOut, ' ');
1169 blob_append_tcl_literal(p->pOut,
1170 pY->z + span.a[i].iStart2, span.a[i].iLen2);
1171 }
1172 if( x<pX->n ){
1173 blob_append_char(p->pOut, ' ');
1174 blob_append_tcl_literal(p->pOut, pX->z + x, pX->n - x);
1175 }
@@ -1237,22 +1231,22 @@
1237 blob_append_json_literal(p->pOut, pY->z, (int)pY->n);
1238 blob_append(p->pOut, ",\"\"],\n",-1);
1239 }
1240 static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1241 int i, x;
1242 ChangeSpan span;
1243 blob_append(p->pOut, "5,[", 3);
1244 oneLineChange(pX, pY, &span);
1245 for(i=x=0; i<span.n; i++){
1246 blob_append_json_literal(p->pOut, pX->z + x, span.a[i].iStart1 - x);
1247 x = span.a[i].iStart1;
1248 blob_append_char(p->pOut, ',');
1249 blob_append_json_literal(p->pOut, pX->z + x, span.a[i].iLen1);
1250 x += span.a[i].iLen1;
1251 blob_append_char(p->pOut, ',');
1252 blob_append_json_literal(p->pOut,
1253 pY->z + span.a[i].iStart2, span.a[i].iLen2);
1254 }
1255 blob_append_char(p->pOut, ',');
1256 blob_append_json_literal(p->pOut, pX->z + x, pX->n - x);
1257 blob_append(p->pOut, "],\n",3);
1258 }
@@ -1423,12 +1417,12 @@
1423 p->nPending++;
1424 }
1425 static void dfunifiedEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1426 int i;
1427 int x;
1428 ChangeSpan span;
1429 oneLineChange(pX, pY, &span);
1430 dfunifiedStartRow(p);
1431 if( p->eState==0 ){
1432 dfunifiedFinishInsert(p);
1433 blob_append(p->pOut, "<del>", 5);
1434 blob_append(&p->aCol[2], "<del>", 5);
@@ -1438,13 +1432,13 @@
1438 p->lnRight++;
1439 blob_appendf(p->pOut,"%d\n", p->lnLeft);
1440 blob_append_char(&p->aCol[0], '\n');
1441 blob_append(&p->aCol[1], "-\n", 2);
1442
1443 for(i=x=0; i<span.n; i++){
1444 int ofst = span.a[i].iStart1;
1445 int len = span.a[i].iLen1;
1446 if( len ){
1447 htmlize_to_blob(&p->aCol[2], pX->z+x, ofst - x);
1448 x = ofst;
1449 blob_append(&p->aCol[2], "<del>", 5);
1450 htmlize_to_blob(&p->aCol[2], pX->z+x, len);
@@ -1454,13 +1448,13 @@
1454 }
1455 htmlize_to_blob(&p->aCol[2], pX->z+x, pX->n - x);
1456 blob_append_char(&p->aCol[2], '\n');
1457
1458 blob_appendf(&p->aCol[3],"%d\n", p->lnRight);
1459 for(i=x=0; i<span.n; i++){
1460 int ofst = span.a[i].iStart2;
1461 int len = span.a[i].iLen2;
1462 if( len ){
1463 htmlize_to_blob(&p->aCol[4], pY->z+x, ofst - x);
1464 x = ofst;
1465 blob_append(&p->aCol[4], "<ins>", 5);
1466 htmlize_to_blob(&p->aCol[4], pY->z+x, len);
@@ -1631,24 +1625,24 @@
1631 blob_append_char(&p->aCol[3], '\n');
1632 }
1633 static void dfsplitEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1634 int i;
1635 int x;
1636 ChangeSpan span;
1637 oneLineChange(pX, pY, &span);
1638 dfsplitStartRow(p);
1639 dfsplitChangeState(p, 3);
1640 p->lnLeft++;
1641 p->lnRight++;
1642 blob_appendf(p->pOut,"%d\n", p->lnLeft);
1643 for(i=x=0; i<span.n; i++){
1644 int ofst = span.a[i].iStart1;
1645 int len = span.a[i].iLen1;
1646 if( len ){
1647 htmlize_to_blob(&p->aCol[0], pX->z+x, ofst - x);
1648 x = ofst;
1649 if( span.a[i].iLen2 ){
1650 blob_append(&p->aCol[0], "<del class='edit'>", -1);
1651 }else{
1652 blob_append(&p->aCol[0], "<del>", 5);
1653 }
1654 htmlize_to_blob(&p->aCol[0], pX->z+x, len);
@@ -1660,17 +1654,17 @@
1660 blob_append_char(&p->aCol[0], '\n');
1661
1662 blob_append(&p->aCol[1], "|\n", 2);
1663
1664 blob_appendf(&p->aCol[2],"%d\n", p->lnRight);
1665 for(i=x=0; i<span.n; i++){
1666 int ofst = span.a[i].iStart2;
1667 int len = span.a[i].iLen2;
1668 if( len ){
1669 htmlize_to_blob(&p->aCol[3], pY->z+x, ofst - x);
1670 x = ofst;
1671 if( span.a[i].iLen1 ){
1672 blob_append(&p->aCol[3], "<ins class='edit'>", -1);
1673 }else{
1674 blob_append(&p->aCol[3], "<ins>", 5);
1675 }
1676 htmlize_to_blob(&p->aCol[3], pY->z+x, len);
@@ -2030,11 +2024,11 @@
2030 int n; /* Loop limit */
2031 DLine *pA, *pB; /* Pointers to lines */
2032 int iSX, iSY, iEX, iEY; /* Current match */
2033 int skew = 0; /* How lopsided is the match */
2034 int dist = 0; /* Distance of match from center */
2035 int mid; /* Center of the span */
2036 int iSXb, iSYb, iEXb, iEYb; /* Best match so far */
2037 int iSXp, iSYp, iEXp, iEYp; /* Previous match */
2038 sqlite3_int64 bestScore; /* Best score so far */
2039 sqlite3_int64 score; /* Score for current candidate LCS */
2040 int span; /* combined width of the input sequences */
2041
--- src/diff.c
+++ src/diff.c
@@ -124,16 +124,10 @@
124 DLine *aTo; /* File on right side of the diff */
125 int nTo; /* Number of lines in aTo[] */
126 int (*xDiffer)(const DLine*,const DLine*); /* comparison function */
127 };
128
 
 
 
 
 
 
129 /*
130 ** Count the number of lines in the input string. Include the last line
131 ** in the count even if it lacks the \n terminator. If an empty string
132 ** is specified, the number of lines is zero. For the purposes of this
133 ** function, a string is considered empty if it contains no characters
@@ -461,26 +455,26 @@
455 appendDiffLine(pOut, ' ', &A[a+j]);
456 }
457 }
458 }
459
460 #define MX_CSN 8 /* Maximum number of change spans across a change region */
461
462 /*
463 ** A description of zero or more (up to SBS_CSN) areas of commonality
464 ** between two lines of text.
465 */
466 typedef struct LineChange LineChange;
467 struct LineChange {
468 int n; /* Number of change spans */
469 struct Span {
470 int iStart1; /* Byte offset to start of a change on the left */
471 int iLen1; /* Length of the left change in bytes */
472 int iStart2; /* Byte offset to start of a change on the right */
473 int iLen2; /* Length of the change on the right in bytes */
474 int isMin; /* True if this change is known to have no useful subdivs */
475 } a[MX_CSN]; /* Array of change spans, sorted order */
476 };
477
478 /*
479 ** The two text segments zLeft and zRight are known to be different on
480 ** both ends, but they might have a common segment in the middle. If
@@ -527,22 +521,22 @@
521
522 /*
523 ** Find the smallest spans that are different between two text strings that
524 ** are known to be different on both ends.
525 */
526 static int textLineChanges(
527 const char *zLeft, int nA, /* String on the left */
528 const char *zRight, int nB, /* String on the right */
529 LineChange *p /* Write results here */
530 ){
531 p->n = 1;
532 p->a[0].iStart1 = 0;
533 p->a[0].iLen1 = nA;
534 p->a[0].iStart2 = 0;
535 p->a[0].iLen2 = nB;
536 p->a[0].isMin = 0;
537 while( p->n<MX_CSN ){
538 int mxi = -1;
539 int mxLen = -1;
540 int x, i;
541 int aLCS[4];
542 struct Span *a, *b;
@@ -581,17 +575,17 @@
575
576 /*
577 ** Given two lines of text, pFrom and pTo, compute a set of changes
578 ** between those two lines, for enhanced display purposes.
579 **
580 ** The result is written into the LineChange object given by the
581 ** third parameter.
582 */
583 static void oneLineChange(
584 const DLine *pLeft, /* Left line of the change */
585 const DLine *pRight, /* Right line of the change */
586 LineChange *p /* OUTPUT: Write the results here */
587 ){
588 int nLeft; /* Length of left line in bytes */
589 int nRight; /* Length of right line in bytes */
590 int nShort; /* Shortest of left and right */
591 int nPrefix; /* Length of common prefix */
@@ -689,11 +683,11 @@
683 */
684 nLeftDiff = nLeft - nCommon;
685 nRightDiff = nRight - nCommon;
686 if( nLeftDiff >= 4
687 && nRightDiff >= 4
688 && textLineChanges(&zLeft[nPrefix], nLeftDiff,
689 &zRight[nPrefix], nRightDiff, p)>1
690 ){
691 int i;
692 for(i=0; i<p->n; i++){
693 p->a[i].iStart1 += nPrefix;
@@ -717,22 +711,22 @@
711 ** Show the differences between the two strings. Used for testing
712 ** the oneLineChange() routine in the diff logic.
713 */
714 void test_line_diff(void){
715 DLine a, b;
716 LineChange chng;
717 int i, j, x;
718 if( g.argc!=4 ) usage("STRING1 STRING2");
719 a.z = g.argv[2];
720 a.n = (int)strlen(a.z);
721 b.z = g.argv[3];
722 b.n = (int)strlen(b.z);
723 oneLineChange(&a, &b, &chng);
724 fossil_print("left: [%s]\n", a.z);
725 for(i=x=0; i<chng.n; i++){
726 int ofst = chng.a[i].iStart1;
727 int len = chng.a[i].iLen1;
728 if( len ){
729 if( x==0 ){ fossil_print("%*s", 8, ""); }
730 while( ofst > x ){
731 if( (a.z[x]&0xc0)!=0x80 ) fossil_print(" ");
732 x++;
@@ -742,13 +736,13 @@
736 }
737 }
738 }
739 if( x ) fossil_print("\n");
740 fossil_print("right: [%s]\n", b.z);
741 for(i=x=0; i<chng.n; i++){
742 int ofst = chng.a[i].iStart2;
743 int len = chng.a[i].iLen2;
744 if( len ){
745 if( x==0 ){ fossil_print("%*s", 8, ""); }
746 while( ofst > x ){
747 if( (b.z[x]&0xc0)!=0x80 ) fossil_print(" ");
748 x++;
@@ -1042,19 +1036,19 @@
1036 p->lnRight, (int)pY->n, pY->z);
1037 }
1038 static void dfdebugEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1039 int i, j;
1040 int x;
1041 LineChange chng;
1042 p->lnLeft++;
1043 p->lnRight++;
1044 blob_appendf(p->pOut, "EDIT %8u %.*s\n",
1045 p->lnLeft, (int)pX->n, pX->z);
1046 oneLineChange(pX, pY, &chng);
1047 for(i=x=0; i<chng.n; i++){
1048 int ofst = chng.a[i].iStart1;
1049 int len = chng.a[i].iLen1;
1050 if( len ){
1051 if( x==0 ){ blob_appendf(p->pOut, "%*s", 25, ""); }
1052 while( ofst > x ){
1053 if( (pX->z[x]&0xc0)!=0x80 ) blob_append_char(p->pOut, ' ');
1054 x++;
@@ -1065,13 +1059,13 @@
1059 }
1060 }
1061 if( x ) blob_append_char(p->pOut, '\n');
1062 blob_appendf(p->pOut, " %8u %.*s\n",
1063 p->lnRight, (int)pY->n, pY->z);
1064 for(i=x=0; i<chng.n; i++){
1065 int ofst = chng.a[i].iStart2;
1066 int len = chng.a[i].iLen2;
1067 if( len ){
1068 if( x==0 ){ blob_appendf(p->pOut, "%*s", 25, ""); }
1069 while( ofst > x ){
1070 if( (pY->z[x]&0xc0)!=0x80 ) blob_append_char(p->pOut, ' ');
1071 x++;
@@ -1153,23 +1147,23 @@
1147 blob_append_tcl_literal(p->pOut, pY->z, pY->n);
1148 blob_append_char(p->pOut, '\n');
1149 }
1150 static void dftclEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1151 int i, x;
1152 LineChange chng;
1153 blob_append(p->pOut, "EDIT", 4);
1154 oneLineChange(pX, pY, &chng);
1155 for(i=x=0; i<chng.n; i++){
1156 blob_append_char(p->pOut, ' ');
1157 blob_append_tcl_literal(p->pOut, pX->z + x, chng.a[i].iStart1 - x);
1158 x = chng.a[i].iStart1;
1159 blob_append_char(p->pOut, ' ');
1160 blob_append_tcl_literal(p->pOut, pX->z + x, chng.a[i].iLen1);
1161 x += chng.a[i].iLen1;
1162 blob_append_char(p->pOut, ' ');
1163 blob_append_tcl_literal(p->pOut,
1164 pY->z + chng.a[i].iStart2, chng.a[i].iLen2);
1165 }
1166 if( x<pX->n ){
1167 blob_append_char(p->pOut, ' ');
1168 blob_append_tcl_literal(p->pOut, pX->z + x, pX->n - x);
1169 }
@@ -1237,22 +1231,22 @@
1231 blob_append_json_literal(p->pOut, pY->z, (int)pY->n);
1232 blob_append(p->pOut, ",\"\"],\n",-1);
1233 }
1234 static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1235 int i, x;
1236 LineChange chng;
1237 blob_append(p->pOut, "5,[", 3);
1238 oneLineChange(pX, pY, &chng);
1239 for(i=x=0; i<chng.n; i++){
1240 blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iStart1 - x);
1241 x = chng.a[i].iStart1;
1242 blob_append_char(p->pOut, ',');
1243 blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iLen1);
1244 x += chng.a[i].iLen1;
1245 blob_append_char(p->pOut, ',');
1246 blob_append_json_literal(p->pOut,
1247 pY->z + chng.a[i].iStart2, chng.a[i].iLen2);
1248 }
1249 blob_append_char(p->pOut, ',');
1250 blob_append_json_literal(p->pOut, pX->z + x, pX->n - x);
1251 blob_append(p->pOut, "],\n",3);
1252 }
@@ -1423,12 +1417,12 @@
1417 p->nPending++;
1418 }
1419 static void dfunifiedEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1420 int i;
1421 int x;
1422 LineChange chng;
1423 oneLineChange(pX, pY, &chng);
1424 dfunifiedStartRow(p);
1425 if( p->eState==0 ){
1426 dfunifiedFinishInsert(p);
1427 blob_append(p->pOut, "<del>", 5);
1428 blob_append(&p->aCol[2], "<del>", 5);
@@ -1438,13 +1432,13 @@
1432 p->lnRight++;
1433 blob_appendf(p->pOut,"%d\n", p->lnLeft);
1434 blob_append_char(&p->aCol[0], '\n');
1435 blob_append(&p->aCol[1], "-\n", 2);
1436
1437 for(i=x=0; i<chng.n; i++){
1438 int ofst = chng.a[i].iStart1;
1439 int len = chng.a[i].iLen1;
1440 if( len ){
1441 htmlize_to_blob(&p->aCol[2], pX->z+x, ofst - x);
1442 x = ofst;
1443 blob_append(&p->aCol[2], "<del>", 5);
1444 htmlize_to_blob(&p->aCol[2], pX->z+x, len);
@@ -1454,13 +1448,13 @@
1448 }
1449 htmlize_to_blob(&p->aCol[2], pX->z+x, pX->n - x);
1450 blob_append_char(&p->aCol[2], '\n');
1451
1452 blob_appendf(&p->aCol[3],"%d\n", p->lnRight);
1453 for(i=x=0; i<chng.n; i++){
1454 int ofst = chng.a[i].iStart2;
1455 int len = chng.a[i].iLen2;
1456 if( len ){
1457 htmlize_to_blob(&p->aCol[4], pY->z+x, ofst - x);
1458 x = ofst;
1459 blob_append(&p->aCol[4], "<ins>", 5);
1460 htmlize_to_blob(&p->aCol[4], pY->z+x, len);
@@ -1631,24 +1625,24 @@
1625 blob_append_char(&p->aCol[3], '\n');
1626 }
1627 static void dfsplitEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1628 int i;
1629 int x;
1630 LineChange chng;
1631 oneLineChange(pX, pY, &chng);
1632 dfsplitStartRow(p);
1633 dfsplitChangeState(p, 3);
1634 p->lnLeft++;
1635 p->lnRight++;
1636 blob_appendf(p->pOut,"%d\n", p->lnLeft);
1637 for(i=x=0; i<chng.n; i++){
1638 int ofst = chng.a[i].iStart1;
1639 int len = chng.a[i].iLen1;
1640 if( len ){
1641 htmlize_to_blob(&p->aCol[0], pX->z+x, ofst - x);
1642 x = ofst;
1643 if( chng.a[i].iLen2 ){
1644 blob_append(&p->aCol[0], "<del class='edit'>", -1);
1645 }else{
1646 blob_append(&p->aCol[0], "<del>", 5);
1647 }
1648 htmlize_to_blob(&p->aCol[0], pX->z+x, len);
@@ -1660,17 +1654,17 @@
1654 blob_append_char(&p->aCol[0], '\n');
1655
1656 blob_append(&p->aCol[1], "|\n", 2);
1657
1658 blob_appendf(&p->aCol[2],"%d\n", p->lnRight);
1659 for(i=x=0; i<chng.n; i++){
1660 int ofst = chng.a[i].iStart2;
1661 int len = chng.a[i].iLen2;
1662 if( len ){
1663 htmlize_to_blob(&p->aCol[3], pY->z+x, ofst - x);
1664 x = ofst;
1665 if( chng.a[i].iLen1 ){
1666 blob_append(&p->aCol[3], "<ins class='edit'>", -1);
1667 }else{
1668 blob_append(&p->aCol[3], "<ins>", 5);
1669 }
1670 htmlize_to_blob(&p->aCol[3], pY->z+x, len);
@@ -2030,11 +2024,11 @@
2024 int n; /* Loop limit */
2025 DLine *pA, *pB; /* Pointers to lines */
2026 int iSX, iSY, iEX, iEY; /* Current match */
2027 int skew = 0; /* How lopsided is the match */
2028 int dist = 0; /* Distance of match from center */
2029 int mid; /* Center of the chng */
2030 int iSXb, iSYb, iEXb, iEYb; /* Best match so far */
2031 int iSXp, iSYp, iEXp, iEYp; /* Previous match */
2032 sqlite3_int64 bestScore; /* Best score so far */
2033 sqlite3_int64 score; /* Score for current candidate LCS */
2034 int span; /* combined width of the input sequences */
2035

Keyboard Shortcuts

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