b8563b69c56541b075fa3cd397e9ce761ebf79b4 jnavarr5 Mon May 12 09:41:53 2025 -0700 Adding a NULL value for the extra parameter that was added for setContextSpecificHelp(), refs #35724 diff --git src/hg/near/hgNear/hgNear.c src/hg/near/hgNear/hgNear.c index cde2ff7cd25..fdc1c22aecc 100644 --- src/hg/near/hgNear/hgNear.c +++ src/hg/near/hgNear/hgNear.c @@ -1,2030 +1,2030 @@ /* hgNear - gene sorter. */ /* Copyright (C) 2013 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ #include "common.h" #include "linefile.h" #include "hash.h" #include "dystring.h" #include "obscure.h" #include "portable.h" #include "cheapcgi.h" #include "memalloc.h" #include "jksql.h" #include "htmshell.h" #include "hVarSubst.h" #include "cart.h" #include "dbDb.h" #include "hdb.h" #include "hui.h" #include "web.h" #include "ra.h" #include "hgColors.h" #include "hgNear.h" #include "versionInfo.h" #include "botDelay.h" /* for earlyBotCheck() function at the beginning of main() */ #define delayFraction 1.0 /* standard penalty is 1.0 for most CGIs */ static boolean issueBotWarning = FALSE; char *excludeVars[] = { "submit", "Submit", idPosVarName, NULL }; /* The excludeVars are not saved to the cart. (We also exclude * any variables that start "near.do.") */ /* ---- Global variables. ---- */ struct cart *cart; /* This holds cgi and other variables between clicks. */ struct hash *oldVars = NULL; /* The cart vars before new cgi stuff added. */ char *database; /* Name of genome database - hg15, mm3, or the like. */ char *genome; /* Name of genome - mouse, human, etc. */ char *groupOn; /* Current grouping strategy. */ int displayCount; /* Number of items to display. */ char *displayCountString; /* Ascii version of display count, including 'all'. */ struct hash *genomeSettings; /* Genome-specific settings from settings.ra. */ struct hash *columnHash; /* Hash of active columns keyed by name. */ struct genePos *curGeneId; /* Identity of current gene. */ int kgVersion = KG_UNKNOWN; /* KG version */ /* ---- General purpose helper routines. ---- */ int genePosCmpName(const void *va, const void *vb) /* Sort function to compare two genePos by name. */ { const struct genePos *a = *((struct genePos **)va); const struct genePos *b = *((struct genePos **)vb); return strcmp(a->name, b->name); } int genePosCmpPos(const void *va, const void *vb) /* Sort function to compare two genePos by chrom,start. */ { const struct genePos *a = *((struct genePos **)va); const struct genePos *b = *((struct genePos **)vb); int diff = strcmp(a->chrom, b->chrom); if (diff == 0) diff = a->start - b->start; return diff; } void genePosFillFrom5(struct genePos *gp, char **row) /* Fill in genePos from row containing ascii version of * name/chrom/start/end/protein. */ { gp->name = cloneString(row[0]); gp->chrom = cloneString(row[1]); gp->start = sqlUnsigned(row[2]); gp->end = sqlUnsigned(row[3]); gp->protein = cloneString(row[4]); gp->distance = genePosTooFar; } int genePosCmpDistance(const void *va, const void *vb) /* Compare to sort based on distance. */ { const struct genePos *a = *((struct genePos **)va); const struct genePos *b = *((struct genePos **)vb); float diff = a->distance - b->distance; if (diff > 0) return 1; else if (diff < 0) return -1; else { return strcmp(a->protein, b->protein); } } boolean wildMatchAny(char *word, struct slName *wildList) /* Return TRUE if word matches any thing in wildList. */ { struct slName *w; for (w = wildList; w != NULL; w = w->next) if (wildMatch(w->name, word) ) return TRUE; return FALSE; } boolean wildMatchAll(char *word, struct slName *wildList) /* Return TRUE if word matches all things in wildList. */ { struct slName *w; for (w = wildList; w != NULL; w = w->next) if (!wildMatch(w->name, word) ) return FALSE; return TRUE; } boolean wildMatchList(char *word, struct slName *wildList, boolean orLogic) /* Return TRUE if word matches things in wildList. */ { if (orLogic) return wildMatchAny(word, wildList); else return wildMatchAll(word, wildList); } boolean anyRealInCart(struct cart *cart, char *wild) /* Return TRUE if variables are set matching wildcard. */ { struct hashEl *varList = NULL, *var; boolean ret = FALSE; varList = cartFindLike(cart, wild); for (var = varList; var != NULL; var = var->next) { char *s = var->val; if (s != NULL) { s = trimSpaces(s); if (s[0] != 0) { ret = TRUE; break; } } } hashElFreeList(&varList); return ret; } void fixSafariSpaceInQuotes(char *s) /* Safari on the Mac changes a space (ascii 32) to a * ascii 160 if it's inside of a single-quote in a * text input box!? This tuns it back to a 32. */ { unsigned char c; while ((c = *s) != 0) { if (c == 160) *s = 32; ++s; } } void makeTitle(char *title, char *helpName) /* Print main menu and the title bar. */ { char buf[1024]; if(!helpName) helpName = "hgNearHelp.html"; safef(buf, sizeof(buf), "../goldenPath/help/%s", helpName); -setContextSpecificHelp(buf, NULL); +setContextSpecificHelp(buf, NULL, NULL); cartWebStart(cart, database, "%s", title); } /* ---- Some helper routines for order methods. ---- */ char *orderSetting(struct order *ord, char *name, char *defaultVal) /* Return value of named setting in order, or default if it doesn't exist. */ { char *result = hashFindVal(ord->settings, name); if (result == NULL) result = defaultVal; return result; } char *orderRequiredSetting(struct order *ord, char *name) /* Return value of named setting. Abort if it doesn't exist. */ { char *result = hashFindVal(ord->settings, name); if (result == NULL) errAbort("Missing required %s field in %s record of orderDb.ra", name, ord->name); return result; } int orderIntSetting(struct order *ord, char *name, int defaultVal) /* Return value of named integer setting or default if it doesn't exist. */ { char *result = hashFindVal(ord->settings, name); if (result == NULL) return defaultVal; return atoi(result); } boolean orderSettingExists(struct order *ord, char *name) /* Return TRUE if setting exists in column. */ { return hashFindVal(ord->settings, name) != NULL; } /* ---- Some helper routines for column methods. ---- */ char *columnSetting(struct column *col, char *name, char *defaultVal) /* Return value of named setting in column, or default if it doesn't exist. */ { char *result = hashFindVal(col->settings, name); if (result == NULL) result = defaultVal; return result; } char *columnRequiredSetting(struct column *col, char *name) /* Return value of named setting. Abort if it doesn't exist. */ { char *result = hashFindVal(col->settings, name); if (result == NULL) errAbort("Missing required %s field in %s record of columnDb.ra", name, col->name); return result; } int columnSettingInt(struct column *col, char *name, int defaultVal) /* Return value of named integer setting or default if it doesn't exist. */ { char *result = hashFindVal(col->settings, name); if (result == NULL) return defaultVal; return atoi(result); } boolean columnSettingExists(struct column *col, char *name) /* Return TRUE if setting exists in column. */ { return hashFindVal(col->settings, name) != NULL; } struct sqlConnection *hgFixedConn() /* Return connection to hgFixed database. * This is effectively a global, but not * opened until needed. */ { static struct sqlConnection *conn = NULL; if (conn == NULL) conn = sqlConnect("hgFixed"); return conn; } char *colVarName(struct column *col, char *prefix) /* Return variable name prefix.col->name. This is just a static * variable, so don't nest these calls*/ { static char name[64]; safef(name, sizeof(name), "%s%s", prefix, col->name); return name; } void colButton(struct column *col, char *prefix, char *label) /* Make a button named prefix.col->name with given label. */ { static char name[64]; safef(name, sizeof(name), "%s%s", prefix, col->name); cgiMakeButton(name, label); } struct column *colButtonPressed(struct column *colList, char *prefix) /* See if a button named prefix.column is pressed for some * column, and if so return the column, else NULL. */ { static char pattern[64]; char colName[64]; char *match; safef(pattern, sizeof(pattern), "%s*", prefix); match = cartFindFirstLike(cart, pattern); if (match == NULL) return NULL; /* Construct column name. If variable is from an file upload * there __filename suffix attached that we need to remove. */ safef(colName, sizeof(colName), "%s", match + strlen(prefix)); if (endsWith(colName, "__filename")) { int newLen = strlen(colName) - strlen("__filename"); colName[newLen] = 0; } return findNamedColumn(colName); } static char *keyFileName(struct column *col) /* Return key file name for this column. Return * NULL if no key file. */ { char *fileName = advFilterVal(col, "keyFile"); if (fileName == NULL) return NULL; if (!fileExists(fileName)) { cartRemove(cart, advFilterName(col, "keyFile")); return NULL; } return fileName; } struct slName *keyFileList(struct column *col) /* Make up list from key file for this column. * return NULL if no key file. */ { char *fileName = keyFileName(col); char *buf; struct slName *list; if (fileName == NULL) return NULL; readInGulp(fileName, &buf, NULL); list = stringToSlNames(buf); freez(&buf); return list; } static struct hash *upcHashWordsInFile(char *fileName, int hashSize) /* Create a hash of space delimited uppercased words in file. */ { struct hash *hash = newHash(hashSize); struct lineFile *lf = lineFileOpen(fileName, TRUE); char *line, *word; while (lineFileNext(lf, &line, NULL)) { while ((word = nextQuotedWord(&line)) != NULL) { touppers(word); hashAdd(hash, word, NULL); } } lineFileClose(&lf); return hash; } struct hash *keyFileHash(struct column *col) /* Make up a hash from key file for this column. * Return NULL if no key file. */ { char *fileName = keyFileName(col); if (fileName == NULL) return NULL; return upcHashWordsInFile(fileName, 16); } char *cellLookupVal(struct column *col, struct genePos *gp, struct sqlConnection *conn) /* Get a field in a table defined by col->table, col->keyField, * col->valField. If an xrefLookup is specified in col->settings, * use that to look up an alternate name for the result. */ { char *xrefDb = hashFindVal(col->settings, "xrefDb"); char *xrefTable = hashFindVal(col->settings, "xrefTable"); char *xrefNameField = hashFindVal(col->settings, "xrefNameField"); char *xrefAliasField = hashFindVal(col->settings, "xrefAliasField"); char query[1024]; if (xrefDb) sqlSafef(query, sizeof(query), "select %s.%s.%s " "from %s.%s, %s " "where %s.%s = '%s' " "and %s.%s = %s.%s.%s;", xrefDb, xrefTable, xrefAliasField, xrefDb, xrefTable, col->table, col->table, col->keyField, gp->name, col->table, col->valField, xrefDb, xrefTable, xrefNameField); else sqlSafef(query, sizeof(query), "select %s from %s where %s = '%s'", col->valField, col->table, col->keyField, gp->name); return sqlQuickString(conn, query); } char *lookupItemUrlVal(struct column *col, char *sVal, struct sqlConnection *conn) { char query[512]; sqlSafef(query, sizeof(query), col->itemUrlQuery, sVal); return sqlQuickString(conn, query); } void cellSimplePrintExt(struct column *col, struct genePos *gp, struct sqlConnection *conn, boolean lookupForUrl) /* This just prints one field from table. */ { char *s = col->cellVal(col, gp, conn); hPrintf("
"); /* Theabove helps Internet Explorer avoid wrapping * in the label column, which helps us avoid wrapping in * the data columns below. Wrapping in the data columns * makes the expression display less effective so we try * to minimize it. -jk */ if (colWidth == 0) { colInfoLink(col); } else { int labelLen = strlen(col->shortLabel); int diff = colWidth - labelLen; if (diff < 0) diff = 0; colInfoLink(col); hPrintSpaces(diff); } hPrintf("
");
hPrintf("
|
"); else col->cellPrint(col,gene,conn); } } hPrintf(" |
"); /* Print labels. */ hPrintf("#"); for (col = colList; col != NULL; col = col->next) { if (col->on) { if (first) first = FALSE; else hPrintf("\t"); hPrintf("%s", col->name); } } hPrintf("\n"); for (gene = geneList; gene != NULL; gene = gene->next) { first = TRUE; for (col = colList; col != NULL; col = col->next) { if (col->on) { char *val = col->cellVal(col, gene, conn); if (first) first = FALSE; else hPrintf("\t"); if (val == NULL) hPrintf("n/a"); else hPrintf("%s", val); freez(&val); } } hPrintf("\n"); } hPrintf(""); } void doMainDisplay(struct sqlConnection *conn, struct order *ord, struct order *ordList, struct column *colList, struct genePos *geneList) /* Put up the main gene sorter display - a control panel followed by * a big table. */ { cartWebStart(cart, database, "UCSC %s Gene Sorter", genome); hPrintf("\n"); hPrintf(""); } struct order *curOrder(struct order *ordList) /* Get ordering currently selected by user, or default * (first in list) if none selected. */ { char *selName; struct order *ord; if (ordList == NULL) errAbort("No orderings available"); selName = cartUsualString(cart, orderVarName, ordList->name); for (ord = ordList; ord != NULL; ord = ord->next) { if (sameString(ord->name, selName)) return ord; } return ordList; } char *lookupProtein(struct sqlConnection *conn, char *mrnaName) /* Given mrna name look up protein. FreeMem result when done. */ { char query[256]; char buf[64]; if (kgVersion == KG_III) { sqlSafef(query, sizeof(query), "select spDisplayID from kgXref where kgId='%s'", mrnaName); } else { sqlSafef(query, sizeof(query), "select protein from %s where transcript='%s'", genomeSetting("canonicalTable"), mrnaName); } if (!sqlQuickQuery(conn, query, buf, sizeof(buf))) return NULL; return cloneString(buf); } void displayData(struct sqlConnection *conn, struct column *colList, struct genePos *gp) /* Display data in neighborhood of gene. */ { struct genePos *geneList = NULL; struct order *ordList = orderGetAll(conn); struct order *ord = curOrder(ordList); if (gp != NULL && gp->protein == NULL) gp->protein = lookupProtein(conn, gp->name); curGeneId = gp; if (cartVarExists(cart, getTextVarName)) { if (gp) geneList = getOrderedList(ord, colList, conn, BIGNUM); doGetText(conn, colList, geneList); } else if (cartVarExists(cart, getSeqVarName)) { if (gp) geneList = getOrderedList(ord, colList, conn, BIGNUM); doGetSeq(conn, colList, geneList, cartString(cart, getSeqHowVarName)); } else if (cartVarExists(cart, getGenomicSeqVarName)) { if (gp) geneList = getOrderedList(ord, colList, conn, BIGNUM); doGetGenomicSeq(conn, colList, geneList); } else { if (gp) geneList = getOrderedList(ord, colList, conn, displayCount); doMainDisplay(conn, ord, ordList, colList, geneList); } } static struct genePos *curGenePos() /* Return current gene pos from cart variables. */ { struct genePos *gp; AllocVar(gp); gp->name = cloneString(cartString(cart, idVarName)); /* Update cart's searchVarName to idVarName so that subsequent clicks will * have the right value in orgForm's searchVarName. */ cartSetString(cart, searchVarName, gp->name); if (cartVarExists(cart, idPosVarName)) { hgParseChromRange(database, cartString(cart, idPosVarName), &gp->chrom, &gp->start, &gp->end); gp->chrom = cloneString(gp->chrom); } return gp; } void doFixedId(struct sqlConnection *conn, struct column *colList) /* Put up the main page based on id/idPos. */ { displayData(conn, colList, curGenePos()); } static char *colHtmlFileName(struct column *col) /* Return html file associated with column. You can * freeMem this when done. */ { char name[PATH_LEN]; char *org = hgDirForOrg(genome); safef(name, sizeof(name), "%s/%s/%s/%s.html", rootDir, org, database, col->name); if (!fileExists(name)) { safef(name, sizeof(name), "%s/%s/%s.html", rootDir, org, col->name); if (!fileExists(name)) safef(name, sizeof(name), "%s/%s.html", rootDir, col->name); } freez(&org); return cloneString(name); } void doColInfo(struct sqlConnection *conn, struct column *colList, char *colName) /* Put up info page on column. */ { struct column *col = findNamedColumn(colName); char buf[1024]; char *htmlFileName; if (col == NULL) errAbort("Can't find column '%s'", colName); safef(buf, sizeof(buf), "Column %s - %s", col->shortLabel, col->longLabel); makeTitle(buf, NULL); htmlFileName = colHtmlFileName(col); if (fileExists(htmlFileName)) { char *html; readInGulp(htmlFileName, &html, NULL); hVarSubstInVar(colName, NULL,database, &html); hPrintf("%s", html); freez(&html); } else { hPrintf("No additional info available on %s column", col->shortLabel); } freeMem(htmlFileName); } static char *defaultHgNearDb(char *genome) /* Return default database for hgNear for given * genome (or NULL for default genome.) * You can freeMem the returned value when done. */ { char *dbName = NULL; struct dbDb *db = NULL, *dbList = NULL; if (genome != NULL) { dbName = hDefaultDbForGenome(genome); if (dbName != NULL && hgNearOk(dbName)) return dbName; freez(&dbName); // Find first db with given genome and hgNearOk in ordered list: dbList = hGetIndexedDatabases(); for (db = dbList; db != NULL; db = db->next) { if (sameString(genome, db->genome) && db->hgNearOk) { dbName = cloneString(db->name); dbDbFree(&dbList); return dbName; } } } freez(&dbName); dbName = hDefaultDb(); if (dbName != NULL && hgNearOk(dbName)) return dbName; freez(&dbName); // Find first db with hgNearOk in ordered list: if (dbList == NULL) dbList = hGetIndexedDatabases(); for (db = dbList; db != NULL; db = db->next) { if (db->hgNearOk) { dbName = cloneString(db->name); break; } } dbDbFree(&dbList); return dbName; } static void makeSureDbHasHgNear() /* Check that current database supports hgNear. * If not try to find one that does. */ { if (hgNearOk(database)) return; else { database = defaultHgNearDb(genome); if (database == NULL) errAbort("No databases are supporting hgNear."); genome = hGenome(database); cartSetString(cart, dbVarName, database); cartSetString(cart, orgVarName, genome); } } void doMiddle(struct cart *theCart) /* Write the middle parts of the HTML page. * This routine sets up some globals and then * dispatches to the appropriate page-maker. */ { /* Using earlyBotCheck() at the beginning of main() to output message here if in delay time */ if (issueBotWarning) { char *ip = getenv("REMOTE_ADDR"); botDelayMessage(ip, botDelayMillis); } if (hIsBrowserbox()) { printf("The Gene Sorter is not supported on the Genome Browser in a Box Virtual Machine.
"); printf("Please use this tool on the UCSC website
"); return; } char *var = NULL; struct sqlConnection *conn; struct column *colList, *col; cart = theCart; getDbAndGenome(cart, &database, &genome, oldVars); makeSureDbHasHgNear(); getGenomeSettings(); char *knownDb = hdbDefaultKnownDb(database); conn = hAllocConn(knownDb); /* if kgProtMap2 table exists, this means we are doing KG III */ if (hTableExists(database, "kgProtMap2")) kgVersion = KG_III; /* Get groupOn. Revert to default if no advanced filter. */ groupOn = cartUsualString(cart, groupVarName, "expression"); displayCountString = cartUsualString(cart, countVarName, "50"); if (sameString(displayCountString, "all")) displayCount = BIGNUM; else displayCount = atoi(displayCountString); colList = getColumns(conn); /* Main dispatch logic on near.do.XXXX */ if (cartVarExists(cart, confVarName)) doConfigure(conn, colList, NULL); else if (cartVarExists(cart, colInfoVarName)) doColInfo(conn, colList, cartString(cart, colInfoVarName)); else if ((var = cartFindFirstLike(cart, "near.do.up.*")) != NULL) { doConfigure(conn, colList, var); } else if ((var = cartFindFirstLike(cart, "near.do.down.*")) != NULL) { doConfigure(conn, colList, var); } else if (cartVarExists(cart, defaultConfName)) doDefaultConfigure(conn, colList); else if (cartVarExists(cart, hideAllConfName)) doConfigHideAll(conn, colList); else if (cartVarExists(cart, showAllConfName)) doConfigShowAll(conn, colList); else if (cartVarExists(cart, saveCurrentConfName)) doNameCurrentColumns(); else if (cartVarExists(cart, savedCurrentConfName)) doSaveCurrentColumns(conn, colList); else if (cartVarExists(cart, useSavedConfName)) doConfigUseSaved(conn, colList); else if (cartVarExists(cart, filSaveCurrentVarName)) doNameCurrentFilters(); else if (cartVarExists(cart, filSavedCurrentVarName)) doSaveCurrentFilters(conn, colList); else if (cartVarExists(cart, filUseSavedVarName)) doUseSavedFilters(conn, colList); else if (cartVarExists(cart, advFilterVarName)) doAdvFilter(conn, colList); else if (cartVarExists(cart, advFilterClearVarName)) doAdvFilterClear(conn, colList); else if (cartVarExists(cart, advFilterListVarName)) doAdvFilterList(conn, colList); else if (cartVarExists(cart, getSeqPageVarName)) doGetSeqPage(conn, colList); else if (cartVarExists(cart, idVarName)) doFixedId(conn, colList); else if ((col = advFilterKeyPastePressed(colList)) != NULL) doAdvFilterKeyPaste(conn, colList, col); else if ((col = advFilterKeyPastedPressed(colList)) != NULL) doAdvFilterKeyPasted(conn, colList, col); else if ((col = advFilterKeyUploadPressed(colList)) != NULL) doAdvFilterKeyUpload(conn, colList, col); else if ((col = advFilterKeyClearPressed(colList)) != NULL) doAdvFilterKeyClear(conn, colList, col); else if (cartVarExists(cart, customPageDoName)) doCustomPage(conn, colList); else if (cartVarExists(cart, customSubmitDoName)) doCustomSubmit(conn, colList); else if (cartVarExists(cart, customClearDoName)) doCustomClear(conn, colList); else if (cartVarExists(cart, customPasteDoName)) doCustomPaste(conn, colList); else if (cartVarExists(cart, customUploadDoName)) doCustomUpload(conn, colList); else if (cartVarExists(cart, customFromUrlDoName)) doCustomFromUrl(conn, colList); else if (cartVarExists(cart, orderInfoDoName)) doOrderInfo(conn); else if (cartVarExists(cart, affineAliVarName)) doAffineAlignment(conn); else if (cartNonemptyString(cart, searchVarName)) doSearch(conn, colList); else if (gotAdvFilter()) displayData(conn, colList, knownPosFirst(conn)); else doExamples(conn, colList); hFreeConn(&conn); cartRemovePrefix(cart, "near.do."); cartWebEnd(); } void usage() /* Explain usage and exit. */ { errAbort( "hgNear - gene sorter - a cgi script\n" "usage:\n" " hgNear\n" ); } int main(int argc, char *argv[]) /* Process command line. */ { long enteredMainTime = clock1000(); // pushCarefulMemHandler(100000000); issueBotWarning = earlyBotCheck(enteredMainTime, "hgNear", delayFraction, 0, 0, "html"); cgiSpoof(&argc, argv); htmlSetStyle(htmlStyleUndecoratedLink); htmlSetBgColor(HG_CL_OUTSIDE); oldVars = hashNew(10); cartEmptyShell(doMiddle, hUserCookie(), excludeVars, oldVars); cgiExitTime("hgNear", enteredMainTime); return 0; }