home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / glob.inc < prev    next >
Text File  |  1998-05-20  |  9KB  |  362 lines

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