This is Thinspector.m in view mode; [Download] [Up]
// Thinspector.m
//
// contains more routines for the Thinker class, mostly related to
// BackSpace's inspectors.
//
// You may freely copy, distribute, and reuse the code in this example.
// NeXT disclaims any warranty of any kind, expressed or implied, as to its
// fitness for any particular use.
#import "Thinker.h"
#import "BackWindow.h"
#import "BackView.h"
#import "SpaceView.h"
#import "MySlider.h"
#import "Password.h"
#import "psfuncts.h"
#import "ModuleList.h"
#import <appkit/appkit.h>
#import <objc/NXBundle.h>
#import <sys/dir.h> /* for opendir(), etc. */
@implementation Thinker(inspector)
- commonImageInspector
{
return commonImageInspector;
}
- nullInspector
{
return nullInspector;
}
- spaceInspector
{
return spaceInspector;
}
- boinkInspector
{
return boinkInspector;
}
- revertToDefaultImage:sender
{
[self setImageFromName: "defaultImage"];
NXRemoveDefault([NXApp appName], "imageFile");
return self;
}
- (BOOL)browser:sender columnIsValid:(int)column
{
return browserValid;
}
- addCellWithString:(const char *)str at:(int)row toMatrix:matrix
{
id theCell;
[matrix insertRowAt:row];
theCell = [matrix cellAt:row :0];
[theCell setStringValue:str];
[theCell setLoaded:YES];
[theCell setLeaf:YES];
return self;
}
- (int)browser:sender fillMatrix:matrix inColumn:(int)column
{
const char *ptr;
int i;
// this shouldn't happen...
// if (browserValid) return [matrix cellCount];
[self addCellWithString:NXLocalString("All", 0, 0)
at:0 toMatrix:matrix];
for (i = 0; i < [moduleList count]; i++)
[self addCellWithString:NXLocalString([moduleList nameAt: i], 0, 0)
at:(i+1) toMatrix:matrix];
realViewIndex = 0;
if(modeType == SAVERMODE)
{
ptr = NXGetDefaultValue([NXApp appName], "viewType");
}
else // (modeType == BACKMODE)
{
ptr = NXGetDefaultValue([NXApp appName], "backViewType");
}
if (ptr)
{
for (i = 0; i < [moduleList count]; i++)
if (strcmp(ptr, [moduleList nameAt: i]) == 0)
{
realViewIndex = i+1;
break;
}
}
browserValid = YES;
return [matrix cellCount];
}
// Dynamically load all object files found in the specified directory
// if we find a module in several places, we save the additional paths
// in case they point to modules for different architectures
- loadViewsFrom: (const char *) dirname
{
DIR *dir;
struct direct *de;
char path[MAXPATHLEN];
char name[60];
char *iptr;
ModuleInfo *m;
BOOL validName, filePackage;
dir = opendir(dirname);
if (dir == NULL) {
//perror(dirname);
return self;
}
while ((de = readdir(dir)) != NULL)
{
int i, numstrings;
// Ignore '.'-files (not really necessary, I guess)
if (de->d_name[0] == '.')
continue;
filePackage = validName = NO;
if (de->d_namlen > 10 &&
!strcmp(&de->d_name[de->d_namlen-10], "View.BackO"))
{
validName = YES;
filePackage = NO;
}
else if (de->d_namlen > 15 &&
!strcmp(&de->d_name[de->d_namlen-15], "View.BackModule"))
{
validName = YES;
filePackage = YES;
}
if (!validName) continue;
// refuse to load if the name matches a module already loaded
numstrings = [moduleList count];
strcpy(name, de->d_name);
// Smash out the 'V' in "FooView.BackO"
if (iptr = rindex(name, 'V'))
*iptr = '\0';
for (i=0; i< numstrings; i++)
{
if (!strcmp(name, [moduleList nameAt:i]))
{
// we already have a module with this name, but will save the path anyway
validName = NO;
if (filePackage) sprintf(path,"%s/%sView.BackModule",dirname,name);
else strcpy(path, dirname);
[[moduleList objectAt:i] appendPath:path];
break;
}
}
if (!validName) continue;
// I used to load the class at this time; this got horribly
// inefficient. I now wait until I'm about to instantiate
// a view before doing this (thanx bbum!)
if (filePackage) sprintf(path,"%s/%sView.BackModule",dirname,name);
else strcpy(path, dirname);
m = [[ModuleInfo alloc]
initWithView:NULL name:name path:path];
[moduleList addObject: m];
}
closedir(dir);
return self;
}
- (BOOL)appAcceptsAnotherFile:sender
{
// return openAnother;
// if I just return openAnother, I fail to open the module if
// I get launched to do it. Punt until I think of a better solution.
return YES;
}
- (int)app:sender openFile:(const char *)filename type:(const char *)aType
{
// Here we have caught BackSpace off guard; Speaker says open a file,
// but BackSpace is already locked on a view because it doesn't unlock
// focus or bail out of the event loop unless there's an event.
// This is good for performance but it means it handles openfile badly;
// it must post an event telling it to bail out of the event loop and
// open the file later; multi file opens are therefore broken, and
// the return value here is bogus...
char path[MAXPATHLEN];
NXEvent anEvent;
char *iptr;
if (fileToOpen)
{ free(fileToOpen);
fileToOpen = NULL;
}
strcpy(path,filename);
if (!strcmp(aType,"BackModule"))
{
iptr = rindex(filename, '/');
strcat(path,iptr); // /xxx/fooView.BackModule/fooView.BackModule
iptr = rindex(path, 'M');
strcat(iptr,"O"); // /xxx/fooView.BackModule/fooView.BackO
}
fileToOpen = NXCopyStringBuffer(path);
openAnother = NO;
anEvent.type = NX_APPDEFINED;
anEvent.data.compound.subtype = BSOPENFILE;
anEvent.ctxt = [NXApp context];
DPSPostEvent(&anEvent,0);
return YES;
}
- doDelayedOpenFile
{
int i, numstrings;
int ret = YES;
char path[MAXPATHLEN];
id theMatrix;
char *name;
char *iptr;
ModuleInfo *m;
numstrings = [moduleList count];
strcpy(path, fileToOpen);
if ((name = rindex(path, '/')) != NULL)
*name = '\0';
name++;
// Smash out the 'V' in "FooView.BackO"
if ((iptr = rindex(name, 'V')) != NULL)
*iptr = '\0';
for (i=0; i< numstrings; i++)
{
if (!strcmp(name, [moduleList nameAt:i]))
{ ret = NO;
break;
}
}
if (ret)
{
m = [[ModuleInfo alloc]
initWithView:NULL name:name path:path];
[moduleList addObject: m];
browserValid = NO;
[moduleList sort];
[viewSelectionBrowser loadColumnZero];
}
theMatrix = [viewSelectionBrowser matrixInColumn:0];
numstrings = [moduleList count];
for (i=0; i< numstrings; i++)
{
if (!strcmp(name, [moduleList nameAt:i]))
break;
}
realViewIndex = i+1;
[theMatrix selectCellAt:realViewIndex :0];
[theMatrix scrollCellToVisible:realViewIndex :0];
[viewSelectionBrowser display];
[self setVirtualViewIndexAndIncrement:NO];
free(fileToOpen);
fileToOpen = NULL;
openAnother = YES;
return self;
}
extern const char *appDirectory();
- (const char *) appDirectory
{
return appDirectory();
}
- (const char *) moduleDirectory:(const char *)name
{
int i, numstrings;
numstrings = [moduleList count];
for (i=0; i< numstrings; i++)
{
if (!strcmp(name, [moduleList nameAt:i]))
return [[moduleList objectAt:i] path];
}
return NULL;
}
- (struct mach_header *) headerForModule:(const char *)name
{
int i, numstrings;
numstrings = [moduleList count];
for (i=0; i< numstrings; i++)
{
if (!strcmp(name, [moduleList nameAt:i]))
return [[moduleList objectAt:i] header];
}
return NULL;
}
static char *launchDir = NULL; /* if this is NULL, it will be calculated */
/**
** which-dir -- find the path for the named exectuable file
** Returns malloc'd string if it finds it, or NULL if it can't
**
** borrowed from Lennart, munged by sam
**/
const char *which_dir(const char *file)
{
char buf[MAXPATHLEN];
char *paths, *p, *q;
char *ret;
int dirlen;
paths = getenv("PATH");
if (paths == NULL) return NULL;
for (p = q = paths; *q != '\0'; p = q + 1)
{
q = index(p, ':');
if (q == NULL) q = p + strlen(p);
dirlen = q - p;
sprintf(buf, "%.*s/%s", dirlen, p, file);
if (access(buf, X_OK) != 0) continue;
buf[dirlen] = '\0';
ret = malloc((dirlen+1)*sizeof(char));
strcpy(ret,buf);
return ret;
}
return NULL;
}
const char *appDirectory()
{
char buf[MAXPATHLEN];
char *suffix, *path;
if (launchDir) return launchDir;
strcpy (buf,NXArgv[0]);
suffix = rindex(buf,'/');
if (suffix != NULL) // explicit path
{
*suffix = '\0'; // remove executable name
}
else
{
path = (char *)which_dir([NXApp appName]);
if (path != NULL)
{
launchDir = path;
return launchDir;
}
else
{
// Don't know where we came from -- arbitrarily
// presume "." and continue (it's better than breaking)
strcpy(buf, ".");
}
}
launchDir = malloc((strlen(buf)+1)*sizeof(char));
strcpy(launchDir,buf);
return launchDir;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.