| | @@ -21,11 +21,11 @@ |
| 21 | 21 | #include "graph.h" |
| 22 | 22 | #include <assert.h> |
| 23 | 23 | |
| 24 | 24 | #if INTERFACE |
| 25 | 25 | |
| 26 | | -#define GR_MAX_RAIL 32 /* Max number of "rails" to display */ |
| 26 | +#define GR_MAX_RAIL 40 /* Max number of "rails" to display */ |
| 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. |
| | @@ -51,13 +51,13 @@ |
| 51 | 51 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 52 | 52 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| 53 | 53 | u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ |
| 54 | 54 | int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ |
| 55 | 55 | int mergeUpto; /* Draw the mergeOut rail up to this level */ |
| 56 | | - u32 mergeDown; /* Draw merge lines up from bottom of graph */ |
| 56 | + u64 mergeDown; /* Draw merge lines up from bottom of graph */ |
| 57 | 57 | |
| 58 | | - u32 railInUse; /* Mask of occupied rails at this row */ |
| 58 | + u64 railInUse; /* Mask of occupied rails at this row */ |
| 59 | 59 | }; |
| 60 | 60 | |
| 61 | 61 | /* Context while building a graph |
| 62 | 62 | */ |
| 63 | 63 | struct GraphContext { |
| | @@ -73,10 +73,13 @@ |
| 73 | 73 | GraphRow **apHash; /* Hash table of GraphRow objects. Key: rid */ |
| 74 | 74 | }; |
| 75 | 75 | |
| 76 | 76 | #endif |
| 77 | 77 | |
| 78 | +/* The N-th bit */ |
| 79 | +#define BIT(N) (((u64)1)<<(N)) |
| 80 | + |
| 78 | 81 | /* |
| 79 | 82 | ** Malloc for zeroed space. Panic if unable to provide the |
| 80 | 83 | ** requested space. |
| 81 | 84 | */ |
| 82 | 85 | void *safeMalloc(int nByte){ |
| | @@ -216,11 +219,11 @@ |
| 216 | 219 | ** top and bottom, inclusive. |
| 217 | 220 | */ |
| 218 | 221 | static int findFreeRail( |
| 219 | 222 | GraphContext *p, /* The graph context */ |
| 220 | 223 | int top, int btm, /* Span of rows for which the rail is needed */ |
| 221 | | - u32 inUseMask, /* Mask or rails already in use */ |
| 224 | + u64 inUseMask, /* Mask or rails already in use */ |
| 222 | 225 | int iNearto /* Find rail nearest to this rail */ |
| 223 | 226 | ){ |
| 224 | 227 | GraphRow *pRow; |
| 225 | 228 | int i; |
| 226 | 229 | int iBest = 0; |
| | @@ -229,11 +232,11 @@ |
| 229 | 232 | while( pRow && pRow->idx<=btm ){ |
| 230 | 233 | inUseMask |= pRow->railInUse; |
| 231 | 234 | pRow = pRow->pNext; |
| 232 | 235 | } |
| 233 | 236 | for(i=0; i<32; i++){ |
| 234 | | - if( (inUseMask & (1<<i))==0 ){ |
| 237 | + if( (inUseMask & BIT(i))==0 ){ |
| 235 | 238 | int dist; |
| 236 | 239 | if( iNearto<=0 ){ |
| 237 | 240 | return i; |
| 238 | 241 | } |
| 239 | 242 | dist = i - iNearto; |
| | @@ -254,11 +257,11 @@ |
| 254 | 257 | */ |
| 255 | 258 | static void assignChildrenToRail(GraphRow *pBottom){ |
| 256 | 259 | int iRail = pBottom->iRail; |
| 257 | 260 | GraphRow *pCurrent; |
| 258 | 261 | GraphRow *pPrior; |
| 259 | | - u32 mask = 1<<iRail; |
| 262 | + u64 mask = ((u64)1)<<iRail; |
| 260 | 263 | |
| 261 | 264 | pBottom->iRail = iRail; |
| 262 | 265 | pBottom->railInUse |= mask; |
| 263 | 266 | pPrior = pBottom; |
| 264 | 267 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| | @@ -282,11 +285,11 @@ |
| 282 | 285 | GraphContext *p, |
| 283 | 286 | GraphRow *pParent, |
| 284 | 287 | GraphRow *pChild |
| 285 | 288 | ){ |
| 286 | 289 | int u; |
| 287 | | - u32 mask; |
| 290 | + u64 mask; |
| 288 | 291 | GraphRow *pLoop; |
| 289 | 292 | |
| 290 | 293 | if( pParent->mergeOut<0 ){ |
| 291 | 294 | u = pParent->aiRiser[pParent->iRail]; |
| 292 | 295 | if( u>=0 && u<pChild->idx ){ |
| | @@ -301,11 +304,11 @@ |
| 301 | 304 | ** child riser, so use separate rails. */ |
| 302 | 305 | int iTarget = pParent->iRail; |
| 303 | 306 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, |
| 304 | 307 | 0, iTarget)*4 + 1; |
| 305 | 308 | pParent->mergeUpto = pChild->idx; |
| 306 | | - mask = 1<<(pParent->mergeOut/4); |
| 309 | + mask = BIT(pParent->mergeOut/4); |
| 307 | 310 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 308 | 311 | pLoop=pLoop->pNext){ |
| 309 | 312 | pLoop->railInUse |= mask; |
| 310 | 313 | } |
| 311 | 314 | } |
| | @@ -320,11 +323,11 @@ |
| 320 | 323 | GraphRow *pRow; |
| 321 | 324 | p->mxRail = 0; |
| 322 | 325 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 323 | 326 | if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; |
| 324 | 327 | if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4; |
| 325 | | - while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){ |
| 328 | + while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>(BIT(p->mxRail+1)-1) ){ |
| 326 | 329 | p->mxRail++; |
| 327 | 330 | } |
| 328 | 331 | } |
| 329 | 332 | } |
| 330 | 333 | |
| | @@ -333,12 +336,12 @@ |
| 333 | 336 | ** Compute the complete graph |
| 334 | 337 | */ |
| 335 | 338 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 336 | 339 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 337 | 340 | int i; |
| 338 | | - u32 mask; |
| 339 | | - u32 inUse; |
| 341 | + u64 mask; |
| 342 | + u64 inUse; |
| 340 | 343 | int hasDup = 0; /* True if one or more isDup entries */ |
| 341 | 344 | const char *zTrunk; |
| 342 | 345 | |
| 343 | 346 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 344 | 347 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| | @@ -423,11 +426,11 @@ |
| 423 | 426 | pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0, 0); |
| 424 | 427 | }else{ |
| 425 | 428 | pRow->iRail = ++p->mxRail; |
| 426 | 429 | } |
| 427 | 430 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 428 | | - mask = 1<<(pRow->iRail); |
| 431 | + mask = BIT(pRow->iRail); |
| 429 | 432 | if( !omitDescenders ){ |
| 430 | 433 | pRow->bDescender = pRow->nParent>0; |
| 431 | 434 | for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ |
| 432 | 435 | pLoop->railInUse |= mask; |
| 433 | 436 | } |
| | @@ -437,21 +440,21 @@ |
| 437 | 440 | } |
| 438 | 441 | } |
| 439 | 442 | |
| 440 | 443 | /* Assign rails to all rows that are still unassigned. |
| 441 | 444 | */ |
| 442 | | - inUse = (1<<(p->mxRail+1))-1; |
| 445 | + inUse = BIT(p->mxRail+1) - 1; |
| 443 | 446 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 444 | 447 | int parentRid; |
| 445 | 448 | |
| 446 | 449 | if( pRow->iRail>=0 ){ |
| 447 | 450 | if( pRow->pChild==0 && !pRow->timeWarp ){ |
| 448 | 451 | if( omitDescenders || count_nonbranch_children(pRow->rid)==0 ){ |
| 449 | | - inUse &= ~(1<<pRow->iRail); |
| 452 | + inUse &= ~BIT(pRow->iRail); |
| 450 | 453 | }else{ |
| 451 | 454 | pRow->aiRiser[pRow->iRail] = 0; |
| 452 | | - mask = 1<<pRow->iRail; |
| 455 | + mask = BIT(pRow->iRail); |
| 453 | 456 | for(pLoop=pRow; pLoop; pLoop=pLoop->pPrev){ |
| 454 | 457 | pLoop->railInUse |= mask; |
| 455 | 458 | } |
| 456 | 459 | } |
| 457 | 460 | } |
| | @@ -464,11 +467,11 @@ |
| 464 | 467 | parentRid = pRow->aParent[0]; |
| 465 | 468 | pParent = hashFind(p, parentRid); |
| 466 | 469 | if( pParent==0 ){ |
| 467 | 470 | pRow->iRail = ++p->mxRail; |
| 468 | 471 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 469 | | - pRow->railInUse = 1<<pRow->iRail; |
| 472 | + pRow->railInUse = BIT(pRow->iRail); |
| 470 | 473 | continue; |
| 471 | 474 | } |
| 472 | 475 | if( pParent->idx>pRow->idx ){ |
| 473 | 476 | /* Common case: Child occurs after parent and is above the |
| 474 | 477 | ** parent in the timeline */ |
| | @@ -480,20 +483,20 @@ |
| 480 | 483 | ** appears below the parent in the timeline. */ |
| 481 | 484 | int iDownRail = ++p->mxRail; |
| 482 | 485 | if( iDownRail<1 ) iDownRail = ++p->mxRail; |
| 483 | 486 | pRow->iRail = ++p->mxRail; |
| 484 | 487 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 485 | | - pRow->railInUse = 1<<pRow->iRail; |
| 488 | + pRow->railInUse = BIT(pRow->iRail); |
| 486 | 489 | pParent->aiRiser[iDownRail] = pRow->idx; |
| 487 | | - mask = 1<<iDownRail; |
| 490 | + mask = BIT(iDownRail); |
| 488 | 491 | inUse |= mask; |
| 489 | 492 | for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){ |
| 490 | 493 | pLoop->railInUse |= mask; |
| 491 | 494 | } |
| 492 | 495 | } |
| 493 | 496 | } |
| 494 | | - mask = 1<<pRow->iRail; |
| 497 | + mask = BIT(pRow->iRail); |
| 495 | 498 | pRow->railInUse |= mask; |
| 496 | 499 | if( pRow->pChild==0 ){ |
| 497 | 500 | inUse &= ~mask; |
| 498 | 501 | }else{ |
| 499 | 502 | inUse |= mask; |
| | @@ -515,11 +518,11 @@ |
| 515 | 518 | pDesc = hashFind(p, parentRid); |
| 516 | 519 | if( pDesc==0 ){ |
| 517 | 520 | /* Merge from a node that is off-screen */ |
| 518 | 521 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0); |
| 519 | 522 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 520 | | - mask = 1<<iMrail; |
| 523 | + mask = BIT(iMrail); |
| 521 | 524 | pRow->mergeIn[iMrail] = 2; |
| 522 | 525 | pRow->mergeDown |= mask; |
| 523 | 526 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 524 | 527 | pLoop->railInUse |= mask; |
| 525 | 528 | } |
| | @@ -560,7 +563,9 @@ |
| 560 | 563 | |
| 561 | 564 | /* |
| 562 | 565 | ** Find the maximum rail number. |
| 563 | 566 | */ |
| 564 | 567 | find_max_rail(p); |
| 568 | + p->iRailPitch = 18 - (p->mxRail/3); |
| 569 | + if( p->iRailPitch<12 ) p->iRailPitch = 12; |
| 565 | 570 | p->nErr = 0; |
| 566 | 571 | } |
| 567 | 572 | |