2d9d194b4bb0e2ec25ca1d45739fdd418632dbb8
lrnassar
  Wed Jul 8 13:53:54 2026 -0700
Add db= to same-CGI self-links in hgTrackUi and hgc. refs #37840

Extends #37840 to same-CGI links that omitted db= and relied on the cart db,
which still broke as shared, bookmarked, or search-indexed URLs. In hgTrackUi
adds db to the superTrack member list, container-configure, description,
sibling-track, duplicate/unduplicate, and quickLift-remove links. In hgc adds
the current assembly's db to the shared anchor helpers (hgcAnchorSomewhereExt,
hgcAnchorPosition, hgcAnchorWindow, hgcAnchorTranslatedChain,
hgcAnchorPseudoGene), covering all their callers, plus the getDna, htcExtSeq,
refGene, stsMap, cutter, cgapSage, mgc, peakClusters, regMotif, and pubs links.
The foreign-assembly variant hgcAnchorSomewhereDb and the db2=/qlSourceDb=
params are left untouched.

diff --git src/hg/hgTrackUi/hgTrackUi.c src/hg/hgTrackUi/hgTrackUi.c
index 58f9d0a9e1e..842e8d53a84 100644
--- src/hg/hgTrackUi/hgTrackUi.c
+++ src/hg/hgTrackUi/hgTrackUi.c
@@ -2881,33 +2881,33 @@
             char *buttonViz = vizList[i];
             // the currently active viz mode is an 'active' button = pressed
             if (strcasecmp(buttonViz, trackVizStr) == 0)
                 printf("<button class='seg-active'>");
             else
                 printf("<button>");
             printf("%c%s", toupper((unsigned char)buttonViz[0]), buttonViz + 1); // upcase first letter
             puts("</button>");
         }
         puts("</div>");
         
         printf("</TD>\n<TD>");
         hPrintIcons(tdb);
 	safef(id, sizeof id, "%s_link", tdb->track);
         // the <select> tag is only needed to send arguments to the hgTracks CGI. It will be hidden, see below.
-        printf("<A HREF='%s?%s=%s&c=%s&g=%s' id='%s'>%s</A>&nbsp;", 
+        printf("<A HREF='%s?%s=%s&db=%s&c=%s&g=%s' id='%s'>%s</A>&nbsp;", 
                     tdbIsDownloadsOnly(tdb) ? hgFileUiName(): hTrackUiForTrack(tdb->track),
-                    cartSessionVarName(), cartSessionId(cart), chromosome, cgiEncode(tdb->track), 
+                    cartSessionVarName(), cartSessionId(cart), database, chromosome, cgiEncode(tdb->track), 
                     id, tdb->shortLabel);
 	jsOnEventById("click", id, "superT.submitAndLink(this);");
         }
     else
         {
         printf("<A HREF='%s?%s=%s&g=%s'>Downloads</A>",
                hgFileUiName(),cartSessionVarName(), cartSessionId(cart), cgiEncode(tdb->track));
         printf("</TD>\n<TD>");
         printf("%s&nbsp;",tdb->shortLabel);
         }
     printf("</TD>\n");
     printf("<TD>%s", tdb->longLabel);
 
     printf("&nbsp;&nbsp;");
     printDataVersion(database, tdb);
@@ -3644,93 +3644,93 @@
 jsonObjectAdd(jsonGlobalsHash, name, ele);
 }
 
 void showSupertrackInfo(struct trackDb *tdb)
 {
 // A bit of context when we're in hierarchy: parent description and sibling track list
 
 if (!tdb->parent)
     return;
 
 // show super-track info
 struct trackDb *tdbParent = tdb->parent;
 
 printf("<b>Configure track container: "
            "<img height=12 src='../images/ab_up.gif'>"
-            "<a href='%s?%s=%s&c=%s&g=%s'>%s </a></b>",
+            "<a href='%s?%s=%s&db=%s&c=%s&g=%s'>%s </a></b>",
             hgTrackUiName(), cartSessionVarName(), cartSessionId(cart),
-            chromosome, cgiEncode(tdbParent->track), tdbParent->longLabel);
+            database, chromosome, cgiEncode(tdbParent->track), tdbParent->longLabel);
 printf("<p>");
 
 if (tdbIsComposite(tdb) && sameOk(trackDbLocalSetting(tdb, "compositeTrack"), "faceted"))
     return;
 
 if (tdbParent->html)
     {
     // collapsed panel for Description
     printf("<p><table>");  // required by jsCollapsible
     jsBeginCollapsibleSectionFontSize(cart, tdb->track, "superDescription", "Description", FALSE,
                                             "medium");
     // TODO: better done with regex
     char *html = replaceChars(tdbParent->html, "<H", "<h");
     html = replaceChars(html, "</H", "</h");
 
     // remove Description header
     html = replaceChars(html, "<h2>Description</h2>", "");
     html = replaceChars(html, "<h3>Description</h3>", "");
     html = replaceChars(html, "<h1>Description</h1>", "");
 
     // remove everything after Description text
     char *end = stringIn("<h2>", html);
     if (!end)
         end = stringIn("<h1>", html);
     if (!end)
         end = stringIn("<h3>", html);
     if (end)
         *end = '\0';
     printf("%s", html);
     printf("<p><i>To view the full description, click "
-                "<a target='_blank' href='%s?%s=%s&c=%s&g=%s#TRACK_HTML'>here.</a></i>\n",
+                "<a target='_blank' href='%s?%s=%s&db=%s&c=%s&g=%s#TRACK_HTML'>here.</a></i>\n",
                         hgTrackUiName(), cartSessionVarName(), cartSessionId(cart),
-                        chromosome, cgiEncode(tdbParent->track));
+                        database, chromosome, cgiEncode(tdbParent->track));
     jsEndCollapsibleSection();
     printf("</table>\n"); // required by jsCollapsible
     }
 
 // collapsed panel for list of other tracks in the supertrack
 
 char listTitle[1000];
 safef(listTitle, sizeof listTitle, "All tracks in this collection (%d)", 
                     slCount(tdbParent->children));
 printf("<table>");  // required by jsCollapsible
 jsBeginCollapsibleSectionFontSize(cart, tdb->track, "superMembers", listTitle, FALSE, "medium");
 printf("<table cellpadding='2' style='margin-left: 50px';>");
 struct slRef *childRef;
 tdbRefSortPrioritiesFromCart(cart, &tdbParent->children);
 for (childRef = tdbParent->children; childRef != NULL; childRef = childRef->next)
     {
     struct trackDb *sibTdb = childRef->val;
     if (sameString(sibTdb->track, tdb->track))
         {
         printf("<tr><td><b>%s</b></td>\n", sibTdb->shortLabel);
         printf("<td>%s</td></tr>\n", sibTdb->longLabel);
         continue;
         }
     printf("<tr>");
-    printf("<td><a href='%s?%s=%s&c=%s&g=%s'>%s</a>&nbsp;</td>", 
+    printf("<td><a href='%s?%s=%s&db=%s&c=%s&g=%s'>%s</a>&nbsp;</td>", 
                 tdbIsDownloadsOnly(sibTdb) ? hgFileUiName(): hTrackUiForTrack(sibTdb->track),
-                cartSessionVarName(), cartSessionId(cart), chromosome, cgiEncode(sibTdb->track), 
+                cartSessionVarName(), cartSessionId(cart), database, chromosome, cgiEncode(sibTdb->track), 
                 sibTdb->shortLabel);
     printf("<td>%s</td></tr>\n", sibTdb->longLabel);
     }
 printf("</table>");
 jsEndCollapsibleSection();
 printf("</table>"); // required by jsCollapsible
 printf("<hr>");
 printf("</p>");
 }
 
 boolean tdbIsDupable(struct trackDb *tdb)
 /* Return TRUE if a track is duplicatable */
 {
 if (!dupTrackEnabled())
     return FALSE;
@@ -4001,49 +4001,49 @@
             }
 
         if (tdbIsComposite(tdb) || tdbIsSuperTrack(tdb))
 	    {
             printf("\n&nbsp;&nbsp;<a href='#' id='htui_reset'>Reset to defaults</a>\n");
 	    jsOnEventByIdF("click", "htui_reset",
                    "setVarAndPostForm('%s','1','mainForm'); return false;", setting);
 	    }
         if ( isCustomComposite(tdb))
             {
             printf("\n&nbsp;&nbsp;<a href='%s' >Go to Track Collection Builder</a>\n", hgCollectionName());
             }
 	/* Offer to dupe the non-containery tracks including composite and supertrack elements */
 	if (tdbIsDupable(tdb))
 	    {
-	    printf("\n&nbsp;&nbsp;<a href='%s?%s=%s&c=%s&g=%s&hgTrackUi_op=dupe' >Duplicate track</a>\n", 
+	    printf("\n&nbsp;&nbsp;<a href='%s?%s=%s&db=%s&c=%s&g=%s&hgTrackUi_op=dupe' >Duplicate track</a>\n", 
 		hgTrackUiName(), cartSessionVarName(), cartSessionId(cart),
-		chromosome, cgiEncode(tdb->track));
+		database, chromosome, cgiEncode(tdb->track));
 	    if (isDupTrack(tdb->track))
 		{
 		/* Offer to undupe */
-		printf("\n&nbsp;&nbsp;<a href='%s?%s=%s&c=%s&g=%s&hgTrackUi_op=undupe' >Remove duplicate</a>\n", 
+		printf("\n&nbsp;&nbsp;<a href='%s?%s=%s&db=%s&c=%s&g=%s&hgTrackUi_op=undupe' >Remove duplicate</a>\n", 
 		    hgTrackUiName(), cartSessionVarName(), cartSessionId(cart),
-		    chromosome, cgiEncode(tdb->track));
+		    database, chromosome, cgiEncode(tdb->track));
 		}
 
 	    }
 	/* Offer to remove tracks coming from a quickLift hub. */
 	char *quickLiftSourceDb = trackDbSetting(tdb, "quickLiftDb");
 	if (quickLiftSourceDb != NULL)
 	    {
-	    printf("\n&nbsp;&nbsp;<a href='%s?%s=%s&c=%s&g=%s&hgTrackUi_op=quickLiftRemove&qlSourceDb=%s' >Remove from QuickLift</a>\n",
+	    printf("\n&nbsp;&nbsp;<a href='%s?%s=%s&db=%s&c=%s&g=%s&hgTrackUi_op=quickLiftRemove&qlSourceDb=%s' >Remove from QuickLift</a>\n",
 		hgTrackUiName(), cartSessionVarName(), cartSessionId(cart),
-		chromosome, cgiEncode(tdb->track), cgiEncode(quickLiftSourceDb));
+		database, chromosome, cgiEncode(tdb->track), cgiEncode(quickLiftSourceDb));
 	    }
 	}
 
     if (ct)
         {
         puts("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
         cgiMakeButton(CT_DO_REMOVE_VAR, "Remove custom track");
         cgiMakeHiddenVar(CT_SELECTED_TABLE_VAR, tdb->track);
         puts("&nbsp;");
         if (differentString(tdb->type, "chromGraph") &&
             !isMyVariantsType(tdb->type))
             {
             char buf[256];
             if (ajax)
                 // reference to a separate form doesn't work in modal dialog,