This is InformerDispatcher.m in view mode; [Download] [Up]
// InformerDispatcher.m
//
// Purpose :
// This is the main event handler for the entire application.
//
// History :
// 9.20.1992 : created by Max Tardiveau
#import "InformerDispatcher.h"
// theClass is used by the callback function loadModulesCallback to pass
// the just-loaded class.
static id theClass;
@implementation InformerDispatcher
char baseDir[256]; // base directory for our stuff
/////////////////////////////////////////////////
// Create a new "document" window
- newWindow:sender
{
id newWindow;
char tmpChar[32];
NXRect tmpRect;
newWindow = [InformerWindow new];
[newWindow setDispatcher:self];
sprintf(tmpChar, "Informer window #%i", ++windowNumber);
[[newWindow window] setTitle:tmpChar];
[[newWindow window] getFrame:&tmpRect];
[[newWindow window] moveTo:tmpRect.origin.x + (((windowNumber-1) % 5)*30)
:tmpRect.origin.y - (((windowNumber - 1) % 5)*30)];
return self;
}
/////////////////////////////////////////////////
// Pops up an error panel.
- showError:(char *)message
{
[ErrorPanelText setStringValue:message];
[ErrorPanel makeKeyAndOrderFront:self];
return self;
}
//////////////////////////////////////////////////////////////
// This is called every time an Informer window becomes active.
// The sender is NOT the window itself, but the InformerWindow
// responsible for it (which is its delegate).
- newFrontWindow:sender
{
//[closeMenuCell setEnabled:YES];
currentWindow = sender;
return self;
}
//////////////////////////////////////////////////////////////
// This is called every time an Informer window becomes inactive.
// The sender is NOT the window itself, but the InformerWindow
// responsible for it (which is its delegate).
- oldFrontWindow:sender
{
if (currentWindow == sender) // Only if this was the current window
{
//[closeMenuCell setEnabled:NO];
currentWindow = nil;
}
return self;
}
/////////////////////////////////////////////////
//
- explode:sender
{
Explode();
[AboutPanel performClose:self];
return self;
}
/////////////////////////////////////////////////
// This is the callback function used in objc_loadModules to get a hold
// of the loaded class.
void loadModulesCallback(Class tmpClass, Category unused)
{
theClass = (id)tmpClass;
}
//////////////////////////////////////////////////////////////////////
// This method loads a class if needed.
// The directories of all loaded classes are stored in a linked
// list, along with the class.
- loadClassFromCell:theCell
{
NXStream *errorStream;
char *errorstring;
int length, max;
char tmpchar[512], tmpchar2[512], tmpchar3[512];
char *char_array[4];
FILE *libsFile;
struct stat myStat;
struct LoadedClassNode
{
char DirName[256];
id Class;
struct LoadedClassNode *next;
};
static struct LoadedClassNode *firstNode = NULL;
struct LoadedClassNode *newNodePtr, *tmpNodePtr;
// Search linked list, see if the class is already loaded.
for (tmpNodePtr = firstNode; tmpNodePtr != NULL; tmpNodePtr = tmpNodePtr->next)
{
if ( ! strncmp( [theCell getDir], tmpNodePtr->DirName, 255))
return tmpNodePtr->Class; // Got it, return the class
}
// Nope, not loaded yet, add it to the linked list.
newNodePtr = (struct LoadedClassNode *) malloc(sizeof(struct LoadedClassNode));
newNodePtr->next = NULL;
strncpy(newNodePtr->DirName, [theCell getDir], 255);
if (firstNode == NULL)
firstNode = newNodePtr;
else
for (tmpNodePtr = firstNode; tmpNodePtr != NULL;
tmpNodePtr = tmpNodePtr->next)
if (tmpNodePtr->next == NULL)
{
tmpNodePtr->next = newNodePtr;
break;
}
sprintf(tmpchar, "%s/Main.o", [theCell getDir]);
char_array[0] = tmpchar;
char_array[1] = NIL;
// Is there a special library to load ?
sprintf(tmpchar2, "%s/Libs", [theCell getDir]);
if (stat(tmpchar2, &myStat) == 0)
{
if ((libsFile = fopen(tmpchar2, "r")) == NULL)
fprintf(stderr, "InformerDispatcher : error in fopen(loadClass).\n");
if (fgets(tmpchar2, 511, libsFile) == NULL)
fprintf(stderr, "InformerDispatcher : error in fgets().\n");
length = strlen(tmpchar2);
if (tmpchar2[length - 1] == '\n') // Get rid of final NL
tmpchar2[length - 1] = '\0';
fclose(libsFile);
if (tmpchar2[0] == '/') // Absolute path
char_array[1] = tmpchar2;
else // Relative path
{
sprintf(tmpchar3, "%s/%s", [theCell getDir], tmpchar2);
char_array[1] = tmpchar3;
}
char_array[2] = NIL;
#ifdef DEBUG
fprintf(stderr, "Loading additional lib : %s\n", tmpchar2);
#endif // DEBUG
}
// Try loading Main.o alone, then with libsys.a
errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
#ifdef DEBUG
if (objc_loadModules(char_array, errorStream, &loadModulesCallback, NIL,
"LoadedClass.debug"))
#else
if (objc_loadModules(char_array, errorStream, &loadModulesCallback, NIL, NIL))
#endif /* DEBUG */
{
// Try with the system library : it could be a few missing symbols
if (char_array[1] != NIL) // Already an extra library;
{
char_array[2] = "/lib/libsys_s.a";
char_array[3] = NIL;
}
else
{
char_array[1] = "/lib/libsys_s.a";
char_array[2] = NIL;
}
if (objc_loadModules(char_array, errorStream,
&loadModulesCallback, NIL, NIL))
{
NXGetMemoryBuffer(errorStream, &errorstring, &length, &max);
sprintf(tmpchar, "InformerDispatcher : %s\n", errorstring);
[currentWindow addMessage:tmpchar];
[self showError:"Error loading object file."];
NXClose(errorStream);
return NIL;
}
}
NXClose(errorStream);
newNodePtr->Class = theClass;
return theClass;
}
///////////////////////////////////////////////////////////////////////////////
// Delegate methods
//
//////////////////////////////////////////////////////////////
// Is called after the application has opened.
- appDidInit:sender
{
FILE *process;
char command[256];
char tmpDir[256];
char *suffix;
strncpy (tmpDir,NXArgv[0], 255);
if (tmpDir[0] == '/') // if absolute path
{
if (suffix = rindex(tmpDir,'/'))
*suffix = '\0'; // remove executable name
}
else // pretty ugly, but that's what NeXT recommands
{
sprintf(command, "which '%s'\n", NXArgv[0]);
process = popen(command,"r");
fscanf(process, "%s", tmpDir);
pclose(process);
if (suffix = rindex(tmpDir, '/'))
*suffix = '\0'; // remove executable name
chdir(tmpDir);
getwd(tmpDir);
}
sprintf(baseDir, "%s/Lib", tmpDir);
[self newWindow:self];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.