Fossil SCM
GNU diff doesn't translate \t to whitespace and strip eol-spacing from diff output (when using -w/-Z options), so "fossil diff" shouldn't do that either.
Commit
ac3fcebb192a6ba58f46748165cb50357a68b315
Parent
bae235bf1a5dbcb…
1 file changed
+27
-48
+27
-48
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -76,11 +76,12 @@ | ||
| 76 | 76 | */ |
| 77 | 77 | typedef struct DLine DLine; |
| 78 | 78 | struct DLine { |
| 79 | 79 | const char *z; /* The text of the line */ |
| 80 | 80 | unsigned int h; /* Hash of the line */ |
| 81 | - unsigned short indent; /* Indent of the line. Only !=0 with --ignore-space-at sol option */ | |
| 81 | + unsigned short indent; /* Indent of the line. Only !=0 with -w/-Z option */ | |
| 82 | + unsigned short n; /* number of bytes */ | |
| 82 | 83 | unsigned int iNext; /* 1+(Index of next line with same the same hash) */ |
| 83 | 84 | |
| 84 | 85 | /* an array of DLine elements serves two purposes. The fields |
| 85 | 86 | ** above are one per line of input text. But each entry is also |
| 86 | 87 | ** a bucket in a hash table, as follows: */ |
| @@ -130,11 +131,11 @@ | ||
| 130 | 131 | ** |
| 131 | 132 | ** Profiling show that in most cases this routine consumes the bulk of |
| 132 | 133 | ** the CPU time on a diff. |
| 133 | 134 | */ |
| 134 | 135 | static DLine *break_into_lines(const char *z, int n, int *pnLine, u64 diffFlags){ |
| 135 | - int nLine, i, j, k, s, indent, x; | |
| 136 | + int nLine, i, j, k, s, x; | |
| 136 | 137 | unsigned int h, h2; |
| 137 | 138 | DLine *a; |
| 138 | 139 | |
| 139 | 140 | /* Count the number of lines. Allocate space to hold |
| 140 | 141 | ** the returned array. |
| @@ -163,27 +164,19 @@ | ||
| 163 | 164 | } |
| 164 | 165 | |
| 165 | 166 | /* Fill in the array */ |
| 166 | 167 | for(i=0; i<nLine; i++){ |
| 167 | 168 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 168 | - k = j; | |
| 169 | + a[i].z = z; | |
| 170 | + a[i].n = k = j; | |
| 169 | 171 | s = 0; |
| 170 | - indent = 0; | |
| 171 | 172 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 172 | 173 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 173 | 174 | } |
| 174 | 175 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 175 | - while( s<k && fossil_isspace(z[s]) ){ | |
| 176 | - if( z[s]=='\t' ){ | |
| 177 | - indent = ((indent+9)/8)*8; | |
| 178 | - }else if( z[s]==' ' ){ | |
| 179 | - indent++; | |
| 180 | - } | |
| 181 | - s++; | |
| 182 | - } | |
| 183 | - } | |
| 184 | - a[i].z = z+s; | |
| 176 | + while( s<k && fossil_isspace(z[s]) ){ s++; } | |
| 177 | + } | |
| 185 | 178 | a[i].indent = s; |
| 186 | 179 | for(h=0, x=s; x<k; x++){ |
| 187 | 180 | h = h ^ (h<<2) ^ z[x]; |
| 188 | 181 | } |
| 189 | 182 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| @@ -200,11 +193,12 @@ | ||
| 200 | 193 | |
| 201 | 194 | /* |
| 202 | 195 | ** Return true if two DLine elements are identical. |
| 203 | 196 | */ |
| 204 | 197 | static int same_dline(DLine *pA, DLine *pB){ |
| 205 | - return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0; | |
| 198 | + return pA->h==pB->h && memcmp(pA->z+pA->indent,pB->z+pB->indent, | |
| 199 | + pA->h & LENGTH_MASK)==0; | |
| 206 | 200 | } |
| 207 | 201 | |
| 208 | 202 | /* |
| 209 | 203 | ** Return true if the regular expression *pRe matches any of the |
| 210 | 204 | ** N dlines |
| @@ -240,22 +234,16 @@ | ||
| 240 | 234 | }else if( cPrefix=='+' ){ |
| 241 | 235 | blob_append(pOut, "<span class=\"diffadd\">", -1); |
| 242 | 236 | }else if( cPrefix=='-' ){ |
| 243 | 237 | blob_append(pOut, "<span class=\"diffrm\">", -1); |
| 244 | 238 | } |
| 245 | - if( pLine->indent ){ | |
| 246 | - blob_appendf(pOut, "%*s", pLine->indent, " "); | |
| 247 | - } | |
| 248 | - htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK)); | |
| 239 | + htmlize_to_blob(pOut, pLine->z, pLine->n); | |
| 249 | 240 | if( cPrefix!=' ' ){ |
| 250 | 241 | blob_append(pOut, "</span>", -1); |
| 251 | 242 | } |
| 252 | 243 | }else{ |
| 253 | - if( pLine->indent ){ | |
| 254 | - blob_appendf(pOut, "%*s", pLine->indent, " "); | |
| 255 | - } | |
| 256 | - blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK); | |
| 244 | + blob_append(pOut, pLine->z, pLine->n); | |
| 257 | 245 | } |
| 258 | 246 | blob_append(pOut, "\n", 1); |
| 259 | 247 | } |
| 260 | 248 | |
| 261 | 249 | /* |
| @@ -501,11 +489,11 @@ | ||
| 501 | 489 | ** This comment contains multibyte unicode characters (ü, Æ, ð) in order |
| 502 | 490 | ** to test the ability of the diff code to handle such characters. |
| 503 | 491 | */ |
| 504 | 492 | static void sbsWriteText(SbsLine *p, DLine *pLine, int col){ |
| 505 | 493 | Blob *pCol = p->apCols[col]; |
| 506 | - int n = pLine->h & LENGTH_MASK; | |
| 494 | + int n = pLine->n; | |
| 507 | 495 | int i; /* Number of input characters consumed */ |
| 508 | 496 | int k; /* Cursor position */ |
| 509 | 497 | int needEndSpan = 0; |
| 510 | 498 | const char *zIn = pLine->z; |
| 511 | 499 | int w = p->width; |
| @@ -532,13 +520,10 @@ | ||
| 532 | 520 | p->iEnd = p->iEnd2; |
| 533 | 521 | p->iEnd2 = 0; |
| 534 | 522 | } |
| 535 | 523 | } |
| 536 | 524 | } |
| 537 | - if( pLine->indent && i==0 ){ | |
| 538 | - blob_appendf(pCol, "%*s", pLine->indent, " "); | |
| 539 | - } | |
| 540 | 525 | if( c=='\t' && !p->escHtml ){ |
| 541 | 526 | blob_append(pCol, " ", 1); |
| 542 | 527 | while( (k&7)!=7 && (p->escHtml || k<w) ){ |
| 543 | 528 | blob_append(pCol, " ", 1); |
| 544 | 529 | k++; |
| @@ -562,11 +547,11 @@ | ||
| 562 | 547 | blob_append(pCol, "</span>", 7); |
| 563 | 548 | } |
| 564 | 549 | if( col==SBS_TXTB ){ |
| 565 | 550 | sbsWriteNewlines(p); |
| 566 | 551 | }else if( !p->escHtml ){ |
| 567 | - sbsWriteSpace(p, w-k-pLine->indent, SBS_TXTA); | |
| 552 | + sbsWriteSpace(p, w-k, SBS_TXTA); | |
| 568 | 553 | } |
| 569 | 554 | } |
| 570 | 555 | |
| 571 | 556 | /* |
| 572 | 557 | ** Append a column to the final output blob. |
| @@ -1969,14 +1954,11 @@ | ||
| 1969 | 1954 | typedef struct Annotator Annotator; |
| 1970 | 1955 | struct Annotator { |
| 1971 | 1956 | DContext c; /* The diff-engine context */ |
| 1972 | 1957 | struct AnnLine { /* Lines of the original files... */ |
| 1973 | 1958 | const char *z; /* The text of the line */ |
| 1974 | - short int n; /* Number of bytes. Whether this omits sol/eol spacing | |
| 1975 | - depends on the diffFlags) */ | |
| 1976 | - unsigned short indent; /* Indenting (number of initial spaces, only used | |
| 1977 | - if sol-spacing is ignored in the diffFlags) */ | |
| 1959 | + short int n; /* Number of bytes (omitting trailing space and \n) */ | |
| 1978 | 1960 | short int iVers; /* Level at which tag was set */ |
| 1979 | 1961 | } *aOrig; |
| 1980 | 1962 | int nOrig; /* Number of elements in aOrig[] */ |
| 1981 | 1963 | int nVers; /* Number of versions analyzed */ |
| 1982 | 1964 | int bLimit; /* True if the iLimit was reached */ |
| @@ -2006,12 +1988,11 @@ | ||
| 2006 | 1988 | return 1; |
| 2007 | 1989 | } |
| 2008 | 1990 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2009 | 1991 | for(i=0; i<p->c.nTo; i++){ |
| 2010 | 1992 | p->aOrig[i].z = p->c.aTo[i].z; |
| 2011 | - p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK; | |
| 2012 | - p->aOrig[i].indent = p->c.aTo[i].indent; | |
| 1993 | + p->aOrig[i].n = p->c.aTo[i].n; | |
| 2013 | 1994 | p->aOrig[i].iVers = -1; |
| 2014 | 1995 | } |
| 2015 | 1996 | p->nOrig = p->c.nTo; |
| 2016 | 1997 | return 0; |
| 2017 | 1998 | } |
| @@ -2315,11 +2296,10 @@ | ||
| 2315 | 2296 | @ <pre> |
| 2316 | 2297 | for(i=0; i<ann.nOrig; i++){ |
| 2317 | 2298 | int iVers = ann.aOrig[i].iVers; |
| 2318 | 2299 | char *z = (char*)ann.aOrig[i].z; |
| 2319 | 2300 | int n = ann.aOrig[i].n; |
| 2320 | - int indent = ann.aOrig[i].indent+1; | |
| 2321 | 2301 | char zPrefix[300]; |
| 2322 | 2302 | z[n] = 0; |
| 2323 | 2303 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2324 | 2304 | |
| 2325 | 2305 | if( bBlame ){ |
| @@ -2330,26 +2310,26 @@ | ||
| 2330 | 2310 | "<span style='background-color:%s'>" |
| 2331 | 2311 | "%s%.10s</a> %s</span> %13.13s:", |
| 2332 | 2312 | p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser); |
| 2333 | 2313 | fossil_free(zLink); |
| 2334 | 2314 | }else{ |
| 2335 | - sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s%*s", indent, " "); | |
| 2315 | + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s", ""); | |
| 2336 | 2316 | } |
| 2337 | 2317 | }else{ |
| 2338 | 2318 | if( iVers>=0 ){ |
| 2339 | 2319 | struct AnnVers *p = ann.aVers+iVers; |
| 2340 | 2320 | char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid); |
| 2341 | 2321 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, |
| 2342 | 2322 | "<span style='background-color:%s'>" |
| 2343 | - "%s%.10s</a> %s</span> %4d:%*s", | |
| 2344 | - p->zBgColor, zLink, p->zMUuid, p->zDate, i+1, indent, " "); | |
| 2323 | + "%s%.10s</a> %s</span> %4d:", | |
| 2324 | + p->zBgColor, zLink, p->zMUuid, p->zDate, i+1); | |
| 2345 | 2325 | fossil_free(zLink); |
| 2346 | 2326 | }else{ |
| 2347 | - sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:%*s", "", i+1, indent, " "); | |
| 2327 | + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:", "", i+1); | |
| 2348 | 2328 | } |
| 2349 | 2329 | } |
| 2350 | - @ %s(zPrefix)%h(z) | |
| 2330 | + @ %s(zPrefix) %h(z) | |
| 2351 | 2331 | |
| 2352 | 2332 | } |
| 2353 | 2333 | @ </pre> |
| 2354 | 2334 | style_footer(); |
| 2355 | 2335 | } |
| @@ -2437,28 +2417,27 @@ | ||
| 2437 | 2417 | fossil_print("---------------------------------------------------\n"); |
| 2438 | 2418 | } |
| 2439 | 2419 | for(i=0; i<ann.nOrig; i++){ |
| 2440 | 2420 | int iVers = ann.aOrig[i].iVers; |
| 2441 | 2421 | char *z = (char*)ann.aOrig[i].z; |
| 2442 | - int indent = ann.aOrig[i].indent + 1; | |
| 2443 | 2422 | int n = ann.aOrig[i].n; |
| 2444 | 2423 | struct AnnVers *p; |
| 2445 | 2424 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2446 | 2425 | p = ann.aVers + iVers; |
| 2447 | 2426 | if( bBlame ){ |
| 2448 | 2427 | if( iVers>=0 ){ |
| 2449 | - fossil_print("%.10s %s %13.13s:%*s%.*s\n", | |
| 2450 | - fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, indent, " ", n, z); | |
| 2428 | + fossil_print("%.10s %s %13.13s: %.*s\n", | |
| 2429 | + fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z); | |
| 2451 | 2430 | }else{ |
| 2452 | - fossil_print("%35s %*s%.*s\n", "", indent, " ", n, z); | |
| 2431 | + fossil_print("%35s %.*s\n", "", n, z); | |
| 2453 | 2432 | } |
| 2454 | 2433 | }else{ |
| 2455 | 2434 | if( iVers>=0 ){ |
| 2456 | - fossil_print("%.10s %s %5d:%*s%.*s\n", | |
| 2457 | - fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, indent, " ", n, z); | |
| 2435 | + fossil_print("%.10s %s %5d: %.*s\n", | |
| 2436 | + fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z); | |
| 2458 | 2437 | }else{ |
| 2459 | - fossil_print("%21s %5d:%*s%.*s\n", | |
| 2460 | - "", i+1, indent, " ", n, z); | |
| 2438 | + fossil_print("%21s %5d: %.*s\n", | |
| 2439 | + "", i+1, n, z); | |
| 2461 | 2440 | } |
| 2462 | 2441 | } |
| 2463 | 2442 | } |
| 2464 | 2443 | } |
| 2465 | 2444 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -76,11 +76,12 @@ | |
| 76 | */ |
| 77 | typedef struct DLine DLine; |
| 78 | struct DLine { |
| 79 | const char *z; /* The text of the line */ |
| 80 | unsigned int h; /* Hash of the line */ |
| 81 | unsigned short indent; /* Indent of the line. Only !=0 with --ignore-space-at sol option */ |
| 82 | unsigned int iNext; /* 1+(Index of next line with same the same hash) */ |
| 83 | |
| 84 | /* an array of DLine elements serves two purposes. The fields |
| 85 | ** above are one per line of input text. But each entry is also |
| 86 | ** a bucket in a hash table, as follows: */ |
| @@ -130,11 +131,11 @@ | |
| 130 | ** |
| 131 | ** Profiling show that in most cases this routine consumes the bulk of |
| 132 | ** the CPU time on a diff. |
| 133 | */ |
| 134 | static DLine *break_into_lines(const char *z, int n, int *pnLine, u64 diffFlags){ |
| 135 | int nLine, i, j, k, s, indent, x; |
| 136 | unsigned int h, h2; |
| 137 | DLine *a; |
| 138 | |
| 139 | /* Count the number of lines. Allocate space to hold |
| 140 | ** the returned array. |
| @@ -163,27 +164,19 @@ | |
| 163 | } |
| 164 | |
| 165 | /* Fill in the array */ |
| 166 | for(i=0; i<nLine; i++){ |
| 167 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 168 | k = j; |
| 169 | s = 0; |
| 170 | indent = 0; |
| 171 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 172 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 173 | } |
| 174 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 175 | while( s<k && fossil_isspace(z[s]) ){ |
| 176 | if( z[s]=='\t' ){ |
| 177 | indent = ((indent+9)/8)*8; |
| 178 | }else if( z[s]==' ' ){ |
| 179 | indent++; |
| 180 | } |
| 181 | s++; |
| 182 | } |
| 183 | } |
| 184 | a[i].z = z+s; |
| 185 | a[i].indent = s; |
| 186 | for(h=0, x=s; x<k; x++){ |
| 187 | h = h ^ (h<<2) ^ z[x]; |
| 188 | } |
| 189 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| @@ -200,11 +193,12 @@ | |
| 200 | |
| 201 | /* |
| 202 | ** Return true if two DLine elements are identical. |
| 203 | */ |
| 204 | static int same_dline(DLine *pA, DLine *pB){ |
| 205 | return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0; |
| 206 | } |
| 207 | |
| 208 | /* |
| 209 | ** Return true if the regular expression *pRe matches any of the |
| 210 | ** N dlines |
| @@ -240,22 +234,16 @@ | |
| 240 | }else if( cPrefix=='+' ){ |
| 241 | blob_append(pOut, "<span class=\"diffadd\">", -1); |
| 242 | }else if( cPrefix=='-' ){ |
| 243 | blob_append(pOut, "<span class=\"diffrm\">", -1); |
| 244 | } |
| 245 | if( pLine->indent ){ |
| 246 | blob_appendf(pOut, "%*s", pLine->indent, " "); |
| 247 | } |
| 248 | htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK)); |
| 249 | if( cPrefix!=' ' ){ |
| 250 | blob_append(pOut, "</span>", -1); |
| 251 | } |
| 252 | }else{ |
| 253 | if( pLine->indent ){ |
| 254 | blob_appendf(pOut, "%*s", pLine->indent, " "); |
| 255 | } |
| 256 | blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK); |
| 257 | } |
| 258 | blob_append(pOut, "\n", 1); |
| 259 | } |
| 260 | |
| 261 | /* |
| @@ -501,11 +489,11 @@ | |
| 501 | ** This comment contains multibyte unicode characters (ü, Æ, ð) in order |
| 502 | ** to test the ability of the diff code to handle such characters. |
| 503 | */ |
| 504 | static void sbsWriteText(SbsLine *p, DLine *pLine, int col){ |
| 505 | Blob *pCol = p->apCols[col]; |
| 506 | int n = pLine->h & LENGTH_MASK; |
| 507 | int i; /* Number of input characters consumed */ |
| 508 | int k; /* Cursor position */ |
| 509 | int needEndSpan = 0; |
| 510 | const char *zIn = pLine->z; |
| 511 | int w = p->width; |
| @@ -532,13 +520,10 @@ | |
| 532 | p->iEnd = p->iEnd2; |
| 533 | p->iEnd2 = 0; |
| 534 | } |
| 535 | } |
| 536 | } |
| 537 | if( pLine->indent && i==0 ){ |
| 538 | blob_appendf(pCol, "%*s", pLine->indent, " "); |
| 539 | } |
| 540 | if( c=='\t' && !p->escHtml ){ |
| 541 | blob_append(pCol, " ", 1); |
| 542 | while( (k&7)!=7 && (p->escHtml || k<w) ){ |
| 543 | blob_append(pCol, " ", 1); |
| 544 | k++; |
| @@ -562,11 +547,11 @@ | |
| 562 | blob_append(pCol, "</span>", 7); |
| 563 | } |
| 564 | if( col==SBS_TXTB ){ |
| 565 | sbsWriteNewlines(p); |
| 566 | }else if( !p->escHtml ){ |
| 567 | sbsWriteSpace(p, w-k-pLine->indent, SBS_TXTA); |
| 568 | } |
| 569 | } |
| 570 | |
| 571 | /* |
| 572 | ** Append a column to the final output blob. |
| @@ -1969,14 +1954,11 @@ | |
| 1969 | typedef struct Annotator Annotator; |
| 1970 | struct Annotator { |
| 1971 | DContext c; /* The diff-engine context */ |
| 1972 | struct AnnLine { /* Lines of the original files... */ |
| 1973 | const char *z; /* The text of the line */ |
| 1974 | short int n; /* Number of bytes. Whether this omits sol/eol spacing |
| 1975 | depends on the diffFlags) */ |
| 1976 | unsigned short indent; /* Indenting (number of initial spaces, only used |
| 1977 | if sol-spacing is ignored in the diffFlags) */ |
| 1978 | short int iVers; /* Level at which tag was set */ |
| 1979 | } *aOrig; |
| 1980 | int nOrig; /* Number of elements in aOrig[] */ |
| 1981 | int nVers; /* Number of versions analyzed */ |
| 1982 | int bLimit; /* True if the iLimit was reached */ |
| @@ -2006,12 +1988,11 @@ | |
| 2006 | return 1; |
| 2007 | } |
| 2008 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2009 | for(i=0; i<p->c.nTo; i++){ |
| 2010 | p->aOrig[i].z = p->c.aTo[i].z; |
| 2011 | p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK; |
| 2012 | p->aOrig[i].indent = p->c.aTo[i].indent; |
| 2013 | p->aOrig[i].iVers = -1; |
| 2014 | } |
| 2015 | p->nOrig = p->c.nTo; |
| 2016 | return 0; |
| 2017 | } |
| @@ -2315,11 +2296,10 @@ | |
| 2315 | @ <pre> |
| 2316 | for(i=0; i<ann.nOrig; i++){ |
| 2317 | int iVers = ann.aOrig[i].iVers; |
| 2318 | char *z = (char*)ann.aOrig[i].z; |
| 2319 | int n = ann.aOrig[i].n; |
| 2320 | int indent = ann.aOrig[i].indent+1; |
| 2321 | char zPrefix[300]; |
| 2322 | z[n] = 0; |
| 2323 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2324 | |
| 2325 | if( bBlame ){ |
| @@ -2330,26 +2310,26 @@ | |
| 2330 | "<span style='background-color:%s'>" |
| 2331 | "%s%.10s</a> %s</span> %13.13s:", |
| 2332 | p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser); |
| 2333 | fossil_free(zLink); |
| 2334 | }else{ |
| 2335 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s%*s", indent, " "); |
| 2336 | } |
| 2337 | }else{ |
| 2338 | if( iVers>=0 ){ |
| 2339 | struct AnnVers *p = ann.aVers+iVers; |
| 2340 | char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid); |
| 2341 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, |
| 2342 | "<span style='background-color:%s'>" |
| 2343 | "%s%.10s</a> %s</span> %4d:%*s", |
| 2344 | p->zBgColor, zLink, p->zMUuid, p->zDate, i+1, indent, " "); |
| 2345 | fossil_free(zLink); |
| 2346 | }else{ |
| 2347 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:%*s", "", i+1, indent, " "); |
| 2348 | } |
| 2349 | } |
| 2350 | @ %s(zPrefix)%h(z) |
| 2351 | |
| 2352 | } |
| 2353 | @ </pre> |
| 2354 | style_footer(); |
| 2355 | } |
| @@ -2437,28 +2417,27 @@ | |
| 2437 | fossil_print("---------------------------------------------------\n"); |
| 2438 | } |
| 2439 | for(i=0; i<ann.nOrig; i++){ |
| 2440 | int iVers = ann.aOrig[i].iVers; |
| 2441 | char *z = (char*)ann.aOrig[i].z; |
| 2442 | int indent = ann.aOrig[i].indent + 1; |
| 2443 | int n = ann.aOrig[i].n; |
| 2444 | struct AnnVers *p; |
| 2445 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2446 | p = ann.aVers + iVers; |
| 2447 | if( bBlame ){ |
| 2448 | if( iVers>=0 ){ |
| 2449 | fossil_print("%.10s %s %13.13s:%*s%.*s\n", |
| 2450 | fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, indent, " ", n, z); |
| 2451 | }else{ |
| 2452 | fossil_print("%35s %*s%.*s\n", "", indent, " ", n, z); |
| 2453 | } |
| 2454 | }else{ |
| 2455 | if( iVers>=0 ){ |
| 2456 | fossil_print("%.10s %s %5d:%*s%.*s\n", |
| 2457 | fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, indent, " ", n, z); |
| 2458 | }else{ |
| 2459 | fossil_print("%21s %5d:%*s%.*s\n", |
| 2460 | "", i+1, indent, " ", n, z); |
| 2461 | } |
| 2462 | } |
| 2463 | } |
| 2464 | } |
| 2465 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -76,11 +76,12 @@ | |
| 76 | */ |
| 77 | typedef struct DLine DLine; |
| 78 | struct DLine { |
| 79 | const char *z; /* The text of the line */ |
| 80 | unsigned int h; /* Hash of the line */ |
| 81 | unsigned short indent; /* Indent of the line. Only !=0 with -w/-Z option */ |
| 82 | unsigned short n; /* number of bytes */ |
| 83 | unsigned int iNext; /* 1+(Index of next line with same the same hash) */ |
| 84 | |
| 85 | /* an array of DLine elements serves two purposes. The fields |
| 86 | ** above are one per line of input text. But each entry is also |
| 87 | ** a bucket in a hash table, as follows: */ |
| @@ -130,11 +131,11 @@ | |
| 131 | ** |
| 132 | ** Profiling show that in most cases this routine consumes the bulk of |
| 133 | ** the CPU time on a diff. |
| 134 | */ |
| 135 | static DLine *break_into_lines(const char *z, int n, int *pnLine, u64 diffFlags){ |
| 136 | int nLine, i, j, k, s, x; |
| 137 | unsigned int h, h2; |
| 138 | DLine *a; |
| 139 | |
| 140 | /* Count the number of lines. Allocate space to hold |
| 141 | ** the returned array. |
| @@ -163,27 +164,19 @@ | |
| 164 | } |
| 165 | |
| 166 | /* Fill in the array */ |
| 167 | for(i=0; i<nLine; i++){ |
| 168 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 169 | a[i].z = z; |
| 170 | a[i].n = k = j; |
| 171 | s = 0; |
| 172 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 173 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 174 | } |
| 175 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 176 | while( s<k && fossil_isspace(z[s]) ){ s++; } |
| 177 | } |
| 178 | a[i].indent = s; |
| 179 | for(h=0, x=s; x<k; x++){ |
| 180 | h = h ^ (h<<2) ^ z[x]; |
| 181 | } |
| 182 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| @@ -200,11 +193,12 @@ | |
| 193 | |
| 194 | /* |
| 195 | ** Return true if two DLine elements are identical. |
| 196 | */ |
| 197 | static int same_dline(DLine *pA, DLine *pB){ |
| 198 | return pA->h==pB->h && memcmp(pA->z+pA->indent,pB->z+pB->indent, |
| 199 | pA->h & LENGTH_MASK)==0; |
| 200 | } |
| 201 | |
| 202 | /* |
| 203 | ** Return true if the regular expression *pRe matches any of the |
| 204 | ** N dlines |
| @@ -240,22 +234,16 @@ | |
| 234 | }else if( cPrefix=='+' ){ |
| 235 | blob_append(pOut, "<span class=\"diffadd\">", -1); |
| 236 | }else if( cPrefix=='-' ){ |
| 237 | blob_append(pOut, "<span class=\"diffrm\">", -1); |
| 238 | } |
| 239 | htmlize_to_blob(pOut, pLine->z, pLine->n); |
| 240 | if( cPrefix!=' ' ){ |
| 241 | blob_append(pOut, "</span>", -1); |
| 242 | } |
| 243 | }else{ |
| 244 | blob_append(pOut, pLine->z, pLine->n); |
| 245 | } |
| 246 | blob_append(pOut, "\n", 1); |
| 247 | } |
| 248 | |
| 249 | /* |
| @@ -501,11 +489,11 @@ | |
| 489 | ** This comment contains multibyte unicode characters (ü, Æ, ð) in order |
| 490 | ** to test the ability of the diff code to handle such characters. |
| 491 | */ |
| 492 | static void sbsWriteText(SbsLine *p, DLine *pLine, int col){ |
| 493 | Blob *pCol = p->apCols[col]; |
| 494 | int n = pLine->n; |
| 495 | int i; /* Number of input characters consumed */ |
| 496 | int k; /* Cursor position */ |
| 497 | int needEndSpan = 0; |
| 498 | const char *zIn = pLine->z; |
| 499 | int w = p->width; |
| @@ -532,13 +520,10 @@ | |
| 520 | p->iEnd = p->iEnd2; |
| 521 | p->iEnd2 = 0; |
| 522 | } |
| 523 | } |
| 524 | } |
| 525 | if( c=='\t' && !p->escHtml ){ |
| 526 | blob_append(pCol, " ", 1); |
| 527 | while( (k&7)!=7 && (p->escHtml || k<w) ){ |
| 528 | blob_append(pCol, " ", 1); |
| 529 | k++; |
| @@ -562,11 +547,11 @@ | |
| 547 | blob_append(pCol, "</span>", 7); |
| 548 | } |
| 549 | if( col==SBS_TXTB ){ |
| 550 | sbsWriteNewlines(p); |
| 551 | }else if( !p->escHtml ){ |
| 552 | sbsWriteSpace(p, w-k, SBS_TXTA); |
| 553 | } |
| 554 | } |
| 555 | |
| 556 | /* |
| 557 | ** Append a column to the final output blob. |
| @@ -1969,14 +1954,11 @@ | |
| 1954 | typedef struct Annotator Annotator; |
| 1955 | struct Annotator { |
| 1956 | DContext c; /* The diff-engine context */ |
| 1957 | struct AnnLine { /* Lines of the original files... */ |
| 1958 | const char *z; /* The text of the line */ |
| 1959 | short int n; /* Number of bytes (omitting trailing space and \n) */ |
| 1960 | short int iVers; /* Level at which tag was set */ |
| 1961 | } *aOrig; |
| 1962 | int nOrig; /* Number of elements in aOrig[] */ |
| 1963 | int nVers; /* Number of versions analyzed */ |
| 1964 | int bLimit; /* True if the iLimit was reached */ |
| @@ -2006,12 +1988,11 @@ | |
| 1988 | return 1; |
| 1989 | } |
| 1990 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 1991 | for(i=0; i<p->c.nTo; i++){ |
| 1992 | p->aOrig[i].z = p->c.aTo[i].z; |
| 1993 | p->aOrig[i].n = p->c.aTo[i].n; |
| 1994 | p->aOrig[i].iVers = -1; |
| 1995 | } |
| 1996 | p->nOrig = p->c.nTo; |
| 1997 | return 0; |
| 1998 | } |
| @@ -2315,11 +2296,10 @@ | |
| 2296 | @ <pre> |
| 2297 | for(i=0; i<ann.nOrig; i++){ |
| 2298 | int iVers = ann.aOrig[i].iVers; |
| 2299 | char *z = (char*)ann.aOrig[i].z; |
| 2300 | int n = ann.aOrig[i].n; |
| 2301 | char zPrefix[300]; |
| 2302 | z[n] = 0; |
| 2303 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2304 | |
| 2305 | if( bBlame ){ |
| @@ -2330,26 +2310,26 @@ | |
| 2310 | "<span style='background-color:%s'>" |
| 2311 | "%s%.10s</a> %s</span> %13.13s:", |
| 2312 | p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser); |
| 2313 | fossil_free(zLink); |
| 2314 | }else{ |
| 2315 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s", ""); |
| 2316 | } |
| 2317 | }else{ |
| 2318 | if( iVers>=0 ){ |
| 2319 | struct AnnVers *p = ann.aVers+iVers; |
| 2320 | char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid); |
| 2321 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, |
| 2322 | "<span style='background-color:%s'>" |
| 2323 | "%s%.10s</a> %s</span> %4d:", |
| 2324 | p->zBgColor, zLink, p->zMUuid, p->zDate, i+1); |
| 2325 | fossil_free(zLink); |
| 2326 | }else{ |
| 2327 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:", "", i+1); |
| 2328 | } |
| 2329 | } |
| 2330 | @ %s(zPrefix) %h(z) |
| 2331 | |
| 2332 | } |
| 2333 | @ </pre> |
| 2334 | style_footer(); |
| 2335 | } |
| @@ -2437,28 +2417,27 @@ | |
| 2417 | fossil_print("---------------------------------------------------\n"); |
| 2418 | } |
| 2419 | for(i=0; i<ann.nOrig; i++){ |
| 2420 | int iVers = ann.aOrig[i].iVers; |
| 2421 | char *z = (char*)ann.aOrig[i].z; |
| 2422 | int n = ann.aOrig[i].n; |
| 2423 | struct AnnVers *p; |
| 2424 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2425 | p = ann.aVers + iVers; |
| 2426 | if( bBlame ){ |
| 2427 | if( iVers>=0 ){ |
| 2428 | fossil_print("%.10s %s %13.13s: %.*s\n", |
| 2429 | fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z); |
| 2430 | }else{ |
| 2431 | fossil_print("%35s %.*s\n", "", n, z); |
| 2432 | } |
| 2433 | }else{ |
| 2434 | if( iVers>=0 ){ |
| 2435 | fossil_print("%.10s %s %5d: %.*s\n", |
| 2436 | fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z); |
| 2437 | }else{ |
| 2438 | fossil_print("%21s %5d: %.*s\n", |
| 2439 | "", i+1, n, z); |
| 2440 | } |
| 2441 | } |
| 2442 | } |
| 2443 | } |
| 2444 |