Fossil SCM

Timeline graph layout changes that strive to do better a communicating the merging and branching activity between multiple branches.

drh 2022-03-08 01:07 trunk
Commit d1d7fce64eefa15c8d9c029c05b09b27336176370cc2d241f8339d11769316cd
1 file changed +88 -37
+88 -37
--- src/graph.c
+++ src/graph.c
@@ -109,10 +109,11 @@
109109
GraphRow *pLast; /* Last row in the list. Bottom row of graph. */
110110
int nBranch; /* Number of distinct branches */
111111
char **azBranch; /* Names of the branches */
112112
int nRow; /* Number of rows */
113113
int nHash; /* Number of slots in apHash[] */
114
+ u64 mergeRail; /* Rails used for merge lines */
114115
GraphRow **apHash; /* Hash table of GraphRow objects. Key: rid */
115116
u8 aiRailMap[GR_MAX_RAIL]; /* Mapping of rails to actually columns */
116117
};
117118
118119
#endif
@@ -119,11 +120,11 @@
119120
120121
/* The N-th bit */
121122
#define BIT(N) (((u64)1)<<(N))
122123
123124
/*
124
-** Number of rows before and answer a node with a riser or descender
125
+** Number of rows before and after a node with a riser or descender
125126
** that goes off-screen before we can reuse that rail.
126127
*/
127128
#define RISER_MARGIN 4
128129
129130
@@ -275,11 +276,12 @@
275276
** top and bottom, inclusive.
276277
*/
277278
static int findFreeRail(
278279
GraphContext *p, /* The graph context */
279280
int top, int btm, /* Span of rows for which the rail is needed */
280
- int iNearto /* Find rail nearest to this rail */
281
+ int iNearto, /* Find rail nearest to this rail */
282
+ int bMergeRail /* This rail will be used for a merge line */
281283
){
282284
GraphRow *pRow;
283285
int i;
284286
int iBest = 0;
285287
int iBestDist = 9999;
@@ -287,15 +289,38 @@
287289
for(pRow=p->pFirst; pRow && pRow->idx<top; pRow=pRow->pNext){}
288290
while( pRow && pRow->idx<=btm ){
289291
inUseMask |= pRow->railInUse;
290292
pRow = pRow->pNext;
291293
}
292
- for(i=0; i<GR_MAX_RAIL; i++){
293
- if( (inUseMask & BIT(i))==0 ){
294
+
295
+ /* First look for a match that honors bMergeRail */
296
+ for(i=0; i<=p->mxRail; i++){
297
+ u64 m = BIT(i);
298
+ int dist;
299
+ if( inUseMask & m ) continue;
300
+ if( (bMergeRail!=0) != ((p->mergeRail & m)!=0) ) continue;
301
+ if( iNearto<=0 ){
302
+ iBest = i;
303
+ iBestDist = 1;
304
+ break;
305
+ }
306
+ dist = i - iNearto;
307
+ if( dist<0 ) dist = -dist;
308
+ if( dist<iBestDist ){
309
+ iBestDist = dist;
310
+ iBest = i;
311
+ }
312
+ }
313
+
314
+ /* If no match, consider all possible rails */
315
+ if( iBestDist>1000 ){
316
+ for(i=0; i<=p->mxRail+1; i++){
294317
int dist;
318
+ if( inUseMask & BIT(i) ) continue;
295319
if( iNearto<=0 ){
296320
iBest = i;
321
+ iBestDist = 1;
297322
break;
298323
}
299324
dist = i - iNearto;
300325
if( dist<0 ) dist = -dist;
301326
if( dist<iBestDist ){
@@ -304,10 +329,11 @@
304329
}
305330
}
306331
}
307332
if( iBestDist>1000 ) p->nErr++;
308333
if( iBest>p->mxRail ) p->mxRail = iBest;
334
+ if( bMergeRail ) p->mergeRail |= BIT(iBest);
309335
return iBest;
310336
}
311337
312338
/*
313339
** Assign all children of node pBottom to the same rail as pBottom.
@@ -369,11 +395,12 @@
369395
pParent->mergeOut = pParent->iRail;
370396
}else{
371397
/* The thin merge arrow riser is taller than the thick primary
372398
** child riser, so use separate rails. */
373399
int iTarget = pParent->iRail;
374
- pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget);
400
+ pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1,
401
+ iTarget, 1);
375402
mask = BIT(pParent->mergeOut);
376403
for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
377404
pLoop=pLoop->pNext){
378405
pLoop->railInUse |= mask;
379406
}
@@ -646,11 +673,11 @@
646673
if( i==0 && pRow->zBranch!=zTrunk ) continue;
647674
if( pRow->iRail>=0 ) continue;
648675
if( pRow->isDup ) continue;
649676
if( pRow->nParent<0 ) continue;
650677
if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){
651
- pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx+riserMargin, 0);
678
+ pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx+riserMargin,0,0);
652679
if( p->mxRail>=GR_MAX_RAIL ) return;
653680
mask = BIT(pRow->iRail);
654681
if( !omitDescenders ){
655682
int n = RISER_MARGIN;
656683
pRow->bDescender = pRow->nParent>0;
@@ -690,11 +717,11 @@
690717
}
691718
if( pParent->idx>pRow->idx ){
692719
/* Common case: Child occurs after parent and is above the
693720
** parent in the timeline */
694721
pRow->iRail = findFreeRail(p, pRow->idxTop, pParent->idx,
695
- pParent->iRail);
722
+ pParent->iRail, 0);
696723
if( p->mxRail>=GR_MAX_RAIL ) return;
697724
pParent->aiRiser[pRow->iRail] = pRow->idx;
698725
}else{
699726
/* Timewarp case: Child occurs earlier in time than parent and
700727
** appears below the parent in the timeline. */
@@ -741,11 +768,11 @@
741768
int isCherrypick = 0;
742769
for(i=1; i<pRow->nParent; i++){
743770
GraphRowId parentRid = pRow->aParent[i];
744771
if( i==pRow->nNonCherrypick ){
745772
/* Because full merges are laid out before cherrypicks,
746
- ** it is ok to use a full-merge raise for a cherrypick.
773
+ ** it is ok to use a full-merge raiser for a cherrypick.
747774
** See the graph on check-in 8ac66ef33b464d28 for example
748775
** iReuseIdx = -1;
749776
** iReuseRail = -1; */
750777
isCherrypick = 1;
751778
}
@@ -761,11 +788,11 @@
761788
iMrail = j;
762789
break;
763790
}
764791
}
765792
if( iMrail==-1 ){
766
- iMrail = findFreeRail(p, pRow->idx, p->pLast->idx, 0);
793
+ iMrail = findFreeRail(p, pRow->idx, p->pLast->idx, 0, 1);
767794
if( p->mxRail>=GR_MAX_RAIL ) return;
768795
mergeRiserFrom[iMrail] = parentRid;
769796
}
770797
iReuseIdx = p->nRow+1;
771798
iReuseRail = iMrail;
@@ -847,40 +874,64 @@
847874
**
848875
** aMap[X]=Y means that the X-th rail is drawn as the Y-th rail.
849876
*/
850877
aMap = p->aiRailMap;
851878
for(i=0; i<=p->mxRail; i++) aMap[i] = i;
852
- if( zLeftBranch && nTimewarp==0 ){
853
- char *zLeft = persistBranchName(p, zLeftBranch);
854
- u64 pureMergeRail = (BIT(p->mxRail)-1)<<1|1;
855
- u64 toLeft = 0;
856
- j = 0;
857
- for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
858
- pureMergeRail &= ~BIT(pRow->iRail);
859
- if( pRow->zBranch==zLeft ){
860
- for(i=0; i<=p->mxRail; i++){
861
- if( pRow->mergeIn[i] ) toLeft |= BIT(i);
862
- }
863
- if( aMap[pRow->iRail]>=j ){
864
- for(i=0; i<=p->mxRail; i++){
865
- if( aMap[i]>=j && aMap[i]<=pRow->iRail ) aMap[i]++;
866
- }
867
- aMap[pRow->iRail] = j++;
868
- }
869
- }
870
- }
871
- toLeft &= pureMergeRail;
872
- for(i=j; i<=p->mxRail; i++){
873
- int k;
874
- if( (BIT(i) & toLeft)==0 ) continue;
875
- for(k=0; k<=p->mxRail; k++){
876
- if( aMap[k]>=j && aMap[k]<=i ) aMap[k]++;
877
- }
878
- aMap[i] = j;
879
- }
879
+ if( nTimewarp==0 ){
880
+ u8 aPriority[GR_MAX_RAIL];
881
+ memset(aPriority, 0, p->mxRail+1);
882
+ if( zLeftBranch ){
883
+ char *zLeft = persistBranchName(p, zLeftBranch);
884
+ for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
885
+ if( pRow->zBranch==zLeft ){
886
+ aPriority[pRow->iRail] |= 4;
887
+ for(i=0; i<=p->mxRail; i++){
888
+ if( pRow->mergeIn[i] ) aPriority[i] |= 1;
889
+ }
890
+ if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
891
+ }
892
+ }
893
+ }else{
894
+ j = 1;
895
+ aPriority[0] = 4;
896
+ for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
897
+ if( pRow->iRail==0 ){
898
+ for(i=0; i<=p->mxRail; i++){
899
+ if( pRow->mergeIn[i] ) aPriority[i] |= 1;
900
+ }
901
+ if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
902
+ }
903
+ }
904
+ }
905
+ j = 0;
906
+ for(i=0; i<=p->mxRail; i++){
907
+ if( p->mergeRail & BIT(i) ){
908
+ aPriority[i] |= 2;
909
+ }
910
+ }
911
+
912
+#if 0
913
+ fprintf(stderr,"mergeRail: 0x%llx\n", p->mergeRail);
914
+ fprintf(stderr,"Priority:");
915
+ for(i=0; i<=p->mxRail; i++) fprintf(stderr," %d", aPriority[i]);
916
+ fprintf(stderr,"\n");
917
+#endif
918
+
919
+ for(i=0; i<=p->mxRail; i++){
920
+ if( aPriority[i]>=4 ) aMap[i] = j++;
921
+ }
922
+ for(i=p->mxRail; i>=0; i--){
923
+ if( aPriority[i]==3 ) aMap[i] = j++;
924
+ }
925
+ for(i=0; i<=p->mxRail; i++){
926
+ if( aPriority[i]==1 || aPriority[i]==2 ) aMap[i] = j++;
927
+ }
928
+ for(i=0; i<=p->mxRail; i++){
929
+ if( aPriority[i]==0 ) aMap[i] = j++;
930
+ }
880931
cgi_printf("<!-- aiRailMap =");
881932
for(i=0; i<=p->mxRail; i++) cgi_printf(" %d", aMap[i]);
882933
cgi_printf(" -->\n");
883934
}
884935
885936
p->nErr = 0;
886937
}
887938
--- src/graph.c
+++ src/graph.c
@@ -109,10 +109,11 @@
109 GraphRow *pLast; /* Last row in the list. Bottom row of graph. */
110 int nBranch; /* Number of distinct branches */
111 char **azBranch; /* Names of the branches */
112 int nRow; /* Number of rows */
113 int nHash; /* Number of slots in apHash[] */
 
114 GraphRow **apHash; /* Hash table of GraphRow objects. Key: rid */
115 u8 aiRailMap[GR_MAX_RAIL]; /* Mapping of rails to actually columns */
116 };
117
118 #endif
@@ -119,11 +120,11 @@
119
120 /* The N-th bit */
121 #define BIT(N) (((u64)1)<<(N))
122
123 /*
124 ** Number of rows before and answer a node with a riser or descender
125 ** that goes off-screen before we can reuse that rail.
126 */
127 #define RISER_MARGIN 4
128
129
@@ -275,11 +276,12 @@
275 ** top and bottom, inclusive.
276 */
277 static int findFreeRail(
278 GraphContext *p, /* The graph context */
279 int top, int btm, /* Span of rows for which the rail is needed */
280 int iNearto /* Find rail nearest to this rail */
 
281 ){
282 GraphRow *pRow;
283 int i;
284 int iBest = 0;
285 int iBestDist = 9999;
@@ -287,15 +289,38 @@
287 for(pRow=p->pFirst; pRow && pRow->idx<top; pRow=pRow->pNext){}
288 while( pRow && pRow->idx<=btm ){
289 inUseMask |= pRow->railInUse;
290 pRow = pRow->pNext;
291 }
292 for(i=0; i<GR_MAX_RAIL; i++){
293 if( (inUseMask & BIT(i))==0 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294 int dist;
 
295 if( iNearto<=0 ){
296 iBest = i;
 
297 break;
298 }
299 dist = i - iNearto;
300 if( dist<0 ) dist = -dist;
301 if( dist<iBestDist ){
@@ -304,10 +329,11 @@
304 }
305 }
306 }
307 if( iBestDist>1000 ) p->nErr++;
308 if( iBest>p->mxRail ) p->mxRail = iBest;
 
309 return iBest;
310 }
311
312 /*
313 ** Assign all children of node pBottom to the same rail as pBottom.
@@ -369,11 +395,12 @@
369 pParent->mergeOut = pParent->iRail;
370 }else{
371 /* The thin merge arrow riser is taller than the thick primary
372 ** child riser, so use separate rails. */
373 int iTarget = pParent->iRail;
374 pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget);
 
375 mask = BIT(pParent->mergeOut);
376 for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
377 pLoop=pLoop->pNext){
378 pLoop->railInUse |= mask;
379 }
@@ -646,11 +673,11 @@
646 if( i==0 && pRow->zBranch!=zTrunk ) continue;
647 if( pRow->iRail>=0 ) continue;
648 if( pRow->isDup ) continue;
649 if( pRow->nParent<0 ) continue;
650 if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){
651 pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx+riserMargin, 0);
652 if( p->mxRail>=GR_MAX_RAIL ) return;
653 mask = BIT(pRow->iRail);
654 if( !omitDescenders ){
655 int n = RISER_MARGIN;
656 pRow->bDescender = pRow->nParent>0;
@@ -690,11 +717,11 @@
690 }
691 if( pParent->idx>pRow->idx ){
692 /* Common case: Child occurs after parent and is above the
693 ** parent in the timeline */
694 pRow->iRail = findFreeRail(p, pRow->idxTop, pParent->idx,
695 pParent->iRail);
696 if( p->mxRail>=GR_MAX_RAIL ) return;
697 pParent->aiRiser[pRow->iRail] = pRow->idx;
698 }else{
699 /* Timewarp case: Child occurs earlier in time than parent and
700 ** appears below the parent in the timeline. */
@@ -741,11 +768,11 @@
741 int isCherrypick = 0;
742 for(i=1; i<pRow->nParent; i++){
743 GraphRowId parentRid = pRow->aParent[i];
744 if( i==pRow->nNonCherrypick ){
745 /* Because full merges are laid out before cherrypicks,
746 ** it is ok to use a full-merge raise for a cherrypick.
747 ** See the graph on check-in 8ac66ef33b464d28 for example
748 ** iReuseIdx = -1;
749 ** iReuseRail = -1; */
750 isCherrypick = 1;
751 }
@@ -761,11 +788,11 @@
761 iMrail = j;
762 break;
763 }
764 }
765 if( iMrail==-1 ){
766 iMrail = findFreeRail(p, pRow->idx, p->pLast->idx, 0);
767 if( p->mxRail>=GR_MAX_RAIL ) return;
768 mergeRiserFrom[iMrail] = parentRid;
769 }
770 iReuseIdx = p->nRow+1;
771 iReuseRail = iMrail;
@@ -847,40 +874,64 @@
847 **
848 ** aMap[X]=Y means that the X-th rail is drawn as the Y-th rail.
849 */
850 aMap = p->aiRailMap;
851 for(i=0; i<=p->mxRail; i++) aMap[i] = i;
852 if( zLeftBranch && nTimewarp==0 ){
853 char *zLeft = persistBranchName(p, zLeftBranch);
854 u64 pureMergeRail = (BIT(p->mxRail)-1)<<1|1;
855 u64 toLeft = 0;
856 j = 0;
857 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
858 pureMergeRail &= ~BIT(pRow->iRail);
859 if( pRow->zBranch==zLeft ){
860 for(i=0; i<=p->mxRail; i++){
861 if( pRow->mergeIn[i] ) toLeft |= BIT(i);
862 }
863 if( aMap[pRow->iRail]>=j ){
864 for(i=0; i<=p->mxRail; i++){
865 if( aMap[i]>=j && aMap[i]<=pRow->iRail ) aMap[i]++;
866 }
867 aMap[pRow->iRail] = j++;
868 }
869 }
870 }
871 toLeft &= pureMergeRail;
872 for(i=j; i<=p->mxRail; i++){
873 int k;
874 if( (BIT(i) & toLeft)==0 ) continue;
875 for(k=0; k<=p->mxRail; k++){
876 if( aMap[k]>=j && aMap[k]<=i ) aMap[k]++;
877 }
878 aMap[i] = j;
879 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
880 cgi_printf("<!-- aiRailMap =");
881 for(i=0; i<=p->mxRail; i++) cgi_printf(" %d", aMap[i]);
882 cgi_printf(" -->\n");
883 }
884
885 p->nErr = 0;
886 }
887
--- src/graph.c
+++ src/graph.c
@@ -109,10 +109,11 @@
109 GraphRow *pLast; /* Last row in the list. Bottom row of graph. */
110 int nBranch; /* Number of distinct branches */
111 char **azBranch; /* Names of the branches */
112 int nRow; /* Number of rows */
113 int nHash; /* Number of slots in apHash[] */
114 u64 mergeRail; /* Rails used for merge lines */
115 GraphRow **apHash; /* Hash table of GraphRow objects. Key: rid */
116 u8 aiRailMap[GR_MAX_RAIL]; /* Mapping of rails to actually columns */
117 };
118
119 #endif
@@ -119,11 +120,11 @@
120
121 /* The N-th bit */
122 #define BIT(N) (((u64)1)<<(N))
123
124 /*
125 ** Number of rows before and after a node with a riser or descender
126 ** that goes off-screen before we can reuse that rail.
127 */
128 #define RISER_MARGIN 4
129
130
@@ -275,11 +276,12 @@
276 ** top and bottom, inclusive.
277 */
278 static int findFreeRail(
279 GraphContext *p, /* The graph context */
280 int top, int btm, /* Span of rows for which the rail is needed */
281 int iNearto, /* Find rail nearest to this rail */
282 int bMergeRail /* This rail will be used for a merge line */
283 ){
284 GraphRow *pRow;
285 int i;
286 int iBest = 0;
287 int iBestDist = 9999;
@@ -287,15 +289,38 @@
289 for(pRow=p->pFirst; pRow && pRow->idx<top; pRow=pRow->pNext){}
290 while( pRow && pRow->idx<=btm ){
291 inUseMask |= pRow->railInUse;
292 pRow = pRow->pNext;
293 }
294
295 /* First look for a match that honors bMergeRail */
296 for(i=0; i<=p->mxRail; i++){
297 u64 m = BIT(i);
298 int dist;
299 if( inUseMask & m ) continue;
300 if( (bMergeRail!=0) != ((p->mergeRail & m)!=0) ) continue;
301 if( iNearto<=0 ){
302 iBest = i;
303 iBestDist = 1;
304 break;
305 }
306 dist = i - iNearto;
307 if( dist<0 ) dist = -dist;
308 if( dist<iBestDist ){
309 iBestDist = dist;
310 iBest = i;
311 }
312 }
313
314 /* If no match, consider all possible rails */
315 if( iBestDist>1000 ){
316 for(i=0; i<=p->mxRail+1; i++){
317 int dist;
318 if( inUseMask & BIT(i) ) continue;
319 if( iNearto<=0 ){
320 iBest = i;
321 iBestDist = 1;
322 break;
323 }
324 dist = i - iNearto;
325 if( dist<0 ) dist = -dist;
326 if( dist<iBestDist ){
@@ -304,10 +329,11 @@
329 }
330 }
331 }
332 if( iBestDist>1000 ) p->nErr++;
333 if( iBest>p->mxRail ) p->mxRail = iBest;
334 if( bMergeRail ) p->mergeRail |= BIT(iBest);
335 return iBest;
336 }
337
338 /*
339 ** Assign all children of node pBottom to the same rail as pBottom.
@@ -369,11 +395,12 @@
395 pParent->mergeOut = pParent->iRail;
396 }else{
397 /* The thin merge arrow riser is taller than the thick primary
398 ** child riser, so use separate rails. */
399 int iTarget = pParent->iRail;
400 pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1,
401 iTarget, 1);
402 mask = BIT(pParent->mergeOut);
403 for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
404 pLoop=pLoop->pNext){
405 pLoop->railInUse |= mask;
406 }
@@ -646,11 +673,11 @@
673 if( i==0 && pRow->zBranch!=zTrunk ) continue;
674 if( pRow->iRail>=0 ) continue;
675 if( pRow->isDup ) continue;
676 if( pRow->nParent<0 ) continue;
677 if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){
678 pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx+riserMargin,0,0);
679 if( p->mxRail>=GR_MAX_RAIL ) return;
680 mask = BIT(pRow->iRail);
681 if( !omitDescenders ){
682 int n = RISER_MARGIN;
683 pRow->bDescender = pRow->nParent>0;
@@ -690,11 +717,11 @@
717 }
718 if( pParent->idx>pRow->idx ){
719 /* Common case: Child occurs after parent and is above the
720 ** parent in the timeline */
721 pRow->iRail = findFreeRail(p, pRow->idxTop, pParent->idx,
722 pParent->iRail, 0);
723 if( p->mxRail>=GR_MAX_RAIL ) return;
724 pParent->aiRiser[pRow->iRail] = pRow->idx;
725 }else{
726 /* Timewarp case: Child occurs earlier in time than parent and
727 ** appears below the parent in the timeline. */
@@ -741,11 +768,11 @@
768 int isCherrypick = 0;
769 for(i=1; i<pRow->nParent; i++){
770 GraphRowId parentRid = pRow->aParent[i];
771 if( i==pRow->nNonCherrypick ){
772 /* Because full merges are laid out before cherrypicks,
773 ** it is ok to use a full-merge raiser for a cherrypick.
774 ** See the graph on check-in 8ac66ef33b464d28 for example
775 ** iReuseIdx = -1;
776 ** iReuseRail = -1; */
777 isCherrypick = 1;
778 }
@@ -761,11 +788,11 @@
788 iMrail = j;
789 break;
790 }
791 }
792 if( iMrail==-1 ){
793 iMrail = findFreeRail(p, pRow->idx, p->pLast->idx, 0, 1);
794 if( p->mxRail>=GR_MAX_RAIL ) return;
795 mergeRiserFrom[iMrail] = parentRid;
796 }
797 iReuseIdx = p->nRow+1;
798 iReuseRail = iMrail;
@@ -847,40 +874,64 @@
874 **
875 ** aMap[X]=Y means that the X-th rail is drawn as the Y-th rail.
876 */
877 aMap = p->aiRailMap;
878 for(i=0; i<=p->mxRail; i++) aMap[i] = i;
879 if( nTimewarp==0 ){
880 u8 aPriority[GR_MAX_RAIL];
881 memset(aPriority, 0, p->mxRail+1);
882 if( zLeftBranch ){
883 char *zLeft = persistBranchName(p, zLeftBranch);
884 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
885 if( pRow->zBranch==zLeft ){
886 aPriority[pRow->iRail] |= 4;
887 for(i=0; i<=p->mxRail; i++){
888 if( pRow->mergeIn[i] ) aPriority[i] |= 1;
889 }
890 if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
891 }
892 }
893 }else{
894 j = 1;
895 aPriority[0] = 4;
896 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
897 if( pRow->iRail==0 ){
898 for(i=0; i<=p->mxRail; i++){
899 if( pRow->mergeIn[i] ) aPriority[i] |= 1;
900 }
901 if( pRow->mergeOut>=0 ) aPriority[pRow->mergeOut] |= 1;
902 }
903 }
904 }
905 j = 0;
906 for(i=0; i<=p->mxRail; i++){
907 if( p->mergeRail & BIT(i) ){
908 aPriority[i] |= 2;
909 }
910 }
911
912 #if 0
913 fprintf(stderr,"mergeRail: 0x%llx\n", p->mergeRail);
914 fprintf(stderr,"Priority:");
915 for(i=0; i<=p->mxRail; i++) fprintf(stderr," %d", aPriority[i]);
916 fprintf(stderr,"\n");
917 #endif
918
919 for(i=0; i<=p->mxRail; i++){
920 if( aPriority[i]>=4 ) aMap[i] = j++;
921 }
922 for(i=p->mxRail; i>=0; i--){
923 if( aPriority[i]==3 ) aMap[i] = j++;
924 }
925 for(i=0; i<=p->mxRail; i++){
926 if( aPriority[i]==1 || aPriority[i]==2 ) aMap[i] = j++;
927 }
928 for(i=0; i<=p->mxRail; i++){
929 if( aPriority[i]==0 ) aMap[i] = j++;
930 }
931 cgi_printf("<!-- aiRailMap =");
932 for(i=0; i<=p->mxRail; i++) cgi_printf(" %d", aMap[i]);
933 cgi_printf(" -->\n");
934 }
935
936 p->nErr = 0;
937 }
938

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button