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 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 </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 </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 </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)