5e8e0ed53c05f2ef9b51ce897440bae308367f47
chmalee
  Wed Feb 9 14:45:54 2022 -0800
Add csv output option to table browser to support opening files in
Excel, refs #27623. Also change the output filename message to hint
that Excel can auto-recognize .csv extensions and behave appropriately.
Lastly, fix output dropdown selection to properly warn on update
when using GTF output option or a snp table.

diff --git src/hg/hgTables/hic.c src/hg/hgTables/hic.c
index 1905826..ab36720 100644
--- src/hg/hgTables/hic.c
+++ src/hg/hgTables/hic.c
@@ -112,64 +112,72 @@
 assert(numPt < numBufEnd);
 }
 
 int hicCompare(const void *elem1, const void *elem2)
 /* Simple comparison function for sorting hic data in interact structures,
  * since it is not always returned in sorted order. */
 {
 const struct interact *first = *((struct interact **)elem1);
 const struct interact *second = *((struct interact **)elem2);
 int dif = strcmp(first->chrom, second->chrom);
 if (dif == 0)
     dif = first->chromStart - second->chromStart;
 return dif;
 }
 
-void hicTabOut(char *db, char *table, struct sqlConnection *conn, char *fields, FILE *f)
+void hicTabOut(char *db, char *table, struct sqlConnection *conn, char *fields, FILE *f, char outSep)
 /* Print out selected fields from hic.  If fields is NULL, then print out all fields. */
 {
 if (f == NULL)
     f = stdout;
 
 /* Convert comma separated list of fields to array. */
 int fieldCount = chopByChar(fields, ',', NULL, 0);
 char **fieldArray;
 AllocArray(fieldArray, fieldCount);
 chopByChar(fields, ',', fieldArray, fieldCount);
 
 /* Get list of all fields in hic and turn it into a hash of column indexes keyed by
  * column name. */
 struct hash *fieldHash = hashNew(0);
 struct slName *field, *fieldList = hicGetFields();
 int i;
 for (field = fieldList, i=0; field != NULL; field = field->next, ++i)
     {
     hashAddInt(fieldHash, field->name, i);
     }
 
 /* Create an array of column indexes corresponding to the selected field list. */
 int *columnArray;
 AllocArray(columnArray, fieldCount);
 for (i=0; i<fieldCount; ++i)
     {
     columnArray[i] = hashIntVal(fieldHash, fieldArray[i]);
     }
 
 /* Output row of labels */
-fprintf(f, "#%s", fieldArray[0]);
+fprintf(f, "#");
+if (outSep == ',') fputc('"', f);
+fprintf(f, "%s", fieldArray[0]);
+if (outSep == ',') fputc('"', f);
 for (i=1; i<fieldCount; ++i)
-    fprintf(f, "\t%s", fieldArray[i]);
+    {
+    fputc(outSep, f);
+    if (outSep == ',') fputc('"', f);
+    fprintf(f, "%s", fieldArray[i]);
+    if (outSep == ',') fputc('"', f);
+    }
 fprintf(f, "\n");
 
 struct asObject *as = interactAsObj();
 struct asFilter *filter = NULL;
 
 if (anyFilter())
     {
     filter = asFilterFromCart(cart, db, table, as);
     if (filter)
         {
 	fprintf(f, "# Filtering on %d columns\n", slCount(filter->columnList));
 	}
     }
 
 /* Loop through outputting each region */
@@ -190,33 +198,40 @@
     struct interact *results = NULL, *result = NULL;
     int res = hicUiFetchResolutionAsInt(cart, tdb, fileInfo, region->end-region->start);
     char *errMsg = hicLoadData(fileInfo, res, norm, region->chrom, region->start, region->end,
             region->chrom, region->start, region->end, &results);
     if (errMsg != NULL)
         warn("%s", errMsg);
     slSort(&results, &hicCompare);
     char *row[INTERACT_NUM_COLS];
     char numBuf[HIC_NUM_BUF_SIZE];
     for (result = results; result != NULL && (maxOut > 0); result = result->next)
         {
 	hicRecordToRow(result, numBuf, row);
 	if (asFilterOnRow(filter, row))
 	    {
 	    int i;
+            if (outSep == ',') fputc('"', f);
 	    fprintf(f, "%s", row[columnArray[0]]);
+            if (outSep == ',') fputc('"', f);
 	    for (i=1; i<fieldCount; ++i)
-		fprintf(f, "\t%s", row[columnArray[i]]);
+                {
+                fputc(outSep, f);
+                if (outSep == ',') fputc('"', f);
+		fprintf(f, "%s", row[columnArray[i]]);
+                if (outSep == ',') fputc('"', f);
+                }
 	    fprintf(f, "\n");
 	    maxOut --;
 	    }
 	}
     }
 freeMem(fileName);
 
 if (maxOut == 0)
     errAbort("Reached output limit of %d data values, please make region smaller,\n\tor set a higher output line limit with the filter settings.", bigFileMaxOutput());
 /* Clean up and exit. */
 hashFree(&fieldHash);
 freeMem(fieldArray);
 freeMem(columnArray);
 }