4a030195664cbdd1d3c1a4b81b1ed41dbf6d9bc5 angie Fri Feb 15 14:02:58 2019 -0800 Prevent hgFind lib (specifically genomePos -> hgPositionsHtml) from opening a web page; instead, pass up results and warning messages to the calling CGI so it can open the page its own way. refs #22945 hgTracks, hgTables and hgVai used to call findGenomePos{,Web} to resolve positions; hgTables and hgVai had to detect after the fact whether an HTML page had been started (with warnings and/or multiple results). In fact, hgPositionsHtml called webEnd which could cause conflicts with what the CGI was doing afterwards. Now, instead of findGenomePos{,Web} there is hgFindSearch which returns hgp and also warning messages, if any, via a dyString parameter. The calling CGI decides how to open the page if necessary (for hgTracks, it's already open) and displays warnings/multiple results -- or just proceeds as usual with the single position result. diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c index 275ab9c..40a8a0d 100644 --- src/hg/hgTracks/hgTracks.c +++ src/hg/hgTracks/hgTracks.c @@ -132,31 +132,31 @@ char *protDbName; /* Name of proteome database for this genome. */ #define MAX_CONTROL_COLUMNS 6 #define LOW 1 #define MEDIUM 2 #define BRIGHT 3 #define MAXCHAINS 50000000 boolean hgDebug = FALSE; /* Activate debugging code. Set to true by hgDebug=on in command line*/ int imagePixelHeight = 0; struct hash *oldVars = NULL; struct jsonElement *jsonForClient = NULL; boolean hideControls = FALSE; /* Hide all controls? */ boolean trackImgOnly = FALSE; /* caller wants just the track image and track table html */ boolean ideogramToo = FALSE; /* caller wants the ideoGram (when requesting just one track) */ -/* Structure returned from findGenomePos. +/* Structure returned from resolvePosition. * We use this to to expand any tracks to full * that were found to contain the searched-upon * position string */ struct hgPositions *hgp = NULL; /* Other global variables. */ struct group *groupList = NULL; /* List of all tracks. */ char *browserName; /* Test, preview, or public browser */ char *organization; /* UCSC */ struct hash *trackHash = NULL; /* Hash of the tracks by their name. */ #ifdef DEBUG void uglySnoopTrackList(int depth, struct track *trackList) /* Print out some info on track list. */ @@ -8910,37 +8910,30 @@ "<A HREF=\"hgTracks?hgTracksConfigPage=configure\">image configuration menu</A>."); printf("<LI>In the image configuration menu, change the size of the image,\n" "to make it look more square.\n"); printf("</UL>\n"); printf("</div>\n"); } else printf("<BR><BR>PDF format not available"); printf("<a href='%s?%s=%s'><input type='button' VALUE='Return to Browser'></a>\n", hgTracksName(), cartSessionVarName(), cartSessionId(cart)); } -boolean isGenome(char *pos) -/* Return TRUE if pos is genome. */ -{ -pos = trimSpaces(pos); -return(sameWord(pos, "genome") || sameWord(pos, "hgBatch")); -} - void setRulerMode() /* Set the rulerMode variable from cart. */ { char *s = cartUsualString(cart, RULER_TRACK_NAME, "dense"); if (sameWord(s, "full") || sameWord(s, "on")) rulerMode = tvFull; else if (sameWord(s, "dense")) rulerMode = tvDense; else rulerMode = tvHide; } void setLayoutGlobals() /* Figure out basic dimensions of display. */ { @@ -8954,39 +8947,69 @@ withNextExonArrows = cartUsualBoolean(cart, "nextExonArrows", TRUE); } withExonNumbers = cartUsualBoolean(cart, "exonNumbers", TRUE); emAltHighlight = cartUsualBoolean(cart, "emAltHighlight", FALSE); if (!hIsGsidServer()) { revCmplDisp = cartUsualBooleanDb(cart, database, REV_CMPL_DISP, FALSE); } emPadding = cartUsualInt(cart, "emPadding", emPadding); gmPadding = cartUsualInt(cart, "gmPadding", gmPadding); withPriorityOverride = cartUsualBoolean(cart, configPriorityOverride, FALSE); fullInsideX = trackOffsetX(); fullInsideWidth = tl.picWidth-gfxBorder-fullInsideX; } +static boolean resolvePosition(char **pPosition) +/* Position may be an already-resolved chr:start-end, or a search term. + * If it is a search term: + * 1 match ==> set globals chromName, winStart, winEnd, return TRUE. + * 0 matches ==> switch back to lastPosition, hopefully get 1 match from that; + * set globals chromName, winStart, winEnd, return TRUE. If no lastPosition, try w/hDefaultPos(). + * multiple matches ==> Display a page with links to match positions, return FALSE. */ +{ +boolean resolved = TRUE; +struct dyString *dyWarn = dyStringNew(0); +hgp = hgFindSearch(cart, pPosition, &chromName, &winStart, &winEnd, hgTracksName(), dyWarn); +if (isNotEmpty(dyWarn->string)) + warn("%s", dyWarn->string); +if (hgp->singlePos) + { + createHgFindMatchHash(); + } +else + { + char *menuStr = menuBar(cart, database); + if (menuStr) + puts(menuStr); + hgPositionsHtml(database, hgp, hgTracksName(), cart); + resolved = FALSE; + } +cartSetString(cart, "position", *pPosition); +return resolved; +} + void parseVirtPosition(char *position) /* parse virtual position * TODO this is just temporary */ { if (!position) { errAbort("position NULL"); } char *vPos = cloneString(position); +stripChar(vPos, ','); char *colon = strchr(vPos, ':'); if (!colon) errAbort("position has no colon"); char *dash = strchr(vPos, '-'); if (!dash) errAbort("position has no dash"); *colon = 0; *dash = 0; virtWinStart = atol(colon+1) - 1; virtWinEnd = atol(dash+1); } void parseNonVirtPosition(char *position) /* parse non-virtual position */ { @@ -9064,94 +9087,63 @@ cartSetString(cart, "highlight", cartVar); } else { // erase the highlight cartvar if it has no overlap with the new virt chrom cartRemove(cart, "highlight"); } } } void tracksDisplay() /* Put up main tracks display. This routine handles zooming and * scrolling. */ { -char *defaultPosition = hDefaultPos(database); char titleVar[256]; char *oldPosition = cartUsualString(cart, "oldPosition", ""); boolean findNearest = cartUsualBoolean(cart, "findNearest", FALSE); cartRemove(cart, "findNearest"); boolean positionIsVirt = FALSE; position = getPositionFromCustomTracks(); if (NULL == position) { position = cartGetPosition(cart, database, &lastDbPosCart); if (sameOk(cgiOptionalString("position"), "lastDbPos")) { restoreSavedVirtPosition(); } if (startsWith("virt:", position)) { position = stripCommas(position); // sometimes the position string arrives with commas in it. positionIsVirt = TRUE; } } if (sameString(position, "")) { hUserAbort("Please go back and enter a coordinate range or a search term in the \"search term\" field.<br>For example: chr22:20100000-20200000.\n"); } if (!positionIsVirt) { - chromName = NULL; - winStart = 0; - if (isGenome(position) || NULL == - (hgp = findGenomePos(database, position, &chromName, &winStart, &winEnd, cart))) - { - if (winStart == 0) /* number of positions found */ - { - freeMem(position); - position = cloneString(cartUsualString(cart, "lastPosition", defaultPosition)); - hgp = findGenomePos(database, position, &chromName, &winStart, &winEnd,cart); - if (hgp != NULL && differentString(position, defaultPosition)) - cartSetString(cart, "position", position); - } - } - - /* After position is found set up hash of matches that should - be drawn with names highlighted for easy identification. */ - createHgFindMatchHash(); - - /* This means that no single result was found - I.e., multiple results may have been found and are printed out prior to this code*/ - if (NULL == chromName) - { - // In case user manually edits the browser location as described in #13009, - // revert the position. If they instead choose from the list as we expect, - // that will set the position to their choice. - // lastPosition gets set in cart.c - char *lastPosition = cartUsualString(cart, "lastPosition", hDefaultPos(database)); - cartSetString(cart, "position", lastPosition); + if (! resolvePosition(&position)) return; } - } - virtMode = cartUsualBoolean(cart, "virtMode", FALSE); /* Figure out basic dimensions of display. This * needs to be done early for the sake of the * zooming and dinking routines. */ setLayoutGlobals(); virtModeType = cartUsualString(cart, "virtModeType", virtModeType); if (positionIsVirt && virtualSingleChrom()) { // we need chromName to be set before initRegionList() gets called. position = cartUsualString(cart, "nonVirtPosition", ""); if (!sameString(position,"")) parseNonVirtPosition(position); @@ -9185,32 +9177,31 @@ if (nvh) cartSetString(cart, "highlight", nvh); if (!sameString(position,"")) parseNonVirtPosition(position); } if (initRegionList()) // initialize the region list, sets virtModeExtraState { break; } else { // virt mode failed, forced to return to default virtModeType = "default"; cartSetString(cart, "virtModeType", virtModeType); position = cloneString(hDefaultPos(database)); - hgp = findGenomePos(database, position, &chromName, &winStart, &winEnd, cart); - cartSetString(cart, "position", position); + resolvePosition(&position); positionIsVirt=FALSE; virtMode=FALSE; } } // PAD padding of exon regions is now being done inside the fetch/merge. //if (emPadding > 0) //padVirtRegions(emPadding); // this old routine does not handle multiple chroms yet //testRegionList(); // check if it is ascending non-overlapping regions. (this is not the case with custom user-defined-regions) makeVirtChrom(); //testVirtChromBinarySearch(); @@ -10243,31 +10234,31 @@ configPageSetTrackVis(-2); } else { tracksDisplay(); } if (cartVarExists(cart, "hgt.convertChromToVirtChrom")) { cartRemove(cart, "hgt.convertChromToVirtChrom"); return; } jsonObjectAdd(jsonForClient, "measureTiming", newJsonBoolean(measureTiming)); // js code needs to know if a highlightRegion is defined for this db -checkAddHighlight(); // call again in case tracksDisplay's call to findGenomePos changed vars +checkAddHighlight(); // call again in case tracksDisplay's call to resolvePosition changed vars char *highlightDef = cartOptionalString(cart, "highlight"); if (highlightDef && startsWith(database,highlightDef) && highlightDef[strlen(database)] == '.') jsonObjectAdd(jsonForClient, "highlight", newJsonString(highlightDef)); jsonObjectAdd(jsonForClient, "enableHighlightingDialog", newJsonBoolean(cartUsualBoolean(cart, "enableHighlightingDialog", TRUE))); struct dyString *dy = dyStringNew(1024); jsonDyStringPrint(dy, (struct jsonElement *) jsonForClient, "hgTracks", 0); jsInline(dy->string); dyStringFree(&dy); if (measureTiming) measureTime("Time at end of doMiddle, next up cart write"); if (cartOptionalString(cart, "udcTimeout"))