6b045fb4555e28c738cab4be57b8a3750584fe9b angie Fri Sep 29 17:14:01 2017 -0700 Don't inject highlight straight into cart when hgFind finds a match for a search with padding -- only set highlight when there's a single match or when the user clicks on a link to select a specific match. fixes #20245 diff --git src/hg/lib/hgFind.c src/hg/lib/hgFind.c index 2142977..7018a05 100644 --- src/hg/lib/hgFind.c +++ src/hg/lib/hgFind.c @@ -2438,30 +2438,36 @@ fprintf(f, "%s&", extraCgi); fprintf(f, "%s=%s&", trackName, vis); // this is magic to tell the browser to make the // composite and this subTrack visible if (tdb->parent) { if (tdbIsSuperTrackChild(tdb)) fprintf(f, "%s=show&", tdb->parent->track); else { // tdb is a subtrack of a composite or a view fprintf(f, "%s_sel=1&", trackName); fprintf(f, "%s_sel=1&", tdb->parent->track); } } + if (isNotEmpty(pos->highlight)) + { + char *encHighlight = cgiEncode(pos->highlight); + fprintf(f, "highlight=%s&", encHighlight); + freeMem(encHighlight); + } fprintf(f, "hgFind.matches=%s,\">", encMatches); // Bold canonical genes. if(pos->canonical) { fprintf(f, "<B>"); } htmTextOut(f, pos->name); if(pos->canonical) { fprintf(f, "</B>"); } fprintf(f, " at %s</A>", range); desc = pos->description; if (desc) { fprintf(f, " - "); htmTextOut(f, desc); @@ -2724,50 +2730,55 @@ { if (!isFuzzy || keyIsPrefixIgnoreCase(term, row[1])) { xrefPtr = slPairNew(cloneString(row[1]), cloneString(row[0])); slAddHead(&xrefList, xrefPtr); } } sqlFreeResult(&sr); hFreeConn(&conn); slReverse(&xrefList); if (xrefList == NULL && hgFindSpecSetting(hfs, "searchBoth") != NULL) xrefList = slPairNew(cloneString(""), cloneString(term)); return(xrefList); } -static void addHighlight(struct cart *cart, char *db, char *chrom, unsigned start, unsigned end) -/* Add the given region to the cart variable highlight. */ +static char *addHighlight(struct cart *cart, char *db, char *chrom, unsigned start, unsigned end) +/* Add the given region to the existing value of the cart variable highlight. + * Return new value for highlight, or NULL if no change is necessary (already highlighted). */ { char *color = "fcfcac"; struct dyString *dy = dyStringCreate("%s.%s:%u-%u#%s", db, chrom, start+1, end, color); +boolean alreadySet = FALSE; char *existing = cartOptionalString(cart, "highlight"); -if (isEmpty(existing)) - cartSetString(cart, "highlight", dyStringContents(dy)); -else +if (isNotEmpty(existing)) { // Don't add region if it is already in the existing highlight setting. char *alreadyIn = strstr(existing, dyStringContents(dy)); - if (!alreadyIn || - !(alreadyIn[dyStringLen(dy)] == '|' || alreadyIn[dyStringLen(dy)] == '\0')) - { + if (alreadyIn && + (alreadyIn[dyStringLen(dy)] == '|' || alreadyIn[dyStringLen(dy)] == '\0')) + alreadySet = TRUE; + else dyStringPrintf(dy, "|%s", existing); - cartSetString(cart, "highlight", dyStringContents(dy)); - } } +if (alreadySet) + { dyStringFree(&dy); + return NULL; + } +else + return dyStringCannibalize(&dy); } static boolean doQuery(char *db, struct hgFindSpec *hfs, char *xrefTerm, char *term, struct hgPositions *hgp, boolean relativeFlag, int relStart, int relEnd, boolean multiTerm) /* Perform a query as specified in hfs, assuming table existence has been * checked and xref'ing has been taken care of. */ { struct slName *tableList = hSplitTableNames(db, hfs->searchTable); struct slName *tPtr = NULL; struct hgPosTable *table = NULL; struct hgPos *pos = NULL; struct sqlConnection *conn = hAllocConn(db); struct sqlResult *sr = NULL; @@ -2824,31 +2835,31 @@ pos->browserName = cloneString(row[3]); if (isNotEmpty(xrefTerm)) { safef(buf, sizeof(buf), "(%s%s)", termPrefix ? termPrefix : "", row[3]); pos->description = cloneString(buf); } if (relativeFlag && (pos->chromStart + relEnd) <= pos->chromEnd) { pos->chromEnd = pos->chromStart + relEnd; pos->chromStart = pos->chromStart + relStart; } else if (padding > 0 && !multiTerm) { // highlight the item bases to distinguish from padding - addHighlight(cart, db, pos->chrom, pos->chromStart, pos->chromEnd); + pos->highlight = addHighlight(cart, db, pos->chrom, pos->chromStart, pos->chromEnd); int chromSize = hChromSize(db, pos->chrom); pos->chromStart -= padding; pos->chromEnd += padding; if (pos->chromStart < 0) pos->chromStart = 0; if (pos->chromEnd > chromSize) pos->chromEnd = chromSize; } slAddHead(&table->posList, pos); } } if (table != NULL) slReverse(&table->posList); sqlFreeResult(&sr); @@ -3080,31 +3091,32 @@ if (dyStringLen(dyWarn) > 0) warn("%s", dyStringContents(dyWarn)); if (mapping) { int padding = 5; char *trackTable; if (isEmpty(pslTable)) trackTable = "chromInfo"; else if (startsWith("lrg", pslTable)) trackTable = "lrgTranscriptAli"; else trackTable = "refGene"; singlePos(hgp, "HGVS", NULL, trackTable, term, "", mapping->chrom, mapping->chromStart-padding, mapping->chromEnd+padding); // highlight the mapped bases to distinguish from padding - addHighlight(cart, db, mapping->chrom, mapping->chromStart, mapping->chromEnd); + hgp->tableList->posList->highlight = addHighlight(cart, db, mapping->chrom, + mapping->chromStart, mapping->chromEnd); foundIt = TRUE; } dyStringFree(&dyWarn); } return foundIt; } struct hgPositions *hgPositionsFind(char *db, char *term, char *extraCgi, char *hgAppNameIn, struct cart *cart, boolean multiTerm) /* Return table of positions that match term or NULL if none such. */ { struct hgPositions *hgp = NULL, *hgpItem = NULL; regmatch_t substrs[4]; boolean canonicalSpec = FALSE; boolean gbrowserSpec = FALSE; @@ -3253,30 +3265,32 @@ { struct hgPos *pos = NULL; for(pos = hpTable->posList; pos != NULL; pos = pos->next) { dyStringPrintf(hgpMatchNames, "%s,", pos->browserName); } } } if (cart != NULL) cartSetString(cart, "hgFind.matches", hgpMatchNames->string); } slReverse(&hgp->tableList); if (multiTerm) collapseSamePos(hgp); fixSinglePos(hgp); +if (cart && hgp->singlePos && isNotEmpty(hgp->singlePos->highlight)) + cartSetString(cart, "highlight", hgp->singlePos->highlight); return hgp; } void hgPositionsHelpHtml(char *organism, char *database) /* Display contents of dbDb.htmlPath for database, or print an HTML comment * explaining what's missing. */ { char *htmlPath = hHtmlPath(database); char *htmlString = NULL; size_t htmlStrLength = 0; if (strstrNoCase(organism, "zoo")) webNewSection("About the NISC Comparative Sequencing Program Browser"); else