Added initial OS X implementation of the wxDataViewCtrl
[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 //-----------------------------------------------------------------------------