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