This is DynamicItemSpec.m in view mode; [Download] [Up]
/* 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
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.