Index: auto.def ================================================================== --- auto.def +++ auto.def @@ -376,11 +376,10 @@ if {[string match *-darwin* [get-define host]]} { if {[cctest -cflags {-Wdeprecated-declarations}]} { define-append EXTRA_CFLAGS -Wdeprecated-declarations } } - cc-check-function-in-lib BIO_ADDR_hostname_string ssl } else { user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support" } } else { if {[info exists ::zlib_lib]} { Index: src/branch.c ================================================================== --- src/branch.c +++ src/branch.c @@ -657,9 +657,9 @@ ** many descenders to (off-screen) parents. */ tmFlags = TIMELINE_DISJOINT | TIMELINE_NOSCROLL; if( PB("ng")==0 ) tmFlags |= TIMELINE_GRAPH; if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR; if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR; - www_print_timeline(&q, tmFlags, 0, 0, 0, brtimeline_extra); + www_print_timeline(&q, tmFlags, 0, 0, 0, 0, brtimeline_extra); db_finalize(&q); style_footer(); } Index: src/configure.c ================================================================== --- src/configure.c +++ src/configure.c @@ -94,12 +94,17 @@ { "logo-mimetype", CONFIGSET_SKIN }, { "logo-image", CONFIGSET_SKIN }, { "background-mimetype", CONFIGSET_SKIN }, { "background-image", CONFIGSET_SKIN }, { "timeline-block-markup", CONFIGSET_SKIN }, + { "timeline-date-format", CONFIGSET_SKIN }, + { "timeline-dwelltime", CONFIGSET_SKIN }, + { "timeline-closetime", CONFIGSET_SKIN }, { "timeline-max-comment", CONFIGSET_SKIN }, { "timeline-plaintext", CONFIGSET_SKIN }, + { "timeline-truncate-at-blank", CONFIGSET_SKIN }, + { "timeline-utc", CONFIGSET_SKIN }, { "adunit", CONFIGSET_SKIN }, { "adunit-omit-if-admin", CONFIGSET_SKIN }, { "adunit-omit-if-user", CONFIGSET_SKIN }, { "sitemap-docidx", CONFIGSET_SKIN }, { "sitemap-download", CONFIGSET_SKIN }, Index: src/default_css.txt ================================================================== --- src/default_css.txt +++ src/default_css.txt @@ -196,22 +196,17 @@ border-left-width: 2px; border-left-style: dotted; background: rgba(255,255,255,0); } .tl-tooltip { - background-color: #fecd4b; - color: black; text-align: center; padding: 5px 1em; border: 1px solid black; border-radius: 6px; position: absolute; z-index: 100; -} -.tl-tooltip a { - background-color: #fecd4b; - color: black; + box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.75); } span.tagDsp { font-weight: bold; } Index: src/descendants.c ================================================================== --- src/descendants.c +++ src/descendants.c @@ -540,11 +540,11 @@ ** many descenders to (off-screen) parents. */ tmFlags = TIMELINE_LEAFONLY | TIMELINE_DISJOINT | TIMELINE_NOSCROLL; if( fNg==0 ) tmFlags |= TIMELINE_GRAPH; if( fBrBg ) tmFlags |= TIMELINE_BRCOLOR; if( fUBg ) tmFlags |= TIMELINE_UCOLOR; - www_print_timeline(&q, tmFlags, 0, 0, 0, 0); + www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0); db_finalize(&q); @
style_footer(); } Index: src/finfo.c ================================================================== --- src/finfo.c +++ src/finfo.c @@ -645,11 +645,11 @@ @ } db_finalize(&q); db_finalize(&qparent); if( pGraph ){ - graph_finish(pGraph, TIMELINE_DISJOINT); + graph_finish(pGraph, 0, TIMELINE_DISJOINT); if( pGraph->nErr ){ graph_free(pGraph); pGraph = 0; }else{ @ \ Index: src/graph.c ================================================================== --- src/graph.c +++ src/graph.c @@ -73,10 +73,11 @@ u8 isLeaf; /* True if this is a leaf node */ u8 isStepParent; /* pChild is actually a step-child */ u8 hasNormalOutMerge; /* Is parent of at laest 1 non-cherrypick merge */ u8 timeWarp; /* Child is earlier in time */ u8 bDescender; /* True if riser from bottom of graph to here. */ + u8 selfUp; /* Space above this node but belonging */ i8 iRail; /* Which rail this check-in appears on. 0-based.*/ i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ int mergeUpto; /* Draw the mergeOut rail up to this level */ @@ -96,10 +97,11 @@ int nBranch; /* Number of distinct branches */ char **azBranch; /* Names of the branches */ int nRow; /* Number of rows */ int nHash; /* Number of slots in apHash[] */ GraphRow **apHash; /* Hash table of GraphRow objects. Key: rid */ + u8 aiRailMap[GR_MAX_RAIL]; /* Mapping of rails to actually columns */ }; #endif /* The N-th bit */ @@ -318,11 +320,13 @@ } /* Mask of additional rows for the riser to infinity */ if( !pPrior->isLeaf && (tmFlags & TIMELINE_DISJOINT)==0 ){ int n = RISER_MARGIN; GraphRow *p; + pPrior->selfUp = 0; for(p=pPrior; p && (n--)>0; p=p->pPrev){ + pPrior->selfUp++; p->railInUse |= mask; } } } @@ -344,16 +348,17 @@ if( u>0 && uidx ){ /* The thick arrow up to the next primary child of pDesc goes ** further up than the thin merge arrow riser, so draw them both ** on the same rail. */ pParent->mergeOut = pParent->iRail; + }else if( pParent->idx - pChild->idx < pParent->selfUp ){ + pParent->mergeOut = pParent->iRail; }else{ /* The thin merge arrow riser is taller than the thick primary ** child riser, so use separate rails. */ int iTarget = pParent->iRail; - int iBtm = pParent->idx - (u==0 ? RISER_MARGIN : 1); - pParent->mergeOut = findFreeRail(p, pChild->idx, iBtm, iTarget); + pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget); mask = BIT(pParent->mergeOut); for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; pLoop=pLoop->pNext){ pLoop->railInUse |= mask; } @@ -417,16 +422,17 @@ ** ** TIMELINE_DISJOINT: Omit descenders ** TIMELINE_FILLGAPS: Use step-children ** TIMELINE_XMERGE: Omit off-graph merge lines */ -void graph_finish(GraphContext *p, u32 tmFlags){ +void graph_finish(GraphContext *p, const char *zLeftBranch, u32 tmFlags){ GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; int i, j; u64 mask; int hasDup = 0; /* True if one or more isDup entries */ const char *zTrunk; + u8 *aMap; /* Copy of p->aiRailMap */ int omitDescenders = (tmFlags & TIMELINE_DISJOINT)!=0; /* If mergeRiserFrom[X]==Y that means rail X holds a merge riser ** coming up from the bottom of the graph from off-screen check-in Y ** where Y is the RID. There is no riser on rail X if mergeRiserFrom[X]==0. @@ -516,19 +522,20 @@ pParent = hashFind(p, pRow->aParent[0]); if( pParent==0 ) continue; /* Parent off-screen */ if( pParent->zBranch!=pRow->zBranch ) continue; /* Different branch */ if( pParent->idx <= pRow->idx ){ pParent->timeWarp = 1; - }else if( pRow->idx < pParent->idx ){ + }else if( pRow->idxTop < pParent->idxTop ){ pParent->pChild = pRow; + pParent->idxTop = pRow->idxTop; } } if( tmFlags & TIMELINE_FILLGAPS ){ - /* If a node has no pChild but there is a node higher up in the graph - ** that is in the same branch and that other node has no parent in - ** the graph, the lower node a step-child of the upper node. This will + /* If a node has no pChild and there is a node higher up in the graph + ** that is in the same branch and has no in-graph parent, then + ** make the lower node a step-child of the upper node. This will ** be represented on the graph by a thick dotted line without an arrowhead. */ for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ if( pRow->pChild ) continue; for(pLoop=pRow->pPrev; pLoop; pLoop=pLoop->pPrev){ @@ -713,7 +720,29 @@ /* ** Find the maximum rail number. */ find_max_rail(p); + + /* + ** Compute the rail mapping. + */ + aMap = p->aiRailMap; + for(i=0; i<=p->mxRail; i++) aMap[i] = i; + if( zLeftBranch ){ + char *zLeft = persistBranchName(p, zLeftBranch); + j = 0; + for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ + if( pRow->zBranch==zLeft && aMap[pRow->iRail]>=j ){ + for(i=0; i<=p->mxRail; i++){ + if( aMap[i]>=j && aMap[i]<=pRow->iRail ) aMap[i]++; + } + aMap[pRow->iRail] = j++; + } + } + cgi_printf("\n"); + } + p->nErr = 0; } Index: src/graph.js ================================================================== --- src/graph.js +++ src/graph.js @@ -1,6 +1,9 @@ /* This module contains javascript needed to render timeline graphs in Fossil. +** +** There can be multiple graphs on a single webpage, but this script is only +** loaded once. ** ** Prior to sourcing this script, there should be a separate **