8e0eda99af6f7bb85342ef814c06bcda481377b2
Merge parents 96df520 edae7ad
tdreszer
  Tue Nov 1 11:24:18 2011 -0700
Merge up straighten out.
diff --cc src/hg/lib/hui.c
index 7428436,b0f2ce6..2fe53e9
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@@ -4867,174 -4734,140 +4867,171 @@@
              printf("<TD align='left'%s> (%d to %d)",altLabel,minLimit, maxLimit);
          else if(minLimit != NO_VALUE)
              printf("<TD align='left'%s> (minimum %d)",altLabel,minLimit);
          else if(maxLimit != NO_VALUE)
              printf("<TD align='left'%s> (maximum %d)",altLabel,maxLimit);
          else
              printf("<TD align='left'%s",altLabel);
          }
      puts("</TR>");
      return TRUE;
      }
  return FALSE;
  }
  
  
 -#ifdef ALL_SCORE_FILTERS_LOGIC
  static int numericFiltersShowAll(struct cart *cart, struct trackDb *tdb, boolean *opened, boolean boxed,
 -                               boolean compositeLevel,char *name, char *title)
 +                               boolean viewLevel,char *name, char *title)
  // Shows all *Filter style filters.  Note that these are in random order and have no graceful title
  {
  int count = 0;
  struct slName *filterSettings = trackDbSettingsWildMatch(tdb, "*Filter");
  if (filterSettings)
      {
      puts("<BR>");
      struct slName *filter = NULL;
-     struct slPair *extras = NULL;
-     char *extraFields = trackDbSetting(tdb, "extraFields");  // TODo: seems like there should be a cleaner way
-     if (extraFields != NULL)
-         extras = slPairListFromString(extraFields,TRUE); // Quoted strings may be okay
+     struct extraField *extras = extraFieldsGet(tdb);
  
      while ((filter = slPopHead(&filterSettings)) != NULL)
          {
 -        if (differentString(filter->name,"noScoreFilter") && differentString(filter->name,"scoreFilter")) // TODO: scoreFilter could be included
 +        if (differentString(filter->name,NO_SCORE_FILTER) && differentString(filter->name,SCORE_FILTER)) // TODO: scoreFilter could be included
              {
-             char *field = cloneString(filter->name);
+             // Determine floating point or integer
+             char *setting = trackDbSetting(tdb, filter->name);
+             boolean isFloat = (strchr(setting,'.') != NULL);
+ 
+             char *scoreName = cloneString(filter->name);
+             char *field = filter->name;   // No need to clone: will be thrown away at end of cycle
              int ix = strlen(field) - strlen("Filter");
              assert(ix > 0);
              field[ix] = '\0';
-             // Could lookup extraFields  // TODO: Should we be using extra fields?  Could this be sorted by the order in extraFields?
+ 
              if (extras != NULL)
                  {
-                 char *foundLabel = slPairFindVal(extras, field);
-                 if (foundLabel != NULL)
+                 struct extraField *extra = extraFieldsFind(extras, field);
+                 if (extra != NULL)
                      { // Found label so replace field
-                     freeMem(field);
-                     field = strchr(foundLabel,']');
-                     if (field == NULL)
-                         field = cloneString(foundLabel);
-                     else
-                         field = cloneString(field + 1);
-                     strSwapChar(field,'_',' ');
+                     field = extra->label;
+                     if (!isFloat)
+                         isFloat = (extra->type == ftFloat);
                      }
                  }
              char label[128];
              safef(label,sizeof(label),"Minimum %s",field);
-             freeMem(field);
-             // Determine floating point or integer
-             char *setting = trackDbSetting(tdb, filter->name);
-             boolean isFloat = (strchr(setting,'.') != NULL);
-             showScoreFilter(cart,tdb,opened,boxed,viewLevel,name,title,label,filter->name,isFloat);
+             showScoreFilter(cart,tdb,opened,boxed,compositeLevel,name,title,label,scoreName,isFloat);
+             freeMem(scoreName);
              count++;
              }
          slNameFree(&filter);
          }
+     if (extras != NULL)
+         extraFieldsFree(&extras);
      }
  if (count > 0)
      puts("</TABLE>");
  return count;
  }
 -#endif///def ALL_SCORE_FILTERS_LOGIC
 +
 +
 +boolean bedScoreHasCfgUi(struct trackDb *tdb)
 +// Confirms that this track has a bedScore Cfg UI
 +{
 +// Assumes that cfgType == cfgBedScore
 +if (trackDbSettingClosestToHome(tdb, FILTER_BY))
 +    return TRUE;
 +if (trackDbSettingClosestToHome(tdb, GRAY_LEVEL_SCORE_MIN))
 +    return TRUE;
 +boolean blocked = FALSE;
 +struct slName *filterSettings = trackDbSettingsWildMatch(tdb, "*Filter");
 +if (filterSettings != NULL)
 +    {
 +    boolean one = FALSE;
 +    struct slName *oneFilter = filterSettings;
 +    for (;oneFilter != NULL;oneFilter=oneFilter->next)
 +        {
 +        if (sameWord(NO_SCORE_FILTER,oneFilter->name))
 +            {
 +            blocked = TRUE;
 +            continue;
 +            }
 +        if (differentString(oneFilter->name,SCORE_FILTER)) // scoreFilter is implicit but could be blocked
 +            {
 +            one = TRUE;
 +            break;
 +            }
 +        }
 +    slNameFreeList(&filterSettings);
 +    if (one)
 +        return TRUE;
 +    }
 +if (!blocked)  // scoreFilter is implicit unless NO_SCORE_FILTER
 +    return TRUE;
 +
 +return FALSE;
 +}
  
  
  void scoreCfgUi(char *db, struct cart *cart, struct trackDb *tdb, char *name, char *title,  int maxScore, boolean boxed)
  /* Put up UI for filtering bed track based on a score */
  {
  char option[256];
 -boolean compositeLevel = isNameAtCompositeLevel(tdb,name);
 +boolean viewLevel = isNameAtCompositeLevel(tdb,name);
  boolean skipScoreFilter = FALSE;
  boolean bigBed = startsWith("bigBed",tdb->type);
  
  if (!bigBed)  // bigBed filters are limited!
      {
 -    filterBy_t *filterBySet = filterBySetGet(tdb,cart,name);
 -
 -    #ifdef ALL_SCORE_FILTERS_LOGIC
      // Numeric filters are first
      boolean isBoxOpened = FALSE;
 -    if (numericFiltersShowAll(cart, tdb, &isBoxOpened, boxed, compositeLevel, name, title) > 0)
 +    if (numericFiltersShowAll(cart, tdb, &isBoxOpened, boxed, viewLevel, name, title) > 0)
          skipScoreFilter = TRUE;
 -    #endif///def ALL_SCORE_FILTERS_LOGIC
  
      // Add any multi-selects next
 +    filterBy_t *filterBySet = filterBySetGet(tdb,cart,name);
      if(filterBySet != NULL)
          {
          if(!tdbIsComposite(tdb) && cartOptionalString(cart, "ajax") == NULL)
              jsIncludeFile("hui.js",NULL);
  
          if (!isBoxOpened)   // Note filterBy boxes are not double "boxed", if there are no other filters
              printf("<BR>");
 -        filterBySetCfgUi(tdb,filterBySet,TRUE);
 +        filterBySetCfgUi(cart,tdb,filterBySet,TRUE);
          filterBySetFree(&filterBySet);
          skipScoreFilter = TRUE;
          }
  
      // For no good reason scoreFilter is incompatible with filterBy and or numericFilters
      // FIXME scoreFilter should be implemented inside numericFilters and is currently specificly excluded to avoid unexpected changes
      if (skipScoreFilter)
          {
 -        #ifdef ALL_SCORE_FILTERS_LOGIC
          if (isBoxOpened)
              cfgEndBox(boxed);
 -        #endif///def ALL_SCORE_FILTERS_LOGIC
  
          return; // Cannot have both '*filter' and 'scoreFilter'
          }
      }
  
  boolean scoreFilterOk = (trackDbSettingClosestToHome(tdb, NO_SCORE_FILTER) == NULL);
  boolean glvlScoreMin = (trackDbSettingClosestToHome(tdb, GRAY_LEVEL_SCORE_MIN) != NULL);
  if (! (scoreFilterOk || glvlScoreMin))
      return;
  boxed = cfgBeginBoxAndTitle(tdb, boxed, title);
  
  if (scoreFilterOk)
      {
      int minLimit=0,maxLimit=maxScore,minVal=0,maxVal=maxScore;
 -    getScoreIntRangeFromCart(cart,tdb,SCORE_FILTER,&minLimit,&maxLimit,&minVal,&maxVal);
 +    getScoreIntRangeFromCart(cart,tdb,viewLevel,SCORE_FILTER,&minLimit,&maxLimit,&minVal,&maxVal);
  
      boolean filterByRange = trackDbSettingClosestToHomeOn(tdb, SCORE_FILTER _BY_RANGE);
      if (!bigBed && filterByRange)
          {
          puts("<B>Filter score range:  min:</B>");
          snprintf(option, sizeof(option), "%s.%s", name,SCORE_FILTER _MIN);
          cgiMakeIntVarWithLimits(option, minVal, "Minimum score",0, minLimit,maxLimit);
          puts("<B>max:</B>");
          snprintf(option, sizeof(option), "%s.%s", name,SCORE_FILTER _MAX);
          cgiMakeIntVarWithLimits(option, maxVal, "Maximum score",0,minLimit,maxLimit);
          printf("(%d to %d)\n",minLimit,maxLimit);
          }
      else
          {
          printf("<b>Show only items with score at or above:</b> ");