]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/glob.inc
[ 1509599 ] 'Split pickers page in widgets sample' with more icons and rebaking.
[wxWidgets.git] / src / common / glob.inc
... / ...
CommitLineData
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 */
42bool
43wxIsWild (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
82bool
83wxMatchWild (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 */
262static bool wxPatternMatch (const char *pattern, const char *text, size_t i, size_t j);
263
264// @@@@ dotSpecial is ignored by MS-DOS
265bool
266wxMatchWild (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
294static bool
295wxPatternMatch (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//-----------------------------------------------------------------------------