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.