This is Background.m in view mode; [Download] [Up]
// #import <math.h> #include <sys/stat.h> #import "Background.h" #import <dpsclient/wraps.h> #import <appkit/Application.h> #import <objc/hashtable.h> #import <defaults/defaults.h> #import "PSsplat.h" #import <appkit/OpenPanel.h> #import <appkit/Control.h> #import <appkit/Menu.h> #import <appkit/MenuCell.h> #import <appkit/Matrix.h> #import <appkit/nextstd.h> #define PSsplat( r, p) _PSsplat( (r)->origin.x, (r)->origin.y, \ (r)->size.width, (r)->size.height, (p)->x, (p)->y) // @implementation Background:View // // void handler(DPSTimedEntry teNumber, double now, id background) { [background next:nil]; } - initFrame:(const NXRect *)frameRect { char *d,*f; int len; [super initFrame:frameRect]; imageNames = NULL; imageTimes = NULL; images = NULL; imageCount = 0; max = 0; current = 0; d = getenv("HOME"); if (!d) d=""; f = ".background"; len = strlen(d) + 1 + strlen(f) + 1; defaultfile = NX_ZONEMALLOC([self zone], defaultfile, char, len); strcpy(defaultfile, d); strcat(defaultfile,"/"); strcat(defaultfile,f); timer = NULL; repeat = 600; permanent = NO; updateMenu = YES; return self; } - reset { int i; for (i=0; i<imageCount; i++) { NXZoneFree([self zone], imageNames[i]); if(images[i]) [images[i] free]; } if (imageCount) { NXZoneFree([self zone], imageNames); NXZoneFree([self zone], imageTimes); NXZoneFree([self zone], images); } imageCount=0; current=0; return self; } - free { [self reset]; if (timer) DPSRemoveTimedEntry(timer); return [super free]; } // - loadImageNamed:(const char *)aName { // printf("Loading %s.\n", aName); if ([self getImage:aName]<0) return nil; return self; } - setImageNamed:(const char *)aName { int i; i = [self getImage:aName]; if (i>=0) [self setImage:i]; else return nil; return self; } - setRepeatValue:(float)r { char str[7]; repeat = r; if (timer) DPSRemoveTimedEntry(timer); if (repeat<1) { strcpy(str,"off"); timer=NULL; } else { if (r<60) sprintf(str,"%2ds",(int)r); else if (r<3600) sprintf(str,"%2dmin",(int)(r/60)); else sprintf(str,"%2dh",(int)(r/3600)); timer = DPSAddTimedEntry(repeat, (DPSTimedEntryProc)handler, self, NX_BASETHRESHOLD); } [repeatText setStringValue:str]; [repeatSlider setFloatValue:log(r+1)/12]; // printf("Setting repeat to %s.\n", str); [self writeDefault]; return self; } - setRepeatText:aText { repeatText = aText; return self; } - setRepeatSlider:aSlider { repeatSlider = aSlider; return self; } - setPermanent:(BOOL)flag { permanent = flag; return self; } // // target/action // - open:sender { OpenPanel *op=[OpenPanel new]; char *types[]={ "tiff", "eps", NULL}; char *directory, *filename, *fn; const char *d; const char * const *files; int l, len, ind; if( !imageCount) { directory=getenv( "HOME"); if( !directory) directory="/"; filename=NXCopyStringBufferFromZone("", [self zone]); } else { fn=NXCopyStringBufferFromZone(imageNames[current], [self zone]); if (filename=rindex(fn, '/')) *filename++='\0', directory=fn; else { filename=imageNames[current]; directory=getenv( "HOME"); if( !directory) directory="/"; } } ind = current; [op allowMultipleFiles:YES]; if( [op runModalForDirectory:directory file:filename types:types]) { len = 0; for (files=[op filenames]; *files; files++) if ((l=strlen(*files))>len) len=l; len += strlen(d=[op directory])+2; NX_ZONEMALLOC([self zone], fn, char, len); strcpy(fn,d); strcat(fn,"/"); filename=rindex(fn, '/')+1; for (files=[op filenames]; *files; files++) { strcpy(filename,*files); if ((l=[self getImage:fn])>0) ind = l; } } [self setImage:ind]; [self writeDefault]; return self; } - next:sender { if (++current>=imageCount) current=0; [self setImage:current]; return self; } - resize:sender { char *p; p = imageNames[current]; if (p[0]=='*') { NX_ZONEMALLOC([self zone], imageNames[current], char, strlen(p)); strcpy(imageNames[current], p+1); NXZoneFree([self zone], p); [images[current] free]; images[current]=nil; } else { NX_ZONEMALLOC([self zone], imageNames[current], char, strlen(p)+2); strcpy(imageNames[current],"*"); strcat(imageNames[current],p); NXZoneFree([self zone], p); } [self resizeImage:current]; [self setImage:current]; [self writeDefault]; return self; } - previous:sender { if (--current<0) current=imageCount-1; [self setImage:current]; return self; } - redraw:sender { [self display]; return self; } - select:sender { sender = [sender selectedCell]; updateMenu=NO; [self setImageNamed:[sender title]]; updateMenu=YES; return self; } - toFront:sender { PSsetwindowlevel( NX_DOCKLEVEL+1, [window windowNum]); [window orderFront:sender]; [window addToEventMask:NX_MOUSEDOWNMASK]; return self; } - toTop:sender { int i; char *n; time_t t; id img; n = imageNames[current]; t = imageTimes[current]; img = images[current]; for (i=current; i>0; i--) { imageNames[i] = imageNames[i-1]; imageTimes[i] = imageTimes[i-1]; images[i] = images[i-1]; } imageNames[0] = n; imageTimes[0] = t; images[0] = img; current = 0; [self setImage:current]; [self writeDefault]; return self; } - delete:sender { int i; for (i=current; i<imageCount; i++) { imageNames[i] = imageNames[i+1]; imageTimes[i] = imageTimes[i+1]; images[i] = images[i+1]; } imageCount--; if (current>=imageCount && current>0) current--; [self setImage:current]; [self writeDefault]; return self; } - deleteAll:sender { [self reset]; [self setImage:current]; return self; } - takeRepeatValueFrom:sender { [self setRepeatValue:exp(12*[sender floatValue])-1]; return self; } /// /// Menu generation /// - setMenu:aMenuCell { menu = [aMenuCell target]; [self updateMenu]; return self; } - updateMenu { id cell; id matrix; int i; if (!updateMenu) return self; matrix = [menu itemList]; while([matrix cellCount]) [matrix removeRowAt:0 andFree:YES]; [menu setItemList:matrix]; for (i=0; i<imageCount; i++) { cell = [menu addItem:imageNames[i] action:@selector(select:) keyEquivalent:0]; [cell setTarget:self]; } [menu display]; return self; } // // private: // - (int)getImage:(const char *)aName { int i; if (aName==NULL) return -1; for (i=0; i<imageCount; i++) if (strcmp(aName, imageNames[i])==0) break; if (i>=imageCount) { if (++imageCount>max) { if (!max) { imageNames = NX_ZONEMALLOC([self zone], imageNames, char *, 1); imageTimes = NX_ZONEMALLOC([self zone], imageTimes, time_t, 1); images = NX_ZONEMALLOC([self zone], images, NXImage *, 1); max = 1; } else { max *= 2; imageNames = NX_ZONEREALLOC([self zone], imageNames, char *, max); imageTimes = NX_ZONEREALLOC([self zone], imageTimes, time_t, max); images = NX_ZONEREALLOC([self zone], images, NXImage *, max); } } imageNames[i]=NXCopyStringBufferFromZone(aName, [self zone]); images[i] = nil; } return i; } - setImage:(int)i { struct stat sb; char *p; int flag; if (i>=0 && i<imageCount) { if (imageNames[i][0]=='*') p=imageNames[i]+1; else p=imageNames[i]; flag = stat(p, &sb); if (!images[i] || (flag==0 && imageTimes[i]<sb.st_mtime)) { images[i]=[[NXImage allocFromZone:[self zone]] initFromFile:p]; imageTimes[i]=sb.st_mtime; if (imageNames[i][0]=='*') [self resizeImage:i]; } current = i; } [self updateMenu]; [self display]; return self; } - resizeImage:(int)i { const NXScreen *screen; NXSize size; if (i>=0 && i<imageCount && images[i]) { screen = [window screen]; size = screen->screenBounds.size; [images[i] setScalable:YES]; [images[i] setSize:&size]; } return self; } // // read and write defaults // - readDefault { char p[256], f[256]; NXStream *s; FILE *temp; int ret; // pictures==NXReadDefault( "Background", "Image"); if (s=NXMapFile(defaultfile, NX_READONLY)) { while (NXScanf(s, " %255[^ \n=]%1[ \n]", p, f)==2) [self loadImageNamed:p]; ret = 1; while (ret && (ret=NXScanf(s," = \"%255[^\n\"]\" ", f))!=EOF) { // printf("Default read: %s = %s.\n", p, f); if (strncmp(p, "rep", 3)==0) [self setRepeatValue:atof(f)]; else printf("Illegal default in %s: %s=%s.\n", defaultfile, p, f); ret=NXScanf(s," %255[^=\n] ", p); } NXCloseMemory(s, NX_FREEBUFFER); [self setImage:0]; } else { fprintf(stderr, "Could not read from %s - creating it.\n", defaultfile); temp = fopen(defaultfile, "w"); fclose(temp); } return self; } - writeDefault { int i; NXStream *s; s = NXOpenMemory(NULL, 0, NX_WRITEONLY) ; for (i=0; i<imageCount; i++) NXPrintf(s,"%s ",imageNames[i]); NXPrintf(s, " \nrepeat=\"%g\"\n", repeat); if (NXSaveToFile(s, defaultfile)<0) { printf("Could not write to %s.\n", defaultfile); exit(1); } NXCloseMemory(s, NX_FREEBUFFER); // NXWriteDefault( "Background", "Image", p); // Crashes default database return self; } // - mouseDown:(NXEvent *)event { PSsetwindowlevel( -1, [window windowNum]); [window orderWindow:NX_ABOVE relativeTo:0]; [window removeFromEventMask:NX_MOUSEDOWNMASK]; return self; } - (BOOL)acceptsFirstMouse { return YES; } - drawSelf:(NXRect *)r :(int)count { PSsetgray( NX_DKGRAY); NXRectFill( &bounds); if (permanent) { printf("Making permanent.\n"); PSputback(); } if(imageCount) { int i; NXSize s; NXSize screenSize; NXPoint p={ 0, 0}; NXRect r={ p}; [NXApp getScreenSize:&screenSize]; [images[current] getSize:&s]; r.size=s; // printf("Drawing image %s: [%g,%g].\n",imageNames[current],s.width,s.height); if (s.width>0 && s.height>0) { [images[current] composite:NX_COPY toPoint:&p]; for( i=s.width; i<screenSize.width; i+=s.width) { p.x=i; PSsplat( &r, &p); } p.x=0; r.size.width=screenSize.width; for( i=s.height; i<screenSize.height; i+=s.height) { p.y=i; PSsplat( &r, &p); } } } return self; } // - windowDidBecomeKey:sender { PSsetwindowlevel( NX_DOCKLEVEL+1, [sender windowNum]); return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.