| | @@ -27,14 +27,17 @@ |
| 27 | 27 | |
| 28 | 28 | /* The graph appears vertically beside a timeline. Each row in the |
| 29 | 29 | ** timeline corresponds to a row in the graph. GraphRow.idx is 0 for |
| 30 | 30 | ** the top-most row and increases moving down. Hence (in the absence of |
| 31 | 31 | ** time skew) parents have a larger index than their children. |
| 32 | +** |
| 33 | +** The nParent field is -1 for entires that do not participate in the graph |
| 34 | +** but which are included just so that we can capture their background color. |
| 32 | 35 | */ |
| 33 | 36 | struct GraphRow { |
| 34 | 37 | int rid; /* The rid for the check-in */ |
| 35 | | - i8 nParent; /* Number of parents */ |
| 38 | + i8 nParent; /* Number of parents. -1 for technote lines */ |
| 36 | 39 | int *aParent; /* Array of parents. 0 element is primary .*/ |
| 37 | 40 | char *zBranch; /* Branch name */ |
| 38 | 41 | char *zBgClr; /* Background Color */ |
| 39 | 42 | char zUuid[41]; /* Check-in for file ID */ |
| 40 | 43 | |
| | @@ -188,23 +191,23 @@ |
| 188 | 191 | int nByte; |
| 189 | 192 | static int nRow = 0; |
| 190 | 193 | |
| 191 | 194 | if( p->nErr ) return 0; |
| 192 | 195 | nByte = sizeof(GraphRow); |
| 193 | | - nByte += sizeof(pRow->aParent[0])*nParent; |
| 196 | + if( nParent>0 ) nByte += sizeof(pRow->aParent[0])*nParent; |
| 194 | 197 | pRow = (GraphRow*)safeMalloc( nByte ); |
| 195 | | - pRow->aParent = (int*)&pRow[1]; |
| 198 | + pRow->aParent = nParent>0 ? (int*)&pRow[1] : 0; |
| 196 | 199 | pRow->rid = rid; |
| 197 | 200 | pRow->nParent = nParent; |
| 198 | 201 | pRow->zBranch = persistBranchName(p, zBranch); |
| 199 | 202 | if( zUuid==0 ) zUuid = ""; |
| 200 | 203 | sqlite3_snprintf(sizeof(pRow->zUuid), pRow->zUuid, "%s", zUuid); |
| 201 | 204 | pRow->isLeaf = isLeaf; |
| 202 | 205 | memset(pRow->aiRiser, -1, sizeof(pRow->aiRiser)); |
| 203 | 206 | if( zBgClr==0 ) zBgClr = ""; |
| 204 | 207 | pRow->zBgClr = persistBranchName(p, zBgClr); |
| 205 | | - memcpy(pRow->aParent, aParent, sizeof(aParent[0])*nParent); |
| 208 | + if( nParent>0 ) memcpy(pRow->aParent, aParent, sizeof(aParent[0])*nParent); |
| 206 | 209 | if( p->pFirst==0 ){ |
| 207 | 210 | p->pFirst = pRow; |
| 208 | 211 | }else{ |
| 209 | 212 | p->pLast->pNext = pRow; |
| 210 | 213 | } |
| | @@ -432,11 +435,11 @@ |
| 432 | 435 | ** In the case of a fork, choose the pChild that results in the |
| 433 | 436 | ** longest rail. |
| 434 | 437 | */ |
| 435 | 438 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 436 | 439 | if( pRow->isDup ) continue; |
| 437 | | - if( pRow->nParent==0 ) continue; /* Root node */ |
| 440 | + if( pRow->nParent<=0 ) continue; /* Root node */ |
| 438 | 441 | pParent = hashFind(p, pRow->aParent[0]); |
| 439 | 442 | if( pParent==0 ) continue; /* Parent off-screen */ |
| 440 | 443 | if( pParent->zBranch!=pRow->zBranch ) continue; /* Different branch */ |
| 441 | 444 | if( pParent->idx <= pRow->idx ){ |
| 442 | 445 | pParent->timeWarp = 1; |
| | @@ -455,10 +458,11 @@ |
| 455 | 458 | */ |
| 456 | 459 | zTrunk = persistBranchName(p, "trunk"); |
| 457 | 460 | for(i=0; i<2; i++){ |
| 458 | 461 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 459 | 462 | if( pRow->isDup ) continue; |
| 463 | + if( pRow->nParent<0 ) continue; |
| 460 | 464 | if( i==0 ){ |
| 461 | 465 | if( pRow->zBranch!=zTrunk ) continue; |
| 462 | 466 | }else { |
| 463 | 467 | if( pRow->iRail>=0 ) continue; |
| 464 | 468 | } |
| | @@ -492,11 +496,11 @@ |
| 492 | 496 | riser_to_top(pRow); |
| 493 | 497 | } |
| 494 | 498 | } |
| 495 | 499 | continue; |
| 496 | 500 | } |
| 497 | | - if( pRow->isDup ){ |
| 501 | + if( pRow->isDup || pRow->nParent<0 ){ |
| 498 | 502 | continue; |
| 499 | 503 | }else{ |
| 500 | 504 | assert( pRow->nParent>0 ); |
| 501 | 505 | parentRid = pRow->aParent[0]; |
| 502 | 506 | pParent = hashFind(p, parentRid); |
| 503 | 507 | |