Fossil SCM
Make sure side-by-side diff highlighting encloses complete UTF8 characters and does not divide a UTF8 character into two invalid characters.
Commit
e2b34906761dd94ae5c0701c12ac636605272d06
Parent
cae8b6964d73c61…
1 file changed
+27
-7
+27
-7
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -855,21 +855,33 @@ | ||
| 855 | 855 | /* |
| 856 | 856 | ** Simplify iStart and iStart2: |
| 857 | 857 | ** |
| 858 | 858 | ** * If iStart is a null-change then move iStart2 into iStart |
| 859 | 859 | ** * Make sure any null-changes are in canonoical form. |
| 860 | +** * Make sure all changes are at character boundaries for | |
| 861 | +** multi-byte characters. | |
| 860 | 862 | */ |
| 861 | 863 | static void sbsSimplifyLine(SbsLine *p){ |
| 862 | - if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0; | |
| 864 | + if( p->iStart2==p->iEnd2 ){ | |
| 865 | + p->iStart2 = p->iEnd2 = 0; | |
| 866 | + }else if( p->iStart2 ){ | |
| 867 | + while( p->iStart2>0 && (p->zLine[p->iStart2]&0xc0)==0x80 ) p->iStart2--; | |
| 868 | + while( (p->zLine[p->iEnd2+1]&0xc0)==0x80 ) p->iEnd2++; | |
| 869 | + } | |
| 863 | 870 | if( p->iStart==p->iEnd ){ |
| 864 | 871 | p->iStart = p->iStart2; |
| 865 | 872 | p->iEnd = p->iEnd2; |
| 866 | 873 | p->zStart = p->zStart2; |
| 867 | 874 | p->iStart2 = 0; |
| 868 | 875 | p->iEnd2 = 0; |
| 869 | 876 | } |
| 870 | - if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1; | |
| 877 | + if( p->iStart==p->iEnd ){ | |
| 878 | + p->iStart = p->iEnd = -1; | |
| 879 | + }else if( p->iStart>0 ){ | |
| 880 | + while( p->iStart>0 && (p->zLine[p->iStart]&0xc0)==0x80 ) p->iStart--; | |
| 881 | + while( (p->zLine[p->iEnd+1]&0xc0)==0x80 ) p->iEnd++; | |
| 882 | + } | |
| 871 | 883 | } |
| 872 | 884 | |
| 873 | 885 | /* |
| 874 | 886 | ** Write out lines that have been edited. Adjust the highlight to cover |
| 875 | 887 | ** only those parts of the line that actually changed. |
| @@ -881,10 +893,11 @@ | ||
| 881 | 893 | DLine *pRight, /* Right line of the change */ |
| 882 | 894 | int lnRight /* Line number of the right line */ |
| 883 | 895 | ){ |
| 884 | 896 | int nLeft; /* Length of left line in bytes */ |
| 885 | 897 | int nRight; /* Length of right line in bytes */ |
| 898 | + int nShort; /* Shortest of left and right */ | |
| 886 | 899 | int nPrefix; /* Length of common prefix */ |
| 887 | 900 | int nSuffix; /* Length of common suffix */ |
| 888 | 901 | const char *zLeft; /* Text of the left line */ |
| 889 | 902 | const char *zRight; /* Text of the right line */ |
| 890 | 903 | int nLeftDiff; /* nLeft - nPrefix - nSuffix */ |
| @@ -896,25 +909,32 @@ | ||
| 896 | 909 | |
| 897 | 910 | nLeft = pLeft->h & LENGTH_MASK; |
| 898 | 911 | zLeft = pLeft->z; |
| 899 | 912 | nRight = pRight->h & LENGTH_MASK; |
| 900 | 913 | zRight = pRight->z; |
| 914 | + nShort = nLeft<nRight ? nLeft : nRight; | |
| 901 | 915 | |
| 902 | 916 | nPrefix = 0; |
| 903 | - while( nPrefix<nLeft && nPrefix<nRight && zLeft[nPrefix]==zRight[nPrefix] ){ | |
| 917 | + while( nPrefix<nShort && zLeft[nPrefix]==zRight[nPrefix] ){ | |
| 904 | 918 | nPrefix++; |
| 905 | 919 | } |
| 920 | + if( nPrefix<nShort ){ | |
| 921 | + while( nPrefix>0 && (zLeft[nPrefix]&0xc0)==0x80 ) nPrefix--; | |
| 922 | + } | |
| 906 | 923 | nSuffix = 0; |
| 907 | - if( nPrefix<nLeft && nPrefix<nRight ){ | |
| 908 | - while( nSuffix<nLeft && nSuffix<nRight | |
| 924 | + if( nPrefix<nShort ){ | |
| 925 | + while( nSuffix<nShort | |
| 909 | 926 | && zLeft[nLeft-nSuffix-1]==zRight[nRight-nSuffix-1] ){ |
| 910 | 927 | nSuffix++; |
| 911 | 928 | } |
| 929 | + if( nSuffix<nShort ){ | |
| 930 | + while( nSuffix>0 && (zLeft[nLeft-nSuffix+1]&0xc0)==0x80 ) nSuffix--; | |
| 931 | + } | |
| 912 | 932 | if( nSuffix==nLeft || nSuffix==nRight ) nPrefix = 0; |
| 913 | 933 | } |
| 914 | - if( nPrefix+nSuffix > nLeft ) nPrefix = nLeft - nSuffix; | |
| 915 | - if( nPrefix+nSuffix > nRight ) nPrefix = nRight - nSuffix; | |
| 934 | + if( nPrefix+nSuffix > nShort ) nPrefix = nShort - nSuffix; | |
| 935 | + | |
| 916 | 936 | |
| 917 | 937 | /* A single chunk of text inserted on the right */ |
| 918 | 938 | if( nPrefix+nSuffix==nLeft ){ |
| 919 | 939 | sbsWriteLineno(p, lnLeft); |
| 920 | 940 | p->iStart2 = p->iEnd2 = 0; |
| 921 | 941 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -855,21 +855,33 @@ | |
| 855 | /* |
| 856 | ** Simplify iStart and iStart2: |
| 857 | ** |
| 858 | ** * If iStart is a null-change then move iStart2 into iStart |
| 859 | ** * Make sure any null-changes are in canonoical form. |
| 860 | */ |
| 861 | static void sbsSimplifyLine(SbsLine *p){ |
| 862 | if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0; |
| 863 | if( p->iStart==p->iEnd ){ |
| 864 | p->iStart = p->iStart2; |
| 865 | p->iEnd = p->iEnd2; |
| 866 | p->zStart = p->zStart2; |
| 867 | p->iStart2 = 0; |
| 868 | p->iEnd2 = 0; |
| 869 | } |
| 870 | if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1; |
| 871 | } |
| 872 | |
| 873 | /* |
| 874 | ** Write out lines that have been edited. Adjust the highlight to cover |
| 875 | ** only those parts of the line that actually changed. |
| @@ -881,10 +893,11 @@ | |
| 881 | DLine *pRight, /* Right line of the change */ |
| 882 | int lnRight /* Line number of the right line */ |
| 883 | ){ |
| 884 | int nLeft; /* Length of left line in bytes */ |
| 885 | int nRight; /* Length of right line in bytes */ |
| 886 | int nPrefix; /* Length of common prefix */ |
| 887 | int nSuffix; /* Length of common suffix */ |
| 888 | const char *zLeft; /* Text of the left line */ |
| 889 | const char *zRight; /* Text of the right line */ |
| 890 | int nLeftDiff; /* nLeft - nPrefix - nSuffix */ |
| @@ -896,25 +909,32 @@ | |
| 896 | |
| 897 | nLeft = pLeft->h & LENGTH_MASK; |
| 898 | zLeft = pLeft->z; |
| 899 | nRight = pRight->h & LENGTH_MASK; |
| 900 | zRight = pRight->z; |
| 901 | |
| 902 | nPrefix = 0; |
| 903 | while( nPrefix<nLeft && nPrefix<nRight && zLeft[nPrefix]==zRight[nPrefix] ){ |
| 904 | nPrefix++; |
| 905 | } |
| 906 | nSuffix = 0; |
| 907 | if( nPrefix<nLeft && nPrefix<nRight ){ |
| 908 | while( nSuffix<nLeft && nSuffix<nRight |
| 909 | && zLeft[nLeft-nSuffix-1]==zRight[nRight-nSuffix-1] ){ |
| 910 | nSuffix++; |
| 911 | } |
| 912 | if( nSuffix==nLeft || nSuffix==nRight ) nPrefix = 0; |
| 913 | } |
| 914 | if( nPrefix+nSuffix > nLeft ) nPrefix = nLeft - nSuffix; |
| 915 | if( nPrefix+nSuffix > nRight ) nPrefix = nRight - nSuffix; |
| 916 | |
| 917 | /* A single chunk of text inserted on the right */ |
| 918 | if( nPrefix+nSuffix==nLeft ){ |
| 919 | sbsWriteLineno(p, lnLeft); |
| 920 | p->iStart2 = p->iEnd2 = 0; |
| 921 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -855,21 +855,33 @@ | |
| 855 | /* |
| 856 | ** Simplify iStart and iStart2: |
| 857 | ** |
| 858 | ** * If iStart is a null-change then move iStart2 into iStart |
| 859 | ** * Make sure any null-changes are in canonoical form. |
| 860 | ** * Make sure all changes are at character boundaries for |
| 861 | ** multi-byte characters. |
| 862 | */ |
| 863 | static void sbsSimplifyLine(SbsLine *p){ |
| 864 | if( p->iStart2==p->iEnd2 ){ |
| 865 | p->iStart2 = p->iEnd2 = 0; |
| 866 | }else if( p->iStart2 ){ |
| 867 | while( p->iStart2>0 && (p->zLine[p->iStart2]&0xc0)==0x80 ) p->iStart2--; |
| 868 | while( (p->zLine[p->iEnd2+1]&0xc0)==0x80 ) p->iEnd2++; |
| 869 | } |
| 870 | if( p->iStart==p->iEnd ){ |
| 871 | p->iStart = p->iStart2; |
| 872 | p->iEnd = p->iEnd2; |
| 873 | p->zStart = p->zStart2; |
| 874 | p->iStart2 = 0; |
| 875 | p->iEnd2 = 0; |
| 876 | } |
| 877 | if( p->iStart==p->iEnd ){ |
| 878 | p->iStart = p->iEnd = -1; |
| 879 | }else if( p->iStart>0 ){ |
| 880 | while( p->iStart>0 && (p->zLine[p->iStart]&0xc0)==0x80 ) p->iStart--; |
| 881 | while( (p->zLine[p->iEnd+1]&0xc0)==0x80 ) p->iEnd++; |
| 882 | } |
| 883 | } |
| 884 | |
| 885 | /* |
| 886 | ** Write out lines that have been edited. Adjust the highlight to cover |
| 887 | ** only those parts of the line that actually changed. |
| @@ -881,10 +893,11 @@ | |
| 893 | DLine *pRight, /* Right line of the change */ |
| 894 | int lnRight /* Line number of the right line */ |
| 895 | ){ |
| 896 | int nLeft; /* Length of left line in bytes */ |
| 897 | int nRight; /* Length of right line in bytes */ |
| 898 | int nShort; /* Shortest of left and right */ |
| 899 | int nPrefix; /* Length of common prefix */ |
| 900 | int nSuffix; /* Length of common suffix */ |
| 901 | const char *zLeft; /* Text of the left line */ |
| 902 | const char *zRight; /* Text of the right line */ |
| 903 | int nLeftDiff; /* nLeft - nPrefix - nSuffix */ |
| @@ -896,25 +909,32 @@ | |
| 909 | |
| 910 | nLeft = pLeft->h & LENGTH_MASK; |
| 911 | zLeft = pLeft->z; |
| 912 | nRight = pRight->h & LENGTH_MASK; |
| 913 | zRight = pRight->z; |
| 914 | nShort = nLeft<nRight ? nLeft : nRight; |
| 915 | |
| 916 | nPrefix = 0; |
| 917 | while( nPrefix<nShort && zLeft[nPrefix]==zRight[nPrefix] ){ |
| 918 | nPrefix++; |
| 919 | } |
| 920 | if( nPrefix<nShort ){ |
| 921 | while( nPrefix>0 && (zLeft[nPrefix]&0xc0)==0x80 ) nPrefix--; |
| 922 | } |
| 923 | nSuffix = 0; |
| 924 | if( nPrefix<nShort ){ |
| 925 | while( nSuffix<nShort |
| 926 | && zLeft[nLeft-nSuffix-1]==zRight[nRight-nSuffix-1] ){ |
| 927 | nSuffix++; |
| 928 | } |
| 929 | if( nSuffix<nShort ){ |
| 930 | while( nSuffix>0 && (zLeft[nLeft-nSuffix+1]&0xc0)==0x80 ) nSuffix--; |
| 931 | } |
| 932 | if( nSuffix==nLeft || nSuffix==nRight ) nPrefix = 0; |
| 933 | } |
| 934 | if( nPrefix+nSuffix > nShort ) nPrefix = nShort - nSuffix; |
| 935 | |
| 936 | |
| 937 | /* A single chunk of text inserted on the right */ |
| 938 | if( nPrefix+nSuffix==nLeft ){ |
| 939 | sbsWriteLineno(p, lnLeft); |
| 940 | p->iStart2 = p->iEnd2 = 0; |
| 941 |