7a4080b1727435d2c348f5d672823d80411eb1d6
hiram
  Mon May 4 15:01:47 2026 -0700
fix hgc click on mafWig track when GCx accessions are in use with speciesLabels

diff --git src/hg/hgc/mafClick.c src/hg/hgc/mafClick.c
index dba605cdb72..58b25be3afd 100644
--- src/hg/hgc/mafClick.c
+++ src/hg/hgc/mafClick.c
@@ -15,30 +15,54 @@
 #include "hgMaf.h"
 #include "hui.h"
 #include "hCommon.h"
 #include "hubConnect.h"
 #include "trackHub.h"
 #include "chromAlias.h"
 
 extern boolean issueBotWarning;
 
 #define ADDEXONCAPITAL
 
 /* Javascript to help make a selection from a drop-down
  * go back to the server. */
 static char *autoSubmit = "document.gpForm.submit();";
 
+static char *splitMafSrc(char *src, char *dbOnly, int dbOnlySize, struct hash *labelHash)
+/* Split a maf component src ("db.chrom") into db (in dbOnly) and chrom
+ * (return value).  If labelHash has an entry whose key is a prefix of src
+ * ending at a dot, prefer that.  This handles multi-dot db names like assembly
+ * hub accessions ("GCF_000009085.1.NC_002163v1").
+ * Falls back to chopping at the first dot when no labelHash hit. */
+{
+safef(dbOnly, dbOnlySize, "%s", src);
+if (labelHash != NULL)
+    {
+    for (int i = strlen(dbOnly) - 1; i > 0; i--)
+        {
+        if (dbOnly[i] == '.')
+            {
+            dbOnly[i] = 0;
+            if (hashFindVal(labelHash, dbOnly) != NULL)
+                return &dbOnly[i + 1];
+            dbOnly[i] = '.';
+            }
+        }
+    }
+return chopPrefix(dbOnly);
+}
+
 static void blueCapWrite(FILE *f, char *s, int size, char *r)
 /* Write capital letters in blue. */
 {
 boolean isBlue = FALSE;
 int i;
 for (i=0; i<size; ++i)
     {
     if (r!=NULL && s[i]==r[i])
 	fprintf(f, ".");
     else
 	{
 	char c = s[i];
 	if (isupper(c))
             {
             if (!isBlue)
@@ -98,32 +122,31 @@
 boolean haveInserts = FALSE;
 struct mafComp *masterMc = maf->components;
 
 startChars = sizeChars = srcSizeChars = 0;
 
 for (mc = maf->components; mc != NULL; mc = mc->next)
     {
     /* Figure out length of source (species) field. */
     /*if (mc->size != 0)*/
 	{
 	char dbOnly[128];
 	int len;
 	char *org;
 
 	memset(dbOnly, 0, sizeof(dbOnly));
-	safef(dbOnly, sizeof(dbOnly), "%s", mc->src);
-	chopPrefix(dbOnly);
+	splitMafSrc(mc->src, dbOnly, sizeof(dbOnly), labelHash);
 
 	if ((org = hOrganism(dbOnly)) == NULL)
 	    len = strlen(dbOnly);
 	else
 	    len = strlen(org);
 	if (srcChars < len)
 	    srcChars = len;
 
 	len = digitsBaseTen(mc->start);
 	if (startChars < len)
 	    startChars = len;
 	len = digitsBaseTen(mc->size);
 	if (sizeChars < len)
 	    sizeChars = len;
 	len = digitsBaseTen(mc->srcSize);
@@ -156,32 +179,31 @@
 	char dbOnly[128], *chrom;
 	int s = mc->start;
 	int e = s + mc->size;
 	char *org;
 	char *revComp = "";
 	char strand = mc->strand;
 	struct dyString *dy = dyStringNew(512);
 #ifdef REVERSESTRAND
 	if (cartCgiUsualBoolean(cart, COMPLEMENT_BASES_VAR, FALSE))
 	    strand = (strand == '+') ? '-' : '+';
 #endif
 	if (strand == '-') revComp = "&hgSeq.revComp=on";
 
 	dyStringClear(dy);
 
-	safef(dbOnly, sizeof(dbOnly), "%s", mc->src);
-	chrom = chopPrefix(dbOnly);
+	chrom = splitMafSrc(mc->src, dbOnly, sizeof(dbOnly), labelHash);
         if ((labelHash == NULL) || ((org = hashFindVal(labelHash, dbOnly)) == NULL))
             {
             if ((org = hOrganism(dbOnly)) == NULL)
                 org = dbOnly;
             }
 
 	if (mc->strand == '-')
 	    reverseIntRange(&s, &e, mc->srcSize);
 
 
 	if (mc->text != NULL)
 	    {
             if (lineStart == 0)
 		{
 		if (hDbIsActive(dbOnly))
@@ -296,32 +318,31 @@
     {
     fprintf(f, "<B>Inserts between block %d and %d in window</B>\n",blockNo, blockNo+1);
     for (mc = maf->components; mc != NULL; mc = mc->next)
 	{
 	char dbOnly[128], *chrom;
 	int s = mc->start + mc->size;
 	int e = s + mc->rightLen;
 	char *org;
 
 	if (mc->text == NULL)
 	    continue;
 
 	if (mc->strand == '-')
 	    reverseIntRange(&s, &e, mc->srcSize);
 
-	safef(dbOnly, sizeof(dbOnly), "%s", mc->src);
-	chrom = chopPrefix(dbOnly);
+	chrom = splitMafSrc(mc->src, dbOnly, sizeof(dbOnly), labelHash);
 
         if ((labelHash == NULL) || ((org = hashFindVal(labelHash, dbOnly)) == NULL))
             {
             if ((org = hOrganism(dbOnly)) == NULL)
                 org = dbOnly;
             }
 
 	if (mc->rightStatus == MAF_INSERT_STATUS)
 	    {
 	    char *revComp = "";
 	    if (hDbIsActive(dbOnly))
 		{
 		char strand = mc->strand;
 #ifdef REVERSESTRAND
 		if (cartCgiUsualBoolean(cart, COMPLEMENT_BASES_VAR, FALSE))