Fossil SCM
Refactor the name of the sub-line change detection object.
Commit
3e08b15858b770fff871b60b60ae4ca66cf34aa04da58b01b3d0b2a308cfb72c
Parent
fd2d27f01b6c80e…
1 file changed
+69
-75
+69
-75
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -124,16 +124,10 @@ | ||
| 124 | 124 | DLine *aTo; /* File on right side of the diff */ |
| 125 | 125 | int nTo; /* Number of lines in aTo[] */ |
| 126 | 126 | int (*xDiffer)(const DLine*,const DLine*); /* comparison function */ |
| 127 | 127 | }; |
| 128 | 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 | 129 | /* |
| 136 | 130 | ** Count the number of lines in the input string. Include the last line |
| 137 | 131 | ** in the count even if it lacks the \n terminator. If an empty string |
| 138 | 132 | ** is specified, the number of lines is zero. For the purposes of this |
| 139 | 133 | ** function, a string is considered empty if it contains no characters |
| @@ -461,26 +455,26 @@ | ||
| 461 | 455 | appendDiffLine(pOut, ' ', &A[a+j]); |
| 462 | 456 | } |
| 463 | 457 | } |
| 464 | 458 | } |
| 465 | 459 | |
| 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 */ | |
| 467 | 461 | |
| 468 | 462 | /* |
| 469 | 463 | ** A description of zero or more (up to SBS_CSN) areas of commonality |
| 470 | 464 | ** between two lines of text. |
| 471 | 465 | */ |
| 472 | -typedef struct ChangeSpan ChangeSpan; | |
| 473 | -struct ChangeSpan { | |
| 466 | +typedef struct LineChange LineChange; | |
| 467 | +struct LineChange { | |
| 474 | 468 | int n; /* Number of change spans */ |
| 475 | 469 | 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 */ | |
| 482 | 476 | }; |
| 483 | 477 | |
| 484 | 478 | /* |
| 485 | 479 | ** The two text segments zLeft and zRight are known to be different on |
| 486 | 480 | ** both ends, but they might have a common segment in the middle. If |
| @@ -527,22 +521,22 @@ | ||
| 527 | 521 | |
| 528 | 522 | /* |
| 529 | 523 | ** Find the smallest spans that are different between two text strings that |
| 530 | 524 | ** are known to be different on both ends. |
| 531 | 525 | */ |
| 532 | -static int textChangeSpans( | |
| 526 | +static int textLineChanges( | |
| 533 | 527 | const char *zLeft, int nA, /* String on the left */ |
| 534 | 528 | const char *zRight, int nB, /* String on the right */ |
| 535 | - ChangeSpan *p /* Write results here */ | |
| 529 | + LineChange *p /* Write results here */ | |
| 536 | 530 | ){ |
| 537 | 531 | p->n = 1; |
| 538 | 532 | p->a[0].iStart1 = 0; |
| 539 | 533 | p->a[0].iLen1 = nA; |
| 540 | 534 | p->a[0].iStart2 = 0; |
| 541 | 535 | p->a[0].iLen2 = nB; |
| 542 | 536 | p->a[0].isMin = 0; |
| 543 | - while( p->n<SBS_CSN ){ | |
| 537 | + while( p->n<MX_CSN ){ | |
| 544 | 538 | int mxi = -1; |
| 545 | 539 | int mxLen = -1; |
| 546 | 540 | int x, i; |
| 547 | 541 | int aLCS[4]; |
| 548 | 542 | struct Span *a, *b; |
| @@ -581,17 +575,17 @@ | ||
| 581 | 575 | |
| 582 | 576 | /* |
| 583 | 577 | ** Given two lines of text, pFrom and pTo, compute a set of changes |
| 584 | 578 | ** between those two lines, for enhanced display purposes. |
| 585 | 579 | ** |
| 586 | -** The result is written into the ChangeSpan object given by the | |
| 580 | +** The result is written into the LineChange object given by the | |
| 587 | 581 | ** third parameter. |
| 588 | 582 | */ |
| 589 | 583 | static void oneLineChange( |
| 590 | 584 | const DLine *pLeft, /* Left line of the change */ |
| 591 | 585 | const DLine *pRight, /* Right line of the change */ |
| 592 | - ChangeSpan *p /* OUTPUT: Write the results here */ | |
| 586 | + LineChange *p /* OUTPUT: Write the results here */ | |
| 593 | 587 | ){ |
| 594 | 588 | int nLeft; /* Length of left line in bytes */ |
| 595 | 589 | int nRight; /* Length of right line in bytes */ |
| 596 | 590 | int nShort; /* Shortest of left and right */ |
| 597 | 591 | int nPrefix; /* Length of common prefix */ |
| @@ -689,11 +683,11 @@ | ||
| 689 | 683 | */ |
| 690 | 684 | nLeftDiff = nLeft - nCommon; |
| 691 | 685 | nRightDiff = nRight - nCommon; |
| 692 | 686 | if( nLeftDiff >= 4 |
| 693 | 687 | && nRightDiff >= 4 |
| 694 | - && textChangeSpans(&zLeft[nPrefix], nLeftDiff, | |
| 688 | + && textLineChanges(&zLeft[nPrefix], nLeftDiff, | |
| 695 | 689 | &zRight[nPrefix], nRightDiff, p)>1 |
| 696 | 690 | ){ |
| 697 | 691 | int i; |
| 698 | 692 | for(i=0; i<p->n; i++){ |
| 699 | 693 | p->a[i].iStart1 += nPrefix; |
| @@ -717,22 +711,22 @@ | ||
| 717 | 711 | ** Show the differences between the two strings. Used for testing |
| 718 | 712 | ** the oneLineChange() routine in the diff logic. |
| 719 | 713 | */ |
| 720 | 714 | void test_line_diff(void){ |
| 721 | 715 | DLine a, b; |
| 722 | - ChangeSpan span; | |
| 716 | + LineChange chng; | |
| 723 | 717 | int i, j, x; |
| 724 | 718 | if( g.argc!=4 ) usage("STRING1 STRING2"); |
| 725 | 719 | a.z = g.argv[2]; |
| 726 | 720 | a.n = (int)strlen(a.z); |
| 727 | 721 | b.z = g.argv[3]; |
| 728 | 722 | b.n = (int)strlen(b.z); |
| 729 | - oneLineChange(&a, &b, &span); | |
| 723 | + oneLineChange(&a, &b, &chng); | |
| 730 | 724 | 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; | |
| 734 | 728 | if( len ){ |
| 735 | 729 | if( x==0 ){ fossil_print("%*s", 8, ""); } |
| 736 | 730 | while( ofst > x ){ |
| 737 | 731 | if( (a.z[x]&0xc0)!=0x80 ) fossil_print(" "); |
| 738 | 732 | x++; |
| @@ -742,13 +736,13 @@ | ||
| 742 | 736 | } |
| 743 | 737 | } |
| 744 | 738 | } |
| 745 | 739 | if( x ) fossil_print("\n"); |
| 746 | 740 | 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; | |
| 750 | 744 | if( len ){ |
| 751 | 745 | if( x==0 ){ fossil_print("%*s", 8, ""); } |
| 752 | 746 | while( ofst > x ){ |
| 753 | 747 | if( (b.z[x]&0xc0)!=0x80 ) fossil_print(" "); |
| 754 | 748 | x++; |
| @@ -1042,19 +1036,19 @@ | ||
| 1042 | 1036 | p->lnRight, (int)pY->n, pY->z); |
| 1043 | 1037 | } |
| 1044 | 1038 | static void dfdebugEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){ |
| 1045 | 1039 | int i, j; |
| 1046 | 1040 | int x; |
| 1047 | - ChangeSpan span; | |
| 1041 | + LineChange chng; | |
| 1048 | 1042 | p->lnLeft++; |
| 1049 | 1043 | p->lnRight++; |
| 1050 | 1044 | blob_appendf(p->pOut, "EDIT %8u %.*s\n", |
| 1051 | 1045 | 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; | |
| 1056 | 1050 | if( len ){ |
| 1057 | 1051 | if( x==0 ){ blob_appendf(p->pOut, "%*s", 25, ""); } |
| 1058 | 1052 | while( ofst > x ){ |
| 1059 | 1053 | if( (pX->z[x]&0xc0)!=0x80 ) blob_append_char(p->pOut, ' '); |
| 1060 | 1054 | x++; |
| @@ -1065,13 +1059,13 @@ | ||
| 1065 | 1059 | } |
| 1066 | 1060 | } |
| 1067 | 1061 | if( x ) blob_append_char(p->pOut, '\n'); |
| 1068 | 1062 | blob_appendf(p->pOut, " %8u %.*s\n", |
| 1069 | 1063 | 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; | |
| 1073 | 1067 | if( len ){ |
| 1074 | 1068 | if( x==0 ){ blob_appendf(p->pOut, "%*s", 25, ""); } |
| 1075 | 1069 | while( ofst > x ){ |
| 1076 | 1070 | if( (pY->z[x]&0xc0)!=0x80 ) blob_append_char(p->pOut, ' '); |
| 1077 | 1071 | x++; |
| @@ -1153,23 +1147,23 @@ | ||
| 1153 | 1147 | blob_append_tcl_literal(p->pOut, pY->z, pY->n); |
| 1154 | 1148 | blob_append_char(p->pOut, '\n'); |
| 1155 | 1149 | } |
| 1156 | 1150 | static void dftclEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){ |
| 1157 | 1151 | 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; | |
| 1168 | 1162 | blob_append_char(p->pOut, ' '); |
| 1169 | 1163 | 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); | |
| 1171 | 1165 | } |
| 1172 | 1166 | if( x<pX->n ){ |
| 1173 | 1167 | blob_append_char(p->pOut, ' '); |
| 1174 | 1168 | blob_append_tcl_literal(p->pOut, pX->z + x, pX->n - x); |
| 1175 | 1169 | } |
| @@ -1237,22 +1231,22 @@ | ||
| 1237 | 1231 | blob_append_json_literal(p->pOut, pY->z, (int)pY->n); |
| 1238 | 1232 | blob_append(p->pOut, ",\"\"],\n",-1); |
| 1239 | 1233 | } |
| 1240 | 1234 | static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){ |
| 1241 | 1235 | int i, x; |
| 1242 | - ChangeSpan span; | |
| 1236 | + LineChange chng; | |
| 1243 | 1237 | 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; | |
| 1248 | 1242 | 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; | |
| 1251 | 1245 | blob_append_char(p->pOut, ','); |
| 1252 | 1246 | 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); | |
| 1254 | 1248 | } |
| 1255 | 1249 | blob_append_char(p->pOut, ','); |
| 1256 | 1250 | blob_append_json_literal(p->pOut, pX->z + x, pX->n - x); |
| 1257 | 1251 | blob_append(p->pOut, "],\n",3); |
| 1258 | 1252 | } |
| @@ -1423,12 +1417,12 @@ | ||
| 1423 | 1417 | p->nPending++; |
| 1424 | 1418 | } |
| 1425 | 1419 | static void dfunifiedEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){ |
| 1426 | 1420 | int i; |
| 1427 | 1421 | int x; |
| 1428 | - ChangeSpan span; | |
| 1429 | - oneLineChange(pX, pY, &span); | |
| 1422 | + LineChange chng; | |
| 1423 | + oneLineChange(pX, pY, &chng); | |
| 1430 | 1424 | dfunifiedStartRow(p); |
| 1431 | 1425 | if( p->eState==0 ){ |
| 1432 | 1426 | dfunifiedFinishInsert(p); |
| 1433 | 1427 | blob_append(p->pOut, "<del>", 5); |
| 1434 | 1428 | blob_append(&p->aCol[2], "<del>", 5); |
| @@ -1438,13 +1432,13 @@ | ||
| 1438 | 1432 | p->lnRight++; |
| 1439 | 1433 | blob_appendf(p->pOut,"%d\n", p->lnLeft); |
| 1440 | 1434 | blob_append_char(&p->aCol[0], '\n'); |
| 1441 | 1435 | blob_append(&p->aCol[1], "-\n", 2); |
| 1442 | 1436 | |
| 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; | |
| 1446 | 1440 | if( len ){ |
| 1447 | 1441 | htmlize_to_blob(&p->aCol[2], pX->z+x, ofst - x); |
| 1448 | 1442 | x = ofst; |
| 1449 | 1443 | blob_append(&p->aCol[2], "<del>", 5); |
| 1450 | 1444 | htmlize_to_blob(&p->aCol[2], pX->z+x, len); |
| @@ -1454,13 +1448,13 @@ | ||
| 1454 | 1448 | } |
| 1455 | 1449 | htmlize_to_blob(&p->aCol[2], pX->z+x, pX->n - x); |
| 1456 | 1450 | blob_append_char(&p->aCol[2], '\n'); |
| 1457 | 1451 | |
| 1458 | 1452 | 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; | |
| 1462 | 1456 | if( len ){ |
| 1463 | 1457 | htmlize_to_blob(&p->aCol[4], pY->z+x, ofst - x); |
| 1464 | 1458 | x = ofst; |
| 1465 | 1459 | blob_append(&p->aCol[4], "<ins>", 5); |
| 1466 | 1460 | htmlize_to_blob(&p->aCol[4], pY->z+x, len); |
| @@ -1631,24 +1625,24 @@ | ||
| 1631 | 1625 | blob_append_char(&p->aCol[3], '\n'); |
| 1632 | 1626 | } |
| 1633 | 1627 | static void dfsplitEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){ |
| 1634 | 1628 | int i; |
| 1635 | 1629 | int x; |
| 1636 | - ChangeSpan span; | |
| 1637 | - oneLineChange(pX, pY, &span); | |
| 1630 | + LineChange chng; | |
| 1631 | + oneLineChange(pX, pY, &chng); | |
| 1638 | 1632 | dfsplitStartRow(p); |
| 1639 | 1633 | dfsplitChangeState(p, 3); |
| 1640 | 1634 | p->lnLeft++; |
| 1641 | 1635 | p->lnRight++; |
| 1642 | 1636 | 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; | |
| 1646 | 1640 | if( len ){ |
| 1647 | 1641 | htmlize_to_blob(&p->aCol[0], pX->z+x, ofst - x); |
| 1648 | 1642 | x = ofst; |
| 1649 | - if( span.a[i].iLen2 ){ | |
| 1643 | + if( chng.a[i].iLen2 ){ | |
| 1650 | 1644 | blob_append(&p->aCol[0], "<del class='edit'>", -1); |
| 1651 | 1645 | }else{ |
| 1652 | 1646 | blob_append(&p->aCol[0], "<del>", 5); |
| 1653 | 1647 | } |
| 1654 | 1648 | htmlize_to_blob(&p->aCol[0], pX->z+x, len); |
| @@ -1660,17 +1654,17 @@ | ||
| 1660 | 1654 | blob_append_char(&p->aCol[0], '\n'); |
| 1661 | 1655 | |
| 1662 | 1656 | blob_append(&p->aCol[1], "|\n", 2); |
| 1663 | 1657 | |
| 1664 | 1658 | 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; | |
| 1668 | 1662 | if( len ){ |
| 1669 | 1663 | htmlize_to_blob(&p->aCol[3], pY->z+x, ofst - x); |
| 1670 | 1664 | x = ofst; |
| 1671 | - if( span.a[i].iLen1 ){ | |
| 1665 | + if( chng.a[i].iLen1 ){ | |
| 1672 | 1666 | blob_append(&p->aCol[3], "<ins class='edit'>", -1); |
| 1673 | 1667 | }else{ |
| 1674 | 1668 | blob_append(&p->aCol[3], "<ins>", 5); |
| 1675 | 1669 | } |
| 1676 | 1670 | htmlize_to_blob(&p->aCol[3], pY->z+x, len); |
| @@ -2030,11 +2024,11 @@ | ||
| 2030 | 2024 | int n; /* Loop limit */ |
| 2031 | 2025 | DLine *pA, *pB; /* Pointers to lines */ |
| 2032 | 2026 | int iSX, iSY, iEX, iEY; /* Current match */ |
| 2033 | 2027 | int skew = 0; /* How lopsided is the match */ |
| 2034 | 2028 | int dist = 0; /* Distance of match from center */ |
| 2035 | - int mid; /* Center of the span */ | |
| 2029 | + int mid; /* Center of the chng */ | |
| 2036 | 2030 | int iSXb, iSYb, iEXb, iEYb; /* Best match so far */ |
| 2037 | 2031 | int iSXp, iSYp, iEXp, iEYp; /* Previous match */ |
| 2038 | 2032 | sqlite3_int64 bestScore; /* Best score so far */ |
| 2039 | 2033 | sqlite3_int64 score; /* Score for current candidate LCS */ |
| 2040 | 2034 | int span; /* combined width of the input sequences */ |
| 2041 | 2035 |
| --- 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 |