| | @@ -1627,25 +1627,27 @@ |
| 1627 | 1627 | ** lines and formats them for display. Subclasses of this object format |
| 1628 | 1628 | ** the diff output in different ways. |
| 1629 | 1629 | */ |
| 1630 | 1630 | typedef struct DiffBuilder DiffBuilder; |
| 1631 | 1631 | struct DiffBuilder { |
| 1632 | | - void (*xSkip)(DiffBuilder*, unsigned int); |
| 1632 | + void (*xSkip)(DiffBuilder*, unsigned int, int); |
| 1633 | 1633 | void (*xCommon)(DiffBuilder*,const DLine*); |
| 1634 | 1634 | void (*xInsert)(DiffBuilder*,const DLine*); |
| 1635 | 1635 | void (*xDelete)(DiffBuilder*,const DLine*); |
| 1636 | 1636 | void (*xEdit)(DiffBuilder*,const DLine*,const DLine*); |
| 1637 | 1637 | void (*xEnd)(DiffBuilder*); |
| 1638 | 1638 | unsigned int lnLeft; /* Lines seen on the left (delete) side */ |
| 1639 | 1639 | unsigned int lnRight; /* Lines seen on the right (insert) side */ |
| 1640 | 1640 | Blob *pOut; /* Output blob */ |
| 1641 | + Blob aCol[5]; /* Holding blobs */ |
| 1641 | 1642 | }; |
| 1642 | 1643 | |
| 1643 | 1644 | /************************* DiffBuilderDebug ********************************/ |
| 1644 | | -static void dfdebugSkip(DiffBuilder *p, unsigned int n){ |
| 1645 | | - blob_appendf(p->pOut, "SKIP %d (%d..%d left and %d..%d right)\n", |
| 1646 | | - n, p->lnLeft+1, p->lnLeft+n, p->lnRight+1, p->lnRight+n); |
| 1645 | +static void dfdebugSkip(DiffBuilder *p, unsigned int n, int isFinal){ |
| 1646 | + blob_appendf(p->pOut, "SKIP %d (%d..%d left and %d..%d right)%s\n", |
| 1647 | + n, p->lnLeft+1, p->lnLeft+n, p->lnRight+1, p->lnRight+n, |
| 1648 | + isFinal ? " FINAL" : ""); |
| 1647 | 1649 | p->lnLeft += n; |
| 1648 | 1650 | p->lnRight += n; |
| 1649 | 1651 | } |
| 1650 | 1652 | static void dfdebugCommon(DiffBuilder *p, const DLine *pLine){ |
| 1651 | 1653 | p->lnLeft++; |
| | @@ -1782,11 +1784,11 @@ |
| 1782 | 1784 | break; |
| 1783 | 1785 | } |
| 1784 | 1786 | } |
| 1785 | 1787 | *piCol = iCol; |
| 1786 | 1788 | } |
| 1787 | | -static void dfjsonSkip(DiffBuilder *p, unsigned int n){ |
| 1789 | +static void dfjsonSkip(DiffBuilder *p, unsigned int n, int isFinal){ |
| 1788 | 1790 | blob_appendf(p->pOut, "1,%u,\n", n); |
| 1789 | 1791 | } |
| 1790 | 1792 | static void dfjsonCommon(DiffBuilder *p, const DLine *pLine){ |
| 1791 | 1793 | int iCol = 0; |
| 1792 | 1794 | blob_append(p->pOut, "2,\"",3); |
| | @@ -1815,11 +1817,11 @@ |
| 1815 | 1817 | for(i=x=iCol=0; i<span.n; i++){ |
| 1816 | 1818 | int ofst = span.a[i].iStart1; |
| 1817 | 1819 | int len = span.a[i].iLen1; |
| 1818 | 1820 | if( len ){ |
| 1819 | 1821 | jsonize_to_blob(p->pOut, pX->z+x, ofst - x, &iCol); |
| 1820 | | - x += ofst; |
| 1822 | + x = ofst; |
| 1821 | 1823 | blob_append(p->pOut, "<mark>", 6); |
| 1822 | 1824 | jsonize_to_blob(p->pOut, pX->z+x, len, &iCol); |
| 1823 | 1825 | x += len; |
| 1824 | 1826 | blob_append(p->pOut, "</mark>", 7); |
| 1825 | 1827 | } |
| | @@ -1829,11 +1831,11 @@ |
| 1829 | 1831 | for(i=x=iCol=0; i<span.n; i++){ |
| 1830 | 1832 | int ofst = span.a[i].iStart2; |
| 1831 | 1833 | int len = span.a[i].iLen2; |
| 1832 | 1834 | if( len ){ |
| 1833 | 1835 | jsonize_to_blob(p->pOut, pY->z+x, ofst - x, &iCol); |
| 1834 | | - x += ofst; |
| 1836 | + x = ofst; |
| 1835 | 1837 | blob_append(p->pOut, "<mark>", 6); |
| 1836 | 1838 | jsonize_to_blob(p->pOut, pY->z+x, len, &iCol); |
| 1837 | 1839 | x += len; |
| 1838 | 1840 | blob_append(p->pOut, "</mark>", 7); |
| 1839 | 1841 | } |
| | @@ -1856,10 +1858,140 @@ |
| 1856 | 1858 | p->lnLeft = p->lnRight = 0; |
| 1857 | 1859 | p->pOut = pOut; |
| 1858 | 1860 | blob_append_char(pOut, '['); |
| 1859 | 1861 | return p; |
| 1860 | 1862 | } |
| 1863 | + |
| 1864 | +/************************* DiffBuilderUnified********************************/ |
| 1865 | + |
| 1866 | +/* Accumulator strategy: |
| 1867 | +** |
| 1868 | +** * Common and Delete line numbers are output directly to p->pOut |
| 1869 | +** * Common and Delete text accumulates in p->aCol[0]. |
| 1870 | +** * Pending insert lines numbers go into p->aCol[1]. |
| 1871 | +** * Pending insert text goes into p->aCol[2]. |
| 1872 | +*/ |
| 1873 | +static void dfunifiedEmitInsert(DiffBuilder *p){ |
| 1874 | + if( blob_size(&p->aCol[1])==0 ) return; |
| 1875 | + blob_append(p->pOut, blob_buffer(&p->aCol[1]), blob_size(&p->aCol[1])); |
| 1876 | + blob_reset(&p->aCol[1]); |
| 1877 | + blob_append(&p->aCol[0], blob_buffer(&p->aCol[2]), blob_size(&p->aCol[2])); |
| 1878 | + blob_reset(&p->aCol[2]); |
| 1879 | +} |
| 1880 | +static void dfunifiedSkip(DiffBuilder *p, unsigned int n, int isFinal){ |
| 1881 | + dfunifiedEmitInsert(p); |
| 1882 | + if( (p->lnLeft || p->lnRight) && !isFinal ){ |
| 1883 | + blob_append(p->pOut, |
| 1884 | + "<span class=\"diffhr\">" |
| 1885 | + ".................." |
| 1886 | + "</span>\n", |
| 1887 | + -1); |
| 1888 | + blob_append(&p->aCol[0], |
| 1889 | + "<span class=\"diffhr\">" |
| 1890 | + "..............................................................." |
| 1891 | + "</span>\n", |
| 1892 | + -1); |
| 1893 | + } |
| 1894 | + p->lnLeft += n; |
| 1895 | + p->lnRight += n; |
| 1896 | +} |
| 1897 | +static void dfunifiedCommon(DiffBuilder *p, const DLine *pLine){ |
| 1898 | + int iCol = 0; |
| 1899 | + dfunifiedEmitInsert(p); |
| 1900 | + p->lnLeft++; |
| 1901 | + p->lnRight++; |
| 1902 | + blob_appendf(p->pOut,"%6d %6d\n", p->lnLeft, p->lnRight); |
| 1903 | + jsonize_to_blob(&p->aCol[0], pLine->z, (int)pLine->n, &iCol); |
| 1904 | + blob_append_char(&p->aCol[0], '\n'); |
| 1905 | +} |
| 1906 | +static void dfunifiedInsert(DiffBuilder *p, const DLine *pLine){ |
| 1907 | + int iCol = 0; |
| 1908 | + p->lnRight++; |
| 1909 | + blob_appendf(&p->aCol[1]," <ins>%6d</ins>\n", p->lnRight); |
| 1910 | + blob_append(&p->aCol[2],"<ins>",-1); |
| 1911 | + jsonize_to_blob(&p->aCol[2], pLine->z, (int)pLine->n, &iCol); |
| 1912 | + blob_append(&p->aCol[2], "</ins>\n", -1); |
| 1913 | +} |
| 1914 | +static void dfunifiedDelete(DiffBuilder *p, const DLine *pLine){ |
| 1915 | + int iCol = 0; |
| 1916 | + p->lnLeft++; |
| 1917 | + blob_appendf(p->pOut,"<del>%6d</del> \n", p->lnLeft); |
| 1918 | + blob_append(&p->aCol[0],"<del>",-1); |
| 1919 | + jsonize_to_blob(&p->aCol[0], pLine->z, (int)pLine->n, &iCol); |
| 1920 | + blob_append(&p->aCol[0], "</del>\n", -1); |
| 1921 | +} |
| 1922 | +static void dfunifiedEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){ |
| 1923 | + int i; |
| 1924 | + int x; |
| 1925 | + int iCol; |
| 1926 | + ChangeSpan span; |
| 1927 | + oneLineChange(pX, pY, &span); |
| 1928 | + p->lnLeft++; |
| 1929 | + p->lnRight++; |
| 1930 | + blob_appendf(p->pOut,"<del>%6d</del> \n", p->lnLeft); |
| 1931 | + blob_append(&p->aCol[0], "<del>", -1); |
| 1932 | + for(i=x=iCol=0; i<span.n; i++){ |
| 1933 | + int ofst = span.a[i].iStart1; |
| 1934 | + int len = span.a[i].iLen1; |
| 1935 | + if( len ){ |
| 1936 | + jsonize_to_blob(&p->aCol[0], pX->z+x, ofst - x, &iCol); |
| 1937 | + x = ofst; |
| 1938 | + blob_append(&p->aCol[0], "<mark>", 6); |
| 1939 | + jsonize_to_blob(&p->aCol[0], pX->z+x, len, &iCol); |
| 1940 | + x += len; |
| 1941 | + blob_append(&p->aCol[0], "</mark>", 7); |
| 1942 | + } |
| 1943 | + } |
| 1944 | + if( x<pX->n ) jsonize_to_blob(&p->aCol[0], pX->z+x, pX->n - x, &iCol); |
| 1945 | + blob_append(&p->aCol[0], "</del>\n", -1); |
| 1946 | + blob_appendf(&p->aCol[1]," <ins>%6d</ins>\n", p->lnRight); |
| 1947 | + blob_append(&p->aCol[2], "<ins>", -1); |
| 1948 | + for(i=x=iCol=0; i<span.n; i++){ |
| 1949 | + int ofst = span.a[i].iStart2; |
| 1950 | + int len = span.a[i].iLen2; |
| 1951 | + if( len ){ |
| 1952 | + jsonize_to_blob(&p->aCol[2], pY->z+x, ofst - x, &iCol); |
| 1953 | + x = ofst; |
| 1954 | + blob_append(&p->aCol[2], "<mark>", 6); |
| 1955 | + jsonize_to_blob(&p->aCol[2], pY->z+x, len, &iCol); |
| 1956 | + x += len; |
| 1957 | + blob_append(&p->aCol[2], "</mark>", 7); |
| 1958 | + } |
| 1959 | + } |
| 1960 | + if( x<pY->n ) jsonize_to_blob(&p->aCol[2], pY->z+x, pY->n - x, &iCol); |
| 1961 | + blob_append(&p->aCol[2], "</ins>\n", -1); |
| 1962 | +} |
| 1963 | +static void dfunifiedEnd(DiffBuilder *p){ |
| 1964 | + dfunifiedEmitInsert(p); |
| 1965 | + blob_append(p->pOut, |
| 1966 | + "</pre></td>\n" |
| 1967 | + "<td class=\"udifftxt\" width=\"100%\"><pre class=\"udifftxt\">\n", |
| 1968 | + -1); |
| 1969 | + blob_append(p->pOut, blob_buffer(&p->aCol[0]), blob_size(&p->aCol[0])); |
| 1970 | + blob_reset(&p->aCol[0]); |
| 1971 | + blob_append(p->pOut, "</pre></td></tr>\n</table>\n", -1); |
| 1972 | + fossil_free(p); |
| 1973 | +} |
| 1974 | +static DiffBuilder *dfunifiedNew(Blob *pOut){ |
| 1975 | + DiffBuilder *p = fossil_malloc(sizeof(*p)); |
| 1976 | + p->xSkip = dfunifiedSkip; |
| 1977 | + p->xCommon = dfunifiedCommon; |
| 1978 | + p->xInsert = dfunifiedInsert; |
| 1979 | + p->xDelete = dfunifiedDelete; |
| 1980 | + p->xEdit = dfunifiedEdit; |
| 1981 | + p->xEnd = dfunifiedEnd; |
| 1982 | + p->lnLeft = p->lnRight = 0; |
| 1983 | + p->pOut = pOut; |
| 1984 | + blob_append(pOut, |
| 1985 | + "<table class=\"sbsdiffcols\">\n" |
| 1986 | + "<tr><td class=\"udiffln\"><pre class=\"udiffln\">\n", |
| 1987 | + -1); |
| 1988 | + blob_init(&p->aCol[0], 0, 0); |
| 1989 | + blob_init(&p->aCol[1], 0, 0); |
| 1990 | + blob_init(&p->aCol[2], 0, 0); |
| 1991 | + return p; |
| 1992 | +} |
| 1861 | 1993 | /****************************************************************************/ |
| 1862 | 1994 | |
| 1863 | 1995 | /* |
| 1864 | 1996 | ** Format a diff using a DiffBuilder object |
| 1865 | 1997 | */ |
| | @@ -1949,11 +2081,11 @@ |
| 1949 | 2081 | a += skip; |
| 1950 | 2082 | b += skip; |
| 1951 | 2083 | m = R[r] - skip; |
| 1952 | 2084 | if( r ) skip -= nContext; |
| 1953 | 2085 | if( skip>0 ){ |
| 1954 | | - pBuilder->xSkip(pBuilder, skip); |
| 2086 | + pBuilder->xSkip(pBuilder, skip, 0); |
| 1955 | 2087 | } |
| 1956 | 2088 | for(j=0; j<m; j++){ |
| 1957 | 2089 | pBuilder->xCommon(pBuilder, &A[a+j]); |
| 1958 | 2090 | } |
| 1959 | 2091 | a += m; |
| | @@ -2024,11 +2156,11 @@ |
| 2024 | 2156 | for(j=0; j<m && j<nContext; j++){ |
| 2025 | 2157 | pBuilder->xCommon(pBuilder, &A[a+j]); |
| 2026 | 2158 | } |
| 2027 | 2159 | } |
| 2028 | 2160 | if( R[r]>nContext ){ |
| 2029 | | - pBuilder->xSkip(pBuilder, R[r] - nContext); |
| 2161 | + pBuilder->xSkip(pBuilder, R[r] - nContext, 1); |
| 2030 | 2162 | } |
| 2031 | 2163 | pBuilder->xEnd(pBuilder); |
| 2032 | 2164 | } |
| 2033 | 2165 | |
| 2034 | 2166 | |
| | @@ -2587,10 +2719,13 @@ |
| 2587 | 2719 | }else if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 2588 | 2720 | sbsDiff(&c, pOut, pRe, diffFlags); |
| 2589 | 2721 | }else if( diffFlags & DIFF_DEBUG ){ |
| 2590 | 2722 | DiffBuilder *pBuilder = dfdebugNew(pOut); |
| 2591 | 2723 | formatDiff(&c, pRe, diffFlags, pBuilder); |
| 2724 | + }else if( diffFlags & DIFF_HTML ){ |
| 2725 | + DiffBuilder *pBuilder = dfunifiedNew(pOut); |
| 2726 | + formatDiff(&c, pRe, diffFlags, pBuilder); |
| 2592 | 2727 | }else{ |
| 2593 | 2728 | contextDiff(&c, pOut, pRe, diffFlags); |
| 2594 | 2729 | } |
| 2595 | 2730 | fossil_free(c.aFrom); |
| 2596 | 2731 | fossil_free(c.aTo); |
| 2597 | 2732 | |