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))