ebd00966c64d172c0013f67c5a603e2077d84c3c
kate
  Fri May 30 14:35:36 2014 -0700
Cleanup to isolate id/name mapping code.  refs #13230
diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c
index 605952c..d0f911b 100644
--- src/hg/hgc/hgc.c
+++ src/hg/hgc/hgc.c
@@ -1472,88 +1472,105 @@
 		char dbOnly[4096];
 
 		diff = comp2->start - (comp1->start + comp1->size);
 
 		safef(dbOnly, sizeof(dbOnly), "%s", comp1->src);
 		chopPrefix(dbOnly);
 		printf("%-20s %d\n",hOrganism(dbOnly), diff);
 		}
 
 	    printf("<BR>");
 	    }
         }
     }
 }
 
-void printIdOrLinks(struct asColumn *col, struct hash *fieldToUrl, struct trackDb *tdb, char *idList)
-/* if trackDb does not contain a "urls" entry for current column name, just print idList as it is.
- * Otherwise treat idList as a comma-sep list of IDs and print one row per id, with a link to url,
- * ($$ in url is OK, wildcards like $P, $p, are also OK)
- * */
-{
-// try to find a fieldName=url setting in the "urls" tdb statement, print id if not found
-char *url = NULL;
-if (fieldToUrl!=NULL)
-    url = (char*)hashFindVal(fieldToUrl, col->name);
-if (url==NULL)
+char **getIdNameMap(struct trackDb *tdb, struct asColumn *col, int *size)
+/* Allocate and fill an array mapping id to name.  Currently limited to specific columns. */
 {
-    printf("<td>%s</td></tr>\n", idList);
-    return;
-    }
-
-// handle id->name mapping for multi-source items
-char **idNames = NULL;
 char *idNameTable = trackDbSetting(tdb, "sourceTable");
-if (sameString("sourceIds", col->name) && idNameTable)
-    {
+if (!idNameTable || differentString("sourceIds", col->name))
+    return NULL;
+
 struct sqlResult *sr;
 char query[256];
 char **row;
+char **idNames;
+
 sqlSafef(query, sizeof(query), "select max(id) from %s", idNameTable);
 struct sqlConnection *conn = hAllocConnTrack(database, tdb);
 int maxId = sqlQuickNum(conn, query);
 AllocArray(idNames, maxId+1);
 sqlSafef(query, sizeof(query), "select id, name from %s", idNameTable);
 sr = sqlGetResult(conn, query);
 int id;
 while ((row = sqlNextRow(sr)) != NULL)
     {
     id = sqlUnsigned(row[0]);
     if (id > maxId)
         errAbort("Internal error:  id %d > maxId %d in %s", id, maxId, idNameTable);
     idNames[id] = cloneString(row[1]);
     }
 sqlFreeResult(&sr);
 hFreeConn(&conn);
+if (size)
+    *size = maxId+1;
+return idNames;
+}
+
+void printIdOrLinks(struct asColumn *col, struct hash *fieldToUrl, struct trackDb *tdb, char *idList)
+/* if trackDb does not contain a "urls" entry for current column name, just print idList as it is.
+ * Otherwise treat idList as a comma-sep list of IDs and print one row per id, with a link to url,
+ * ($$ in url is OK, wildcards like $P, $p, are also OK)
+ * */
+{
+// try to find a fieldName=url setting in the "urls" tdb statement, print id if not found
+char *url = NULL;
+if (fieldToUrl != NULL)
+    url = (char*)hashFindVal(fieldToUrl, col->name);
+if (url == NULL)
+    {
+    printf("<td>%s</td></tr>\n", idList);
+    return;
     }
 
 // split the id into parts and print each part as a link
 struct slName *slIds = slNameListFromComma(idList);
 struct slName *itemId = NULL;
+
+// handle id->name mapping for multi-source items
+int nameCount;
+char **idNames = getIdNameMap(tdb, col, &nameCount);
+
 printf("<td>");
 for (itemId = slIds; itemId!=NULL; itemId = itemId->next) 
     {
     if (itemId != slIds)
         printf(", ");
     char *itemName = itemId->name;
     if (idNames)
+        {
+        unsigned int id = sqlUnsigned(itemName);
+        if (id < nameCount)
             itemName = idNames[sqlUnsigned(itemName)];
+        }
     char *idUrl = replaceInUrl(tdb, url, trimSpaces(itemName), TRUE);
     printf("<a href=\"%s\" target=\"_blank\">%s</a>", idUrl, itemName);
     } 
 printf("</td></tr>\n");
 freeMem(slIds);
+//freeMem(idNames);
 }
 
 int extraFieldsPrint(struct trackDb *tdb,struct sqlResult *sr,char **fields,int fieldCount)
 // Any extra bed or bigBed fields (defined in as and occurring after N in bed N + types.
 // sr may be null for bigBeds.
 // Returns number of extra fields actually printed.
 {
 struct sqlConnection *conn = NULL ;
 if (!trackHubDatabase(database))
     conn = hAllocConnTrack(database, tdb);
 struct asObject *as = asForTdb(conn, tdb);
 hFreeConn(&conn);
 if (as == NULL)
     return 0;