This is IconMosaicView.m in view mode; [Download] [Up]
/* IconMosaicView.m -- copyright 1993 by Christopher Lane */ #import <c.h> #import <sys/dir.h> #import <mach-o/loader.h> #import <appkit/appkit.h> #import "Thinker.h" #import "DefaultsTable.h" #import "IconMosaicView.h" #define MODULE "IconMosaic" #define DEFAULTSFILE "Defaults.strings" #define IMAGEPATHS getDefault("IconMosaicImagePaths") #define SEGMENTLIST getDefault("IconMosaicSegmentList") #define IMAGESUFFIXLIST getDefault("IconMosaicImageSuffixList") #define APPSUFFIXLIST getDefault("IconMosaicApplicationSuffixList") #define IGNORESECTIONLIST getDefault("IconMosaicIgnoreSectionList") #define MAXIMUMSIZE getSizeDefault("IconMosaicMaximumSize") #define MAXIMUMBYTES getIntDefault("IconMosaicMaximumBytes") #define DENSITYDEFAULTNAME "IconMosaicDensity" #define DENSITY getFloatDefault(DENSITYDEFAULTNAME) #define PATHSEPARATOR "/" #define PATHSEPARATORCHAR (PATHSEPARATOR)[0] #define TOKENSEPARATOR ":" #define TOKENSEPARATORCHAR (TOKENSEPARATOR)[0] #define EXTENSIONSEPARATOR "." #define EXTENSIONSEPARATORCHAR (EXTENSIONSEPARATOR)[0] @implementation IconMosaicView static any_t search(id self) { char *path, *paths = NXCopyStringBuffer(IMAGEPATHS); for(path = strtok(paths, TOKENSEPARATOR); path != NULL; path = strtok(NULL, TOKENSEPARATOR)) [self loadImagesFromDirectory:path]; NX_FREE(paths); return self; } - initFrame:(NXRect *) frameRect { char buffer[MAXPATHLEN]; [super initFrame:frameRect]; [self allocateGState]; images = [[List alloc] init]; inspector = field = nil; thread = NO_CTHREAD; lock = mutex_alloc(); condition = condition_alloc(); (void) sprintf(buffer,"%s/%s", [[NXApp delegate] moduleDirectory:MODULE], DEFAULTSFILE); [(defaults = [[DefaultsTable alloc] initFromFile:buffer]) registerDefaults:[NXApp appName]]; maximumSize = MAXIMUMSIZE; maximumBytes = MAXIMUMBYTES; srandom(time(NULL)); return self; } - drawSelf:(const NXRect *) rects :(int) rectCount { if (rects == NULL || rectCount == 0) return self; PSsetgray(NX_BLACK); NXRectFill(rects); return self; } - didLockFocus { if(thread == NO_CTHREAD) cthread_detach(thread = cthread_fork((cthread_fn_t) search, (any_t) self)); return self; } - free { mutex_lock(lock); { [[images freeObjects] free]; (void) cthread_abort(thread); } mutex_unlock(lock); return [super free]; } - oneStep { id image; NXSize size; unsigned int count; NXPoint point = { 0, 1 }; condition_signal(condition); [self scrollRect:&bounds by:&point]; if(((random() % 100) / 100.0) > [density floatValue]) return self; mutex_lock(lock); { count = [images count]; } mutex_unlock(lock); if(count < 1) return self; mutex_lock(lock); { [(image = [images objectAt:(random() % count)]) getSize:&size]; } mutex_unlock(lock); point.x = random() % (int) (bounds.size.width - size.width); [image composite:NX_SOVER toPoint:&point]; if(field != nil && [field intValue] < count) [field setIntValue:count]; return self; } - inspector:sender { char buffer[MAXPATHLEN]; if (inspector == nil) { (void) sprintf(buffer,"%s/%s.nib", [sender moduleDirectory:MODULE], MODULE); [NXApp loadNibFile:buffer owner:self withNames:NO]; } return inspector; } - inspectorInstalled { mutex_lock(lock); { [field setIntValue:[images count]]; } mutex_unlock(lock); return self; } - (BOOL) useBufferedWindow { return YES; } - (const char *) windowTitle { return MODULE; } - setDefault:sender { [sender setTag:YES]; if([density tag]) (void) writeDefault(DENSITYDEFAULTNAME, [density stringValue]); return self; } - setDensity:anObject { [(density = anObject) setFloatValue:DENSITY]; return self; } - (BOOL) loadFromStream:(NXStream *) stream { NXSize size; BOOL result = NO; NXImage *image = [[NXImage alloc] init]; if([image loadFromStream:stream]) { [image getSize:&size]; if(size.width <= maximumSize.width && size.height <= maximumSize.height) { mutex_lock(lock); { [images addObject:image]; condition_wait(condition, lock); } mutex_unlock(lock); result = YES; } else [image free]; } else [image free]; return result; } - (BOOL) member:(const char *) item ofSet:(const char *) set { BOOL result = NO; char *r, *s, *buffer = NXCopyStringBuffer(set); int index, length, itemLength = strlen(item); r = buffer; while((s = r) != NULL) { if((r = index(s, TOKENSEPARATORCHAR)) != NULL) *r++ = '\0'; if((length = strlen(s)) > itemLength) continue; else index = itemLength - length; if(result = (strncmp(s, item + index, length) == 0)) break; } NX_FREE(buffer); return result; } - loadImagesFromDirectory:(const char *) directory { struct stat fs; NXStream *stream; struct direct *dp; char buffer[MAXPATHLEN]; DIR *dirp = opendir(directory); if(dirp == NULL) return nil; for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { (void) strcat(strcat(strcpy(buffer, directory), PATHSEPARATOR), dp->d_name); if(stat(buffer, &fs) == CERROR) continue; else if(fs.st_mode & S_IFDIR && (dp->d_name)[0] != EXTENSIONSEPARATORCHAR) [self loadImagesFromDirectory:buffer]; else if(fs.st_size <= maximumBytes && [self member:dp->d_name ofSet:IMAGESUFFIXLIST]) { if((stream = NXMapFile(buffer, NX_READONLY)) != NULL) { if([self loadFromStream:stream]) { #ifdef DEBUG (void) fprintf(stderr, "%s\n", buffer); } else { (void) fprintf(stderr, "%s -- failed\n", buffer); #endif } NXCloseMemory(stream, NX_FREEBUFFER); } } else if(fs.st_mode & S_IEXEC && fs.st_mode & S_IFREG) [self loadImagesFromSegment:buffer]; } (void) closedir(dirp); return self; } - loadImagesFromSegment:(const char *) filename { long offset; char *buffer; unsigned int i; NXStream *stream, *memory; unsigned long ncmds, nsects; struct mach_header m_header; struct load_command l_command; struct segment_command s_command; struct section s_section; if ((stream = NXMapFile(filename, NX_READONLY)) == NULL) return nil; if (NXRead(stream, &m_header, sizeof(m_header)) == sizeof(m_header) && m_header.magic == MH_MAGIC) { for (ncmds = m_header.ncmds; ncmds > 0; ncmds--) { offset = NXTell(stream); if (NXRead(stream, &l_command, sizeof(l_command)) != sizeof(l_command)) break; if (l_command.cmd == LC_SEGMENT) { NXSeek(stream, offset, NX_FROMSTART); if (NXRead(stream, &s_command, sizeof(s_command)) != sizeof(s_command)) break; if([self member:s_command.segname ofSet:SEGMENTLIST]) { for (nsects = 0; nsects < s_command.nsects; nsects++) { if (NXRead(stream, &s_section, sizeof(s_section)) != sizeof(s_section)) continue; else if(s_section.size > maximumBytes || [self member:s_section.sectname ofSet:IGNORESECTIONLIST]) continue; offset = NXTell(stream); NXSeek(stream, s_section.offset, NX_FROMSTART); (void) vm_allocate(task_self(), (vm_address_t *) &buffer, (vm_size_t) s_section.size, TRUE); for (i = 0; i < s_section.size; i++) buffer[i] = NXGetc(stream); if((memory = NXOpenMemory(buffer, s_section.size, NX_READONLY)) != NULL) { if([self loadFromStream:memory]) { #ifdef DEBUG (void) fprintf(stderr, "%s:%s:%s\n", filename, s_section.segname, s_section.sectname); } else { (void) fprintf(stderr, "%s:%s:%s -- failed\n", filename, s_section.segname, s_section.sectname); #endif } NXCloseMemory(memory, NX_FREEBUFFER); } NXSeek(stream, offset, NX_FROMSTART); } } else NXSeek(stream, s_command.cmdsize - sizeof(s_command), NX_FROMCURRENT); } else NXSeek(stream, l_command.cmdsize - sizeof(l_command), NX_FROMCURRENT); } } NXCloseMemory(stream, NX_FREEBUFFER); return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.