191a1172e19c7c124fbb09cbad05fcb2f2c0c726
jcasper
  Thu Jun 22 16:53:10 2017 -0700
Fixing position issue for hgHubConnect when changing assemblies, refs #13625

diff --git src/hg/hgHubConnect/hgHubConnect.c src/hg/hgHubConnect/hgHubConnect.c
index 4a1fabe..ab9c5bd 100644
--- src/hg/hgHubConnect/hgHubConnect.c
+++ src/hg/hgHubConnect/hgHubConnect.c
@@ -41,30 +41,31 @@
     struct hubOutputStructure *next;
     struct dyString *descriptionMatch;
     struct genomeOutputStructure *genomes;
     int genomeCount;
     struct hash *genomeOutHash;
     };
 
 struct genomeOutputStructure
     {
     struct genomeOutputStructure *next;
     struct dyString *shortLabel;
     struct dyString *descriptionMatch;
     struct tdbOutputStructure *tracks;
     struct dyString *assemblyLink;
     char *genomeName;
+    char *positionString;
     int trackCount;
     struct hash *tdbOutHash;
     int hitCount;
     };
 
 struct tdbOutputStructure
     {
     struct tdbOutputStructure *next;
     struct dyString *shortLabel;
     struct dyString *descriptionMatch;
     struct dyString *configUrl;
     struct tdbOutputStructure *children;
     int childCount;
     };
 
@@ -691,32 +692,32 @@
     struct trackDb *trackInfo = (struct trackDb *) hashFindVal(tdbHash, track);
     if (trackInfo == NULL)
         {
         // Some tracks are prefixed with the hub name; try that
         char withHubName[4096];
         safef(withHubName, sizeof(withHubName), "%s_%s", hub->name, track);
         trackInfo = hashMustFindVal(tdbHash, withHubName);
         }
     if (isNotEmpty(trackInfo->longLabel))
         dyStringPrintf(tdbOut->shortLabel, "%s", trackInfo->longLabel);
     else if (isNotEmpty(trackInfo->shortLabel))
         dyStringPrintf(tdbOut->shortLabel, "%s", trackInfo->shortLabel);
     else
         dyStringPrintf(tdbOut->shortLabel, "%s", trackHubSkipHubName(trackInfo->track));
 
-    dyStringPrintf(tdbOut->configUrl, "../cgi-bin/hgTrackUi?hubUrl=%s&db=%s&g=%s&hgsid=%s", hub->url,
-            genomeOut->genomeName, trackInfo->track, cartSessionId(cart));
+    dyStringPrintf(tdbOut->configUrl, "../cgi-bin/hgTrackUi?hubUrl=%s&db=%s&g=%s&hgsid=%s&%s", hub->url,
+            genomeOut->genomeName, trackInfo->track, cartSessionId(cart), genomeOut->positionString);
 
     if (trackInfo->parent != NULL)
         {
         struct trackDb *parent = trackInfo->parent;
         struct tdbOutputStructure *parentOut = addOrUpdateTrackOut(parent->track, genomeOut, tdbHash, hub);
         slAddTail(&(parentOut->children), tdbOut);
         parentOut->childCount++;
         }
     else
         slAddTail(&(genomeOut->tracks), tdbOut);
     hashAdd(genomeOut->tdbOutHash, track, tdbOut);
     }
 return tdbOut;
 }
 
@@ -730,30 +731,48 @@
     {
     hashAdd(tdbHash, tdb->track, tdb);
     if (tdb->subtracks != NULL)
         buildTdbHash(tdbHash, tdb->subtracks);
     if (tdb->parent != NULL)
         {
         // supertracks might be omitted from tdbList, but are still referred to by parent links
         if (hashFindVal(tdbHash, tdb->parent->track) == NULL)
             hashAdd(tdbHash, tdb->parent->track, tdb->parent);
         }
     tdb = tdb->next;
     }
 }
 
 
+char *getPositionStringForDb(struct trackHubGenome *genome)
+{
+char positionVar[1024];
+safef(positionVar, sizeof(positionVar), "position.%s", genome->name);
+char *position = cartOptionalString(cart, positionVar);
+if (position == NULL)
+    {
+    struct dyString *tmp = dyStringCreate("position=");
+    if (genome->defaultPos != NULL)
+        dyStringAppend(tmp, genome->defaultPos);
+    else
+        dyStringAppend(tmp, hDefaultPos(genome->name)); // memory leak from hDefaultPos return value
+    position = dyStringCannibalize(&tmp);
+    }
+return position;
+}
+
+
 struct hubOutputStructure *buildHubSearchOutputStructure(struct trackHub *hub,
         struct hubSearchText *searchResults)
 /* Build a structure that contains the data for writing out the hub search results for this hub */
 {
 struct hubOutputStructure *hubOut = NULL;
 AllocVar(hubOut);
 hubOut->descriptionMatch = dyStringNew(0);
 hubOut->genomeOutHash = newHash(5);
 
 struct hash *tdbHashHash = newHash(5);  // takes genome names to trackDb hashes
 
 struct hubSearchText *hst = NULL;
 for (hst = searchResults; hst != NULL; hst = hst->next)
     {
     if (isEmpty(hst->db))
@@ -771,32 +790,33 @@
     if (genome == NULL)
         {
         // assembly hub genomes are stored with a prefix; try that
         char withHubName[4096];
         safef(withHubName, sizeof(withHubName), "%s_%s", hub->name, db);
         genome = hashMustFindVal(hub->genomeHash, withHubName);
         }
     struct genomeOutputStructure *genomeOut = hashFindVal(hubOut->genomeOutHash, db);
     if (genomeOut == NULL)
         {
         AllocVar(genomeOut);
         genomeOut->tdbOutHash = newHash(5);
         genomeOut->descriptionMatch = dyStringNew(0);
         genomeOut->shortLabel = dyStringNew(0);
         genomeOut->assemblyLink = dyStringNew(0);
-        dyStringPrintf(genomeOut->assemblyLink, "../cgi-bin/hgTracks?hubUrl=%s&db=%s&hgsid=%s",
-                hub->url, genome->name, cartSessionId(cart));
+        genomeOut->positionString = getPositionStringForDb(genome);
+        dyStringPrintf(genomeOut->assemblyLink, "../cgi-bin/hgTracks?hubUrl=%s&db=%s&hgsid=%s&%s",
+                hub->url, genome->name, cartSessionId(cart), genomeOut->positionString);
         char *name = trackHubSkipHubName(genome->name);
         if (isNotEmpty(genome->description))
             dyStringPrintf(genomeOut->shortLabel, "%s (%s)", genome->description, name);
         else if (isNotEmpty(genome->organism))
             dyStringPrintf(genomeOut->shortLabel, "%s %s", genome->organism, name);
         else
             dyStringPrintf(genomeOut->shortLabel, "%s", name);
         genomeOut->genomeName = cloneString(genome->name);
         hashAdd(hubOut->genomeOutHash, db, genomeOut);
         slAddTail(&(hubOut->genomes), genomeOut);
         hubOut->genomeCount++;
         }
 
     if (isNotEmpty(hst->track))
         {