Fossil SCM
Partially revert [f73411025e8ebec7]. This fixes a problem that when closing a fork by just doing "fossil merge" and additonal arrow going up is displayed. Probably not the right fix.
Commit
a78e51185326b91f2270c50369f52e5edd2279c1
Parent
5cdaeb0d822d3ae…
1 file changed
+20
-10
+20
-10
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -218,17 +218,17 @@ | ||
| 218 | 218 | ** top and bottom, inclusive. |
| 219 | 219 | */ |
| 220 | 220 | static int findFreeRail( |
| 221 | 221 | GraphContext *p, /* The graph context */ |
| 222 | 222 | int top, int btm, /* Span of rows for which the rail is needed */ |
| 223 | + u64 inUseMask, /* Mask or rails already in use */ | |
| 223 | 224 | int iNearto /* Find rail nearest to this rail */ |
| 224 | 225 | ){ |
| 225 | 226 | GraphRow *pRow; |
| 226 | 227 | int i; |
| 227 | 228 | int iBest = 0; |
| 228 | 229 | int iBestDist = 9999; |
| 229 | - u64 inUseMask = 0; | |
| 230 | 230 | for(pRow=p->pFirst; pRow && pRow->idx<top; pRow=pRow->pNext){} |
| 231 | 231 | while( pRow && pRow->idx<=btm ){ |
| 232 | 232 | inUseMask |= pRow->railInUse; |
| 233 | 233 | pRow = pRow->pNext; |
| 234 | 234 | } |
| @@ -299,11 +299,12 @@ | ||
| 299 | 299 | pParent->mergeUpto = pChild->idx; |
| 300 | 300 | }else{ |
| 301 | 301 | /* The thin merge arrow riser is taller than the thick primary |
| 302 | 302 | ** child riser, so use separate rails. */ |
| 303 | 303 | int iTarget = pParent->iRail; |
| 304 | - pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget); | |
| 304 | + pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, | |
| 305 | + 0, iTarget); | |
| 305 | 306 | pParent->mergeUpto = pChild->idx; |
| 306 | 307 | mask = BIT(pParent->mergeOut); |
| 307 | 308 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 308 | 309 | pLoop=pLoop->pNext){ |
| 309 | 310 | pLoop->railInUse |= mask; |
| @@ -346,10 +347,11 @@ | ||
| 346 | 347 | */ |
| 347 | 348 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 348 | 349 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 349 | 350 | int i; |
| 350 | 351 | u64 mask; |
| 352 | + u64 inUse; | |
| 351 | 353 | int hasDup = 0; /* True if one or more isDup entries */ |
| 352 | 354 | const char *zTrunk; |
| 353 | 355 | |
| 354 | 356 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 355 | 357 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| @@ -450,11 +452,11 @@ | ||
| 450 | 452 | }else { |
| 451 | 453 | if( pRow->iRail>=0 ) continue; |
| 452 | 454 | } |
| 453 | 455 | if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){ |
| 454 | 456 | if( omitDescenders ){ |
| 455 | - pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0); | |
| 457 | + pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0, 0); | |
| 456 | 458 | }else{ |
| 457 | 459 | pRow->iRail = ++p->mxRail; |
| 458 | 460 | } |
| 459 | 461 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 460 | 462 | mask = BIT(pRow->iRail); |
| @@ -469,19 +471,25 @@ | ||
| 469 | 471 | } |
| 470 | 472 | } |
| 471 | 473 | |
| 472 | 474 | /* Assign rails to all rows that are still unassigned. |
| 473 | 475 | */ |
| 476 | + inUse = BIT(p->mxRail+1) - 1; | |
| 474 | 477 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 475 | 478 | int parentRid; |
| 476 | 479 | |
| 477 | 480 | if( pRow->iRail>=0 ){ |
| 478 | 481 | if( pRow->pChild==0 && !pRow->timeWarp ){ |
| 479 | - if( omitDescenders || pRow->isLeaf ){ | |
| 480 | - /* no-op */ | |
| 482 | + if( omitDescenders || count_nonbranch_children(pRow->rid)==0 ){ | |
| 483 | + inUse &= ~BIT(pRow->iRail); | |
| 481 | 484 | }else{ |
| 482 | 485 | riser_to_top(pRow); |
| 486 | + /*pRow->aiRiser[pRow->iRail] = 0; | |
| 487 | + mask = BIT(pRow->iRail); | |
| 488 | + for(pLoop=pRow; pLoop; pLoop=pLoop->pPrev){ | |
| 489 | + pLoop->railInUse |= mask; | |
| 490 | + }*/ | |
| 483 | 491 | } |
| 484 | 492 | } |
| 485 | 493 | continue; |
| 486 | 494 | } |
| 487 | 495 | if( pRow->isDup ){ |
| @@ -497,11 +505,11 @@ | ||
| 497 | 505 | continue; |
| 498 | 506 | } |
| 499 | 507 | if( pParent->idx>pRow->idx ){ |
| 500 | 508 | /* Common case: Child occurs after parent and is above the |
| 501 | 509 | ** parent in the timeline */ |
| 502 | - pRow->iRail = findFreeRail(p, 0, pParent->idx, pParent->iRail); | |
| 510 | + pRow->iRail = findFreeRail(p, 0, pParent->idx, inUse, pParent->iRail); | |
| 503 | 511 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 504 | 512 | pParent->aiRiser[pRow->iRail] = pRow->idx; |
| 505 | 513 | }else{ |
| 506 | 514 | /* Timewarp case: Child occurs earlier in time than parent and |
| 507 | 515 | ** appears below the parent in the timeline. */ |
| @@ -510,21 +518,23 @@ | ||
| 510 | 518 | pRow->iRail = ++p->mxRail; |
| 511 | 519 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 512 | 520 | pRow->railInUse = BIT(pRow->iRail); |
| 513 | 521 | pParent->aiRiser[iDownRail] = pRow->idx; |
| 514 | 522 | mask = BIT(iDownRail); |
| 523 | + inUse |= mask; | |
| 515 | 524 | for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){ |
| 516 | 525 | pLoop->railInUse |= mask; |
| 517 | 526 | } |
| 518 | 527 | } |
| 519 | 528 | } |
| 520 | 529 | mask = BIT(pRow->iRail); |
| 521 | 530 | pRow->railInUse |= mask; |
| 522 | - if( pRow->pChild ){ | |
| 531 | + if( pRow->pChild==0 ){ | |
| 532 | + inUse &= ~mask; | |
| 533 | + }else{ | |
| 534 | + inUse |= mask; | |
| 523 | 535 | assignChildrenToRail(pRow); |
| 524 | - }else if( !pRow->isLeaf && !omitDescenders ){ | |
| 525 | - riser_to_top(pRow); | |
| 526 | 536 | } |
| 527 | 537 | if( pParent ){ |
| 528 | 538 | for(pLoop=pParent->pPrev; pLoop && pLoop!=pRow; pLoop=pLoop->pPrev){ |
| 529 | 539 | pLoop->railInUse |= mask; |
| 530 | 540 | } |
| @@ -538,11 +548,11 @@ | ||
| 538 | 548 | for(i=1; i<pRow->nParent; i++){ |
| 539 | 549 | int parentRid = pRow->aParent[i]; |
| 540 | 550 | pDesc = hashFind(p, parentRid); |
| 541 | 551 | if( pDesc==0 ){ |
| 542 | 552 | /* Merge from a node that is off-screen */ |
| 543 | - int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); | |
| 553 | + int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0); | |
| 544 | 554 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 545 | 555 | mask = BIT(iMrail); |
| 546 | 556 | pRow->mergeIn[iMrail] = 1; |
| 547 | 557 | pRow->mergeDown |= mask; |
| 548 | 558 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 549 | 559 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -218,17 +218,17 @@ | |
| 218 | ** top and bottom, inclusive. |
| 219 | */ |
| 220 | static int findFreeRail( |
| 221 | GraphContext *p, /* The graph context */ |
| 222 | int top, int btm, /* Span of rows for which the rail is needed */ |
| 223 | int iNearto /* Find rail nearest to this rail */ |
| 224 | ){ |
| 225 | GraphRow *pRow; |
| 226 | int i; |
| 227 | int iBest = 0; |
| 228 | int iBestDist = 9999; |
| 229 | u64 inUseMask = 0; |
| 230 | for(pRow=p->pFirst; pRow && pRow->idx<top; pRow=pRow->pNext){} |
| 231 | while( pRow && pRow->idx<=btm ){ |
| 232 | inUseMask |= pRow->railInUse; |
| 233 | pRow = pRow->pNext; |
| 234 | } |
| @@ -299,11 +299,12 @@ | |
| 299 | pParent->mergeUpto = pChild->idx; |
| 300 | }else{ |
| 301 | /* The thin merge arrow riser is taller than the thick primary |
| 302 | ** child riser, so use separate rails. */ |
| 303 | int iTarget = pParent->iRail; |
| 304 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget); |
| 305 | pParent->mergeUpto = pChild->idx; |
| 306 | mask = BIT(pParent->mergeOut); |
| 307 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 308 | pLoop=pLoop->pNext){ |
| 309 | pLoop->railInUse |= mask; |
| @@ -346,10 +347,11 @@ | |
| 346 | */ |
| 347 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 348 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 349 | int i; |
| 350 | u64 mask; |
| 351 | int hasDup = 0; /* True if one or more isDup entries */ |
| 352 | const char *zTrunk; |
| 353 | |
| 354 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 355 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| @@ -450,11 +452,11 @@ | |
| 450 | }else { |
| 451 | if( pRow->iRail>=0 ) continue; |
| 452 | } |
| 453 | if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){ |
| 454 | if( omitDescenders ){ |
| 455 | pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0); |
| 456 | }else{ |
| 457 | pRow->iRail = ++p->mxRail; |
| 458 | } |
| 459 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 460 | mask = BIT(pRow->iRail); |
| @@ -469,19 +471,25 @@ | |
| 469 | } |
| 470 | } |
| 471 | |
| 472 | /* Assign rails to all rows that are still unassigned. |
| 473 | */ |
| 474 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 475 | int parentRid; |
| 476 | |
| 477 | if( pRow->iRail>=0 ){ |
| 478 | if( pRow->pChild==0 && !pRow->timeWarp ){ |
| 479 | if( omitDescenders || pRow->isLeaf ){ |
| 480 | /* no-op */ |
| 481 | }else{ |
| 482 | riser_to_top(pRow); |
| 483 | } |
| 484 | } |
| 485 | continue; |
| 486 | } |
| 487 | if( pRow->isDup ){ |
| @@ -497,11 +505,11 @@ | |
| 497 | continue; |
| 498 | } |
| 499 | if( pParent->idx>pRow->idx ){ |
| 500 | /* Common case: Child occurs after parent and is above the |
| 501 | ** parent in the timeline */ |
| 502 | pRow->iRail = findFreeRail(p, 0, pParent->idx, pParent->iRail); |
| 503 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 504 | pParent->aiRiser[pRow->iRail] = pRow->idx; |
| 505 | }else{ |
| 506 | /* Timewarp case: Child occurs earlier in time than parent and |
| 507 | ** appears below the parent in the timeline. */ |
| @@ -510,21 +518,23 @@ | |
| 510 | pRow->iRail = ++p->mxRail; |
| 511 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 512 | pRow->railInUse = BIT(pRow->iRail); |
| 513 | pParent->aiRiser[iDownRail] = pRow->idx; |
| 514 | mask = BIT(iDownRail); |
| 515 | for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){ |
| 516 | pLoop->railInUse |= mask; |
| 517 | } |
| 518 | } |
| 519 | } |
| 520 | mask = BIT(pRow->iRail); |
| 521 | pRow->railInUse |= mask; |
| 522 | if( pRow->pChild ){ |
| 523 | assignChildrenToRail(pRow); |
| 524 | }else if( !pRow->isLeaf && !omitDescenders ){ |
| 525 | riser_to_top(pRow); |
| 526 | } |
| 527 | if( pParent ){ |
| 528 | for(pLoop=pParent->pPrev; pLoop && pLoop!=pRow; pLoop=pLoop->pPrev){ |
| 529 | pLoop->railInUse |= mask; |
| 530 | } |
| @@ -538,11 +548,11 @@ | |
| 538 | for(i=1; i<pRow->nParent; i++){ |
| 539 | int parentRid = pRow->aParent[i]; |
| 540 | pDesc = hashFind(p, parentRid); |
| 541 | if( pDesc==0 ){ |
| 542 | /* Merge from a node that is off-screen */ |
| 543 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); |
| 544 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 545 | mask = BIT(iMrail); |
| 546 | pRow->mergeIn[iMrail] = 1; |
| 547 | pRow->mergeDown |= mask; |
| 548 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 549 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -218,17 +218,17 @@ | |
| 218 | ** top and bottom, inclusive. |
| 219 | */ |
| 220 | static int findFreeRail( |
| 221 | GraphContext *p, /* The graph context */ |
| 222 | int top, int btm, /* Span of rows for which the rail is needed */ |
| 223 | u64 inUseMask, /* Mask or rails already in use */ |
| 224 | int iNearto /* Find rail nearest to this rail */ |
| 225 | ){ |
| 226 | GraphRow *pRow; |
| 227 | int i; |
| 228 | int iBest = 0; |
| 229 | int iBestDist = 9999; |
| 230 | for(pRow=p->pFirst; pRow && pRow->idx<top; pRow=pRow->pNext){} |
| 231 | while( pRow && pRow->idx<=btm ){ |
| 232 | inUseMask |= pRow->railInUse; |
| 233 | pRow = pRow->pNext; |
| 234 | } |
| @@ -299,11 +299,12 @@ | |
| 299 | pParent->mergeUpto = pChild->idx; |
| 300 | }else{ |
| 301 | /* The thin merge arrow riser is taller than the thick primary |
| 302 | ** child riser, so use separate rails. */ |
| 303 | int iTarget = pParent->iRail; |
| 304 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, |
| 305 | 0, iTarget); |
| 306 | pParent->mergeUpto = pChild->idx; |
| 307 | mask = BIT(pParent->mergeOut); |
| 308 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 309 | pLoop=pLoop->pNext){ |
| 310 | pLoop->railInUse |= mask; |
| @@ -346,10 +347,11 @@ | |
| 347 | */ |
| 348 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 349 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 350 | int i; |
| 351 | u64 mask; |
| 352 | u64 inUse; |
| 353 | int hasDup = 0; /* True if one or more isDup entries */ |
| 354 | const char *zTrunk; |
| 355 | |
| 356 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 357 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| @@ -450,11 +452,11 @@ | |
| 452 | }else { |
| 453 | if( pRow->iRail>=0 ) continue; |
| 454 | } |
| 455 | if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){ |
| 456 | if( omitDescenders ){ |
| 457 | pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0, 0); |
| 458 | }else{ |
| 459 | pRow->iRail = ++p->mxRail; |
| 460 | } |
| 461 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 462 | mask = BIT(pRow->iRail); |
| @@ -469,19 +471,25 @@ | |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | /* Assign rails to all rows that are still unassigned. |
| 475 | */ |
| 476 | inUse = BIT(p->mxRail+1) - 1; |
| 477 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 478 | int parentRid; |
| 479 | |
| 480 | if( pRow->iRail>=0 ){ |
| 481 | if( pRow->pChild==0 && !pRow->timeWarp ){ |
| 482 | if( omitDescenders || count_nonbranch_children(pRow->rid)==0 ){ |
| 483 | inUse &= ~BIT(pRow->iRail); |
| 484 | }else{ |
| 485 | riser_to_top(pRow); |
| 486 | /*pRow->aiRiser[pRow->iRail] = 0; |
| 487 | mask = BIT(pRow->iRail); |
| 488 | for(pLoop=pRow; pLoop; pLoop=pLoop->pPrev){ |
| 489 | pLoop->railInUse |= mask; |
| 490 | }*/ |
| 491 | } |
| 492 | } |
| 493 | continue; |
| 494 | } |
| 495 | if( pRow->isDup ){ |
| @@ -497,11 +505,11 @@ | |
| 505 | continue; |
| 506 | } |
| 507 | if( pParent->idx>pRow->idx ){ |
| 508 | /* Common case: Child occurs after parent and is above the |
| 509 | ** parent in the timeline */ |
| 510 | pRow->iRail = findFreeRail(p, 0, pParent->idx, inUse, pParent->iRail); |
| 511 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 512 | pParent->aiRiser[pRow->iRail] = pRow->idx; |
| 513 | }else{ |
| 514 | /* Timewarp case: Child occurs earlier in time than parent and |
| 515 | ** appears below the parent in the timeline. */ |
| @@ -510,21 +518,23 @@ | |
| 518 | pRow->iRail = ++p->mxRail; |
| 519 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 520 | pRow->railInUse = BIT(pRow->iRail); |
| 521 | pParent->aiRiser[iDownRail] = pRow->idx; |
| 522 | mask = BIT(iDownRail); |
| 523 | inUse |= mask; |
| 524 | for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){ |
| 525 | pLoop->railInUse |= mask; |
| 526 | } |
| 527 | } |
| 528 | } |
| 529 | mask = BIT(pRow->iRail); |
| 530 | pRow->railInUse |= mask; |
| 531 | if( pRow->pChild==0 ){ |
| 532 | inUse &= ~mask; |
| 533 | }else{ |
| 534 | inUse |= mask; |
| 535 | assignChildrenToRail(pRow); |
| 536 | } |
| 537 | if( pParent ){ |
| 538 | for(pLoop=pParent->pPrev; pLoop && pLoop!=pRow; pLoop=pLoop->pPrev){ |
| 539 | pLoop->railInUse |= mask; |
| 540 | } |
| @@ -538,11 +548,11 @@ | |
| 548 | for(i=1; i<pRow->nParent; i++){ |
| 549 | int parentRid = pRow->aParent[i]; |
| 550 | pDesc = hashFind(p, parentRid); |
| 551 | if( pDesc==0 ){ |
| 552 | /* Merge from a node that is off-screen */ |
| 553 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0); |
| 554 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 555 | mask = BIT(iMrail); |
| 556 | pRow->mergeIn[iMrail] = 1; |
| 557 | pRow->mergeDown |= mask; |
| 558 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 559 |