Index: skins/ardoise/css.txt ================================================================== --- skins/ardoise/css.txt +++ skins/ardoise/css.txt @@ -947,10 +947,38 @@ border-radius: 5px; border: solid #ff8000; vertical-align: top; text-align: left; background: #442800 +} +span.timelineSelected { + border-radius: 5px; + border: solid #ff8000; + vertical-align: top; + text-align: left; + background: #442800 +} +.timelineSelected {} +.timelineSecondary {} +.timelineSecondary > .timelineColumnarCell, +.timelineSecondary > .timelineCompactCell, +.timelineSecondary > .timelineDetailCell, +.timelineSecondary > .timelineModernCell, +.timelineSecondary > .timelineVerboseCell { + padding: .75em; + border-radius: 5px; + border: solid #0080ff; + vertical-align: top; + text-align: left; + background: #002844 +} +span.timelineSecondary { + border-radius: 5px; + border: solid #0080ff; + vertical-align: top; + text-align: left; + background: #002844 } .timelineCurrent > .timelineColumnarCell, .timelineCurrent > .timelineCompactCell, .timelineCurrent > .timelineDetailCell, .timelineCurrent > .timelineModernCell, Index: skins/blitz/css.txt ================================================================== --- skins/blitz/css.txt +++ skins/blitz/css.txt @@ -1060,16 +1060,19 @@ background-color: #ffc; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; } -tr.timelineSelected { +.timelineSelected { border-left: 2px solid orange; background-color: #ffffe8; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; } +.timelineSecondary { + background-color: #e8ffff; +} tr.timelineCurrent td.timelineTableCell { } tr.timelineBottom td { Index: skins/eagle/css.txt ================================================================== --- skins/eagle/css.txt +++ skins/eagle/css.txt @@ -168,13 +168,16 @@ font-family: "courier new"; border-spacing: 0px 2px; // border-collapse: collapse; } -tr.timelineSelected { +.timelineSelected { background-color: #7EA2D9; } +.timelineSecondary { + background-color: #7EA27E; +} /* commit node */ .tl-node { width: 10px; height: 10px; Index: skins/xekri/css.txt ================================================================== --- skins/xekri/css.txt +++ skins/xekri/css.txt @@ -803,10 +803,12 @@ .timelineTable .timelineSelected { background: #222; border: 0; box-shadow: none; } +.timelineSelected {} +.timelineSecondary {} .timelineTable .timelineSelected .timelineTime { background: #333; border-radius: 1rem 0 0 1rem; box-shadow: 2px 2px 1px #000; @@ -823,10 +825,17 @@ .timelineTable .timelineSelected .timelineDetailCell { background: #333; border-radius: 0 1rem 1rem 0; box-shadow: 2px 2px 1px #000; } + +span.timelineSelected { + padding: 0 1em 0 1em; + border-radius: 1rem; + background: #333; + box-shadow: 2px 2px 1px #000; +} .timelineTable .timelineModernCell .timelineModernComment , .timelineTable .timelineModernCell .timelineModernDetail , .timelineTable .timelineCompactCell .timelineCompactComment , .timelineTable .timelineCompactCell .timelineCompactDetail , Index: src/branch.c ================================================================== --- src/branch.c +++ src/branch.c @@ -18,10 +18,37 @@ ** This file contains code used to create new branches within a repository. */ #include "config.h" #include "branch.h" #include + +/* +** If RID refers to a check-in, return the name of the branch for that +** check-in. +** +** Space to hold the returned value is obtained from fossil_malloc() +** and should be freed by the caller. +*/ +char *branch_of_rid(int rid){ + char *zBr = 0; + static Stmt q; + db_static_prepare(&q, + "SELECT value FROM tagxref" + " WHERE rid=$rid AND tagid=%d" + " AND tagtype>0", TAG_BRANCH); + db_bind_int(&q, "$rid", rid); + if( db_step(&q)==SQLITE_ROW ){ + zBr = fossil_strdup(db_column_text(&q,0)); + } + db_reset(&q); + if( zBr==0 ){ + static char *zMain = 0; + if( zMain==0 ) zMain = db_get("main-branch","trunk"); + zBr = fossil_strdup(zMain); + } + return zBr; +} /* ** fossil branch new NAME BASIS ?OPTIONS? ** argv0 argv1 argv2 argv3 argv4 */ @@ -661,9 +688,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, 0, brtimeline_extra); + www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, brtimeline_extra); db_finalize(&q); style_footer(); } Index: src/default_css.txt ================================================================== --- src/default_css.txt +++ src/default_css.txt @@ -38,16 +38,19 @@ tr.timelineCurrent { padding: .1em .2em; border: 1px dashed #446979; box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5); } -tr.timelineSelected { +.timelineSelected { padding: .1em .2em; border: 2px solid lightgray; background-color: #ffc; box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5); } +.timelineSecondary { + background-color: #cff; +} tr.timelineSelected td { border-radius: 0; border-width: 0; } tr.timelineCurrent td { Index: src/descendants.c ================================================================== --- src/descendants.c +++ src/descendants.c @@ -183,10 +183,35 @@ "INSERT INTO ok" " SELECT rid FROM ancestor;", rid, rid, directOnly ? "AND plink.isPrim" : "", N ); } + +/* +** Compute the youngest ancestor of record ID rid that is a member of +** branch zBranch. +*/ +int compute_youngest_ancestor_in_branch(int rid, const char *zBranch){ + return db_int(0, + "WITH RECURSIVE " + " ancestor(rid, mtime) AS (" + " SELECT %d, mtime FROM event WHERE objid=%d " + " UNION " + " SELECT plink.pid, event.mtime" + " FROM ancestor, plink, event" + " WHERE plink.cid=ancestor.rid" + " AND event.objid=plink.pid" + " ORDER BY mtime DESC" + " )" + " SELECT ancestor.rid FROM ancestor" + " WHERE EXISTS(SELECT 1 FROM tagxref" + " WHERE tagid=%d AND tagxref.rid=ancestor.rid" + " AND value=%Q AND tagtype>0)" + " LIMIT 1", + rid, rid, TAG_BRANCH, zBranch + ); +} /* ** Compute all direct ancestors (merge ancestors do not count) ** for the check-in rid and put them in a table named "ancestor". ** Label each generation with consecutive integers going backwards @@ -540,11 +565,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, 0); + www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0); db_finalize(&q); @
style_footer(); } Index: src/finfo.c ================================================================== --- src/finfo.c +++ src/finfo.c @@ -780,11 +780,11 @@ /* 7 */ " isaux" " FROM mlink WHERE mid=%d ORDER BY 1", mid ); @

MLINK table for check-in %h(zCI)

- render_checkin_context(mid, 1); + render_checkin_context(mid, 0, 1); style_table_sorter(); @
@
@ @ Index: src/info.c ================================================================== --- src/info.c +++ src/info.c @@ -252,34 +252,46 @@ /* ** Show the context graph (immediate parents and children) for ** check-in rid. */ -void render_checkin_context(int rid, int parentsOnly){ +void render_checkin_context(int rid, int rid2, int parentsOnly){ Blob sql; Stmt q; + int rx[2]; + int i, n; + rx[0] = rid; + rx[1] = rid2; + n = rid2 ? 2 : 1; blob_zero(&sql); blob_append(&sql, timeline_query_for_www(), -1); - db_multi_exec( - "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" - "DELETE FROM ok;" - "INSERT INTO ok VALUES(%d);" - "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;", - rid, rid - ); - if( !parentsOnly ){ - db_multi_exec( - "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;", rid - ); - if( db_table_exists("repository","cherrypick") ){ - db_multi_exec( - "INSERT OR IGNORE INTO ok " - " SELECT parentid FROM cherrypick WHERE childid=%d;" - "INSERT OR IGNORE INTO ok " - " SELECT childid FROM cherrypick WHERE parentid=%d;", - rid, rid - ); + + db_multi_exec( + "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" + "DELETE FROM ok;" + ); + for(i=0; i0", TAG_USER, rid); zEComment = db_text(0, "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d", TAG_COMMENT, rid); - zBrName = db_text(0, - "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d", - TAG_BRANCH, rid); zOrigUser = db_column_text(&q1, 2); zUser = zEUser ? zEUser : zOrigUser; zComment = db_column_text(&q1, 3); zDate = db_column_text(&q1,1); zOrigDate = db_column_text(&q1, 4); @@ -872,11 +884,14 @@ } if( g.perm.Hyperlink ){ @ @ isSelectedOrCurrent = 1; + }else if( rid==secondRid ){ + @ + isSelectedOrCurrent = 1; }else if( rid==vid ){ @ isSelectedOrCurrent = 1; }else { @ @@ -1601,11 +1605,12 @@ int pd_rid; double rBefore, rAfter, rCirca; /* Boundary times */ const char *z; char *zOlderButton = 0; /* URL for Older button at the bottom */ char *zNewerButton = 0; /* URL for Newer button at the top */ - int selectedRid = -9999999; /* Show a highlight on this RID */ + int selectedRid = 0; /* Show a highlight on this RID */ + int secondaryRid = 0; /* Show secondary highlight */ int disableY = 0; /* Disable type selector on submenu */ int advancedMenu = 0; /* Use the advanced menu design */ char *zPlural; /* Ending for plural forms */ int showCherrypicks = 1; /* True to show cherrypick merges */ @@ -1625,10 +1630,12 @@ } }else{ z = "50"; nEntry = 50; } + secondaryRid = name_to_typed_rid(P("sel2"),"ci"); + selectedRid = name_to_typed_rid(P("sel1"),"ci"); cgi_replace_query_parameter("n",z); cookie_write_parameter("n","n",0); tmFlags |= timeline_ss_submenu(); cookie_link_parameter("advm","advm","0"); advancedMenu = atoi(PD("advm","0")); @@ -2387,15 +2394,17 @@ blob_zero(&sql); db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/"); if( fossil_islower(desc.aData[0]) ){ desc.aData[0] = fossil_toupper(desc.aData[0]); } - if( zBrName - && !PB("nowiki") - && wiki_render_associated("branch", zBrName, WIKIASSOC_ALL) - ){ - @
%b(&desc)
+ if( zBrName ){ + if( !PB("nowiki") + && wiki_render_associated("branch", zBrName, WIKIASSOC_ALL) + ){ + @
%b(&desc)
+ } + style_submenu_element("Diff", "%R/vdiff?branch=%T", zBrName); }else if( zTagName && matchStyle==MS_EXACT && zBrName==0 && !PB("nowiki") @@ -2414,11 +2423,11 @@ if( zNewerButton ){ @ %z(chref("button","%z",zNewerButton))More ↑ } www_print_timeline(&q, tmFlags, zThisUser, zThisTag, zBrName, - selectedRid, 0); + selectedRid, secondaryRid, 0); db_finalize(&q); if( zOlderButton ){ @ %z(chref("button","%z",zOlderButton))More ↓ } style_footer(); @@ -2907,11 +2916,11 @@ zId = db_text(0, "SELECT timestamp FROM timeline" " ORDER BY sortby DESC LIMIT 1"); @

%d(iAgo) Year%s(iAgo>1?"s":"") Ago @ %z(href("%R/timeline?c=%t",zId))(more context)\ @

- www_print_timeline(&q, TIMELINE_GRAPH, 0, 0, 0, 0, 0); + www_print_timeline(&q, TIMELINE_GRAPH, 0, 0, 0, 0, 0, 0); } db_finalize(&q); style_footer(); } Index: src/tkt.c ================================================================== --- src/tkt.c +++ src/tkt.c @@ -896,11 +896,11 @@ timeline_query_for_www(), tagid, zFullUuid, zFullUuid, zFullUuid ); } db_prepare(&q, "%z", zSQL/*safe-for-%s*/); www_print_timeline(&q, TIMELINE_ARTID|TIMELINE_DISJOINT|TIMELINE_GRAPH, - 0, 0, 0, 0, 0); + 0, 0, 0, 0, 0, 0); db_finalize(&q); style_footer(); } /*
Other Links: - @ %z(href("%R/artifact/%!S",zUuid))manifest + if( fossil_strcmp(zBrName, db_get("main-branch","trunk"))!=0 ){ + @ %z(href("%R/vdiff?branch=%!S", zUuid))branch diff | + } + @ %z(href("%R/artifact/%!S",zUuid))manifest @ | %z(href("%R/ci_tags/%!S",zUuid))tags if( g.perm.Admin ){ @ | %z(href("%R/mlink?ci=%!S",zUuid))mlink table } if( g.anon.Write ){ @@ -896,11 +911,11 @@ if( !PB("nowiki") ){ wiki_render_associated("checkin", zUuid, 0); } render_backlink_graph(zUuid, "
References
\n"); @
Context
- render_checkin_context(rid, 0); + render_checkin_context(rid, 0, 0); @
Changes
@
diffFlags = construct_diff_flags(diffType); zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; if( diffType!=0 ){ @@ -1097,10 +1112,11 @@ return 0; } return manifest_get(rid, CFTYPE_MANIFEST, 0); } +#if 0 /* not used */ /* ** Output a description of a check-in */ static void checkin_description(int rid){ Stmt q; @@ -1155,10 +1171,11 @@ hyperlink_to_date(zDate, ")"); tag_private_status(rid); } db_finalize(&q); } +#endif /* not used */ /* ** WEBPAGE: vdiff ** URL: /vdiff?from=TAG&to=TAG @@ -1190,10 +1207,12 @@ const char *zFrom; const char *zTo; const char *zRe; const char *zW; const char *zGlob; + char *zQuery; + char *zMergeOrigin = 0; ReCompiled *pRe = 0; login_check_credentials(); if( !g.perm.Read ){ login_needed(g.anon.Read); return; } login_anonymous_available(); load_control(); @@ -1201,13 +1220,18 @@ diffType = atoi(PD("diff","2")); cookie_render(); zRe = P("regex"); if( zRe ) re_compile(&pRe, zRe, 0); zBranch = P("branch"); - if( zBranch && zBranch[0] ){ - cgi_replace_parameter("from", mprintf("root:%s", zBranch)); + if( zBranch && zBranch[0]==0 ) zBranch = 0; + if( zBranch ){ + zQuery = mprintf("branch=%T", zBranch); + zMergeOrigin = mprintf("merge-in:%s", zBranch); + cgi_replace_parameter("from", zMergeOrigin); cgi_replace_parameter("to", zBranch); + }else{ + zQuery = mprintf("from=%T&to=%T",PD("from",""),PD("to","")); } pTo = vdiff_parse_manifest("to", &ridTo); if( pTo==0 ) return; pFrom = vdiff_parse_manifest("from", &ridFrom); if( pFrom==0 ) return; @@ -1217,56 +1241,82 @@ if(zGlob && !*zGlob){ zGlob = NULL; } diffFlags = construct_diff_flags(diffType); zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; - style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo); + if( zBranch==0 ){ + style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo); + } if( diffType!=0 ){ - style_submenu_element("Hide Diff", "%R/vdiff?from=%T&to=%T&diff=0%s%T%s", - zFrom, zTo, + style_submenu_element("Hide Diff", "%R/vdiff?%s&diff=0%s%T%s", + zQuery, zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); } if( diffType!=2 ){ style_submenu_element("Side-by-Side Diff", - "%R/vdiff?from=%T&to=%T&diff=2%s%T%s", - zFrom, zTo, + "%R/vdiff?%s&diff=2%s%T%s", + zQuery, zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); } if( diffType!=1 ) { style_submenu_element("Unified Diff", - "%R/vdiff?from=%T&to=%T&diff=1%s%T%s", - zFrom, zTo, + "%R/vdiff?%s&diff=1%s%T%s", + zQuery, + zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); + } + if( zBranch==0 ){ + style_submenu_element("Invert", + "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom, zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); } - style_submenu_element("Invert", - "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom, - zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); if( zGlob ){ style_submenu_element("Clear glob", - "%R/vdiff?from=%T&to=%T&%s", zFrom, zTo, zW); + "%R/vdiff?%s&%s", zQuery, zW); }else{ style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW); } if( diffType!=0 ){ style_submenu_checkbox("w", "Ignore Whitespace", 0, 0); } - style_header("Check-in Differences"); + if( zBranch ){ + style_header("Changes On Branch %h", zBranch); + }else{ + style_header("Check-in Differences"); + } if( P("nohdr")==0 ){ - @

Difference From:

- checkin_description(ridFrom); - @

To:

- checkin_description(ridTo); - @
+ if( zBranch ){ + char *zRealBranch = branch_of_rid(ridTo); + char *zToUuid = rid_to_uuid(ridTo); + char *zFromUuid = rid_to_uuid(ridFrom); + @

Changes In Branch \ + @ %z(href("%R/timeline?r=%T",zRealBranch))%h(zRealBranch) + if( ridTo != symbolic_name_to_rid(zRealBranch,"ci") ){ + @ Through %z(href("%R/info/%!S",zToUuid))[%S(zToUuid)] + } + @ Excluding Merge-Ins

+ @

This is equivalent to a diff from + @ \ + @ %z(href("%R/info/%!S",zFromUuid))%S(zFromUuid) + @ to \ + @ %z(href("%R/info/%!S",zToUuid))%S(zToUuid)

+ }else{ + @

Difference From \ + @ %z(href("%R/info/%h",zFrom))%h(zFrom) + @ To \ + @ %z(href("%R/info/%h",zTo))%h(zTo)

+ } + render_checkin_context(ridFrom, ridTo, 0); if( pRe ){ @

Only differences that match regular expression "%h(zRe)" @ are shown.

} if( zGlob ){ @

Only files matching the glob "%h(zGlob)" are shown.

} @

} + fossil_free(zQuery); manifest_file_rewind(pFrom); pFileFrom = manifest_file_next(pFrom, 0); manifest_file_rewind(pTo); pFileTo = manifest_file_next(pTo, 0); Index: src/moderate.c ================================================================== --- src/moderate.c +++ src/moderate.c @@ -184,11 +184,11 @@ blob_append_sql(&sql, " AND event.objid IN (SELECT objid FROM modreq)" " ORDER BY event.mtime DESC" ); db_prepare(&q, "%s", blob_sql_text(&sql)); - www_print_timeline(&q, 0, 0, 0, 0, 0, 0); + www_print_timeline(&q, 0, 0, 0, 0, 0, 0, 0); db_finalize(&q); } style_footer(); } Index: src/name.c ================================================================== --- src/name.c +++ src/name.c @@ -108,21 +108,25 @@ return zEDate; } /* ** Return the RID that is the "root" of the branch that contains -** check-in "rid" if inBranch==0 or the first check-in in the branch -** if inBranch==1. +** check-in "rid". Details depending on eType: +** +** eType==0 The check-in of the parent branch off of which +** the branch containing RID originally diverged. +** +** eType==1 The first check-in of the branch that contains RID. +** +** eType==2 The youngest ancestor of RID that is on the branch +** from which the branch containing RID diverged. */ -int start_of_branch(int rid, int inBranch){ +int start_of_branch(int rid, int eType){ Stmt q; int rc; - char *zBr; - zBr = db_text("trunk","SELECT value FROM tagxref" - " WHERE rid=%d AND tagid=%d" - " AND tagtype>0", - rid, TAG_BRANCH); + int ans = rid; + char *zBr = branch_of_rid(rid); db_prepare(&q, "SELECT pid, EXISTS(SELECT 1 FROM tagxref" " WHERE tagid=%d AND tagtype>0" " AND value=%Q AND rid=plink.pid)" " FROM plink" @@ -130,18 +134,23 @@ TAG_BRANCH, zBr ); fossil_free(zBr); do{ db_reset(&q); - db_bind_int(&q, ":cid", rid); + db_bind_int(&q, ":cid", ans); rc = db_step(&q); if( rc!=SQLITE_ROW ) break; - if( inBranch && db_column_int(&q,1)==0 ) break; - rid = db_column_int(&q, 0); - }while( db_column_int(&q, 1)==1 && rid>0 ); + if( eType==1 && db_column_int(&q,1)==0 ) break; + ans = db_column_int(&q, 0); + }while( db_column_int(&q, 1)==1 && ans>0 ); db_finalize(&q); - return rid; + if( eType==2 && ans>0 ){ + zBr = branch_of_rid(ans); + ans = compute_youngest_ancestor_in_branch(rid, zBr); + fossil_free(zBr); + } + return ans; } /* ** Convert a symbolic name into a RID. Acceptable forms: ** @@ -165,10 +174,11 @@ ** ** The zType parameter specifies the type of artifact: ci, t, w, e, g, f. ** If zType is NULL or "" or "*" then any type of artifact will serve. ** If zType is "br" then find the first check-in of the named branch ** rather than the last. +** ** zType is "ci" in most use cases since we are usually searching for ** a check-in. ** ** Note that the input zTag for types "t" and "e" is the artifact hash of ** the ticket-change or technote-change artifact, not the randomly generated @@ -270,14 +280,19 @@ ); if( startOfBranch ) rid = start_of_branch(rid,1); return rid; } - /* root:TAG -> The origin of the branch */ - if( memcmp(zTag, "root:", 5)==0 ){ + /* root:BR -> The origin of the branch named BR */ + if( strncmp(zTag, "root:", 5)==0 ){ rid = symbolic_name_to_rid(zTag+5, zType); return start_of_branch(rid, 0); + } + /* rootx:BR -> Most recent merge-in for the branch name BR */ + if( strncmp(zTag, "merge-in:", 9)==0 ){ + rid = symbolic_name_to_rid(zTag+9, zType); + return start_of_branch(rid, 2); } /* symbolic-name ":" date-time */ nTag = strlen(zTag); for(i=0; i ", g.argv[i]); - if( name_to_uuid(&name, 1, "*") ){ - fossil_print("ERROR: %s\n", g.zErrMsg); - fossil_error_reset(); - }else{ - fossil_print("%s\n", blob_buffer(&name)); - } - blob_reset(&name); + if( strcmp(g.argv[i],"--count")==0 && i+1 ", g.argv[i]); + if( name_to_uuid(&name, 1, "*") ){ + fossil_print("ERROR: %s\n", g.zErrMsg); + fossil_error_reset(); + }else{ + fossil_print("%s\n", blob_buffer(&name)); + } + blob_reset(&name); + }while( n-- > 0 ); } } /* ** Convert a name to a rid. If the name can be any of the various forms Index: src/tag.c ================================================================== --- src/tag.c +++ src/tag.c @@ -776,10 +776,10 @@ ** many descenders to (off-screen) parents. */ tmFlags = TIMELINE_XMERGE | TIMELINE_FILLGAPS | 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, 0, 0); + www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0); db_finalize(&q); @
style_footer(); } Index: src/timeline.c ================================================================== --- src/timeline.c +++ src/timeline.c @@ -243,11 +243,12 @@ Stmt *pQuery, /* Query to implement the timeline */ int tmFlags, /* Flags controlling display behavior */ const char *zThisUser, /* Suppress links to this user */ const char *zThisTag, /* Suppress links to this tag */ const char *zLeftBranch, /* Strive to put this branch on the left margin */ - int selectedRid, /* Highlight the line with this RID value */ + int selectedRid, /* Highlight the line with this RID value or zero */ + int secondRid, /* Secondary highlight (or zero) */ void (*xExtra)(int) /* Routine to call on each line of display */ ){ int mxWikiLen; Blob comment; int prevTagid = 0; @@ -395,10 +396,13 @@ } pendingEndTr = 1; if( rid==selectedRid ){ @