1dcfacd04aaefa861750e177f20619c4382f17cf
tdreszer
  Fri Aug 12 12:45:25 2011 -0700
Divorced simple search entry from description search entry.  Cleaned up a simplified some code.
diff --git src/hg/hgTracks/searchTracks.c src/hg/hgTracks/searchTracks.c
index c0041f4..449f41e 100644
--- src/hg/hgTracks/searchTracks.c
+++ src/hg/hgTracks/searchTracks.c
@@ -20,31 +20,30 @@
 #include "trix.h"
 #include "jsHelper.h"
 #include "imageV2.h"
 
 
 #define TRACK_SEARCH_FORM        "trackSearch"
 #define SEARCH_RESULTS_FORM      "searchResults"
 #define TRACK_SEARCH_CURRENT_TAB "tsCurTab"
 #define TRACK_SEARCH_SIMPLE      "tsSimple"
 #define TRACK_SEARCH_ON_NAME     "tsName"
 #define TRACK_SEARCH_ON_TYPE     "tsType"
 #define TRACK_SEARCH_ON_GROUP    "tsGroup"
 #define TRACK_SEARCH_ON_DESCR    "tsDescr"
 #define TRACK_SEARCH_SORT        "tsSort"
 
-#define SUPPORT_QUOTES_IN_NAME_SEARCH
 #define SUPPORT_SUBTRACKS_INHERIT_DESCRIPTION
 
 static int gCmpGroup(const void *va, const void *vb)
 /* Compare groups based on label. */
 {
 const struct group *a = *((struct group **)va);
 const struct group *b = *((struct group **)vb);
 return strcmp(a->label, b->label);
 }
 
 // Would like to do a radio button choice ofsorts
 enum sortBy
     {
     sbRelevance=0,
     sbAbc      =1,
@@ -80,86 +79,30 @@
 const struct track *a = ((struct track *) aa->val);
 const struct track *b = ((struct track *) bb->val);
 return strcasecmp(a->longLabel, b->longLabel);
 }
 
 static void findTracksSort(struct slRef **pTrack, enum sortBy sortBy)
 {
 if (sortBy == sbHierarchy)
     slSort(pTrack, gCmpTrackHierarchy);
 else if (sortBy == sbAbc)
     slSort(pTrack, gCmpTrack);
 else
     slReverse(pTrack);
 }
 
-#ifndef SUPPORT_QUOTES_IN_NAME_SEARCH
-
-// XXXX make a matchString function to support "contains", "is" etc. and wildcards in contains
-
-//    ((sameString(op, "is") && !strcasecmp(track->shortLabel, str)) ||
-
-static boolean isNameMatch(struct track *track, char *str, char *op)
-{
-return str && strlen(str) &&
-    ((sameString(op, "is") && !strcasecmp(track->shortLabel, str)) ||
-    (sameString(op, "is") && !strcasecmp(track->longLabel, str)) ||
-    (sameString(op, "contains") && containsStringNoCase(track->shortLabel, str) != NULL) ||
-    (sameString(op, "contains") && containsStringNoCase(track->longLabel, str) != NULL));
-}
-
-static boolean isDescriptionMatch(struct track *track, char **words, int wordCount)
-// We parse str and look for every word at the start of any word in track description (i.e. google style).
-{
-if(words)
-    {
-    // We do NOT lookup up parent hierarchy for html descriptions.
-    char *html = track->tdb->html;
-    if(!isEmpty(html))
-        {
-        /* This probably could be made more efficient by parsing the html into some kind of b-tree, but I am assuming
-           that the inner html loop while only happen for 1-2 words for vast majority of the tracks. */
-
-        int i, numMatches = 0;
-        html = stripRegEx(html, "<[^>]*>", REG_ICASE);
-        for(i = 0; i < wordCount; i++)
-            {
-            char *needle = words[i];
-            char *haystack, *tmp = cloneString(html);
-            boolean found = FALSE;
-            while((haystack = nextWord(&tmp)))
-                {
-                char *ptr = strstrNoCase(haystack, needle);
-                if(ptr != NULL && ptr == haystack)
-                    {
-                    found = TRUE;
-                    break;
-                    }
-                }
-            if(found)
-                numMatches++;
-            else
-                break;
-            }
-        if(numMatches == wordCount)
-            return TRUE;
-        }
-    }
-return FALSE;
-}
-#endif///ndef SUPPORT_QUOTES_IN_NAME_SEARCH
-
 static int getFormatTypes(char ***pLabels, char ***pTypes)
 {
 char *crudeTypes[] = {
     ANYLABEL,
     "bam",
     "psl",
     "chain",
     "netAlign",
     "maf",
     "bed",
     "bigBed",
     "ctgPos",
     "expRatio",
     "genePred",
     "broadPeak",
@@ -210,168 +153,185 @@
 int ix = 0, count = sizeof(crudeTypes)/sizeof(char *);
 char **labels;
 char **values;
 AllocArray(labels, count);
 AllocArray(values, count);
 for(ix=0;ix<count;ix++)
     {
     labels[ix] = cloneString(nicerTypes[ix]);
     values[ix] = cloneString(crudeTypes[ix]);
     }
 *pLabels = labels;
 *pTypes = values;
 return count;
 }
 
-static struct slRef *simpleSearchForTracksstruct(struct trix *trix,char **descWords,int descWordCount)
+static struct slRef *simpleSearchForTracksstruct(char *simpleEntry)
 // Performs the simple search and returns the found tracks.
 {
 struct slRef *tracks = NULL;
 
+// Prepare for trix search
+if (!isEmpty(simpleEntry))
+    {
+    int trixWordCount = 0;
+    char *tmp = cloneString(simpleEntry);
+    char *val = nextWord(&tmp);
+    struct slName *el, *trixList = NULL;
+    while (val != NULL)
+        {
+        slNameAddTail(&trixList, val);
+        trixWordCount++;
+        val = nextWord(&tmp);
+        }
+    if (trixWordCount > 0)
+        {
+        // Unfortunately trixSearch can't handle the slName list
+        int i;
+        char **trixWords = needMem(sizeof(char *) * trixWordCount);
+        for(i = 0, el = trixList; el != NULL; i++, el = el->next)
+            trixWords[i] = strLower(el->name);
+
+        // Now open the trix file
+        char trixFile[HDB_MAX_PATH_STRING];
+        getSearchTrixFile(database, trixFile, sizeof(trixFile));
+        struct trix *trix = trixOpen(trixFile);
+
 struct trixSearchResult *tsList;
-for(tsList = trixSearch(trix, descWordCount, descWords, TRUE); tsList != NULL; tsList = tsList->next)
+        for(tsList = trixSearch(trix, trixWordCount, trixWords, TRUE); tsList != NULL; tsList = tsList->next)
     {
     struct track *track = (struct track *) hashFindVal(trackHash, tsList->itemId);
     if (track != NULL)  // It is expected that this is NULL (e.g. when the trix references trackDb tracks which have no tables)
         {
         refAdd(&tracks, track);
         }
     }
+        //trixClose(trix);  // don't bother (this is a CGI that is about to end)
+        }
+    }
 return tracks;
 }
 
-static struct slRef *advancedSearchForTracks(struct sqlConnection *conn,struct group *groupList, char **descWords,int descWordCount,
-                                             char *nameSearch, char *typeSearch, char *descSearch, char *groupSearch, struct slPair *mdbPairs)
+static struct slRef *advancedSearchForTracks(struct sqlConnection *conn,struct group *groupList,
+                                             char *nameSearch, char *typeSearch, char *descSearch,
+                                             char *groupSearch, struct slPair *mdbPairs)
 // Performs the advanced search and returns the found tracks.
 {
 int tracksFound = 0;
 struct slRef *tracks = NULL;
 int numMetadataNonEmpty = 0;
 struct slPair *pair = mdbPairs;
 for (; pair!= NULL;pair=pair->next)
     {
     if (!isEmpty((char *)(pair->val)))
         numMetadataNonEmpty++;
     }
 
-    if(!isEmpty(nameSearch) || typeSearch != NULL || descSearch != NULL || groupSearch != NULL || numMetadataNonEmpty)
-        {
+if(!isEmpty(groupSearch) && sameString(groupSearch,ANYLABEL))
+    groupSearch = NULL;
+if(!isEmpty(typeSearch) && sameString(typeSearch,ANYLABEL))
+    typeSearch = NULL;
+
+if(isEmpty(nameSearch) && isEmpty(typeSearch) && isEmpty(descSearch)
+&& isEmpty(groupSearch) && numMetadataNonEmpty == 0)
+    return NULL;
+
         // First do the metaDb searches, which can be done quickly for all tracks with db queries.
         struct hash *matchingTracks = NULL;
 
         if (numMetadataNonEmpty)
             {
             struct mdbObj *mdbObj, *mdbObjs = mdbObjRepeatedSearch(conn,mdbPairs,TRUE,FALSE);
             if (mdbObjs)
                 {
                 for (mdbObj = mdbObjs; mdbObj != NULL; mdbObj = mdbObj->next)
                     {
                     if (matchingTracks == NULL)
                         matchingTracks = newHash(0);
                     hashAddInt(matchingTracks, mdbObj->obj, 1);
                     }
                 mdbObjsFree(&mdbObjs);
                 }
            if (matchingTracks == NULL)
                 return NULL;
             }
 
-    #ifdef SUPPORT_QUOTES_IN_NAME_SEARCH
         // Set the word lists up once
         struct slName *nameList = NULL;
-        if (nameSearch)
+if (!isEmpty(nameSearch))
             nameList = slNameListOfUniqueWords(cloneString(nameSearch),TRUE); // TRUE means respect quotes
         struct slName *descList = NULL;
-        if (descSearch)
+if (!isEmpty(descSearch))
             descList = slNameListOfUniqueWords(cloneString(descSearch),TRUE);
-    #endif///def SUPPORT_QUOTES_IN_NAME_SEARCH
 
         struct group *group;
         for (group = groupList; group != NULL; group = group->next)
             {
-            if(groupSearch == NULL || sameString(group->name, groupSearch))
-                {
-                if (group->trackList != NULL)
+    if(isEmpty(groupSearch) || sameString(group->name, groupSearch))
                     {
+        if (group->trackList == NULL)
+            continue;
+
                     struct trackRef *tr;
                     for (tr = group->trackList; tr != NULL; tr = tr->next)
                         {
                         struct track *track = tr->track;
                         char *trackType = cloneFirstWord(track->tdb->type); // will be spilled
                         if ((matchingTracks == NULL || hashLookup(matchingTracks, track->track) != NULL)
-                #ifdef SUPPORT_QUOTES_IN_NAME_SEARCH
+            && (isEmpty(typeSearch) || (sameWord(typeSearch, trackType) && !tdbIsComposite(track->tdb)))
                         && (isEmpty(nameSearch) || searchNameMatches(track->tdb, nameList))
-                        && (isEmpty(descSearch) || searchDescriptionMatches(track->tdb, descList))
-                #else///ifndef SUPPORT_QUOTES_IN_NAME_SEARCH
-                        && (isEmpty(nameSearch) || isNameMatch(track, nameSearch, "contains"))
-                        && (isEmpty(descSearch) || isDescriptionMatch(track, descWords, descWordCount))
-                #endif///ndef SUPPORT_QUOTES_IN_NAME_SEARCH
-                        && (isEmpty(typeSearch) || (sameWord(typeSearch, trackType) && !tdbIsComposite(track->tdb))))
+            && (isEmpty(descSearch) || searchDescriptionMatches(track->tdb, descList)))
                             {
                             if (track != NULL)
                                 {
                                 tracksFound++;
                                 refAdd(&tracks, track);
                                 }
                             else
                                 warn("found group track is NULL.");
                             }
                         if (track->subtracks != NULL)
                             {
                             struct track *subTrack;
                             for (subTrack = track->subtracks; subTrack != NULL; subTrack = subTrack->next)
                                 {
                                 trackType = cloneFirstWord(subTrack->tdb->type); // will be spilled
                                 if ((matchingTracks == NULL || hashLookup(matchingTracks, subTrack->track) != NULL)
-                        #ifdef SUPPORT_QUOTES_IN_NAME_SEARCH
+                    && (isEmpty(typeSearch) || sameWord(typeSearch, trackType))
                                 && (isEmpty(nameSearch) || searchNameMatches(subTrack->tdb, nameList))
                             #ifdef SUPPORT_SUBTRACKS_INHERIT_DESCRIPTION
                                 && (isEmpty(descSearch)
                                     || searchDescriptionMatches(subTrack->tdb, descList)
                                     || (tdbIsCompositeChild(subTrack->tdb) && subTrack->parent
-                                        && searchDescriptionMatches(subTrack->parent->tdb, descList)))
+                            && searchDescriptionMatches(subTrack->parent->tdb, descList))))
                             #else///ifndef SUPPORT_SUBTRACKS_INHERIT_DESCRIPTION
-                                && (isEmpty(descSearch) || searchDescriptionMatches(subTrack->tdb, descList))
+                    && (isEmpty(descSearch) || searchDescriptionMatches(subTrack->tdb, descList)))
                             #endif///ndef SUPPORT_SUBTRACKS_INHERIT_DESCRIPTION
-                        #else///ifndef SUPPORT_QUOTES_IN_NAME_SEARCH
-                                && (isEmpty(nameSearch) || isNameMatch(subTrack, nameSearch, "contains"))
-                            #ifdef SUPPORT_SUBTRACKS_INHERIT_DESCRIPTION
-                                && (isEmpty(descSearch)
-                                    || isDescriptionMatch(subTrack, descWords, descWordCount)
-                                    || (tdbIsCompositeChild(subTrack->tdb) && subTrack->parent
-                                        && isDescriptionMatch(subTrack->parent, descWords, descWordCount)))
-                            #else///ifndef SUPPORT_SUBTRACKS_INHERIT_DESCRIPTION
-                                && (isEmpty(descSearch) || isDescriptionMatch(subTrack, descWords, descWordCount))
-                            #endif///ndef SUPPORT_SUBTRACKS_INHERIT_DESCRIPTION
-                        #endif///ndef SUPPORT_QUOTES_IN_NAME_SEARCH
-                                && (isEmpty(typeSearch) || sameWord(typeSearch, trackType)))
                                     {
                                     if (track != NULL)
                                         {
                                         tracksFound++;
                                         refAdd(&tracks, subTrack);
                                         }
                                     else
                                         warn("found subtrack is NULL.");
                                     }
                                 }
                             }
                         }
                     }
                 }
-            }
-        }
 
 return tracks;
 }
 
 #define MAX_FOUND_TRACKS 100
 static void findTracksPageLinks(int tracksFound, int startFrom)
 {
 if (tracksFound <= MAX_FOUND_TRACKS)
     return;
 
 // Opener
 int willStartAt = 0;
 int curPage  = (startFrom/MAX_FOUND_TRACKS) + 1;
 int endAt = startFrom+MAX_FOUND_TRACKS;
 if (endAt > tracksFound)
@@ -605,75 +565,54 @@
 #ifdef NEW_JQUERY
 jsIncludeFile("ddcl.js",NULL);
 hPrintf("<script type='text/javascript'>var newJQuery=true;</script>\n");
 #else///ifndef NEW_JQUERY
 hPrintf("<script type='text/javascript'>var newJQuery=false;</script>\n");
 hPrintf("<script type='text/javascript'>$(document).ready(function() { $('.filterBy').each( function(i) { $(this).dropdownchecklist({ firstItemChecksAll: true, noneIsAll: true, maxDropHeight: filterByMaxHeight(this) });});});</script>\n");
 #endif///ndef NEW_JQUERY
 
 struct group *group;
 char *groups[128];
 char *labels[128];
 int numGroups = 1;
 groups[0] = ANYLABEL;
 labels[0] = ANYLABEL;
 char *nameSearch = cartOptionalString(cart, TRACK_SEARCH_ON_NAME);
-char *typeSearch = cartOptionalString(cart, TRACK_SEARCH_ON_TYPE);
-char *descSearch = NULL;
-char *groupSearch = cartOptionalString(cart, TRACK_SEARCH_ON_GROUP);
+char *typeSearch  = cartUsualString(   cart, TRACK_SEARCH_ON_TYPE,ANYLABEL);
+char *simpleEntry = cartOptionalString(cart, TRACK_SEARCH_SIMPLE);
+char *descSearch  = cartOptionalString(cart, TRACK_SEARCH_ON_DESCR);
+char *groupSearch = cartUsualString(  cart, TRACK_SEARCH_ON_GROUP,ANYLABEL);
 boolean doSearch = sameString(cartOptionalString(cart, TRACK_SEARCH), "Search") || cartUsualInt(cart, TRACK_SEARCH_PAGER, -1) >= 0;
 struct sqlConnection *conn = hAllocConn(database);
 boolean metaDbExists = sqlTableExists(conn, "metaDb");
 int tracksFound = 0;
-struct trix *trix;
-char trixFile[HDB_MAX_PATH_STRING];
-char **descWords = NULL;
-int descWordCount = 0;
 boolean searchTermsExist = FALSE;
 int cols;
 char buf[512];
 
-enum searchTab selectedTab = simpleTab;
 char *currentTab = cartUsualString(cart, TRACK_SEARCH_CURRENT_TAB, "simpleTab");
-if(sameString(currentTab, "simpleTab"))
-    {
-    selectedTab = simpleTab;
-    descSearch = cartOptionalString(cart, TRACK_SEARCH_SIMPLE);
-    freez(&nameSearch);
-    }
-else if(sameString(currentTab, "advancedTab"))
-    {
-    selectedTab = advancedTab;
-    descSearch = cartOptionalString(cart, TRACK_SEARCH_ON_DESCR);
-    }
+enum searchTab selectedTab = (sameString(currentTab, "advancedTab") ? advancedTab : simpleTab);
 
-#ifdef SUPPORT_QUOTES_IN_NAME_SEARCH
-if(descSearch && selectedTab == simpleTab) // TODO: could support quotes in simple tab by detecting quotes and choosing to use doesNameMatch() || doesDescriptionMatch()
-    stripChar(descSearch, '"');
-#else///ifndef SUPPORT_QUOTES_IN_NAME_SEARCH
-if(descSearch)
-    stripChar(descSearch, '"');
-#endif///ndef SUPPORT_QUOTES_IN_NAME_SEARCH
+if(selectedTab == simpleTab && !isEmpty(simpleEntry)) // NOTE: could support quotes in simple tab by detecting quotes and choosing to use doesNameMatch() || doesDescriptionMatch()
+    stripChar(simpleEntry, '"');
 trackList = getTrackList(&groupList, -2); // global
 makeGlobalTrackHash(trackList);
 
 // NOTE: This is necessary when container cfg by '*' results in vis changes
 // This will handle composite/view override when subtrack specific vis exists, AND superTrack reshaping.
 parentChildCartCleanup(trackList,cart,oldVars); // Subtrack settings must be removed when composite/view settings are updated
 
-getSearchTrixFile(database, trixFile, sizeof(trixFile));
-trix = trixOpen(trixFile);
 slSort(&groupList, gCmpGroup);
 for (group = groupList; group != NULL; group = group->next)
     {
     groupTrackListAddSuper(cart, group);
     if (group->trackList != NULL)
         {
         groups[numGroups] = cloneString(group->name);
         labels[numGroups] = cloneString(group->label);
         numGroups++;
         if (numGroups >= ArraySize(groups))
             internalErr();
         }
     }
 
 safef(buf, sizeof(buf),"Search for Tracks in the %s %s Assembly", organism, hFreezeFromDb(database));
@@ -689,32 +628,32 @@
 hPrintf("<input type='hidden' name='db' value='%s'>\n", database);
 hPrintf("<input type='hidden' name='%s' id='currentTab' value='%s'>\n", TRACK_SEARCH_CURRENT_TAB, currentTab);
 hPrintf("<input type='hidden' name='%s' value=''>\n",TRACK_SEARCH_DEL_ROW);
 hPrintf("<input type='hidden' name='%s' value=''>\n",TRACK_SEARCH_ADD_ROW);
 hPrintf("<input type='hidden' name='%s' value=''>\n",TRACK_SEARCH_PAGER);
 
 hPrintf("<div id='tabs' style='display:none; %s'>\n"
         "<ul>\n"
         "<li><a href='#simpleTab'><B style='font-size:.9em;font-family: arial, Geneva, Helvetica, san-serif;'>Search</B></a></li>\n"
         "<li><a href='#advancedTab'><B style='font-size:.9em;font-family: arial, Geneva, Helvetica, san-serif;'>Advanced</B></a></li>\n"
         "</ul>\n"
         "<div id='simpleTab' style='max-width:inherit;'>\n",cgiBrowser()==btIE?"width:1060px;":"max-width:inherit;");
 
 hPrintf("<table id='simpleTable' style='width:100%%; font-size:.9em;'><tr><td colspan='2'>");
 hPrintf("<input type='text' name='%s' id='simpleSearch' class='submitOnEnter' value='%s' style='max-width:1000px; width:100%%;' onkeyup='findTracksSearchButtonsEnable(true);'>\n",
-        TRACK_SEARCH_SIMPLE,descSearch == NULL ? "" : descSearch);
-if (selectedTab==simpleTab && descSearch)
+        TRACK_SEARCH_SIMPLE,simpleEntry == NULL ? "" : simpleEntry);
+if (selectedTab==simpleTab && simpleEntry)
     searchTermsExist = TRUE;
 
 hPrintf("</td></tr><td style='max-height:4px;'></td></tr></table>");
 //hPrintf("</td></tr></table>");
 hPrintf("<input type='submit' name='%s' id='searchSubmit' value='search' style='font-size:.8em;'>\n", TRACK_SEARCH);
 hPrintf("<input type='button' name='clear' value='clear' class='clear' style='font-size:.8em;' onclick='findTracksClear();'>\n");
 hPrintf("<input type='submit' name='submit' value='cancel' class='cancel' style='font-size:.8em;'>\n");
 hPrintf("</div>\n");
 
 // Advanced tab
 hPrintf("<div id='advancedTab' style='width:inherit;'>\n"
         "<table id='advancedTable' cellSpacing=0 style='width:inherit; font-size:.9em;'>\n");
 cols = 8;
 
 // Track Name contains
@@ -722,121 +661,94 @@
 hPrintf("<td nowrap><b style='max-width:100px;'>Track&nbsp;Name:</b></td>");
 hPrintf("<td align='right'>contains</td>\n");
 hPrintf("<td colspan='%d'>", cols - 4);
 hPrintf("<input type='text' name='%s' id='nameSearch' class='submitOnEnter' value='%s' onkeyup='findTracksSearchButtonsEnable(true);' style='min-width:326px; font-size:.9em;'>",
         TRACK_SEARCH_ON_NAME, nameSearch == NULL ? "" : nameSearch);
 hPrintf("</td></tr>\n");
 
 // Description contains
 hPrintf("<tr><td colspan=2></td><td align='right'>and&nbsp;</td>");
 hPrintf("<td><b style='max-width:100px;'>Description:</b></td>");
 hPrintf("<td align='right'>contains</td>\n");
 hPrintf("<td colspan='%d'>", cols - 4);
 hPrintf("<input type='text' name='%s' id='descSearch' value='%s' class='submitOnEnter' onkeyup='findTracksSearchButtonsEnable(true);' style='max-width:536px; width:536px; font-size:.9em;'>",
         TRACK_SEARCH_ON_DESCR, descSearch == NULL ? "" : descSearch);
 hPrintf("</td></tr>\n");
-if (selectedTab==advancedTab && descSearch)
+if (selectedTab==advancedTab && !isEmpty(descSearch))
     searchTermsExist = TRUE;
 
 hPrintf("<tr><td colspan=2></td><td align='right'>and&nbsp;</td>\n");
 hPrintf("<td><b style='max-width:100px;'>Group:</b></td>");
 hPrintf("<td align='right'>is</td>\n");
 hPrintf("<td colspan='%d'>", cols - 4);
 cgiMakeDropListFull(TRACK_SEARCH_ON_GROUP, labels, groups, numGroups, groupSearch, "class='groupSearch' style='min-width:40%; font-size:.9em;'");
 hPrintf("</td></tr>\n");
-if (selectedTab==advancedTab && groupSearch)
+if (selectedTab==advancedTab && !isEmpty(groupSearch) && !sameString(groupSearch,ANYLABEL))
     searchTermsExist = TRUE;
 
 // Track Type is (drop down)
 hPrintf("<tr><td colspan=2></td><td align='right'>and&nbsp;</td>\n");
 hPrintf("<td nowrap><b style='max-width:100px;'>Data Format:</b></td>");
 hPrintf("<td align='right'>is</td>\n");
 hPrintf("<td colspan='%d'>", cols - 4);
 char **formatTypes = NULL;
 char **formatLabels = NULL;
 int formatCount = getFormatTypes(&formatLabels, &formatTypes);
 cgiMakeDropListFull(TRACK_SEARCH_ON_TYPE, formatLabels, formatTypes, formatCount, typeSearch, "class='typeSearch' style='min-width:40%; font-size:.9em;'");
 hPrintf("</td></tr>\n");
-if (selectedTab==advancedTab && typeSearch)
+if (selectedTab==advancedTab && !isEmpty(typeSearch) && !sameString(typeSearch,ANYLABEL))
     searchTermsExist = TRUE;
 
 // mdb selects
 struct slPair *mdbSelects = NULL;
 if(metaDbExists)
     {
     struct slPair *mdbVars = mdbVarsSearchable(conn,TRUE,FALSE); // Tables but not file only objects
-    mdbSelects = mdbSelectPairs(cart,selectedTab, mdbVars);
+    mdbSelects = mdbSelectPairs(cart, mdbVars);
     char *output = mdbSelectsHtmlRows(conn,mdbSelects,mdbVars,cols,FALSE);  // not a fileSearch
     if (output)
         {
         puts(output);
         freeMem(output);
         }
     slPairFreeList(&mdbVars);
     }
 
 hPrintf("</table>\n");
 hPrintf("<input type='submit' name='%s' id='searchSubmit' value='search' style='font-size:.8em;'>\n", TRACK_SEARCH);
 hPrintf("<input type='button' name='clear' value='clear' class='clear' style='font-size:.8em;' onclick='findTracksClear();'>\n");
 hPrintf("<input type='submit' name='submit' value='cancel' class='cancel' style='font-size:.8em;'>\n");
 //hPrintf("<a target='_blank' href='../goldenPath/help/trackSearch.html'>help</a>\n");
 hPrintf("</div>\n");
 
 hPrintf("</div>\n");
 
 hPrintf("</form>\n");
 hPrintf("</div>"); // Restricts to max-width:1000px;
 cgiDown(0.8);
 
 if (measureTiming)
     measureTime("Rendered tabs");
 
-if(descSearch != NULL && !strlen(descSearch))
-    descSearch = NULL;
-if(groupSearch != NULL && sameString(groupSearch, ANYLABEL))
-    groupSearch = NULL;
-if(typeSearch != NULL && sameString(typeSearch, ANYLABEL))
-    typeSearch = NULL;
-
-if(!isEmpty(descSearch))
-    {
-    char *tmp = cloneString(descSearch);
-    char *val = nextWord(&tmp);
-    struct slName *el, *descList = NULL;
-    int i;
-    while (val != NULL)
-        {
-        slNameAddTail(&descList, val);
-        descWordCount++;
-        val = nextWord(&tmp);
-        }
-    descWords = needMem(sizeof(char *) * descWordCount);
-    for(i = 0, el = descList; el != NULL; i++, el = el->next)
-        descWords[i] = strLower(el->name);
-    }
-
-if (doSearch && selectedTab==simpleTab && descWordCount <= 0)
-    doSearch = FALSE;
-
 if(doSearch)
     {
     // Now search
     struct slRef *tracks = NULL;
-    if(selectedTab==simpleTab)
-        tracks = simpleSearchForTracksstruct(trix,descWords,descWordCount);
+    if(selectedTab==simpleTab && !isEmpty(simpleEntry))
+        tracks = simpleSearchForTracksstruct(simpleEntry);
     else if(selectedTab==advancedTab)
-        tracks = advancedSearchForTracks(conn,groupList,descWords,descWordCount,nameSearch,typeSearch,descSearch,groupSearch,mdbSelects);
+        tracks = advancedSearchForTracks(conn,groupList,nameSearch,typeSearch,descSearch,groupSearch,mdbSelects);
 
     if (measureTiming)
         measureTime("Searched for tracks");
 
     // Sort and Print results
     if(selectedTab!=filesTab)
         {
         enum sortBy sortBy = cartUsualInt(cart,TRACK_SEARCH_SORT,sbRelevance);
         tracksFound = slCount(tracks);
         if(tracksFound > 1)
             findTracksSort(&tracks,sortBy);
 
         displayFoundTracks(cart,tracks,tracksFound,sortBy);
 
         if (measureTiming)