home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / graf / macpnt1.zip / WILDCARD.C < prev    next >
Text File  |  1987-01-16  |  7KB  |  250 lines

  1.  
  2.  
  3. /*
  4.  ******************************************************************
  5.  * WILDCARD.C - routine to handle expansion of paths that may include
  6.  * wildcards in the filename. This routine was developed for MACPAINT
  7.  * in Jan 1987 by Joan Riff, but is self-contained and can be included
  8.  * in other packages relatively easily. Like MACPAINT.C, it is written
  9.  * for Microsoft C, version 3.0.
  10.  *
  11.  *
  12.  * (c) Copyright 1987 by:
  13.  *
  14.  *          Computerwise Consulting Services
  15.  *          P.O. Box 813
  16.  *          McLean, VA 22101
  17.  *          (703) 280-2809
  18.  *
  19.  * All rights reserved.
  20.  *
  21.  * Permission is granted for personal use of this program, with the
  22.  * exception that the following potential users ARE EXPLICITLY DENIED
  23.  * PERMISSION TO RECEIVE, USE, OR TRANSFER THIS PROGRAM IN SOURCE OR
  24.  * OBJECT OR EXECUTABLE OR ANY OTHER FORM:
  25.  *
  26.  *     1) Lotus Development Corporation, and any employee thereof
  27.  *        or consultant thereto;
  28.  *
  29.  *     2) ADAPSO, and any firm which is a member thereof, or any
  30.  *        employee of such a firm.
  31.  *
  32.  * These two organizations have - in the opinion of CCS - acted as
  33.  * "software pirates" by continually and intentionally violating
  34.  * U.S. Copyright law, specifically by first "copy-protecting" software
  35.  * disks and then zealously prosecuting innocent users who exercised
  36.  * their rights under the law to make copies of their own property.
  37.  *
  38.  * Further, permission is granted to transfer this program only if
  39.  * it is transferred absolutely unmodified in any form.
  40.  *
  41.  ******************************************************************
  42.  */
  43.  
  44. /*
  45.  * Handle wildcard paths.
  46.  *
  47.  * Use of this routine is a two-part process.
  48.  *
  49.  * In the first part, you call this routine with a func of 0, a path, and
  50.  * an attribute byte. The func of zero says "init yourself for subsequent
  51.  * calls". The path is the plain old path as a user may have typed it in.
  52.  * It may or may not contain wildcards "*" and "?", but if they are present
  53.  * then they had better reside ONLY in the filename part of the path. The
  54.  * attribute byte allows the caller to specify exactly what he's looking
  55.  * for:
  56.  *
  57.  *    Bit 0: Include Read-only files
  58.  *    Bit 1: Include Hidden files
  59.  *    Bit 2: Include System files
  60.  *    Bit 3: Search for the Volume Label. To use this, no other bits may
  61.  *           be set, and the path must identify some root directory.
  62.  *    Bit 4: Include directories
  63.  *    Bit 5: Include Archiveable files
  64.  *
  65.  * This routine then remembers all of this for later use, and returns NULL.
  66.  *
  67.  * In the second part, you call this routine with a func of 1 and dummy values
  68.  * for the path and attribute. It then returns the complete pathname of a
  69.  * file that matches your original pattern, or NULL of no more matches are
  70.  * found. If the name being returned is the name of a directory, then this
  71.  * routine appends a "\" character to the name.
  72.  *
  73.  * This second part is repeated until this routine returns a NULL. After each
  74.  * call you may do whatever you want to do with the returned filename before
  75.  * calling this routine again.
  76.  *
  77.  */
  78.  
  79. BYTE *wildcard( func, path, attrib )
  80. int func;                /* 0 (seed things) or 1 (return a name) */
  81. BYTE *path;                /* Raw input pathname (only if func = 0) */
  82. BYTE attrib;                /* Attribute bits (only if func = 0) */
  83. {
  84.     static struct
  85.         {
  86.         BYTE reserved[21];
  87.         BYTE attribute;
  88.         unsigned time;
  89.         unsigned date;
  90.         unsigned long size;
  91.         BYTE filename[13];
  92.         BYTE filler[85];
  93.         }
  94.         dta;
  95.  
  96.     static BYTE directory[65];
  97.     static BYTE filename[15];
  98.     static BYTE result[90];
  99.  
  100.     BYTE *p;
  101.  
  102.     static unsigned user_attrib;        /* Saved attrib */
  103.     static int first = -1;            /* Need "find first" ? */
  104.     static union REGS inregs, outregs;    /* For intdosx() */
  105.     static struct SREGS segregs;
  106.     static int seeded = 0;            /* Are we seeded for another search? */
  107.  
  108.     if (func == 0)
  109.         {
  110.  
  111.         /*
  112.          * Seed things for subsequent searches
  113.          */
  114.  
  115.         memcpy(directory, path, 64);            /* Save raw path */
  116.         directory[64] = '\0';                /* Truncate to be safe */
  117.  
  118.         /*
  119.          * Look for a divider between directory and filename
  120.          */
  121.  
  122.         p = strrchr(directory, '\\');            /* Try '\' first */
  123.  
  124.         if ( p == NULL )
  125.             {
  126.             p = strrchr( directory, ':' );        /* No '\', so try for ':' */
  127.             }
  128.  
  129.         if ( p == NULL )                /* Any delimiter? */
  130.             {
  131.  
  132.             /*
  133.              * No delimiter found. Assume that path was just
  134.              * a filename.
  135.              */
  136.  
  137.             memcpy( filename, directory, 13 );
  138.             directory[0] = '\0';
  139.             filename[12] = '\0';
  140.             }
  141.         else
  142.             {
  143.  
  144.             /*
  145.              * We found a delimiter. Keep everything up to it
  146.              * so that we can prepend this to found filenames,
  147.              * but copy everything after it as the prototype
  148.              * filename pattern.
  149.              */
  150.  
  151.             memcpy(filename, ++p, 13);
  152.             filename[12] = '\0';
  153.             *p = '\0';
  154.             }
  155.  
  156.         /*
  157.          * Set flags for later use
  158.          */
  159.  
  160.         seeded = -1;            /* Enable search */
  161.         first = -1;            /* Need "find first" */
  162.         user_attrib = attrib;        /* Save his attribute byte */
  163.         return(NULL);
  164.         }
  165.  
  166.     /*
  167.      * Not a "seed things" call, so get set to return a matching filename.
  168.      */
  169.  
  170.     if ( !seeded )
  171.         {
  172.  
  173.         /*
  174.          * Last try failed, so why even try again
  175.          */
  176.  
  177.         return(NULL);
  178.         }
  179.  
  180.     /*
  181.      * Point DOS's opinion of the current DTA to our own DTA
  182.      */
  183.  
  184.     p = (BYTE *) &dta;            /* So that we can use FP_SEG() and FP_OFF() */
  185.     segregs.ds = FP_SEG(p);
  186.     inregs.x.dx = FP_OFF(p);
  187.     inregs.h.ah = 0x1a;
  188.     intdosx( &inregs, &outregs, &segregs);
  189.  
  190.     /*
  191.      * Set up regs for either a "find first" or a "find next"
  192.      */
  193.  
  194.     if ( first )
  195.         {
  196.  
  197.         first = 0;
  198.  
  199.         /*
  200.          * We need to do a "find first". Construct original pathname
  201.          * from directory and filename. This is what DOS uses as a
  202.          * starting point. From then on, it uses info in the DTA.
  203.          */
  204.  
  205.         sprintf( result, "%s%s", directory, filename );
  206.  
  207.         p = result;            /* So that we can use FP_SEG() and FP_OFF() */
  208.         segregs.ds = FP_SEG(p);
  209.         inregs.x.dx = FP_OFF(p);
  210.         inregs.x.cx = user_attrib;
  211.         inregs.h.ah = 0x4e;
  212.         }
  213.     else
  214.         {
  215.  
  216.         /*
  217.          * We are to do a "find next". All info is in the DTA.
  218.          */
  219.  
  220.         inregs.h.ah = 0x4f;
  221.         }
  222.  
  223.     /*
  224.      * Now ask DOS for the first or next matching file.
  225.      */
  226.  
  227.     intdosx( &inregs, &outregs, &segregs );
  228.  
  229.     if ( outregs.x.cflag )            /* Error? */
  230.         {
  231.         seeded = 0;            /* Yes, remember this */
  232.         return(NULL);
  233.         }
  234.  
  235.     /*
  236.      * Put the filename returned by DOS together with our original
  237.      * directory, to give the user something that he can call OPEN with.
  238.      */
  239.  
  240.     sprintf( result, "%s%s", directory, dta.filename );
  241.  
  242.     if ( dta.attribute & 0x10 )        /* Directory? */
  243.         {
  244.         strcat( result, "\\");        /* Yes, add '\' to end */
  245.         }
  246.  
  247.     return( result );
  248. }
  249.  
  250.