]> git.saurik.com Git - wxWidgets.git/blob - src/common/glob.inc
[ 1493802 ] Allow multiple wxComboCtrl::SetPopupControl calls.
[wxWidgets.git] / src / common / glob.inc
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: glob.inc
3 // Purpose: File and other globbing (included by utils.cpp)
4 // Author: Karsten Ballueder
5 // Modified by:
6 // Created: 20/5/1998
7 // RCS-ID: $Id$
8 // Copyright: (c) Karsten Ballueder
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // This file includes:
13 // wxIsWild(const char *pattern)
14 // wxMatchWild(const char *pattern, const char *str, bool dot_special)
15 //
16
17 //---------------------------------------------------------------------------------
18 #ifndef UNIX_GLOB
19 # ifdef wx_x
20 # define UNIX_GLOB 1
21 # else
22 # define UNIX_GLOB 0
23 # endif
24 #endif
25
26 #if UNIX_GLOB
27 # ifdef wx_msw
28 # error "Can't use Unix file globbing under Windows!"
29 # endif
30 #endif
31
32 /*************************************************************************
33 *
34 * wxIsWild checks whether the pattern contains wildcards, and
35 * returns TRUE if it does, and FALSE if it does not (or if the
36 * pattern is NULL -- i.e. no string).
37 *
38 * The argument is:
39 *
40 * 1) pattern - a character string
41 */
42 bool
43 wxIsWild (const char *pattern)
44 {
45 while (*pattern)
46 {
47 switch (*pattern++)
48 {
49 case '?':
50 case '*':
51 #if UNIX_GLOB
52 case '[':
53 case '{': /* } */
54 #endif
55 return TRUE;
56 #if UNIX_GLOB
57 case '\\':
58 if (!*pattern++)
59 return FALSE;
60 #endif
61 } /* switch() */
62 } /* while() */
63 return FALSE;
64 }
65
66
67
68 #if UNIX_GLOB
69
70 // Unix Glob()
71 //
72 // Pattern Function
73 // -----------------------------------------------------
74 // '*' = match 0 or more occurances of anything
75 // "[abc]" = match anyof "abc" (ranges supported)
76 // "{xx,yy,zz}" = match anyof "xx", "yy", or "zz"
77 // '?' = match any character
78 //
79 // '\' is used to "escape" special characters
80 // Recursive
81
82 bool
83 wxMatchWild (const char *pattern, const char *str, bool dot_special)
84 {
85 char c;
86 const char *cp;
87 bool done = FALSE, ret_code, ok;
88 // Below is for vi fans
89 const char OB = '{', CB = '}';
90
91 #if 0
92 if (strcmp(pattern, "*.*") == 0)
93 pattern = "*"; // Hack for MS-DOS compat.
94 #endif
95
96 // dot_special means '.' only matches '.'
97 if (dot_special && *str == '.' && *pattern != *str)
98 return FALSE;
99
100 while ((*pattern != '\0') && (!done) && (((*str == '\0') &&
101 ((*pattern == OB) || (*pattern == '*'))) || (*str != '\0')))
102 {
103 switch (*pattern)
104 {
105 case '\\':
106 pattern++;
107 if (*pattern != '\0')
108 pattern++;
109 break;
110 case '*':
111 pattern++;
112 ret_code = FALSE;
113 while ((*str != '\0') && (!(ret_code = wxMatchWild (pattern, str++, FALSE))));
114 if (ret_code)
115 {
116 while (*str != '\0')
117 str++;
118 while (*pattern != '\0')
119 pattern++;
120 }
121 break;
122 case '[':
123 pattern++;
124 repeat:
125 if ((*pattern == '\0') || (*pattern == ']'))
126 {
127 done = TRUE;
128 break;
129 }
130 if (*pattern == '\\')
131 {
132 pattern++;
133 if (*pattern == '\0')
134 {
135 done = TRUE;
136 break;
137 }
138 }
139 if (*(pattern + 1) == '-')
140 {
141 c = *pattern;
142 pattern += 2;
143 if (*pattern == ']')
144 {
145 done = TRUE;
146 break;
147 }
148 if (*pattern == '\\')
149 {
150 pattern++;
151 if (*pattern == '\0')
152 {
153 done = TRUE;
154 break;
155 }
156 }
157 if ((*str < c) || (*str > *pattern))
158 {
159 pattern++;
160 goto repeat;
161 }
162 }
163 else if (*pattern != *str)
164 {
165 pattern++;
166 goto repeat;
167 }
168 pattern++;
169 while ((*pattern != ']') && (*pattern != '\0'))
170 {
171 if ((*pattern == '\\') && (*(pattern + 1) != '\0'))
172 pattern++;
173 pattern++;
174 } // while()
175 if (*pattern != '\0')
176 {
177 pattern++, str++;
178 }
179 break;
180 case '?':
181 pattern++;
182 str++;
183 break;
184 case OB:
185 pattern++;
186 while ((*pattern != CB) && (*pattern != '\0'))
187 {
188 cp = str;
189 ok = TRUE;
190 while (ok && (*cp != '\0') && (*pattern != '\0') &&
191 (*pattern != ',') && (*pattern != CB))
192 {
193 if (*pattern == '\\')
194 pattern++;
195 ok = (*pattern++ == *cp++);
196 } // while()
197 if (*pattern == '\0')
198 {
199 ok = FALSE;
200 done = TRUE;
201 break;
202 }
203 else if (ok)
204 {
205 str = cp;
206 while ((*pattern != CB) && (*pattern != '\0'))
207 {
208 if (*++pattern == '\\')
209 {
210 if (*++pattern == CB)
211 pattern++;
212 }
213 } // while()
214 }
215 else
216 {
217 while (*pattern != CB && *pattern != ',' && *pattern != '\0')
218 {
219 if (*++pattern == '\\')
220 {
221 if (*++pattern == CB || *pattern == ',')
222 pattern++;
223 }
224 } // while()
225 }
226 if (*pattern != '\0')
227 pattern++;
228 } // while()
229 break;
230 default:
231 if (*str == *pattern)
232 {
233 str++, pattern++;
234 }
235 else
236 {
237 done = TRUE;
238 }
239 } // switch()
240 } // while()
241 while (*pattern == '*')
242 pattern++;
243 return ((*str == '\0') && (*pattern == '\0'));
244 }
245
246 #else /* MS-DOS/Windows glob() */
247 /*************************************************************************
248 *
249 * wxMatchWild matches the given pattern string against
250 * a text string, and returns TRUE if it matches, FALSE otherwise.
251 *
252 * A match means that the entire text string is used up in the matching.
253 * The pattern can contain the following wildcards.
254 *
255 * * -- matches any sequence of characters
256 * ? -- matches one character
257 *
258 * If one or other or both of the string arguments to wxMatchWild function is
259 * NULL (i.e. there isn't a string), then the function returns FALSE.
260 *
261 */
262 static bool wxPatternMatch (const char *pattern, const char *text, size_t i, size_t j);
263
264 // @@@@ dotSpecial is ignored by MS-DOS
265 bool
266 wxMatchWild (const char *pattern, const char *text, bool /* dotSpecial */ )
267 {
268 if (pattern == NULL || text == NULL || *pattern == '\0' || *text == '\0')
269 return FALSE;
270 return wxPatternMatch (pattern, text, 0, 0);
271 }
272
273 /*************************************************************************
274 *
275 * wxPatternMatch does the work for wxMatchWild. wxPatternMatch matches
276 * the given pattern string against a text string, and returns TRUE if
277 * it matches, FALSE otherwise. It is assumed that the string arguments
278 * to wxPatternMatch exist.
279 *
280 * A match means that the entire text string is used up in the matching.
281 * The pattern can contain the following wildcards.
282 *
283 * * -- matches any sequence of characters
284 * ? -- matches one character
285 *
286 * wxPatternMatch works by going down the pattern trying to match the
287 * the same index character in the pattern and string arrays, and stops
288 * when the end of the pattern or text string is reached. However, if a
289 * '*' wildcard is met, the algorithm checks to see whether the remaining
290 * pattern (after the wildcard) matches the rest of the text (i.e. the
291 * wxPatternMatch function is called recursively).
292 */
293 // Recursive
294 static bool
295 wxPatternMatch (const char *pattern, const char *text, size_t i, size_t j)
296 {
297 size_t pattern_length = strlen (pattern);
298 size_t text_length = strlen (text);
299 bool match = FALSE;
300
301 #ifdef wx_msw
302 // MS-DOS file system is case INDEPENDENT
303 # define EQU(x,y) (wxToLower(x) == wxToLower(y))
304 #else
305 # define EQU(x,y) ((x) == (y))
306 #endif
307
308 while (j < pattern_length && i < text_length)
309 {
310 if (EQU(text[i], pattern[j]) || pattern[j] == '?')
311 {
312 match = TRUE;
313 i++, j++;
314 }
315 else if (pattern[j] == '*')
316 {
317 // If pattern ends in '*'
318 if (++j == pattern_length)
319 {
320 match = TRUE;
321 i = text_length;
322 }
323 else
324 {
325 match = FALSE;
326 // after wildcard check to see whether rest of pattern matches
327 // up with rest of text
328 while (i < text_length && match != TRUE)
329 {
330 match = wxPatternMatch (pattern, text, i, j);
331 i++;
332 }
333 // text index is decremented so that it points to where
334 // the text string starts to match the rest of the pattern
335 i--;
336 }
337 }
338 else if (! EQU(text[i], pattern[j]))
339 {
340 j = pattern_length;
341 match = FALSE;
342 }
343 }
344 if (j == pattern_length && i == text_length && match == TRUE)
345 {
346 return TRUE;
347 }
348 else
349 // special case where pattern and text are the same except that pattern
350 // also only has '*' wildcards on the end
351 if (i == text_length && pattern[j] == '*' && match == TRUE)
352 {
353 for (; j < pattern_length; j++)
354 {
355 if (pattern[j] != '*')
356 return FALSE;
357 }
358 return TRUE;
359 }
360 else
361 {
362 return FALSE;
363 }
364 }
365
366 #endif /* UNIX_GLOB */
367 //-----------------------------------------------------------------------------