This is eTApp.m in view mode; [Download] [Up]
{\rtf0\ansi{\fonttbl\f0\fmodern Courier;\f1\ftech Symbol;\f2\fmodern Ohlfs;} \margl40 \margr40 {\colortbl;\red0\green0\blue0;} \pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i0\ulnone\fs24\fc0\cf0 //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \i \b FILENAME \b0 : \b\i0 eTApp.m\ \b0 // \i \b SUMMARY \b0 : \b\i0 Implementation of the eTApp application controller \b0 \ // \b\i SUPERCLASS \b0 : \i0 \b Object:eTApp \b0 \ // \b\i PROTOCOLS \b0 : \i0 \b None \b0 \ // \b\i INTERFACE \b0 : \i0 \b None \b0 \ // \b\i AUTHOR \b0 : \b\i0 Rohit Khare \b0 \ // \b\i COPYRIGHT \b0 : \f1\i0 Ó \f0\b 1993,94 California Institure of Technology, eText Project\ \b0 //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b\i Implementation Comments \b0\i0 \ // At initialization time, eTApp allocates and inits the various objects\ // in the core of eText. It then loads in various custom classes, defined as\ // 1) all *. \b bundle \b0 in the appWrapper\ // 2) all *. \b annotation \b0 and *. \b agent \b0 \ // in the appWrapper, ~Library/eText, and /LocalLibrary/eText\ // At that time, all principal classes are - \b awake \b0 nd, and \b register \b0 themselves\ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b\i History \b0\i0 \ // 10/31/94: \b Moved external bundles in to core image; see -init Phase III. \b0 \ // 09/21/94: \b Revamped for eText5; cleanup. \b0 \ // 01/11/94: \b Revamped for eText4. \b0 \ // 09/09/93: \b Added - uniqueID;\ \b0 // 08/22/93: \b Moved "Accessor Methods" to eTDoc \b0 \ // 08/22/93: \b Added - loadToolFromPath; Added "Accessor Methods" \b0 \ // 08/17/93: \b Implementation of 1) and 2) using FileHandler (in the aW ONLY!) \b0 \ // 08/16/93: \b Created. Assumes the definition of a <Tool> protocol \b0 \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Imported Interfaces \b0 \ //\ #import " \b eTApp.h \b0 "\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Global Object Handles \b0 \ //\ \b id \b0 /* eTApp */ \b etApp \b0 ;\ \b id \b0 /* eTAppUI */ \b etAppUI \b0 ;\ \b id \b0 /* Inspector */ \b inspector \b0 ;\ \b id \b0 /* UserModel */ \b userModel \b0 ;\ \b id \b0 /* Navigator */ \b navigator \b0 ;\ \ \i @implementation eTApp \i0 \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Class Management \b0 \ //\ \b - init \b0 \{ \ \b NXAtom \b0 \b supportedTypes \b0 [13]=\{NX \b Filename \b0 PboardType,\ NX \b FileContents \b0 PboardType, \ NX \b Sound \b0 PboardType,\ NX \b PostScript \b0 PboardType, \ NX \b TIFF \b0 PboardType,\ N3D \b RIB \b0 PboardType, \ NX \b Color \b0 PboardType,\ NX \b Font \b0 PboardType,\ NX \b Ruler \b0 PboardType,\ NX \b RTF \b0 PboardType,\ NX \b Ascii \b0 PboardType,\ NX \b TabularText \b0 PboardType,\ NULL\};\ \b NXAtom \b0 \b docdir \b0 ;\ \b char \b0 \b thePath \b0 [MAXPATHLEN];\ \ // \b PHASE I: Internal intialization\ \b0 [super \b init \b0 ];\ \b docTable \b0 = [[HashTable alloc] \b initKeyDesc \b0 :"i"];\ \b agentTable \b0 = [[HashTable alloc] \b initKeyDesc \b0 :"%"];\ \b annotationTable \b0 = [[HashTable alloc] \b initKeyDesc \b0 :"%"];\ \b typesTable \b0 = [[HashTable alloc] \b initKeyDesc \b0 :"%"];\ [[NXApp \b printInfo \b0 ] \b setHorizPagination \b0 :NX_FITPAGINATION];\ [[NXApp \b printInfo \b0 ] \b setMarginLeft \b0 :36.0 right:36.0 top:36.0 bottom:36.0];\ \ // \b PHASE II: Global initialization\ \b0 \b etApp \b0 = self;\ \b etAppUI \b0 = [NXApp delegate]; // \i relies on Nib setting \i0 .\ \b inspector \b0 = [[Inspector alloc] init];\ \b userModel \b0 = [[UserModel alloc] init];\ \b navigator \b0 = [[Navigator alloc] init];\ [NXApp \b registerServicesMenuSendTypes \b0 :supportedTypes \ \b andReturnTypes \b0 :supportedTypes];\ \ \fc1\cf1 // \b PHASE III: Locate and load tools and document info\ \b0 // \b First, activate the classes compiled into the Kernel \b0 \ \{\ const char * \b internalTools \b0 [12] = \{" \b eTImage \b0 ", " \b eTAudio \b0 ", " \b eTLink \b0 ",\ " \b eTBookmark \b0 ", " \b Divider \b0 ", " \b eTFileLink \b0 ", " \b eTLiteral \b0 ", " \b eTNote \b0 ",\ " \b eTURLink \b0 ", " \b HotLinks \b0 ", " \b MailTo \b0 ", NULL\};\ int i;\ \ for(i=0; \b internalTools \b0 [i]; i++)\ [ \b objc_lookUpClass \b0 ( \b internalTools \b0 [i]) \b toolAwake \b0 :self];\ \}\ \ // \b Create a Library directory, public_html and set the defaults \b0 .\ \ sprintf(thePath, " \b %s/Library/eText/ \b0 ", \b NXHomeDirectory \b0 ());\ \b if \b0 ( \b access \b0 ( \b\fc0\cf0 thePath \b0\fc1\cf1 ,R_OK|W_OK)) \ \fc0\cf0 if ( \b mkdir \b0 ( \b thePath \b0 , 0777)) \{\ NXLogError(" \b Could not mkdir( \b0 \\"%s\\" \b ) \b0 ", \b thePath \b0 ); \fc1\cf1 \ perror("eText5");\ \}\ [userModel \b defaultValue \b0 : \b thePath \b0 \b for \b0 : \b ETFDIRECTORY \b0 ];\ \ sprintf(thePath, " \b %s/public_html/ \b0 ", \b NXHomeDirectory \b0 ());\ \b if \b0 ( \b access \b0 ( \b\fc0\cf0 thePath \b0\fc1\cf1 ,R_OK|W_OK)) \ \fc0\cf0 if ( \b mkdir \b0 ( \b thePath \b0 , 0777)) \{\ NXLogError(" \b Could not mkdir( \b0 \\"%s\\" \b ) \b0 ", \b thePath \b0 ); \fc1\cf1 \ perror("eText5");\ \}\ [userModel \b defaultValue \b0 : \b thePath \b0 \b for \b0 : \b HTMDIRECTORY \b0 ];\ \ // \b Now go out and search for the rest \b0 .\ [ \b navigator \b0 \b find \b0 :"\\\\. \b bundle$ \b0 " \b inDir \b0 :(STR)[[NXBundle \b mainBundle \b0 ] directory]\ target:self action:@selector(loadToolFromPath:)];\ [ \b navigator \b0 \b find \b0 :"\\\\. \b annotation$ \b0 " \b inLibrary \b0 :" \b eText \b0 "\ target:self action:@selector(loadToolFromPath:)];\ [ \b navigator \b0 \b find \b0 :"\\\\. \b agent$ \b0 " \b inLibrary \b0 :" \b eText \b0 "\ target:self action:@selector(loadToolFromPath:)];\ [ \b navigator \b0 \b find \b0 :"\\\\. \b accessory \b0 " \b inLibrary \b0 :" \b eText \b0 "\ target:self action:@selector(loadToolFromPath:)];\ [ \b navigator \b0 \b find \b0 :"\\\\. \b etfd$ \b0 " \b inDir \b0 :[[NXBundle \b mainBundle \b0 ] directory]\ target:self action:@selector(loadDocInfoFromPath:)];\ [ \b navigator \b0 \b find \b0 :"\\\\. \b etfd$ \b0 " \b inDir \b0 :(STR) \b NXHomeDirectory \b0 ()\ target:self action:@selector(loadDocInfoFromPath:)];\ [ \b navigator \b0 \b find \b0 :"\\\\. \b etfd$ \b0 " \b inLibrary \b0 :" \b eText \b0 "\ target:self action:@selector(loadDocInfoFromPath:)];\ \b docdir \b0 = \fc0\cf0 [userModel \b stringQuery \b0 : \b ETFDIRECTORY \b0 ] \fc1\cf1 ;\ if (docdir && *docdir) \{\ [ \b navigator \b0 \b find \b0 :"\\\\. \b etfd$ \b0 " \b inDir \b0 : \b docdir\ \b0 target:self action:@selector(loadDocInfoFromPath:)];\ \}\ return self;\ \fc0\cf0 \}\ - \b free \b0 \{\ typesTable = [ \b typesTable \b0 free];\ annotationTable = [ \b annotationTable \b0 free];\ agentTable = [ \b agentTable \b0 free];\ docTable = [ \b docTable \b0 free];\ return self = [ \b super \b0 free];\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Registration & Lookup \b0 \ //\ - \b registerType \b0 :(NXAtom) \b pbType\ for \b0 :(id) \b factoryClass \b0 \{\ \b if \b0 ( \b ! \b0 [typesTable \b isKey:pbType \b0 ]) \{\ [typesTable \b insertKey \b0 : \b pbType \b0 \b value \b0 : \b factoryClass \b0 ];\ \b typesList \b0 [([typesTable count] % \fc1\cf1 MAX_PBOARD_TYPES \fc0\cf0 ) - 1] = \b pbType \b0 ; \ \}\ return self;\ \}\ - \b registerAgent \b0 :(id) \b factoryClass \b0 \ \b name \b0 :(NXAtom) \b name \b0 \ \b menuLabel \b0 :(NXAtom) \b label \b0 \ \b menuKey \b0 :(char) \b key \b0 \{\ if (![agentTable \b isKey:name \b0 ]) \{\ [agentTable \b insertKey:name \b0 \b value:factoryClass \b0 ];\ [ \b etAppUI registerAgent \b0 :label key:key name:name];\ \}\ return self;\ \}\ - \b registerAnnotation \b0 :(id) \b factoryClass \b0 \ \b name \b0 :(NXAtom) \b name \b0 \ \b RTFDirective \b0 :(NXAtom) \b directive \b0 \ \b menuLabel \b0 :(NXAtom) \b label \b0 \ \b menuKey \b0 :(char) \b key \b0 \ \b menuIcon \b0 :(NXImage*) \b icon \b0 \{\ if (![annotationTable \b isKey:name \b0 ])\{\ [annotationTable \b insertKey:name value:factoryClass \b0 ];\ \b [eText registerDirective:directive forClass:factoryClass];\ \b0 if ((label && *label))\ [ \b etAppUI registerAnnotation \b0 : \b label \b0 key: \b key \b0 name: \b name \b0 icon: \b icon \b0 ];\ \}\ return self;\ \}\ - \b registerAccessory \b0 :(NXAtom) \b menuLabel\ \b0 \b key \b0 :(char) \b key \b0 \ \b name \b0 :(NXAtom) \b name \b0 \ \b target \b0 :(id) \b theTarget \b0 \ \b action \b0 :(SEL) \b theAction \b0 \{\ return [ \b etAppUI registerAccessory \b0 : \b menuLabel \b0 key: \b key \b0 name: \b name \b0 target: \b theTarget \b0 action: \b theAction \b0 ];\ \}\ - \b annotationByName \b0 :(NXAtom) \b name \b0 \{return [ \b annotationTable valueForKey:name \b0 ];\}\ - \b agentByName \b0 :(NXAtom) \b name \b0 \{return [ \b agentTable valueForKey:name \b0 ];\}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Document Management (by docID) \b0 \ //\ - \b openID \b0 :(long) \b docID \b0 \{\ id \b theDoc \b0 ;\ id \b theDocInfo \b0 ;\ \ if ([ \b docTable \b0 \b isKey \b0 :(void *) \b docID \b0 ]) \{\ [(id) [docTable \b valueForKey \b0 :(void *)docID] \b makeVisible \b0 ];\ return \b nil \b0 ;\ \}\ \b theDocInfo \b0 = [eTDocInfo \b findDocInfo \b0 : \b docID \b0 ];\ if (! \b theDocInfo \b0 ) \{\ \b theDocInfo \b0 = [[ \b eTDocInfo \b0 alloc] \b init \b0 ];\ docID = [ \b theDocInfo \b0 \b docID \b0 ];\ \} \b else \b0 if (![theDocInfo \b isVirgin \b0 ] && \ \b access \b0 ([theDocInfo \b docPath \b0 ], R_OK|X_OK)) \{\ int choice=NXRunAlertPanel(" \b Invalid docPath \b0 ",\ " \b Did not find %s at the path %s. \b0 ",\ " \b Create New Document \b0 ", " \b Cancel \b0 ", NULL,\ [theDocInfo \b docTitle \b0 ], [theDocInfo \b docPath \b0 ]);\ if (choice == NX_ALERTALTERNATE) return \b nil \b0 ;\ \}\ \b theDoc \b0 = [[ \b eTDoc \b0 alloc] \b initForDocInfo \b0 : \b theDocInfo \b0 ];\ if ( \b !theDoc \b0 ) return \b nil \b0 ;\ [ \b docTable \b0 \b insertKey \b0 :(void *) \b docID \b0 value:theDoc];\ return \b theDoc \b0 ;\ \}\ - \b closeID \b0 : (long) \b docID \b0 \{\ id \b theDoc \b0 ;\ \ if ( \b ! \b0 [ \b docTable \b0 \b isKey \b0 :(void *) \b docID \b0 ])\ return \b nil \b0 ;\ \b theDoc \b0 = [ \b docTable \b0 \b valueForKey \b0 :(void *) \b docID \b0 ];\ [ \b theDoc free \b0 ];\ [[ \b eTDocInfo \b0 \b findDocInfo \b0 :docID] \b free \b0 ];\ [ \b docTable removeKey \b0 :(void *)docID];\ return self;\ \}\ - (long) \b createID \b0 \{\ char \b newPath \b0 [MAXPATHLEN];\ eTDocInfo * \b theDocInfo \b0 ;\ static int \b count \b0 =0;\ const char * \b docdir \b0 =[ \b userModel \b0 stringQuery: \b ETFDIRECTORY \b0 ];\ \ \b theDocInfo \b0 = [[ \b eTDocInfo \b0 alloc] \b init \b0 ];\ do \{ sprintf( \b newPath \b0 , " \b %s/Untitled-%d.%s \b0 ", \ (docdir && *docdir) ? \b docdir \b0 : \b NXHomeDirectory \b0 (), \ \b count++ \b0 , \b ETFD_EXT \b0 );\ \} while ( \b !access \b0 (newPath, \b F_OK \b0 ));\ [ \b theDocInfo \b0 \b setDocPath \b0 : NXUniqueString( \b newPath \b0 )];\ [self \b openID \b0 :[ \b theDocInfo \b0 docID]];\ return [ \b theDocInfo \b0 docID];\ \}\ - \b documentByID \b0 : (long) \b docID \b0 \{return [ \b docTable \b0 \b valueForKey \b0 :(void *) \b docID \b0 ];\}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Global Operations \b0 \ //\ - \b saveAll \b0 \{\ long key; \ id doc; \ NXHashState state = [docTable initState];\ \ while ([docTable nextState: &state key:(void **)&key value:(void **)&doc]) \ [ \b doc \b0 \b save \b0 :self];\ return self;\ \}\ - \b shutdown \b0 :(BOOL) \b cancellable \b0 \{\ BOOL \b dirtyDocs \b0 ;\ long key; \ id \b theDoc \b0 ; \ int choice;\ NXHashState state = [docTable initState];\ \ \b recheck: \b0 // \i label. Cycle until all docs handled \i0 .\ dirtyDocs = NO;\ state = [docTable initState];\ \b while \b0 ( \b !dirtyDocs \b0 && \ [docTable \b nextState \b0 : &state key:(void **)&key value:(void **)&theDoc]) \ \b dirtyDocs |= \b0 [theDoc \b needsSaving \b0 ];\ \ if ( \b dirtyDocs \b0 ) \{\ if ( \b cancellable \b0 )\ choice=NXRunAlertPanel(" \b Quit \b0 ",\ "There are unsaved files",\ "Review Unsaved", "Quit Anyway", " \b Cancel \b0 ");\ else choice=NXRunAlertPanel(" \b Logout/Power-Off \b0 ",\ "There are unsaved files",\ "Review Unsaved", "Quit Anyway", \b NULL \b0 ); \ if (choice == NX_ALERTDEFAULT)\{\ state = [docTable \b initState \b0 ];\ \b while \b0 ([docTable \b nextState \b0 :&state \ key:(void **)&key value:(void **)& \b theDoc \b0 ]) \ [ \b theDoc \b0 \b close \b0 :self \b allowCancel \b0 : \b cancellable \b0 ];\ \} else if (choice == NX_ALERTOTHER)\ return \b nil \b0 ;\ else if (choice == NX_ALERTALTERNATE)\ return \b self \b0 ;\ \ goto \b recheck \b0 ;\ \}\ return \b self \b0 ; // \i this is a significant return value \i0 .\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Private Methods (for eTAppUI only) \b0 \ //\ - (NXAtom*) \b typesList \b0 \{return \b typesList \b0 ;\}\ - \b annotationByPboard \b0 : \b thePboard \b0 \{\ NXAtom \b theType \b0 ;\ id ret;\ \ \b theType \b0 =[thePboard \b findAvailableTypeFrom:typesList \b0 num:[typesTable count]];\ if ( \b !theType \b0 ) \{\ // Filter out filename pboards -- we can't do squat about fcontents\ if ([thePboard \b findAvailableTypeFrom \b0 :&NX \b Filename \b0 PboardType num:1]) \{\ char *path,*tmp;\ int len;\ \ [ \b thePboard \b0 \b readType \b0 :NX \b Filename \b0 PboardType data:& \b path \b0 length:&len];\ if (index(path, '\\t')) *index(path, '\\t')=0;\ if ((tmp = rindex(path, '.')) && *(tmp+1))\ \b theType \b0 = NX \b CreateFileContents \b0 PboardType(tmp + 1);\ [thePboard deallocatePasteboardData:path length:len];\ \}\ \}\ \b ret \b0 = [typesTable \b valueForKey:theType \b0 ];\ return (ret ? ret : [typesTable \b valueForKey \b0 :\ NXCreateFileContentsPboardType( \b ANY_TYPE \b0 )]);\ \}\ - (BOOL) \b validateSaveAll \b0 \{\ BOOL \b dirtyDocs \b0 ;\ NXAtom key; \ id theDoc; \ NXHashState state = [docTable initState];\ \ \b dirtyDocs \b0 = NO;\ state = [docTable initState];\ \b while \b0 (! \b dirtyDocs \b0 && \ [docTable \b nextState \b0 : &state key:(void **)&key value:(void **)&theDoc]) \ \b dirtyDocs |= \b0 [theDoc \b needsSaving \b0 ];\ return dirtyDocs;\ \}\ - \b loadToolFromPath \b0 :(const char*) \b path \b0 \{\ id theBundle = [[ \b NXBundle \b0 alloc] \b initForDirectory \b0 :NXUniqueString( \b path \b0 )];\ if ([[theBundle principalClass] conformsTo: \b @protocol(Tool \b0 )])\ [[theBundle \b principalClass \b0 ] \b toolAwake \b0 :self];\ return self;\ \}\ - \b loadDocInfoFromPath \b0 :(const char*) \b path \b0 \{\ [[[ \b eTDocInfo \b0 alloc] \b init \b0 ] \b readComponentFromPath \b0 : \b path \b0 ];\ return self;\ \}\ - \b docTable \b0 \{\ return \b docTable \b0 ;\}\ @end }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.