+ stringlist_t resultbuf, dirbuf;
+
+ // Usage:
+ // // store completion patterns (space separated) for command foo in con_completion_foo
+ // set con_completion_foo "foodata/*.foodefault *.foo"
+ // foo <TAB>
+ //
+ // Note: patterns with slash are always treated as absolute
+ // patterns; patterns without slash search in the innermost
+ // directory the user specified. There is no way to "complete into"
+ // a directory as of now, as directories seem to be unknown to the
+ // FS subsystem.
+ //
+ // Examples:
+ // set con_completion_playermodel "models/player/*.zym models/player/*.md3 models/player/*.psk models/player/*.dpm"
+ // set con_completion_playdemo "*.dem"
+ // set con_completion_play "*.wav *.ogg"
+ //
+ // TODO somehow add support for directories; these shall complete
+ // to their name + an appended slash.
+
+ stringlistinit(&resultbuf);
+ stringlistinit(&dirbuf);
+ while(COM_ParseToken_Simple(&patterns, false, false))
+ {
+ fssearch_t *search;
+ if(strchr(com_token, '/'))
+ {
+ search = FS_Search(com_token, true, true);
+ }
+ else
+ {
+ const char *slash = strrchr(s, '/');
+ if(slash)
+ {
+ strlcpy(t, s, min(sizeof(t), (unsigned int)(slash - s + 2))); // + 2, because I want to include the slash
+ strlcat(t, com_token, sizeof(t));
+ search = FS_Search(t, true, true);
+ }
+ else
+ search = FS_Search(com_token, true, true);
+ }
+ if(search)
+ {
+ for(i = 0; i < search->numfilenames; ++i)
+ if(!strncmp(search->filenames[i], s, strlen(s)))
+ if(FS_FileType(search->filenames[i]) == FS_FILETYPE_FILE)
+ stringlistappend(&resultbuf, search->filenames[i]);
+ FS_FreeSearch(search);
+ }
+ }
+
+ // In any case, add directory names
+ {
+ fssearch_t *search;
+ const char *slash = strrchr(s, '/');
+ if(slash)
+ {
+ strlcpy(t, s, min(sizeof(t), (unsigned int)(slash - s + 2))); // + 2, because I want to include the slash
+ strlcat(t, "*", sizeof(t));
+ search = FS_Search(t, true, true);
+ }
+ else
+ search = FS_Search("*", true, true);
+ if(search)
+ {
+ for(i = 0; i < search->numfilenames; ++i)
+ if(!strncmp(search->filenames[i], s, strlen(s)))
+ if(FS_FileType(search->filenames[i]) == FS_FILETYPE_DIRECTORY)
+ stringlistappend(&dirbuf, search->filenames[i]);
+ FS_FreeSearch(search);
+ }
+ }
+
+ if(resultbuf.numstrings > 0 || dirbuf.numstrings > 0)