46169b41deecd48121198e1911c41dc0a3f96b47
chmalee
  Tue Jan 19 18:12:04 2021 -0800
Allow variable size data tables on hgc. Allow these tables to be JSON or
pipe and semi-colon encoded. Add more support for external data
references in bigBeds: allow relevant trackDb settings like
skipEmptyFields, allow variable size tables in external files, allow
gzip compressed external files.

diff --git src/hg/hgc/hgc.h src/hg/hgc/hgc.h
index 7090f02..e4f7027 100644
--- src/hg/hgc/hgc.h
+++ src/hg/hgc/hgc.h
@@ -43,30 +43,40 @@
 #include "bedDetail.h"
 #endif
 
 #include "hgdpGeo.h"
 #include "dnaMotif.h"
 
 extern struct cart *cart;	/* User's settings. */
 extern char *seqName;		/* Name of sequence we're working on. */
 extern int winStart, winEnd;    /* Bounds of sequence. */
 extern char *database;		/* Name of mySQL database. */
 extern char *organism;		/* Colloquial name of organism. */
 extern char *genome;		/* common name, e.g. Mouse, Human */
 extern char *scientificName;	/* Scientific name of organism. */
 extern struct hash *trackHash;	/* A hash of all tracks - trackDb valued */
 
+// A helper struct for allowing variable sized user defined tables. Each table
+// is encoded in one field of the bigBed with '|' as column separators and ';' as
+// field separators.
+struct embeddedTbl
+{
+    struct embeddedTbl *next; // the next custom table
+    char *field; // field name from bigBed, used as title when title is NULL
+    char *title; // title of the table from trackDb, may be NULL
+    char *encodedTbl; // contents of field in bigBed
+};
 
 void hgcStart(char *title);
 /* Print out header of web page with title.  Set
  * error handler to normal html error handler. */
 
 char *hgcPath();
 /* Return path of this CGI script. */
 
 char *hgcPathAndSettings();
 /* Return path with this CGI script and session state variable. */
 
 void hgcAnchorSomewhere(char *group, char *item, char *other, char *chrom);
 /* Generate an anchor that calls click processing program with item
  * and other parameters. */
 
@@ -507,43 +517,59 @@
 
 void printIframe(struct trackDb *tdb, char *itemName);
 /* print an iframe with the URL specified in trackDb (iframeUrl), can have
  * the standard codes in it (like $$ for itemName, etc) */
 
 char *getIdInUrl(struct trackDb *tdb, char *itemName);
 /* If we have an idInUrlSql tag, look up itemName in that, else just
  * return itemName. */
 
 struct slPair* getExtraFields(struct trackDb *tdb, char **fields, int fieldCount);
 /* return the extra field names and their values as a list of slPairs */
 
 struct slPair *getFields(struct trackDb *tdb, char **fields);
 /* return field names and their values as a list of slPairs.  */
 
+void printEmbeddedTable(struct trackDb *tdb, struct embeddedTbl *embeddedTblList,
+                        struct dyString *tableLabelsDy);
+/* Pretty print a '|' and ';' encoded table or a JSON encoded table from a bigBed field.
+ * The JSON encoded tables get passed through as json so hgc.js can build them instead,
+ * which preserves the table order */
+
+void getExtraTableFields(struct trackDb *tdb, struct slName **retFieldNames, struct embeddedTbl **retEmbeddedTblList, struct hash *fieldsToEmbeddedTbl);
+/* Parse the trackDb field "extraTableFields" into the field names and titles specified,
+ * and fill out a hash keyed on the bigBed field name (which may be in an external file
+ * and not in the bigBed itself) to a helper struct for storing user defined tables. */
+
 int extraFieldsPrintAs(struct trackDb *tdb,struct sqlResult *sr,char **fields,int fieldCount, struct asObject *as);
 // 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.
 
 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 slPair *parseDetailsTablUrls(struct trackDb *tdb);
 /* Parse detailsTabUrls setting string into an slPair list of {offset column name, fileOrUrl} */
 
+char *readOneLineMaybeBgzip(char *fileOrUrl, bits64 offset, bits64 len);
+/* If fileOrUrl is bgzip-compressed and indexed, then use htslib's bgzf functions to
+ * retrieve uncompressed data from offset; otherwise (plain text) use udc. If len is 0,
+ * read up to next '\n' delimiter. */
+
 #define NUCCORE_SEARCH "https://www.ncbi.nlm.nih.gov/sites/entrez?db=nuccore&cmd=search&term="
 
 void doJRepeat (struct trackDb *tdb, char *repeat);
 /* New RepeatMasker Visualization defined in joinedRmskClick.c */
 
 INLINE char* strOrNbsp(char* val)
 /* return val if not empty otherwise HTML entity   */
 {
 return isEmpty(val) ? " " : val;
 }
 
 void doInteractDetails(struct trackDb *tdb, char *item);
 /* Details of interaction item */
 
 #endif