32f3679e82b8a42fe2c532219fcfb35be6b1ed28
kent
  Tue Feb 24 10:53:27 2015 -0800
Adding context parameter to wraps.  Minor polish here and there.

diff --git src/hg/lib/tablesTables.c src/hg/lib/tablesTables.c
index a57c2bc..7b1a444 100644
--- src/hg/lib/tablesTables.c
+++ src/hg/lib/tablesTables.c
@@ -17,32 +17,30 @@
 struct fieldedTable *fieldedTableFromDbQuery(struct sqlConnection *conn, char *query)
 /* Return fieldedTable from a database query */
 {
 struct sqlResult *sr = sqlGetResult(conn, query);
 char **fields;
 int fieldCount = sqlResultFieldArray(sr, &fields);
 struct fieldedTable *table = fieldedTableNew(query, fields, fieldCount);
 char **row;
 int i = 0;
 while ((row = sqlNextRow(sr)) != NULL)
     fieldedTableAdd(table, row, fieldCount, ++i);
 sqlFreeResult(&sr);
 return table;
 }
 
-typedef void webTableOutputWrapperType(char *tag, char *val);
-
 static void showTableFilterInstructionsEtc(struct fieldedTable *table, 
     char *itemPlural, struct  fieldedTableSegment *largerContext)
 /* Print instructional text, and basic summary info on who passes filter, and a submit
  * button just in case user needs it */
 {
 /* Print info on matching */
 int matchCount = slCount(table->rowList);
 if (largerContext != NULL)  // Need to page?
      matchCount = largerContext->tableSize;
 printf(" %d %s found. ", matchCount, itemPlural);
 cgiMakeButton("submit", "update");
 
 
 printf("<BR>\n");
 printf("First row of table below, above labels, can be used to filter individual fields. ");    
@@ -110,31 +108,31 @@
 /* Sort on field */
 if (!isEmpty(orderFields))
     {
     boolean doReverse = FALSE;
     char *field = orderFields;
     if (field[0] == '-')
         {
 	field += 1;
 	doReverse = TRUE;
 	}
     fieldedTableSortOnField(table, field, doReverse);
     }
 }
 
 static void showTableDataRows(struct fieldedTable *table, int pageSize, int maxLenField,
-    struct hash *tagOutputWrappers)
+    struct hash *tagOutputWrappers, void *wrapperContext)
 /* Render data rows into HTML */
 {
 int count = 0;
 struct fieldedRow *row;
 for (row = table->rowList; row != NULL; row = row->next)
     {
     if (++count > pageSize)
          break;
     printf("<TR>\n");
     int fieldIx = 0;
     for (fieldIx=0; fieldIx<table->fieldCount; ++fieldIx)
 	{
 	char shortVal[maxLenField+1];
 	char *val = emptyForNull(row->row[fieldIx]);
 	int valLen = strlen(val);
@@ -144,31 +142,31 @@
 		{
 		memcpy(shortVal, val, maxLenField-3);
 		shortVal[maxLenField-3] = 0;
 		strcat(shortVal, "...");
 		val = shortVal;
 		}
 	    }
 	webPrintLinkCellStart();
 	boolean printed = FALSE;
 	if (tagOutputWrappers != NULL && !isEmpty(val))
 	    {
 	    char *field = table->fields[fieldIx];
 	    webTableOutputWrapperType *printer = hashFindVal(tagOutputWrappers, field);
 	    if (printer != NULL)
 		{
-		printer(field, val);
+		printer(table, row, field, val, wrapperContext);
 		printed = TRUE;
 		}
 	    
 	    }
 	if (!printed)
 	    printf("%s", val);
 	webPrintLinkCellEnd();
 	}
     printf("</TR>\n");
     }
 }
 
 static void showTablePaging(struct fieldedTable *table, struct cart *cart, char *varPrefix,
     struct fieldedTableSegment *largerContext, int pageSize)
 /* If larger context exists and is bigger than current display, then draw paging controls. */
@@ -183,79 +181,80 @@
 
 	printf("Displaying page ");
 
 	char pageVar[64];
 	safef(pageVar, sizeof(pageVar), "%s_page", varPrefix);
 	cgiMakeIntVar(pageVar, curPage+1, 3);
 
 	printf(" of %d", totalPages);
 	}
      }
 }
 
 
 void webFilteredFieldedTable(struct cart *cart, struct fieldedTable *table, 
     char *returnUrl, char *varPrefix,
-    int maxLenField, struct hash *tagOutputWrappers, 
+    int maxLenField, struct hash *tagOutputWrappers, void *wrapperContext,
     boolean withFilters, char *itemPlural, 
     int pageSize, struct fieldedTableSegment *largerContext)
 /* Show a fielded table that can be sorted by clicking on column labels and optionally
  * that includes a row of filter controls above the labels .
  * The maxLenField is maximum character length of field before truncation with ...
  * Pass in 0 for no max */
 {
 if (strchr(returnUrl, '?') == NULL)
      errAbort("Expecting returnUrl to include ? in showFieldedTable\nIt's %s", returnUrl);
 
 
 if (withFilters)
     showTableFilterInstructionsEtc(table, itemPlural, largerContext);
 
 /* Set up our table within table look. */
 webPrintLinkTableStart();
 
 /* Draw optional filters cells ahead of column labels*/
 if (withFilters)
     showTableFilterControlRow(table, cart, varPrefix, maxLenField);
 
 showTableSortingLabelRow(table, cart, varPrefix, returnUrl);
-showTableDataRows(table, pageSize, maxLenField, tagOutputWrappers);
+showTableDataRows(table, pageSize, maxLenField, tagOutputWrappers, wrapperContext);
 
 /* Get rid of table within table look */
 webPrintLinkTableEnd();
 
 if (largerContext != NULL)
     showTablePaging(table, cart, varPrefix, largerContext, pageSize);
 }
 
 void webSortableFieldedTable(struct cart *cart, struct fieldedTable *table, 
     char *returnUrl, char *varPrefix,
-    int maxLenField, struct hash *tagOutputWrappers)
+    int maxLenField, struct hash *tagOutputWrappers, void *wrapperContext)
 /* Display all of table including a sortable label row.  The tagOutputWrappers
  * is an optional way to enrich output of specific columns of the table.  It is keyed
  * by column name and has for values functions of type webTableOutputWrapperType. */
 {
 webFilteredFieldedTable(cart, table, returnUrl, varPrefix, 
-    maxLenField, tagOutputWrappers, 
+    maxLenField, tagOutputWrappers, wrapperContext,
     FALSE, NULL, 
     slCount(table->rowList), NULL);
 }
 
 
 void webFilteredSqlTable(struct cart *cart, struct sqlConnection *conn, 
     char *fields, char *from, char *initialWhere,  
-    char *returnUrl, char *varPrefix, int maxFieldWidth, struct hash *tagOutWrappers,
+    char *returnUrl, char *varPrefix, int maxFieldWidth, 
+    struct hash *tagOutWrappers, void *wrapperContext,
     boolean withFilters, char *itemPlural, int pageSize)
 /* Given a query to the database in conn that is basically a select query broken into
  * separate clauses, construct and display an HTML table around results. This HTML table has
  * column names that will sort the table, and optionally (if withFilters is set)
  * it will also allow field-by-field wildcard queries on a set of controls it draws above
  * the labels. 
  *    Much of the functionality rests on the call to webFilteredFieldedTable.  This function
  * does the work needed to bring in sections of potentially huge results sets into
  * the fieldedTable. */
 {
 /* Construct select, from and where clauses in query, keeping an additional copy of where */
 struct dyString *query = dyStringNew(0);
 struct dyString *where = dyStringNew(0);
 struct slName *field, *fieldList = commaSepToSlNames(fields);
 boolean gotWhere = FALSE;
@@ -343,23 +342,23 @@
 int page = 0;
 struct fieldedTableSegment context = { .tableSize=resultsSize};
 if (resultsSize > pageSize)
     {
     page = cartUsualInt(cart, pageVar, 0) - 1;
     if (page < 0)
         page = 0;
     int lastPage = (resultsSize-1)/pageSize;
     if (page > lastPage)
         page = lastPage;
     context.tableOffset = page * pageSize;
     dyStringPrintf(query, " limit %d offset %d", pageSize, context.tableOffset);
     }
 
 struct fieldedTable *table = fieldedTableFromDbQuery(conn, query->string);
-webFilteredFieldedTable(cart, table, returnUrl, varPrefix, maxFieldWidth, tagOutWrappers, 
-    withFilters, itemPlural, pageSize, &context);
+webFilteredFieldedTable(cart, table, returnUrl, varPrefix, maxFieldWidth, 
+    tagOutWrappers, wrapperContext, withFilters, itemPlural, pageSize, &context);
 fieldedTableFree(&table);
 
 dyStringFree(&query);
 dyStringFree(&where);
 }