]> icculus.org git repositories - divverent/darkplaces.git/blob - filematch.c
recalc the 2D view if changing view parameters with R_SetView
[divverent/darkplaces.git] / filematch.c
1
2 #include "quakedef.h"
3
4 // LordHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such...
5
6 int matchpattern(const char *in, const char *pattern, int caseinsensitive)
7 {
8         return matchpattern_with_separator(in, pattern, caseinsensitive, "/\\:", false);
9 }
10
11 // wildcard_least_one: if true * matches 1 or more characters
12 //                     if false * matches 0 or more characters
13 int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qboolean wildcard_least_one)
14 {
15         int c1, c2;
16         while (*pattern)
17         {
18                 switch (*pattern)
19                 {
20                 case 0:
21                         return 1; // end of pattern
22                 case '?': // match any single character
23                         if (*in == 0 || strchr(separators, *in))
24                                 return 0; // no match
25                         in++;
26                         pattern++;
27                         break;
28                 case '*': // match anything until following string
29                         if(wildcard_least_one)
30                         {
31                                 if (*in == 0 || strchr(separators, *in))
32                                         return 0; // no match
33                                 in++;
34                         }
35                         pattern++;
36                         while (*in)
37                         {
38                                 if (strchr(separators, *in))
39                                         break;
40                                 // see if pattern matches at this offset
41                                 if (matchpattern_with_separator(in, pattern, caseinsensitive, separators, wildcard_least_one))
42                                         return 1;
43                                 // nope, advance to next offset
44                                 in++;
45                         }
46                         break;
47                 default:
48                         if (*in != *pattern)
49                         {
50                                 if (!caseinsensitive)
51                                         return 0; // no match
52                                 c1 = *in;
53                                 if (c1 >= 'A' && c1 <= 'Z')
54                                         c1 += 'a' - 'A';
55                                 c2 = *pattern;
56                                 if (c2 >= 'A' && c2 <= 'Z')
57                                         c2 += 'a' - 'A';
58                                 if (c1 != c2)
59                                         return 0; // no match
60                         }
61                         in++;
62                         pattern++;
63                         break;
64                 }
65         }
66         if (*in)
67                 return 0; // reached end of pattern but not end of input
68         return 1; // success
69 }
70
71 // a little strings system
72 void stringlistinit(stringlist_t *list)
73 {
74         memset(list, 0, sizeof(*list));
75 }
76
77 void stringlistfreecontents(stringlist_t *list)
78 {
79         int i;
80         for (i = 0;i < list->numstrings;i++)
81         {
82                 if (list->strings[i])
83                         Z_Free(list->strings[i]);
84                 list->strings[i] = NULL;
85         }
86         list->numstrings = 0;
87         list->maxstrings = 0;
88         if (list->strings)
89                 Z_Free(list->strings);
90         list->strings = NULL;
91 }
92
93 void stringlistappend(stringlist_t *list, const char *text)
94 {
95         size_t textlen;
96         char **oldstrings;
97
98         if (list->numstrings >= list->maxstrings)
99         {
100                 oldstrings = list->strings;
101                 list->maxstrings += 4096;
102                 list->strings = (char **) Z_Malloc(list->maxstrings * sizeof(*list->strings));
103                 if (list->numstrings)
104                         memcpy(list->strings, oldstrings, list->numstrings * sizeof(*list->strings));
105                 if (oldstrings)
106                         Z_Free(oldstrings);
107         }
108         textlen = strlen(text) + 1;
109         list->strings[list->numstrings] = (char *) Z_Malloc(textlen);
110         memcpy(list->strings[list->numstrings], text, textlen);
111         list->numstrings++;
112 }
113
114 void stringlistsort(stringlist_t *list)
115 {
116         int i, j;
117         char *temp;
118         // this is a selection sort (finds the best entry for each slot)
119         for (i = 0;i < list->numstrings - 1;i++)
120         {
121                 for (j = i + 1;j < list->numstrings;j++)
122                 {
123                         if (strcasecmp(list->strings[i], list->strings[j]) > 0)
124                         {
125                                 temp = list->strings[i];
126                                 list->strings[i] = list->strings[j];
127                                 list->strings[j] = temp;
128                         }
129                 }
130         }
131 }
132
133 // operating system specific code
134 static void adddirentry(stringlist_t *list, const char *path, const char *name)
135 {
136         if (strcmp(name, ".") && strcmp(name, ".."))
137         {
138                 char temp[MAX_OSPATH];
139                 dpsnprintf( temp, sizeof( temp ), "%s%s", path, name );
140                 stringlistappend(list, temp);
141         }
142 }
143 #ifdef WIN32
144 #include <windows.h>
145 void listdirectory(stringlist_t *list, const char *basepath, const char *path)
146 {
147         int i;
148         char pattern[4096], *c;
149         WIN32_FIND_DATA n_file;
150         HANDLE hFile;
151         strlcpy (pattern, basepath, sizeof(pattern));
152         strlcat (pattern, path, sizeof (pattern));
153         strlcat (pattern, "*", sizeof (pattern));
154         // ask for the directory listing handle
155         hFile = FindFirstFile(pattern, &n_file);
156         if(hFile == INVALID_HANDLE_VALUE)
157                 return;
158         do {
159                 adddirentry(list, path, n_file.cFileName);
160         } while (FindNextFile(hFile, &n_file) != 0);
161         FindClose(hFile);
162
163         // convert names to lowercase because windows does not care, but pattern matching code often does
164         for (i = 0;i < list->numstrings;i++)
165                 for (c = list->strings[i];*c;c++)
166                         if (*c >= 'A' && *c <= 'Z')
167                                 *c += 'a' - 'A';
168 }
169 #else
170 #include <dirent.h>
171 void listdirectory(stringlist_t *list, const char *basepath, const char *path)
172 {
173         char fullpath[MAX_OSPATH];
174         DIR *dir;
175         struct dirent *ent;
176         dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, *path ? path : "./");
177         dir = opendir(fullpath);
178         if (!dir)
179                 return;
180         while ((ent = readdir(dir)))
181                 adddirentry(list, path, ent->d_name);
182         closedir(dir);
183 }
184 #endif
185