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.