home *** CD-ROM | disk | FTP | other *** search
-
- /*
- Copyright 1993 Jeremy Slade.
-
- You are free to use all or any parts of the Locus project
- however you wish, just give credit where credit is due.
- The author (Jeremy Slade) shall not be held responsible
- for any damages that result out of use or misuse of any
- part of this project.
-
- */
-
- /*
- Project: Locus
-
- File: DynamicItemSpec.m
-
- Description: See DynamicItemSpec.h
-
- Original Author: Jeremy Slade
-
- Revision History:
- Created
- V.101 JGS Tue Feb 2 19:11:44 GMT-0700 1993
-
- */
-
-
- #import "DynamicItemSpec.h"
-
- #import "DynamicItems.h"
- #import "Globals.h"
- #import "Group.h"
- #import "ItemCell.h"
-
- #import <regex.h>
- #import <sys/dir.h>
- #import <sys/types.h>
-
-
- @implementation DynamicItemSpec
-
-
- // -------------------------------------------------------------------------
- // Creating, initializing
- // -------------------------------------------------------------------------
-
-
- + initialize
- {
- [self setVersion:DynamicItemSpec_VERSION];
- return ( self );
- }
-
-
-
- - initExpr:(const char *)aString
- {
- [super init];
-
- [self setExpression:aString];
- enabled = YES;
-
- return ( self );
- }
-
-
-
- - free
- {
- if ( expression ) NX_FREE ( expression );
- if ( regexpr ) NX_FREE ( regexpr );
- return ( [super free] );
- }
-
-
-
- // -------------------------------------------------------------------------
- // Expression
- // -------------------------------------------------------------------------
-
-
- - setExpression:(const char *)aString
- {
- if ( expression ) NX_FREE ( expression );
- if ( regexpr ) NX_FREE ( regexpr ); regexpr = NULL;
-
- expression = aString ? NXCopyStringBuffer ( aString ) : NULL;
-
- return ( self );
- }
-
-
-
- - (const char *)expression
- {
- return ( expression );
- }
-
-
-
- - (const char *)regexpression
- /*
- Translate the shell-style globbing expression into a regular expression so we can use it with recmp.
- */
- {
- char buf[MAXPATHLEN+1] = "";
- char *in, *out;
-
- if ( regexpr )
- return ( regexpr );
-
- // Translate the expression. Following is a brief summary of the
- // translation:
- // '.' is replaced with '\.'
- // '?' is replaced with '.'
- // '*' is replaced with '.*'
- // '[a-z]' is left the same
- // '[!a-z]' is replaced with '[^a-z]'
-
- // Only include part of expression after last '/'
- if ( in = rindex ( expression, '/' ) ) in++;
- else in = expression;
-
- out = buf;
- *out++ = '^';
- while ( *in ) {
- switch ( *in ) {
- case 0x2e: // Period -- '.'
- *out++ = '\\'; *out++ = '.';
- in++;
- break;
- case 0x3f: // Question Mark -- '?'
- *out++ = '.';
- in++;
- break;
- case 0x2a: // Asterisk -- '*'
- *out++ = '.'; *out++ = '*';
- in++;
- break;
- case 0x5b: // Left bracket -- '['
- *out++ = '['; in++; // Output left bracket, move to next char
- if ( *in == '!' ) *out++ = '^'; // Test for next char being '!'
- else *out++ = *in;
- in++;
- while ( *in != ']' && *in != '\0' ) {
- // Output until right bracket
- *out++ = *in++;
- }
- *out++ = ']'; // Output the right bracket
- in++;
- break;
- default: *out++ = *in++;
- }
- }
- *out++ = '$';
- *out = '\0'; // Make sure output is terminated
-
- regexpr = NXCopyStringBuffer ( buf );
- return ( regexpr );
- }
-
-
-
- - setEnabled:(BOOL)flag
- {
- enabled = flag;
- return ( self );
- }
-
-
-
- - (BOOL)enabled
- {
- return ( enabled );
- }
-
-
-
- // -------------------------------------------------------------------------
- // Scanning for Matching Items
- // -------------------------------------------------------------------------
-
-
- const char *match; // Used by matchItems(), set before each search
-
- - addMatchingItemsToGroup:group
- /*
- Scan the directories for all items matching our expression and add them to the group.
- */
- {
- struct direct **namelist;
- int i, count;
- int matchItems ( struct direct *dp );
- char path[MAXPATHLEN+1], *s;
- id newItem;
-
- if ( !expression || !enabled )
- return ( self );
-
- match = [self regexpression]; // assign our expression to the global
-
- // If the expression specifies a full path, search that path
- if ( expression[0] == '/' ) {
- if ( s = rindex ( expression, '/' ) ) *s = '\0';
- strcpy ( path, expression );
- if ( s ) *s = '/';
- } else
-
- // expression has '/' in it, must be a relative path
- if ( index ( expression, '/' ) ) {
- if ( [group defaultPath] ) {
- if ( s = rindex ( expression, '/' ) ) *s = '\0';
- sprintf ( path, "%s/%s", [group defaultPath], expression );
- if ( s ) *s = '/';
- } else
- return ( self ); // No default path specified,
- // can't use relative expression
- } else
-
- // Just do search in the group's defaultPath
- if ( [group defaultPath] ) {
- strcpy ( path, [group defaultPath] );
- } else
- return ( self ); // Don't have a path to search
-
- // Perform the search using scandir()...
- count = scandir ( path, &namelist, matchItems, NULL );
-
- // Add list of matched files to the group...
- // set s to end of path string so we can just append the matching
- // items to create the full path.
- s = path + strlen(path) -1;
- if ( *s != '/' ) {
- strcat ( path, "/" );
- s++;
- }
- s++;
- for ( i=0; i<count; i++ ) {
- strcpy ( s, namelist[i]->d_name );
- newItem = [[ItemCell alloc] initPath:path];
- [[newItem setDynamic:YES] setGroup:group];
- [group addDynamicItem:newItem];
- free ( namelist[i] );
- }
- if ( count != -1 ) free ( namelist );
-
- return ( self );
- }
-
-
-
- int matchItems ( struct direct *dp )
- /*
- This is the matching function used by scandir(). Match the specified entry against the current regular expression defined by match.
- */
- {
- if ( !strcmp ( dp->d_name, "." ) || !strcmp ( dp->d_name, ".." ) )
- return ( 0 );
- else
- return ( (!recmp ( (char *)match, dp->d_name )) ? 1 : 0 );
- }
-
-
-
- // -------------------------------------------------------------------------
- // Archiving
- // -------------------------------------------------------------------------
-
-
- - awake
- {
- [super awake];
-
- // Ignore archived regular expression -- generate it again
- if ( regexpr ) {
- NX_FREE ( regexpr );
- regexpr = NULL;
- }
-
- return ( self );
- }
-
-
-
- - read:(NXTypedStream *)stream
- {
- int versionNumber;
-
- [super read:stream];
-
- versionNumber = NXTypedStreamClassVersion ( stream, [[self class] name] );
-
- if ( versionNumber <= DynamicItemSpec_VERSION ) { // thru current version
- NXReadTypes ( stream, "**s",
- &expression,
- ®expr,
- &enabled );
- }
-
- else { // Unrecongized version!
- [self errMsg:"DynamicItemSpec: unrecognized version %i of archived object!\n", versionNumber];
- }
-
- return ( self );
- }
-
-
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
-
- NXWriteTypes ( stream, "**s",
- &expression,
- ®expr,
- &enabled );
-
- return ( self );
- }
-
-
-
- @end
-
-