Fossil SCM
Fix -w|--ignore-all-space option such that it does exactly the same as GNU diff's option with the same name.
Commit
bb3388345d25eed7ae1dea0de629f7ee8f488ae5
Parent
d9e79f685bf4c7c…
1 file changed
+33
-49
+33
-49
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -77,11 +77,11 @@ | ||
| 77 | 77 | */ |
| 78 | 78 | typedef struct DLine DLine; |
| 79 | 79 | struct DLine { |
| 80 | 80 | const char *z; /* The text of the line */ |
| 81 | 81 | unsigned int h; /* Hash of the line */ |
| 82 | - unsigned short indent; /* Indent of the line. Only !=0 with --ignore-space-at sol option */ | |
| 82 | + unsigned short extent; /* Extent of the line. how much longer than recorded in h */ | |
| 83 | 83 | unsigned int iNext; /* 1+(Index of next line with same the same hash) */ |
| 84 | 84 | |
| 85 | 85 | /* an array of DLine elements serves two purposes. The fields |
| 86 | 86 | ** above are one per line of input text. But each entry is also |
| 87 | 87 | ** a bucket in a hash table, as follows: */ |
| @@ -131,11 +131,11 @@ | ||
| 131 | 131 | ** |
| 132 | 132 | ** Profiling show that in most cases this routine consumes the bulk of |
| 133 | 133 | ** the CPU time on a diff. |
| 134 | 134 | */ |
| 135 | 135 | static DLine *break_into_lines(const char *z, int n, int *pnLine, u64 diffFlags){ |
| 136 | - int nLine, i, j, k, s, indent, x; | |
| 136 | + int nLine, i, j, k, s, extent, x, numws; | |
| 137 | 137 | unsigned int h, h2; |
| 138 | 138 | DLine *a; |
| 139 | 139 | |
| 140 | 140 | /* Count the number of lines. Allocate space to hold |
| 141 | 141 | ** the returned array. |
| @@ -166,32 +166,31 @@ | ||
| 166 | 166 | /* Fill in the array */ |
| 167 | 167 | for(i=0; i<nLine; i++){ |
| 168 | 168 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 169 | 169 | k = j; |
| 170 | 170 | s = 0; |
| 171 | - indent = 0; | |
| 171 | + extent = 0; /* number of spaces ignored from start/end */ | |
| 172 | + numws = 0; /* number of spaces ignored in between */ | |
| 172 | 173 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 173 | - while( k>0 && fossil_isspace(z[k-1]) ){ k--; } | |
| 174 | + while( k>0 && fossil_isspace(z[k-1]) ){ k--; extent++;} | |
| 174 | 175 | }else if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 176 | + /* Don't do "extend++" here, because the CR needs to be stripped! */ | |
| 175 | 177 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 176 | 178 | } |
| 177 | 179 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 178 | - while( s<k && fossil_isspace(z[s]) ){ | |
| 179 | - if( z[s]=='\t' ){ | |
| 180 | - indent = ((indent+9)/8)*8; | |
| 181 | - }else if( z[s]==' ' ){ | |
| 182 | - indent++; | |
| 183 | - } | |
| 184 | - s++; | |
| 185 | - } | |
| 186 | - } | |
| 187 | - a[i].z = z+s; | |
| 188 | - a[i].indent = s; | |
| 180 | + while( s<k && fossil_isspace(z[s]) ){s++; extent++;} | |
| 181 | + } | |
| 189 | 182 | for(h=0, x=s; x<k; x++){ |
| 190 | - h = h ^ (h<<2) ^ z[x]; | |
| 183 | + if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS && fossil_isspace(z[x]) ){ | |
| 184 | + ++numws; | |
| 185 | + }else{ | |
| 186 | + h = h ^ (h<<2) ^ z[x]; | |
| 187 | + } | |
| 191 | 188 | } |
| 192 | - a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); | |
| 189 | + a[i].z = z; | |
| 190 | + a[i].extent = extent+numws; | |
| 191 | + a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s-numws); | |
| 193 | 192 | h2 = h % nLine; |
| 194 | 193 | a[i].iNext = a[h2].iHash; |
| 195 | 194 | a[h2].iHash = i+1; |
| 196 | 195 | z += j+1; |
| 197 | 196 | } |
| @@ -243,22 +242,16 @@ | ||
| 243 | 242 | }else if( cPrefix=='+' ){ |
| 244 | 243 | blob_append(pOut, "<span class=\"diffadd\">", -1); |
| 245 | 244 | }else if( cPrefix=='-' ){ |
| 246 | 245 | blob_append(pOut, "<span class=\"diffrm\">", -1); |
| 247 | 246 | } |
| 248 | - if( pLine->indent ){ | |
| 249 | - blob_appendf(pOut, "%*s", pLine->indent, " "); | |
| 250 | - } | |
| 251 | 247 | htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK)); |
| 252 | 248 | if( cPrefix!=' ' ){ |
| 253 | 249 | blob_append(pOut, "</span>", -1); |
| 254 | 250 | } |
| 255 | 251 | }else{ |
| 256 | - if( pLine->indent ){ | |
| 257 | - blob_appendf(pOut, "%*s", pLine->indent, " "); | |
| 258 | - } | |
| 259 | - blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK); | |
| 252 | + blob_append(pOut, pLine->z, (pLine->h & LENGTH_MASK) + pLine->extent); | |
| 260 | 253 | } |
| 261 | 254 | blob_append(pOut, "\n", 1); |
| 262 | 255 | } |
| 263 | 256 | |
| 264 | 257 | /* |
| @@ -504,11 +497,11 @@ | ||
| 504 | 497 | ** This comment contains multibyte unicode characters (ü, Æ, ð) in order |
| 505 | 498 | ** to test the ability of the diff code to handle such characters. |
| 506 | 499 | */ |
| 507 | 500 | static void sbsWriteText(SbsLine *p, DLine *pLine, int col){ |
| 508 | 501 | Blob *pCol = p->apCols[col]; |
| 509 | - int n = pLine->h & LENGTH_MASK; | |
| 502 | + int n = (pLine->h & LENGTH_MASK) + pLine->extent; | |
| 510 | 503 | int i; /* Number of input characters consumed */ |
| 511 | 504 | int k; /* Cursor position */ |
| 512 | 505 | int needEndSpan = 0; |
| 513 | 506 | const char *zIn = pLine->z; |
| 514 | 507 | int w = p->width; |
| @@ -535,13 +528,10 @@ | ||
| 535 | 528 | p->iEnd = p->iEnd2; |
| 536 | 529 | p->iEnd2 = 0; |
| 537 | 530 | } |
| 538 | 531 | } |
| 539 | 532 | } |
| 540 | - if( pLine->indent && i==0 ){ | |
| 541 | - blob_appendf(pCol, "%*s", pLine->indent, " "); | |
| 542 | - } | |
| 543 | 533 | if( c=='\t' && !p->escHtml ){ |
| 544 | 534 | blob_append(pCol, " ", 1); |
| 545 | 535 | while( (k&7)!=7 && (p->escHtml || k<w) ){ |
| 546 | 536 | blob_append(pCol, " ", 1); |
| 547 | 537 | k++; |
| @@ -565,11 +555,11 @@ | ||
| 565 | 555 | blob_append(pCol, "</span>", 7); |
| 566 | 556 | } |
| 567 | 557 | if( col==SBS_TXTB ){ |
| 568 | 558 | sbsWriteNewlines(p); |
| 569 | 559 | }else if( !p->escHtml ){ |
| 570 | - sbsWriteSpace(p, w-k-pLine->indent, SBS_TXTA); | |
| 560 | + sbsWriteSpace(p, w-k, SBS_TXTA); | |
| 571 | 561 | } |
| 572 | 562 | } |
| 573 | 563 | |
| 574 | 564 | /* |
| 575 | 565 | ** Append a column to the final output blob. |
| @@ -1980,14 +1970,11 @@ | ||
| 1980 | 1970 | typedef struct Annotator Annotator; |
| 1981 | 1971 | struct Annotator { |
| 1982 | 1972 | DContext c; /* The diff-engine context */ |
| 1983 | 1973 | struct AnnLine { /* Lines of the original files... */ |
| 1984 | 1974 | const char *z; /* The text of the line */ |
| 1985 | - short int n; /* Number of bytes. Whether this omits sol/eol spacing | |
| 1986 | - depends on the diffFlags) */ | |
| 1987 | - unsigned short indent; /* Indenting (number of initial spaces, only used | |
| 1988 | - if sol-spacing is ignored in the diffFlags) */ | |
| 1975 | + short int n; /* Number of bytes */ | |
| 1989 | 1976 | short int iVers; /* Level at which tag was set */ |
| 1990 | 1977 | } *aOrig; |
| 1991 | 1978 | int nOrig; /* Number of elements in aOrig[] */ |
| 1992 | 1979 | int nVers; /* Number of versions analyzed */ |
| 1993 | 1980 | int bLimit; /* True if the iLimit was reached */ |
| @@ -2017,12 +2004,11 @@ | ||
| 2017 | 2004 | return 1; |
| 2018 | 2005 | } |
| 2019 | 2006 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2020 | 2007 | for(i=0; i<p->c.nTo; i++){ |
| 2021 | 2008 | p->aOrig[i].z = p->c.aTo[i].z; |
| 2022 | - p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK; | |
| 2023 | - p->aOrig[i].indent = p->c.aTo[i].indent; | |
| 2009 | + p->aOrig[i].n = (p->c.aTo[i].h & LENGTH_MASK) + p->c.aTo[i].extent; | |
| 2024 | 2010 | p->aOrig[i].iVers = -1; |
| 2025 | 2011 | } |
| 2026 | 2012 | p->nOrig = p->c.nTo; |
| 2027 | 2013 | return 0; |
| 2028 | 2014 | } |
| @@ -2325,11 +2311,10 @@ | ||
| 2325 | 2311 | @ <pre> |
| 2326 | 2312 | for(i=0; i<ann.nOrig; i++){ |
| 2327 | 2313 | int iVers = ann.aOrig[i].iVers; |
| 2328 | 2314 | char *z = (char*)ann.aOrig[i].z; |
| 2329 | 2315 | int n = ann.aOrig[i].n; |
| 2330 | - int indent = ann.aOrig[i].indent+1; | |
| 2331 | 2316 | char zPrefix[300]; |
| 2332 | 2317 | z[n] = 0; |
| 2333 | 2318 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2334 | 2319 | |
| 2335 | 2320 | if( bBlame ){ |
| @@ -2340,23 +2325,23 @@ | ||
| 2340 | 2325 | "<span style='background-color:%s'>" |
| 2341 | 2326 | "%s%.10s</a> %s</span> %13.13s:", |
| 2342 | 2327 | p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser); |
| 2343 | 2328 | fossil_free(zLink); |
| 2344 | 2329 | }else{ |
| 2345 | - sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s%*s", indent, " "); | |
| 2330 | + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s ", ""); | |
| 2346 | 2331 | } |
| 2347 | 2332 | }else{ |
| 2348 | 2333 | if( iVers>=0 ){ |
| 2349 | 2334 | struct AnnVers *p = ann.aVers+iVers; |
| 2350 | 2335 | char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid); |
| 2351 | 2336 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, |
| 2352 | 2337 | "<span style='background-color:%s'>" |
| 2353 | - "%s%.10s</a> %s</span> %4d:%*s", | |
| 2354 | - p->zBgColor, zLink, p->zMUuid, p->zDate, i+1, indent, " "); | |
| 2338 | + "%s%.10s</a> %s</span> %4d: ", | |
| 2339 | + p->zBgColor, zLink, p->zMUuid, p->zDate, i+1); | |
| 2355 | 2340 | fossil_free(zLink); |
| 2356 | 2341 | }else{ |
| 2357 | - sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:%*s", "", i+1, indent, " "); | |
| 2342 | + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d: ", "", i+1); | |
| 2358 | 2343 | } |
| 2359 | 2344 | } |
| 2360 | 2345 | @ %s(zPrefix)%h(z) |
| 2361 | 2346 | |
| 2362 | 2347 | } |
| @@ -2448,28 +2433,27 @@ | ||
| 2448 | 2433 | fossil_print("---------------------------------------------------\n"); |
| 2449 | 2434 | } |
| 2450 | 2435 | for(i=0; i<ann.nOrig; i++){ |
| 2451 | 2436 | int iVers = ann.aOrig[i].iVers; |
| 2452 | 2437 | char *z = (char*)ann.aOrig[i].z; |
| 2453 | - int indent = ann.aOrig[i].indent + 1; | |
| 2454 | 2438 | int n = ann.aOrig[i].n; |
| 2455 | 2439 | struct AnnVers *p; |
| 2456 | 2440 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2457 | 2441 | p = ann.aVers + iVers; |
| 2458 | 2442 | if( bBlame ){ |
| 2459 | 2443 | if( iVers>=0 ){ |
| 2460 | - fossil_print("%.10s %s %13.13s:%*s%.*s\n", | |
| 2461 | - fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, indent, " ", n, z); | |
| 2444 | + fossil_print("%.10s %s %13.13s: %.*s\n", | |
| 2445 | + fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z); | |
| 2462 | 2446 | }else{ |
| 2463 | - fossil_print("%35s %*s%.*s\n", "", indent, " ", n, z); | |
| 2447 | + fossil_print("%35s %.*s\n", "", n, z); | |
| 2464 | 2448 | } |
| 2465 | 2449 | }else{ |
| 2466 | 2450 | if( iVers>=0 ){ |
| 2467 | - fossil_print("%.10s %s %5d:%*s%.*s\n", | |
| 2468 | - fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, indent, " ", n, z); | |
| 2469 | - }else{ | |
| 2470 | - fossil_print("%21s %5d:%*s%.*s\n", | |
| 2471 | - "", i+1, indent, " ", n, z); | |
| 2451 | + fossil_print("%.10s %s %5d: %.*s\n", | |
| 2452 | + fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z); | |
| 2453 | + }else { | |
| 2454 | + fossil_print("%21s %5d: %.*s\n", | |
| 2455 | + "", i+1, n, z); | |
| 2472 | 2456 | } |
| 2473 | 2457 | } |
| 2474 | 2458 | } |
| 2475 | 2459 | } |
| 2476 | 2460 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -77,11 +77,11 @@ | |
| 77 | */ |
| 78 | typedef struct DLine DLine; |
| 79 | struct DLine { |
| 80 | const char *z; /* The text of the line */ |
| 81 | unsigned int h; /* Hash of the line */ |
| 82 | unsigned short indent; /* Indent of the line. Only !=0 with --ignore-space-at sol option */ |
| 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: */ |
| @@ -131,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, indent, x; |
| 137 | unsigned int h, h2; |
| 138 | DLine *a; |
| 139 | |
| 140 | /* Count the number of lines. Allocate space to hold |
| 141 | ** the returned array. |
| @@ -166,32 +166,31 @@ | |
| 166 | /* Fill in the array */ |
| 167 | for(i=0; i<nLine; i++){ |
| 168 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 169 | k = j; |
| 170 | s = 0; |
| 171 | indent = 0; |
| 172 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 173 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 174 | }else if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 175 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 176 | } |
| 177 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 178 | while( s<k && fossil_isspace(z[s]) ){ |
| 179 | if( z[s]=='\t' ){ |
| 180 | indent = ((indent+9)/8)*8; |
| 181 | }else if( z[s]==' ' ){ |
| 182 | indent++; |
| 183 | } |
| 184 | s++; |
| 185 | } |
| 186 | } |
| 187 | a[i].z = z+s; |
| 188 | a[i].indent = s; |
| 189 | for(h=0, x=s; x<k; x++){ |
| 190 | h = h ^ (h<<2) ^ z[x]; |
| 191 | } |
| 192 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| 193 | h2 = h % nLine; |
| 194 | a[i].iNext = a[h2].iHash; |
| 195 | a[h2].iHash = i+1; |
| 196 | z += j+1; |
| 197 | } |
| @@ -243,22 +242,16 @@ | |
| 243 | }else if( cPrefix=='+' ){ |
| 244 | blob_append(pOut, "<span class=\"diffadd\">", -1); |
| 245 | }else if( cPrefix=='-' ){ |
| 246 | blob_append(pOut, "<span class=\"diffrm\">", -1); |
| 247 | } |
| 248 | if( pLine->indent ){ |
| 249 | blob_appendf(pOut, "%*s", pLine->indent, " "); |
| 250 | } |
| 251 | htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK)); |
| 252 | if( cPrefix!=' ' ){ |
| 253 | blob_append(pOut, "</span>", -1); |
| 254 | } |
| 255 | }else{ |
| 256 | if( pLine->indent ){ |
| 257 | blob_appendf(pOut, "%*s", pLine->indent, " "); |
| 258 | } |
| 259 | blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK); |
| 260 | } |
| 261 | blob_append(pOut, "\n", 1); |
| 262 | } |
| 263 | |
| 264 | /* |
| @@ -504,11 +497,11 @@ | |
| 504 | ** This comment contains multibyte unicode characters (ü, Æ, ð) in order |
| 505 | ** to test the ability of the diff code to handle such characters. |
| 506 | */ |
| 507 | static void sbsWriteText(SbsLine *p, DLine *pLine, int col){ |
| 508 | Blob *pCol = p->apCols[col]; |
| 509 | int n = pLine->h & LENGTH_MASK; |
| 510 | int i; /* Number of input characters consumed */ |
| 511 | int k; /* Cursor position */ |
| 512 | int needEndSpan = 0; |
| 513 | const char *zIn = pLine->z; |
| 514 | int w = p->width; |
| @@ -535,13 +528,10 @@ | |
| 535 | p->iEnd = p->iEnd2; |
| 536 | p->iEnd2 = 0; |
| 537 | } |
| 538 | } |
| 539 | } |
| 540 | if( pLine->indent && i==0 ){ |
| 541 | blob_appendf(pCol, "%*s", pLine->indent, " "); |
| 542 | } |
| 543 | if( c=='\t' && !p->escHtml ){ |
| 544 | blob_append(pCol, " ", 1); |
| 545 | while( (k&7)!=7 && (p->escHtml || k<w) ){ |
| 546 | blob_append(pCol, " ", 1); |
| 547 | k++; |
| @@ -565,11 +555,11 @@ | |
| 565 | blob_append(pCol, "</span>", 7); |
| 566 | } |
| 567 | if( col==SBS_TXTB ){ |
| 568 | sbsWriteNewlines(p); |
| 569 | }else if( !p->escHtml ){ |
| 570 | sbsWriteSpace(p, w-k-pLine->indent, SBS_TXTA); |
| 571 | } |
| 572 | } |
| 573 | |
| 574 | /* |
| 575 | ** Append a column to the final output blob. |
| @@ -1980,14 +1970,11 @@ | |
| 1980 | typedef struct Annotator Annotator; |
| 1981 | struct Annotator { |
| 1982 | DContext c; /* The diff-engine context */ |
| 1983 | struct AnnLine { /* Lines of the original files... */ |
| 1984 | const char *z; /* The text of the line */ |
| 1985 | short int n; /* Number of bytes. Whether this omits sol/eol spacing |
| 1986 | depends on the diffFlags) */ |
| 1987 | unsigned short indent; /* Indenting (number of initial spaces, only used |
| 1988 | if sol-spacing is ignored in the diffFlags) */ |
| 1989 | short int iVers; /* Level at which tag was set */ |
| 1990 | } *aOrig; |
| 1991 | int nOrig; /* Number of elements in aOrig[] */ |
| 1992 | int nVers; /* Number of versions analyzed */ |
| 1993 | int bLimit; /* True if the iLimit was reached */ |
| @@ -2017,12 +2004,11 @@ | |
| 2017 | return 1; |
| 2018 | } |
| 2019 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2020 | for(i=0; i<p->c.nTo; i++){ |
| 2021 | p->aOrig[i].z = p->c.aTo[i].z; |
| 2022 | p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK; |
| 2023 | p->aOrig[i].indent = p->c.aTo[i].indent; |
| 2024 | p->aOrig[i].iVers = -1; |
| 2025 | } |
| 2026 | p->nOrig = p->c.nTo; |
| 2027 | return 0; |
| 2028 | } |
| @@ -2325,11 +2311,10 @@ | |
| 2325 | @ <pre> |
| 2326 | for(i=0; i<ann.nOrig; i++){ |
| 2327 | int iVers = ann.aOrig[i].iVers; |
| 2328 | char *z = (char*)ann.aOrig[i].z; |
| 2329 | int n = ann.aOrig[i].n; |
| 2330 | int indent = ann.aOrig[i].indent+1; |
| 2331 | char zPrefix[300]; |
| 2332 | z[n] = 0; |
| 2333 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2334 | |
| 2335 | if( bBlame ){ |
| @@ -2340,23 +2325,23 @@ | |
| 2340 | "<span style='background-color:%s'>" |
| 2341 | "%s%.10s</a> %s</span> %13.13s:", |
| 2342 | p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser); |
| 2343 | fossil_free(zLink); |
| 2344 | }else{ |
| 2345 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s%*s", indent, " "); |
| 2346 | } |
| 2347 | }else{ |
| 2348 | if( iVers>=0 ){ |
| 2349 | struct AnnVers *p = ann.aVers+iVers; |
| 2350 | char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid); |
| 2351 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, |
| 2352 | "<span style='background-color:%s'>" |
| 2353 | "%s%.10s</a> %s</span> %4d:%*s", |
| 2354 | p->zBgColor, zLink, p->zMUuid, p->zDate, i+1, indent, " "); |
| 2355 | fossil_free(zLink); |
| 2356 | }else{ |
| 2357 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:%*s", "", i+1, indent, " "); |
| 2358 | } |
| 2359 | } |
| 2360 | @ %s(zPrefix)%h(z) |
| 2361 | |
| 2362 | } |
| @@ -2448,28 +2433,27 @@ | |
| 2448 | fossil_print("---------------------------------------------------\n"); |
| 2449 | } |
| 2450 | for(i=0; i<ann.nOrig; i++){ |
| 2451 | int iVers = ann.aOrig[i].iVers; |
| 2452 | char *z = (char*)ann.aOrig[i].z; |
| 2453 | int indent = ann.aOrig[i].indent + 1; |
| 2454 | int n = ann.aOrig[i].n; |
| 2455 | struct AnnVers *p; |
| 2456 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2457 | p = ann.aVers + iVers; |
| 2458 | if( bBlame ){ |
| 2459 | if( iVers>=0 ){ |
| 2460 | fossil_print("%.10s %s %13.13s:%*s%.*s\n", |
| 2461 | fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, indent, " ", n, z); |
| 2462 | }else{ |
| 2463 | fossil_print("%35s %*s%.*s\n", "", indent, " ", n, z); |
| 2464 | } |
| 2465 | }else{ |
| 2466 | if( iVers>=0 ){ |
| 2467 | fossil_print("%.10s %s %5d:%*s%.*s\n", |
| 2468 | fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, indent, " ", n, z); |
| 2469 | }else{ |
| 2470 | fossil_print("%21s %5d:%*s%.*s\n", |
| 2471 | "", i+1, indent, " ", n, z); |
| 2472 | } |
| 2473 | } |
| 2474 | } |
| 2475 | } |
| 2476 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -77,11 +77,11 @@ | |
| 77 | */ |
| 78 | typedef struct DLine DLine; |
| 79 | struct DLine { |
| 80 | const char *z; /* The text of the line */ |
| 81 | unsigned int h; /* Hash of the line */ |
| 82 | unsigned short extent; /* Extent of the line. how much longer than recorded in h */ |
| 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: */ |
| @@ -131,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, extent, x, numws; |
| 137 | unsigned int h, h2; |
| 138 | DLine *a; |
| 139 | |
| 140 | /* Count the number of lines. Allocate space to hold |
| 141 | ** the returned array. |
| @@ -166,32 +166,31 @@ | |
| 166 | /* Fill in the array */ |
| 167 | for(i=0; i<nLine; i++){ |
| 168 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 169 | k = j; |
| 170 | s = 0; |
| 171 | extent = 0; /* number of spaces ignored from start/end */ |
| 172 | numws = 0; /* number of spaces ignored in between */ |
| 173 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 174 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; extent++;} |
| 175 | }else if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 176 | /* Don't do "extend++" here, because the CR needs to be stripped! */ |
| 177 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 178 | } |
| 179 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 180 | while( s<k && fossil_isspace(z[s]) ){s++; extent++;} |
| 181 | } |
| 182 | for(h=0, x=s; x<k; x++){ |
| 183 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS && fossil_isspace(z[x]) ){ |
| 184 | ++numws; |
| 185 | }else{ |
| 186 | h = h ^ (h<<2) ^ z[x]; |
| 187 | } |
| 188 | } |
| 189 | a[i].z = z; |
| 190 | a[i].extent = extent+numws; |
| 191 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s-numws); |
| 192 | h2 = h % nLine; |
| 193 | a[i].iNext = a[h2].iHash; |
| 194 | a[h2].iHash = i+1; |
| 195 | z += j+1; |
| 196 | } |
| @@ -243,22 +242,16 @@ | |
| 242 | }else if( cPrefix=='+' ){ |
| 243 | blob_append(pOut, "<span class=\"diffadd\">", -1); |
| 244 | }else if( cPrefix=='-' ){ |
| 245 | blob_append(pOut, "<span class=\"diffrm\">", -1); |
| 246 | } |
| 247 | htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK)); |
| 248 | if( cPrefix!=' ' ){ |
| 249 | blob_append(pOut, "</span>", -1); |
| 250 | } |
| 251 | }else{ |
| 252 | blob_append(pOut, pLine->z, (pLine->h & LENGTH_MASK) + pLine->extent); |
| 253 | } |
| 254 | blob_append(pOut, "\n", 1); |
| 255 | } |
| 256 | |
| 257 | /* |
| @@ -504,11 +497,11 @@ | |
| 497 | ** This comment contains multibyte unicode characters (ü, Æ, ð) in order |
| 498 | ** to test the ability of the diff code to handle such characters. |
| 499 | */ |
| 500 | static void sbsWriteText(SbsLine *p, DLine *pLine, int col){ |
| 501 | Blob *pCol = p->apCols[col]; |
| 502 | int n = (pLine->h & LENGTH_MASK) + pLine->extent; |
| 503 | int i; /* Number of input characters consumed */ |
| 504 | int k; /* Cursor position */ |
| 505 | int needEndSpan = 0; |
| 506 | const char *zIn = pLine->z; |
| 507 | int w = p->width; |
| @@ -535,13 +528,10 @@ | |
| 528 | p->iEnd = p->iEnd2; |
| 529 | p->iEnd2 = 0; |
| 530 | } |
| 531 | } |
| 532 | } |
| 533 | if( c=='\t' && !p->escHtml ){ |
| 534 | blob_append(pCol, " ", 1); |
| 535 | while( (k&7)!=7 && (p->escHtml || k<w) ){ |
| 536 | blob_append(pCol, " ", 1); |
| 537 | k++; |
| @@ -565,11 +555,11 @@ | |
| 555 | blob_append(pCol, "</span>", 7); |
| 556 | } |
| 557 | if( col==SBS_TXTB ){ |
| 558 | sbsWriteNewlines(p); |
| 559 | }else if( !p->escHtml ){ |
| 560 | sbsWriteSpace(p, w-k, SBS_TXTA); |
| 561 | } |
| 562 | } |
| 563 | |
| 564 | /* |
| 565 | ** Append a column to the final output blob. |
| @@ -1980,14 +1970,11 @@ | |
| 1970 | typedef struct Annotator Annotator; |
| 1971 | struct Annotator { |
| 1972 | DContext c; /* The diff-engine context */ |
| 1973 | struct AnnLine { /* Lines of the original files... */ |
| 1974 | const char *z; /* The text of the line */ |
| 1975 | short int n; /* Number of bytes */ |
| 1976 | short int iVers; /* Level at which tag was set */ |
| 1977 | } *aOrig; |
| 1978 | int nOrig; /* Number of elements in aOrig[] */ |
| 1979 | int nVers; /* Number of versions analyzed */ |
| 1980 | int bLimit; /* True if the iLimit was reached */ |
| @@ -2017,12 +2004,11 @@ | |
| 2004 | return 1; |
| 2005 | } |
| 2006 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2007 | for(i=0; i<p->c.nTo; i++){ |
| 2008 | p->aOrig[i].z = p->c.aTo[i].z; |
| 2009 | p->aOrig[i].n = (p->c.aTo[i].h & LENGTH_MASK) + p->c.aTo[i].extent; |
| 2010 | p->aOrig[i].iVers = -1; |
| 2011 | } |
| 2012 | p->nOrig = p->c.nTo; |
| 2013 | return 0; |
| 2014 | } |
| @@ -2325,11 +2311,10 @@ | |
| 2311 | @ <pre> |
| 2312 | for(i=0; i<ann.nOrig; i++){ |
| 2313 | int iVers = ann.aOrig[i].iVers; |
| 2314 | char *z = (char*)ann.aOrig[i].z; |
| 2315 | int n = ann.aOrig[i].n; |
| 2316 | char zPrefix[300]; |
| 2317 | z[n] = 0; |
| 2318 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2319 | |
| 2320 | if( bBlame ){ |
| @@ -2340,23 +2325,23 @@ | |
| 2325 | "<span style='background-color:%s'>" |
| 2326 | "%s%.10s</a> %s</span> %13.13s:", |
| 2327 | p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser); |
| 2328 | fossil_free(zLink); |
| 2329 | }else{ |
| 2330 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s ", ""); |
| 2331 | } |
| 2332 | }else{ |
| 2333 | if( iVers>=0 ){ |
| 2334 | struct AnnVers *p = ann.aVers+iVers; |
| 2335 | char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid); |
| 2336 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, |
| 2337 | "<span style='background-color:%s'>" |
| 2338 | "%s%.10s</a> %s</span> %4d: ", |
| 2339 | p->zBgColor, zLink, p->zMUuid, p->zDate, i+1); |
| 2340 | fossil_free(zLink); |
| 2341 | }else{ |
| 2342 | sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d: ", "", i+1); |
| 2343 | } |
| 2344 | } |
| 2345 | @ %s(zPrefix)%h(z) |
| 2346 | |
| 2347 | } |
| @@ -2448,28 +2433,27 @@ | |
| 2433 | fossil_print("---------------------------------------------------\n"); |
| 2434 | } |
| 2435 | for(i=0; i<ann.nOrig; i++){ |
| 2436 | int iVers = ann.aOrig[i].iVers; |
| 2437 | char *z = (char*)ann.aOrig[i].z; |
| 2438 | int n = ann.aOrig[i].n; |
| 2439 | struct AnnVers *p; |
| 2440 | if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; |
| 2441 | p = ann.aVers + iVers; |
| 2442 | if( bBlame ){ |
| 2443 | if( iVers>=0 ){ |
| 2444 | fossil_print("%.10s %s %13.13s: %.*s\n", |
| 2445 | fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z); |
| 2446 | }else{ |
| 2447 | fossil_print("%35s %.*s\n", "", n, z); |
| 2448 | } |
| 2449 | }else{ |
| 2450 | if( iVers>=0 ){ |
| 2451 | fossil_print("%.10s %s %5d: %.*s\n", |
| 2452 | fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z); |
| 2453 | }else { |
| 2454 | fossil_print("%21s %5d: %.*s\n", |
| 2455 | "", i+1, n, z); |
| 2456 | } |
| 2457 | } |
| 2458 | } |
| 2459 | } |
| 2460 |