This is TVController.m in view mode; [Download] [Up]
#import <appkit/OpenPanel.h> #import <appkit/publicWraps.h> #import <appkit/Application.h> #import <appkit/Listener.h> #import <appkit/NXImage.h> #import <appkit/PrintInfo.h> #import <appkit/Pasteboard.h> #import <stdio.h> #import <stdlib.h> #import <string.h> #import <sys/types.h> #import <sys/stat.h> #import <sys/file.h> #import "TVController.h" #import "PrefControl.h" #import "ToyWin.h" #import "ToyWinPPM.h" #import "ToyWinEPS.h" #import "ToyWinBMP.h" #import "ToyWinGIF.h" #import "ToyWinPCD.h" #import "DirList.h" #import "ADController.h" #import "strfunc.h" #import "Exttab.h" #import "common.h" TVController *theController = NULL; @implementation TVController #define typeNumber 18 /* ToyViewer treats these extensions as pre-defined */ static const char *const fileType[typeNumber + 1] = { "tiff", "tif", "TIFF", "TIF", "eps", "EPS", "gif", "GIF", "bmp", "BMP", "dib", "DIB", "ppm", "pgm", "pbm", "pnm", "pcd", "PCD", NULL }; static const char fileTypeID[typeNumber] = { Type_tiff, Type_tiff, Type_tiff, Type_tiff, Type_eps, Type_eps, Type_gif, Type_gif, Type_bmp, Type_bmp, Type_bmp, Type_bmp, Type_ppm, Type_ppm, Type_ppm, Type_ppm, Type_pcd, Type_pcd }; /* extern */ const char **fileTypeBuffer; /* extern */ short *fileTypeIDBuffer; static char odir[MAXFILENAMELEN]; /* Last Opened Directory */ static Exttab *extTable; /* If file has no extension, this func. recognize its file type */ static int discriminate(const char *fn) { int maybe = Type_none; int cc; FILE *fp; if ((fp = fopen(fn, "r")) == NULL) return Type_none; switch (cc = getc(fp)) { case 0x0a: maybe = Type_pcx; break; case '%': maybe = Type_eps; break; case 'B': maybe = Type_bmp; break; case 'G': maybe = Type_gif; break; case 'I': maybe = Type_tiff; break; case 'M': maybe = Type_mag; break; case 'P': maybe = Type_ppm; break; case 0x89: maybe = Type_png; break; case 0xff: if (getc(fp) == 0xd8) maybe = Type_jpg; break; default: break; } fclose(fp); return maybe; } - appDidInit:sender { int i, j, n; char buf[MAXFILENAMELEN], *p, **q; NXCoord lmg, rmg, tmg, bmg; const char *sendTypes[3]; const char *returnTypes[3]; const char *const *types = [NXImage imageFileTypes]; // [preference init]; if (thePreference == NULL) thePreference = preference; theController = self; extTable = [[Exttab alloc] init]; n = dircopy(buf, NXArgv[0], YES); strcpy(&buf[n], toyviewerTAB); [extTable readExtData: buf]; p = getenv("HOME"); sprintf(buf, "%s/%s", p, toyviewerRC); [extTable readExtData: buf]; sprintf(buf, "%s/Library/ToyViewer/rc.%s", p, __ARCHITECTURE__); [extTable readExtData: buf]; n = [extTable entry]; for (i = 0; types[i]; i++) ; n += i + typeNumber + 1; fileTypeBuffer = (const char **)malloc(sizeof(char *const *) * n); fileTypeIDBuffer = (short *)malloc(sizeof(short) * n); i = 0; if ((q = [extTable table]) != NULL) for (j = 0; q[j]; j++) { fileTypeBuffer[i] = q[j]; fileTypeIDBuffer[i++] = Type_user; } for (j = 0; fileType[j]; j++) { fileTypeBuffer[i] = fileType[j]; fileTypeIDBuffer[i++] = fileTypeID[j]; } for (j = 0; types[j]; j++) { fileTypeBuffer[i] = types[j]; fileTypeIDBuffer[i++] = Type_other; } fileTypeBuffer[i] = NULL; [DirList setExtList: fileTypeBuffer]; if ([thePreference isUpdatedServices]) NXUpdateDynamicServices(); // service re-providing [[NXApp appListener] setServicesDelegate: self]; sendTypes[0] = NULL; returnTypes[0] = NXPostScriptPboardType; returnTypes[1] = NXTIFFPboardType; returnTypes[2] = NULL; [NXApp registerServicesMenuSendTypes:sendTypes andReturnTypes:returnTypes]; printInfo = [NXApp printInfo]; [printInfo setOrientation:NX_LANDSCAPE andAdjust:YES]; [printInfo getMarginLeft:&lmg right:&rmg top:&tmg bottom:&bmg]; lmg = (lmg + rmg) * 0.3; tmg = (tmg + bmg) * 0.3; [printInfo setMarginLeft:lmg right:lmg top:tmg bottom:tmg]; [self initWallpaper]; return self; } - (int)getFTypeID: (const char *)aType { int i; if (aType && *aType) { for (i = 0; fileTypeBuffer[i]; i++) if (strcmp(aType, fileTypeBuffer[i]) == 0) return fileTypeIDBuffer[i]; } return Type_none; } /* Local Method */ - allocWinFromFile: (const char *)fn :(const char *)aType type:(int *)ftype display:(BOOL)display /* Return Value: nil: Error, id: New ToyWin */ { id twtmp = nil; int itype = Type_none; const char *key = NULL; itype = [self getFTypeID: aType]; if (itype == Type_none) { /* Unknown Extension */ if ((itype = discriminate(fn)) == Type_none) return nil; key = NULL; }else key = aType; if (viaPipe(itype)) { /* Type_user and ... */ if (key == NULL) switch (itype) { case Type_pcx: key = "pcx"; break; case Type_mag: key = "mag"; break; case Type_jpg: key = "jpg"; break; case Type_xbm: key = "xbm"; break; case Type_jbg: key = "bie"; break; case Type_png: key = "png"; break; } twtmp = [ToyWinPPM alloc]; if (display) [twtmp init:nil by:0]; else [twtmp initMapOnly]; [twtmp setExecList: [extTable execListAlloc: key with: fn] ext: key]; }else if (itype == Type_pcd) { twtmp = [ToyWinPCD alloc]; if (display) [twtmp init:nil by:0]; else [twtmp initMapOnly]; [twtmp setting]; }else { switch (itype) { case Type_bmp: twtmp = [ToyWinBMP alloc]; break; case Type_gif: twtmp = [ToyWinGIF alloc]; break; case Type_eps: twtmp = [ToyWinEPS alloc]; display = YES; break; case Type_ppm: twtmp = [ToyWinPPM alloc]; break; case Type_tiff: case Type_other: default: twtmp = [ToyWin alloc]; display = YES; break; } if (display) [twtmp init:nil by:0]; else [twtmp initMapOnly]; } *ftype = itype; return twtmp; // return New ToyWin } - drawFile: (const char *)fn :(const char *)aType /* Return Value: nil: Error, id: New ToyWin */ { unsigned char *map[MAXPLANE]; id newtw; commonInfo *cinf; int itype, err = 0; newtw = [self allocWinFromFile:fn : aType type:&itype display:YES]; if (!newtw) return nil; cinf = [newtw drawToyWin:(const char *)fn type:itype map:map err:&err]; if (cinf == NULL && err) { if (err > 0) errAlert(fn, err); [newtw free]; return nil; } [self newWindow: newtw]; return newtw; } /* Local Method */ /* This method is NOT used for EPS and TIFF */ - (NXBitmapImageRep *)imageFromFile: (const char *)fn :(const char *)aType map:(unsigned char **)map { id newtw; commonInfo *cinf; NXBitmapImageRep *img; int itype, err = 0, spp; map[0] = NULL; newtw = [self allocWinFromFile:fn : aType type:&itype display:NO]; if (!newtw) return NULL; cinf = [newtw drawToyWin:(const char *)fn type:itype map:map err:&err]; if (cinf == NULL && err) { if (err > 0) errAlert(fn, err); [newtw free]; return NULL; } if ((img = [NXBitmapImageRep alloc]) != NULL) { spp = cinf->numcolors; if (cinf->alpha) spp++; [img initDataPlanes: map pixelsWide: cinf->width pixelsHigh: cinf->height bitsPerSample: cinf->bits samplesPerPixel: spp hasAlpha: cinf->alpha isPlanar: YES colorSpace: cinf->cspace bytesPerRow: cinf->xbytes bitsPerPixel: cinf->bits]; } [newtw free]; if (cinf->palette) free((void *)cinf->palette); free((void *)cinf); /* An instance of ToyWin initialized by "initMapOnly" does not have instances of ToyView in it. So, "cinf" must be freed here. */ return img; } /* Get stream from file without actual window. This method is used to provide Pasteboard-Services and Initial Wallpaper. */ - (NXStream *)openStreamFromFile: (const char *)fn :(const char *)aType { unsigned char *map[MAXPLANE]; NXBitmapImageRep *img; NXStream *pbStream = NULL; ToyWinEPS *tweps; int itype, err; if ((pbStream = NXOpenMemory(NULL, 0, NX_READWRITE)) == NULL) return NULL; itype = [self getFTypeID: aType]; if (itype == Type_eps) { tweps = [[ToyWinEPS alloc] initMapOnly]; pbStream = [tweps openStreamFromFile:fn err:&err]; [tweps free]; if (pbStream == NULL && err > 0) { errAlert(fn, err); if (pbStream) NXCloseMemory(pbStream, NX_FREEBUFFER); return NULL; } return pbStream; } map[0] = NULL; img = (itype == Type_tiff) ? [[NXBitmapImageRep alloc] initFromFile: fn] : [self imageFromFile: fn : aType map: map]; if (img) { [img writeTIFF: pbStream]; NXSeek(pbStream, 0L, NX_FROMSTART); [img free]; }else { NXCloseMemory(pbStream, NX_FREEBUFFER); pbStream = NULL; } if (map[0]) free((void *)map[0]); return pbStream; } - openFile:sender { char fn[MAXFILENAMELEN]; id openPanel; if (!odir[0]) strcpy(odir, getenv("HOME")); openPanel = [OpenPanel new]; [[openPanel chooseDirectories: NO] allowMultipleFiles:YES]; if ([openPanel runModalForDirectory:odir file:NULL types:fileTypeBuffer]) { const char *const *files = [openPanel filenames]; strcpy(odir, [openPanel directory]); for ( ; files && *files; files++) { sprintf(fn, "%s/%s", odir, *files); if (! [self isOpened: fn]) { int j; if ((j = getExtension(fn)) == 0) return self; /* No Extension */ [self drawFile: fn : &fn[j]]; } } } return self; } #define AutoThreshold 4 /* Local Method */ - openDirectory: (const char *)dir { char fn[MAXFILENAMELEN]; const char *p; int n, i; id dirlist; static id autoDisplayCtr = nil; dirlist = [[DirList alloc] init]; n = [dirlist getDirList: dir]; if (n <= 0) { errAlert(dir, Err_NOFILE); [dirlist free]; }else if (n < AutoThreshold) { for (i = 0; i < n; i++) { p = [dirlist filenameAt: i]; sprintf(fn, "%s/%s", dir, p); if (! [self isOpened: fn]) { int j = getExtension(p); (void)[self drawFile: fn : &p[j]]; } } [dirlist free]; }else { /* Auto Display */ char bdir[MAXFILENAMELEN]; id bundle, ad; if (autoDisplayCtr == nil) { n = dircopy(bdir, NXArgv[0], YES); strcpy(&bdir[n], "ADController.bundle"); bundle = [[NXBundle alloc] initForDirectory: bdir]; if (bundle == nil) /* ERROR */ return nil; autoDisplayCtr = [bundle classNamed:"ADController"]; if (autoDisplayCtr == nil) /* ERROR */ return nil; } ad = [autoDisplayCtr alloc]; [ad init:self dir:dir with:dirlist]; } return self; } - autoDisplay:sender { char fn[MAXFILENAMELEN]; id openPanel; const char *const *files; if (!odir[0]) strcpy(odir, getenv("HOME")); openPanel = [OpenPanel new]; [[openPanel chooseDirectories: YES] allowMultipleFiles:NO]; if (![openPanel runModalForDirectory:odir file:NULL]) return self; files = [openPanel filenames]; strcpy(odir, [openPanel directory]); sprintf(fn, "%s/%s", odir, *files); [self openDirectory: fn]; return self; } - readSelectionFromPasteboard:pb { const NXAtom *cont; NXStream *st; id twtmp = nil; char *ext, fn[256]; int err; static int untitledCount = 0; ext = NULL; for (cont = [pb types]; cont && *cont; cont++) { if (*cont == NXTIFFPboardType) { twtmp = [[ToyWin alloc] init:nil by:0]; ext = "tiff"; break; } if (*cont == NXPostScriptPboardType) { twtmp = [[ToyWinEPS alloc] init:nil by:0]; ext = "eps"; break; } } if (ext == NULL) { NXBeep(); return self; } st = [pb readTypeToStream: *cont]; sprintf(fn, "%s/Untitled%d.%s", getenv("HOME"), ++untitledCount, ext); err = [twtmp drawFromFile:(const char *)fn or:st]; if (err == 0) [self newWindow: twtmp]; else { if (err > 0) errAlert(fn, err); [twtmp free]; } NXCloseMemory(st, NX_FREEBUFFER); return self; } - openPasteBoard:sender { Pasteboard *pb = [Pasteboard new]; // don't free it return [self readSelectionFromPasteboard:pb]; } - (int)app:sender openFile:(const char *)fn type:(const char *)aType { struct stat buf; int mode; id res = nil; if (printInfo == nil) [self appDidInit:sender]; if (stat((char *)fn, &buf) != 0) return NO; mode = (buf.st_mode & S_IFMT); if (mode == S_IFDIR) { if (access(fn, X_OK) != 0) return NO; res = [self openDirectory: fn]; }else { if ([self isOpened: fn]) return YES; res = [self drawFile: fn : aType]; } return (res != nil); } - (BOOL)appAcceptsAnotherFile:sender { return YES; } - messageDisplay:(const char *)msg { if (msg) { [messagePanel makeKeyAndOrderFront: self]; [messageText setStringValue: msg]; [messagePanel setFloatingPanel: YES]; NXPing(); }else { [messagePanel setFloatingPanel: NO]; [messagePanel close]; } return messageText; } - validRequestorForSendType:(NXAtom)typeSent andReturnType:(NXAtom)typeReturned { if (typeReturned == NXPostScriptPboardType || typeReturned == NXTIFFPboardType) return self; return nil; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.