else
{
const char *patterns = Cvar_VariableString(va("con_completion_%s", command)); // TODO maybe use a better place for this?
- char t[MAX_QPATH];
- stringlist_t resultbuf;
-
- // 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);
- while(COM_ParseToken_Simple(&patterns, false, false))
+
+ if(patterns && *patterns)
{
- fssearch_t *search;
- if(strchr(com_token, '/'))
+ char t[MAX_QPATH];
+ 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))
{
- search = FS_Search(com_token, true, true);
+ 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);
+ }
}
- else
+
+ // 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, com_token, sizeof(t));
+ strlcat(t, "/*", 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)))
- stringlistappend(&resultbuf, search->filenames[i]);
- FS_FreeSearch(search);
- }
- }
-
- if(resultbuf.numstrings > 0)
- {
- const char *p, *q;
- if(resultbuf.numstrings == 1)
- {
- dpsnprintf(t, sizeof(t), "%s ", resultbuf.strings[0]);
+ 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);
+ }
}
- else
+
+ if(resultbuf.numstrings > 0 || dirbuf.numstrings > 0)
{
- stringlistsort(&resultbuf);
- Con_Printf("\n%i possible filenames\n", resultbuf.numstrings);
- for(i = 0; i < resultbuf.numstrings; ++i)
+ const char *p, *q;
+ unsigned int matchchars;
+ if(resultbuf.numstrings == 0 && dirbuf.numstrings == 1)
{
- Con_Printf("%s\n", resultbuf.strings[i]);
+ dpsnprintf(t, sizeof(t), "%s/", dirbuf.strings[0]);
+ }
+ else
+ if(resultbuf.numstrings == 1 && dirbuf.numstrings == 0)
+ {
+ dpsnprintf(t, sizeof(t), "%s ", resultbuf.strings[0]);
+ }
+ else
+ {
+ stringlistsort(&resultbuf); // dirbuf is already sorted
+ Con_Printf("\n%i possible filenames\n", resultbuf.numstrings + dirbuf.numstrings);
+ for(i = 0; i < dirbuf.numstrings; ++i)
+ {
+ Con_Printf("%s/\n", dirbuf.strings[i]);
+ }
+ for(i = 0; i < resultbuf.numstrings; ++i)
+ {
+ Con_Printf("%s\n", resultbuf.strings[i]);
+ }
+ matchchars = sizeof(t) - 1;
+ if(resultbuf.numstrings > 0)
+ {
+ p = resultbuf.strings[0];
+ q = resultbuf.strings[resultbuf.numstrings - 1];
+ for(; *p && *p == *q; ++p, ++q);
+ matchchars = p - resultbuf.strings[0];
+ }
+ if(dirbuf.numstrings > 0)
+ {
+ p = dirbuf.strings[0];
+ q = dirbuf.strings[dirbuf.numstrings - 1];
+ for(; *p && *p == *q; ++p, ++q);
+ matchchars = min(matchchars, p - dirbuf.strings[0]);
+ }
+ // now p points to the first non-equal character, or to the end
+ // of resultbuf.strings[0]. We want to append the characters
+ // from resultbuf.strings[0] to (not including) p as these are
+ // the unique prefix
+ strlcpy(t, (resultbuf.numstrings > 0 ? resultbuf : dirbuf).strings[0], min(matchchars + 1, sizeof(t)));
}
- p = resultbuf.strings[0];
- q = resultbuf.strings[resultbuf.numstrings - 1];
- for(; *p && *p == *q; ++p, ++q);
- // now p points to the first non-equal character, or to the end
- // of resultbuf.strings[0]. We want to append the characters
- // from resultbuf.strings[0] to (not including) p as these are
- // the unique prefix
- strlcpy(t, resultbuf.strings[0], min((unsigned int)(p - resultbuf.strings[0] + 1), sizeof(t)));
- }
- // first move the cursor
- key_linepos += (int)strlen(t) - (int)strlen(s);
+ // first move the cursor
+ key_linepos += (int)strlen(t) - (int)strlen(s);
- // and now do the actual work
- *s = 0;
- strlcat(key_lines[edit_line], t, MAX_INPUTLINE);
- strlcat(key_lines[edit_line], s2, MAX_INPUTLINE); //add back chars after cursor
+ // and now do the actual work
+ *s = 0;
+ strlcat(key_lines[edit_line], t, MAX_INPUTLINE);
+ strlcat(key_lines[edit_line], s2, MAX_INPUTLINE); //add back chars after cursor
- // and fix the cursor
- if(key_linepos > (int) strlen(key_lines[edit_line]))
- key_linepos = (int) strlen(key_lines[edit_line]);
+ // and fix the cursor
+ if(key_linepos > (int) strlen(key_lines[edit_line]))
+ key_linepos = (int) strlen(key_lines[edit_line]);
+ }
+ stringlistfreecontents(&resultbuf);
+ stringlistfreecontents(&dirbuf);
}
- stringlistfreecontents(&resultbuf);
}
}
}
+/*
+==================
+FS_FileType
+
+Look for a file in the packages and in the filesystem
+==================
+*/
+int FS_FileType (const char *filename)
+{
+ searchpath_t *search;
+ char fullpath[MAX_QPATH];
+
+ search = FS_FindFile (filename, NULL, true);
+ if(!search)
+ return FS_FILETYPE_NONE;
+
+ if(search->pack)
+ return FS_FILETYPE_FILE; // TODO can't check directories in paks yet, maybe later
+
+ dpsnprintf(fullpath, sizeof(fullpath), "%s%s", search->filename, filename);
+ return FS_SysFileType(fullpath);
+}
+
+
/*
==================
FS_FileExists
Look for a file in the filesystem only
==================
*/
-qboolean FS_SysFileExists (const char *path)
+int FS_SysFileType (const char *path)
{
#if WIN32
- int desc;
+ DWORD result = GetFileAttributes(path);
- // TODO: use another function instead, to avoid opening the file
- desc = open (path, O_RDONLY | O_BINARY);
- if (desc < 0)
- return false;
+ if(result == INVALID_FILE_ATTRIBUTES)
+ return FS_FILETYPE_NONE;
- close (desc);
- return true;
+ if(result & FILE_ATTRIBUTE_DIRECTORY)
+ return FS_FILETYPE_DIRECTORY;
+
+ return FS_FILETYPE_FILE;
#else
struct stat buf;
if (stat (path,&buf) == -1)
- return false;
+ return FS_FILETYPE_NONE;
- return true;
+ if(S_ISDIR(buf.st_mode))
+ return FS_FILETYPE_DIRECTORY;
+
+ return FS_FILETYPE_FILE;
#endif
}
+qboolean FS_SysFileExists (const char *path)
+{
+ return FS_SysFileType (path) != FS_FILETYPE_NONE;
+}
+
void FS_mkdir (const char *path)
{
#if WIN32