This is eTAppUI.m in view mode; [Download] [Up]
{\rtf0\ansi{\fonttbl\f0\fmodern Courier;\f1\ftech Symbol;\f2\fmodern Ohlfs;} \paperw11640 \paperh8400 \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 eTAppUI.m\ \b0 // \i \b SUMMARY \b0 : \b\i0 Implementation of eTAppUI, which works with eTApp and Appkit \b0 \ // \b\i SUPERCLASS \b0 : \i0 \b Object:eTAppUI \b0 \ // \b\i PROTOCOLS \b0 : \i0 \b None \b0 \ // \b\i INTERFACE \b0 : \i0 \b eText.nib \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 \ // The nib has a lot of the intelligence hidden in its connections\ // The main challenge is managing the UI, which is constantly changing. \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b\i HISTORY\ \b0\i0 // 02/04/94: \b Added remote printing support. \b0 \ // 11/20/94: \b Added History Panel UI. \b0 \ // 10/29/94: \b Added Line Range hooks for modified MiscFindPanel. \b0 \ // 10/22/94: \b Added Find Panel UI; from MiscFindPanelClass. \b0 \ // 09/21/94: \b Revamped for eText5; removed savePanel, clean interface to eTApp \b0 \ // 07/06/94: \b Added mailDevelopers: \b0 \ // 05/21/94: \b Added savePanel code for multiple-format input. \b0 \ // 05/05/94: \b Added "Accessory" support for future expansion \b0 \ // 08/22/93: \b Added Tools UI \b0 .\ // 08/16/93: \b Created. Implicitly supports an <eTextServices> protocol \b0 \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Imported Interfaces \b0 \ //\ #import " \b eTAppUI.h \b0 "\ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Hacked NXApp mainWindow accessor \b0 \ //\ \i @implementation Application (realMainWindow)\ \i0 // \i the mainWindow method returns nil when the app is not focused. \i0 \ - \b realMainWindow \b0 \{return \b mainWindow \b0 ;\}\ \i @end\ \i0 \ \i @implementation eTAppUI\ \i0 //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b AppKit Delegate \b0 \ //\ - \b appWillInit \b0 :sender \{\ \b static BOOL hasInitted \b0 = NO;\ \b if (hasInitted) return self;\ \ \b0 \b infoController \b0 = \b nil \b0 ;\ \b annotationTable \b0 = [[HashTable alloc] \b initKeyDesc \b0 :"%"];\ \b agentTable \b0 = [[HashTable alloc] \b initKeyDesc \b0 :"%"];\ \b initMenu( \b0 [NXApp mainMenu]);\ [ \b FontManager \b0 \b setFontPanelFactory \b0 : \fc1\cf1 objc_lookUpClass(" \b DPFontPanel \b0 ") \fc0\cf0 ];\ [NXApp \b setAutoupdate:YES \b0 ];\ [[ \b eTApp \b0 alloc] \b init \b0 ];\ [self \b showInspector \b0 :self];\ [self \b showNavigator \b0 :self];\ // \i [self \b showHistory \b0 :self]; \i0 \ \b hasInitted = YES \b0 ;\ return self;\ \}\ \ - \b appWillTerminate \b0 :sender \{\ return [ \b etApp shutdown:YES \b0 ];\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b InfoController UI \b0 \ //\ - \b showInfo \b0 :sender \{\ if (!infoController) \b infoController \b0 = [[ \b InfoController \b0 alloc] \b init \b0 ];\ [ \b infoController \b0 \b showInfo \b0 ];\ return self;\ \}\ \ - \b showCopyright \b0 :sender \{\ if (!infoController) \b infoController \b0 = [[ \b InfoController \b0 alloc] \b init \b0 ];\ [ \b infoController showCopyright \b0 ];\ return self;\ \}\ \ - \b mailDevelopers \b0 :sender \{\ char \b subject[512] \b0 , \b body[512] \b0 ;\ id ret = self;\ \ sprintf ( \b subject \b0 , " \b Comments, bugs, etc for \b0 %s \b version \b0 %s", \ [NXApp \b appName \b0 ], [NXApp \b versionStr \b0 ]);\ sprintf ( \b body \b0 , " \b This is truly the spiffiest app ever written."\ " But, did you know... \b0 \\n\\n\\n%s\\n", \b NXUserName \b0 ());\ ret = [NXApp \b sendMailTo \b0 :" \b khare@caltech.edu \b0 " cc:NULL \ \b subject \b0 :subject \b body \b0 :body deliver:NO];\ if (ret == nil)\ \b NXRunAlertPanel \b0 ([NXApp appName],\ " \b Unable to contact Mail.app \b0 ","OK",NULL,NULL);\ return ret;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b UserModel UI \b0 \ //\ - \b showPreferences \b0 :sender \{\ [ \b userModel showPreferences \b0 ];\ return self;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Navigator UI \b0 \ //\ - \b showNavigator \b0 :sender\{\ [ \b navigator showNavigator \b0 ];\ return self;\ \}\ \ - \b showHistory \b0 :sender\{\ [ \b navigator showHistory \b0 ];\ return self;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Inspector UI \b0 \ //\ - \b showInspector \b0 :sender \{\ [ \b inspector showInspector \b0 ];\ [[[[NXApp \b mainWindow \b0 ] delegate] \b etDoc \b0 ] \b inspect \b0 ];\ return self;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Tool Management/Registration UI \b0 \ //\ - \b loadTool \b0 :sender \{\ const char *directory;\ const char *const *files;\ const char *toolType[6]=\{ \b BNDL_EXT \b0 , \b TOOL_EXT \b0 , \b ANNT_EXT \b0 ,\ \b AGNT_EXT \b0 , \b ACCS_EXT \b0 , NULL\};\ int i;\ char path[MAXPATHLEN];\ \ \b id openpanel \b0 = [[ \b OpenPanel \b0 \b new \b0 ] \b allowMultipleFiles:YES \b0 ];\ [openpanel \b setTreatsFilePackagesAsDirectories:NO \b0 ];\ [openpanel \b chooseDirectories:NO \b0 ];\ i = [openpanel runModalForTypes:toolType];\ if (!i) return self;\ files = [openpanel filenames];\ directory = [openpanel directory];\ i = 0;\ while (files && files[i])\{\ strcpy(path, directory);\ strcat(path, "/");\ strcat(path, files[i]);\ [ \b self \b0 \b openFromPath \b0 :NXUniqueString( \b path \b0 )\ \b type \b0 :NXUniqueString( \b rindex \b0 ( \b path \b0 ,' \b . \b0 ')+1)];\ i++;\ \}\ return self;\ \}\ \ - \b registerAnnotation \b0 :(NXAtom) \b menuLabel\ \b0 \b key \b0 :(char) \b key \b0 \ \b name \b0 :(NXAtom) \b name \b0 \ \b icon \b0 :(NXImage *) \b icon \b0 \{\ \b static id _submenuTable \b0 =nil;\ \ if ([annotationTable \b isKey \b0 : \b menuLabel \b0 ]) \b return \b0 \b self \b0 ;\ if ( \b !_submenuTable \b0 )\ \b _submenuTable \b0 = [[HashTable alloc] \b initKeyDesc \b0 :"%"];\ \ if ( \b index \b0 (menuLabel, ' \b / \b0 ') && (*menuLabel != '/')) \{ // \i is there a slash?\ \i0 char tmp[256]; // C Programmer's Disease\ id _submenu;\ NXAtom tmpA;\ \ \b strncpy \b0 ( \b tmp \b0 , \b menuLabel \b0 , 256);\ if (index(tmp, '/')) \b *index(tmp, '/') = 0 \b0 ; // \i cut out the prefix \i0 \ \b tmpA \b0 = \b NXUniqueString \b0 ( \b tmp \b0 );\ _submenu = [ \b _submenuTable \b0 \b valueForKey \b0 : \b tmpA \b0 ];\ if ( \b !_submenu \b0 ) \{\ \b _submenu \b0 = [[Menu alloc] \b initTitle \b0 : \b tmpA \b0 ];\ [annotationMenu \b setSubmenu \b0 : \b _submenu \b0 \b forItem \b0 :\ [annotationMenu \b addItem \b0 : \b tmpA \b0 \ \b action \b0 :@selector( \b submenuAction \b0 :)\ keyEquivalent:'\\0']];\ [ \b _submenuTable \b0 \b insertKey \b0 :tmpA \b value \b0 :_submenu];\ \}\ [[ \b _submenu addItem \b0 : ( \b index \b0 (menuLabel,' \b / \b0 ')+1)\ \b action \b0 : @selector( \b annotationAction \b0 :)\ \b keyEquivalent \b0 : \b key \b0 ]\ \b setUpdateAction \b0 :@selector( \b menuItemUpdate \b0 :) \b forMenu \b0 : \b _submenu \b0 ];\ [ \b annotationTable \b0 \b insertKey \b0 :( \b index \b0 (menuLabel,' \b / \b0 ')+1) \b value \b0 :(STR) \b name \b0 ];\ \} else \{\ [[ \b annotationMenu \b0 \b addItem \b0 : \b menuLabel\ \b0 \b action \b0 : @selector( \b annotationAction \b0 :)\ \b keyEquivalent \b0 : \b key \b0 ]\ \b setUpdateAction \b0 :@selector( \b menuItemUpdate \b0 :) \b forMenu \b0 : \b annotationMenu \b0 ];\ [ \b annotationTable \b0 \b insertKey \b0 : \b menuLabel \b0 \b value \b0 :(STR) \b name \b0 ];\ \}\ if ( \b icon \b0 ) \{\ // \i Eventually... [ToolsPalette addTool:icon] \i0 \ \}\ return self;\ \}\ \ - \b registerAgent \b0 :(NXAtom) \b menuLabel\ \b0 \b key \b0 :(char) \b key \b0 \ \b name \b0 :(NXAtom) \b name \b0 \{ \ if ( \b ! \b0 [agentTable \b isKey \b0 :menuLabel]) \{\ [agentTable \b insertKey \b0 : \b menuLabel \b0 value:(STR)name];\ [ \b agentMenu \b0 \b addItem \b0 : \b menuLabel \b0 \ \b action \b0 : @selector( \b agentAction \b0 :)\ \b keyEquivalent \b0 : \b key \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 ;\ \{ \ [[ \b accessoryMenu \b0 \b addItem \b0 : \b menuLabel\ \b0 \b action \b0 : \b theAction \b0 \ \b keyEquivalent \b0 : \b key \b0 ] \b setTarget \b0 : \b theTarget \b0 ];\ return self;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Document Management UI \b0 \ //\ - \b new \b0 :sender \{\ [ \b etApp createID \b0 ]; // \i returns new docID \i0 \ return self;\ \}\ \ - \b open \b0 :sender \{\ const char *directory, *docdir;\ const char *const *files;\ const char * \b etfdType \b0 [5] = \{ \b ETFD_EXT \b0 , \b RTFD_EXT \b0 , \b RTF_EXT \b0 , \b LINK_EXT \b0 , NULL\};\ int i;\ char path[MAXPATHLEN];\ static BOOL firstTime=YES;\ \ id \b openpanel \b0 = [[OpenPanel \b new \b0 ] \b allowMultipleFiles \b0 : \b YES \b0 ];\ [openpanel \b setTreatsFilePackagesAsDirectories:NO \b0 ];\ [openpanel \b chooseDirectories:NO \b0 ];\ \ if (firstTime) \{\ \b docdir \b0 = [userModel \b stringQuery \b0 : \b ETFDIRECTORY \b0 ];\ if (docdir && *docdir) \{\ [openpanel \b setDirectory \b0 : \b docdir \b0 ];\ \}\ firstTime = NO;\ \}\ i = [openpanel runModalForTypes:etfdType];\ if (!i) return self;\ files = [openpanel filenames];\ directory = [openpanel directory];\ i = 0;\ while (files && files[i])\{\ strcpy(path, directory);\ strcat(path, "/");\ strcat(path, files[i]);\ [ \b self \b0 \b openFromPath \b0 :NXUniqueString( \b path \b0 )\ \b type \b0 : \b rindex \b0 ( \b path \b0 ,' \b . \b0 ') ? NXUniqueString( \b rindex \b0 ( \b path \b0 ,' \b . \b0 ')+1) : ""];\ i++;\ \}\ return self;\ \}\ \ - \b openAsText \b0 :sender \{\ const char *directory;\ const char *const *files;\ const char * \b textType \b0 [1] = \{NULL\};\ int i;\ char path[MAXPATHLEN];\ \ id \b openpanel \b0 = [[OpenPanel \b new \b0 ] \b allowMultipleFiles \b0 : \b YES \b0 ];\ [openpanel \b setTreatsFilePackagesAsDirectories:YES \b0 ];\ [openpanel \b chooseDirectories:NO \b0 ];\ i = [openpanel runModalForTypes:textType];\ if (!i) return self;\ files = [openpanel filenames];\ directory = [openpanel directory];\ i = 0;\ while (files && files[i])\{\ strcpy(path, directory);\ strcat(path, "/");\ strcat(path, files[i]);\ [ \b self \b0 \b openFromPath \b0 :NXUniqueString( \b path \b0 )\ \b type \b0 :NXUniqueString("")];\ i++;\ \}\ return self;\ \}\ \ - \b openFromPath \b0 :(const char *) \b path \b0 \b type \b0 :(const char *) \b aType \b0 \{ \ id \b theDocInfo \b0 ;\ \ if(!strcmp(aType, \b ETFD_EXT \b0 )) \{\ [ \b etApp \b0 \b openID \b0 :[[[[ \b eTDocInfo \b0 alloc] \b init \b0 ]\ \b readComponentFromPath \b0 :NXUniqueString( \b path \b0 )] \ \b docID \b0 ]];\ \ \} else if(!strcmp(aType, \b LINK_EXT \b0 )) \{\ char tmp[64];\ long dID,aID;\ id \b theTable \b0 = [[[ \b NXStringTable \b0 alloc] init] \b readFromFile \b0 : \b path \b0 ];\ \ strncpy(tmp, [theTable \b valueForStringKey \b0 : \b DOCID \b0 ],63);\ \b sscanf \b0 (tmp, "%x",& \b dID \b0 );\ [ \b etApp \b0 \b openID \b0 : \b dID \b0 ];\ \b\i \ \b0\i0 strncpy(tmp, [theTable \b valueForStringKey \b0 : \b ANCHORID \b0 ],63);\ theTable = [[theTable \b empty \b0 ] \b free \b0 ];\ \b sscanf \b0 (tmp, "%x",& \b aID \b0 ); \b\i \ // This is a really severe kernel violation!\ [[[objc_lookUpClass("eTBookmarkBinder") new] \ bookmarkForID:aID] highlight:self];\ \ \b0\i0 \} else if((!strcmp(aType, \b HTMD_EXT \b0 )) || (!strcmp(aType, \b OLD_HTMD_EXT \b0 ))) \{\ char bounce[MAXPATHLEN];\ \ \b sprintf \b0 ( \b bounce \b0 ,"%s \b /"HTML_INDEX \b0 , \b path \b0 );\ [[Application \b workspace \b0 ] \b openFile \b0 : \b bounce \b0 ];\ \ \} else if(!strcmp(aType, \b URI_EXT \b0 )) \{\ NXStream *s;\ char *data, *url;\ Pasteboard *thePB;\ int len, maxlen;\ \ s = NXMapFile(path, NX_READONLY);\ NXGetMemoryBuffer(s, &data, &len, &maxlen);\ if (!strncmp(data, " \b URL: \b0 ",4)) url = data+4;\ else if (!strncmp(data, " \b <URL: \b0 ",5)) url = data+5;\ else url = data;\ \ thePB = [Pasteboard newUnique];\ [thePB declareTypes:&NXAsciiPboardType num:1 owner:nil];\ [thePB writeType:NXAsciiPboardType data:(url) length:strlen(url)];\ \ \i\fs28 if (!NXPerformService(" \b Open URL \b0 ", thePB) &&\ !NXPerformService(" \b OmniWeb/Open URL \b0 ", thePB) &&\ !NXPerformService(" \b SpiderWoman/Open URL \b0 ", thePB))\ \i0\fs24 NXRunAlertPanel("eTApp","Could not open a " \b URI_EXT \b0 " file (using services): %s.", "OK", NULL, NULL, url);\ \ NXCloseMemory(s, NX_FREEBUFFER);\ \ \} else if(!strcmp(aType, \b TeXD_EXT \b0 )) \{\ \fc1\cf1 [ \b navigator \b0 \b find \b0 :"\\\\. \b tex$ \b0 " \b inDir \b0 :(STR) \b\fc0\cf0 path\ \b0\fc1\cf1 target: \fc0\cf0 [Application \b workspace \b0 ] \fc1\cf1 action:@selector( \b\fc0\cf0 openFile \b0\fc1\cf1 :)];\ \fc0\cf0 \ \} else if ((!strcmp(aType, \b DOCI_EXT \b0 )) || (!strcmp(aType, \b NAVI_EXT \b0 ))) \{\ \fc1\cf1 // \i Create an eTDocInfo, without opening the document\ \i0 [etApp \b loadDocInfoFromPath \b0 :path];\ // \i Navigator will redisplay on the next autoupdate \i0 \ \fc0\cf0 \ \} else if((!strcmp(aType, \b AGNT_EXT \b0 )) || (!strcmp(aType, \b TOOL_EXT \b0 )) ||\ (!strcmp(aType, \b BNDL_EXT \b0 )) || (!strcmp(aType, \b ANNT_EXT \b0 )) ||\ (!strcmp(aType, \b DSBD_EXT \b0 )) || (!strcmp(aType, \b ACCS_EXT \b0 ))) \{\ [ \b etApp \b0 \b loadToolFromPath \b0 : \b path \b0 ];\ \ \} else \{ // \i Pass along a virgin docInfo with the path (RTFD, RTF, or text) \i0 .\ char tmp[MAXPATHLEN], *ext;\ \ \b theDocInfo \b0 = [[ \b eTDocInfo \b0 alloc] \b init \b0 ];\ // \i set the doc's title to be the old name (foo) \i0 \ strcpy(tmp, \b rindex \b0 ( \b path \b0 ,' \b / \b0 ')+1);\ ext = rindex(tmp,'.');\ if (ext && ext+1 && !strcmp(ext+1, \b RTFD_EXT \b0 ) && !strcmp(ext+1, \b RTF_EXT \b0 ))\ * \b ext \b0 = \b 0 \b0 ;\ [theDocInfo \b setDocTitle \b0 :tmp];\ [theDocInfo \b setDocPath \b0 : \b path \b0 ];\ [ \b etApp \b0 \b openID \b0 :[ \b theDocInfo \b0 \b docID \b0 ]];\ \ // \i now that everything is hunky-dory, set a NEW pathname and touch it \i0 \ // \i set the path to be /directory/foo/was/in/foo.id.etfd \i0 \ strcpy(tmp, \b path \b0 );\ ext = rindex(tmp,'.');\ if (ext && ext+1 && !strcmp(ext+1, \b RTFD_EXT \b0 ) && !strcmp(ext+1, \b RTF_EXT \b0 ))\ * \b ext \b0 = \b 0 \b0 ;\ \b strcat \b0 (tmp, "." \b ETFD_EXT \b0 );\ \b while \b0 (! \b access \b0 (tmp, \b F_OK \b0 )) \{ // \i hey, the odds are 1 in 2^32, but...\ \i0 \b sprintf \b0 ( \b rindex \b0 ( \b tmp \b0 ,' \b . \b0 ')," \b .%x. \b0 " \b ETFD_EXT \b0 ,[NXApp \b uniqueID \b0 ]);\ \}\ [theDocInfo \b setDocPath \b0 : \b tmp \b0 ];\ [[theDocInfo \b etDoc \b0 ] \b touch \b0 ];\ \}\ return self;\ \}\ \ - \b import \b0 :sender \{\ const char *directory;\ const char *const *files;\ NXAtom *importTypes;\ int i;\ char path[MAXPATHLEN];\ \b static id thePboard=nil;\ \b0 id openpanel;\ NXAtom filterHack;\ \ // \b\i Transparency violation \b0\i0 \ if ( \b ! \b0 [[[[NXApp \b mainWindow \b0 ] \b delegate \b0 ] \b etDoc \b0 ] \b acceptsAnnotation \b0 ])\{\ NXBeep(); return nil;\ \}\ \ \b openpanel \b0 = [[OpenPanel new] \b allowMultipleFiles \b0 : \b YES \b0 ];\ [openpanel \b setTreatsFilePackagesAsDirectories \b0 : \b NO \b0 ]; // tough call!\ [openpanel \b chooseDirectories \b0 : \b NO \b0 ];\ \ // \i see save panel docs. Assumes there is always an ANY_TYPE handler \i0 \ \b filterHack \b0 = NULL;\ \b importTypes \b0 = \b &filterHack \b0 ;\ \ i = [openpanel runModalForTypes:importTypes];\ if (!i) return self;\ files = [openpanel filenames];\ directory = [openpanel directory];\ i = 0;\ if (! \b thePboard \b0 ) \b thePboard \b0 = [ \b Pasteboard newUnique \b0 ];\ while (files && files[i])\{\ \b id it \b0 ;\ \ strcpy(path, directory);\ strcat(path, "/");\ strcat(path, files[i]);\ \ \b importTypes \b0 [0] = \b NXFileContentsPboardType \b0 ;\ [thePboard \b declareTypes \b0 : \b importTypes \b0 num:1 owner:nil];\ [thePboard \b writeFileContents \b0 : \b path \b0 ];\ \b importTypes \b0 [0] = \b NXFilenamePboardType \b0 ;\ [thePboard \b addTypes \b0 : \b importTypes \b0 num:1 owner:nil];\ [thePboard \b writeType \b0 :importTypes[0] \b data \b0 : \b path \b0 \b length \b0 : \b strlen \b0 ( \b path \b0 )+ \b 1 \b0 ];\ \ \b it \b0 = [[ \b etApp \b0 \b annotationByPboard \b0 : \b thePboard \b0 ] \b alloc \b0 ];\ if ([ \b it \b0 \b respondsTo \b0 :@selector( \b initFromPboard \b0 : \b inDoc \b0 : \b linked \b0 :)]) \{\ [ \b it \b0 \b initFromPboard \b0 : \b thePboard \b0 \ \b inDoc \b0 :[[[NXApp \b mainWindow \b0 ] \b delegate \b0 ] \b etDoc \b0 ]\ \b linked \b0 : \b NO \b0 ];\ [[[[NXApp \b mainWindow \b0 ] \b delegate \b0 ] \b etDoc \b0 ] \b insertAnnotation \b0 : \b it \b0 ];\ \} \b else \b0 \{\ it = [it \b free \b0 ];\ NXLogError(" \b Annotation did not respond to initFromPboard::: \b0 ");\ NXBeep();\ \}\ i++;\ \}\ // \i Attempt to free the imported data from VM. \i0 \ [ \b thePboard \b0 \b declareTypes \b0 :importTypes \b num:0 \b0 \b owner \b0 : \b nil \b0 ];\ return self;\ \}\ \ - \b saveAll \b0 :sender \{\ [ \b etApp \b0 \b saveAll \b0 ];\ return self;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Find Panel UI \b0 \ //\ - \b enterSelection \b0 :sender \{\ return [[ \b MiscFindPanel \b0 \b sharedInstance \b0 ] \b enterSelection \b0 :sender];\}\ - \b findNext \b0 :sender \{\ return [[ \b MiscFindPanel \b0 \b sharedInstance \b0 ] \b findForward \b0 :sender];\}\ - \b findPrevious \b0 :sender \{\ return [[ \b MiscFindPanel \b0 \b sharedInstance \b0 ] \b findBackward \b0 :sender];\}\ - \b jumpToSelection \b0 :sender \{\ return [[ \b MiscFindPanel \b0 \b sharedInstance \b0 ] \b jumpToSelection \b0 :sender];\}\ - \b orderFrontFindPanel \b0 :sender \{\ return [[ \b MiscFindPanel \b0 \b sharedInstance \b0 ] \b makeKeyAndOrderFront \b0 :sender];\}\ - \b orderFrontRangePanel \b0 :sender \{\ return [[ \b MiscFindPanel \b0 \b sharedInstance \b0 ] \b orderFrontRangePanel \b0 :sender];\}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Workspace Delegate \b0 \ //\ - (BOOL) \b appAcceptsAnotherFile \b0 :sender\ \{\ return \b YES \b0 ;\ \}\ \ - (int) \b app \b0 :sender \b openFile \b0 :(const char *) \b path \b0 \b type \b0 :(const char *) \b aType \b0 \ \{\ [self \b appWillInit \b0 :self];\ [self \b openFromPath \b0 :NXUniqueString(path) \b type \b0 :aType];\ return YES;\ \}\ \ - (int) \b app \b0 :sender \b openTempFile \b0 :(const char *)path \b type \b0 :(const char *)aType\ \{\ [self \b app \b0 :sender \b openFile \b0 :path \b type \b0 :aType];\ \b unlink \b0 ( \b path \b0 );\ return YES;\ \}\ \ - \b app \b0 :sender \b powerOffIn \b0 :(int)ms \b andSave \b0 :(int)aFlag\ \{\ [ \b etApp \b0 \b shutdown \b0 : \b NO \b0 ];\ return self;\ \}\ \ // \i This is an example of poor programming style.\ \i0 static BOOL \b msgPrintRunPrintPanel \b0 =YES;\ \ -(BOOL) \b shouldRunPrintPanel \b0 :aView \{return \b msgPrintRunPrintPanel \b0 ;\} \ \ // \i The following is ripped off from Draw.app \i0 .\ \fc1\cf1 - (int) \b msgPrint \b0 :(const char *)fullPath \b ok \b0 :(int *)flag\ \{\ id document = nil;\ char aType[MAXPATHLEN];\ \ if (rindex(fullPath,'.') && *(rindex(fullPath,'.')+1))\ strcpy(aType, rindex(fullPath,'.')+1);\ else\ *aType = '\\0';\ \fc0\cf0 [self \b app \b0 :self \b openFile \b0 :fullPath \b type \b0 :aType];\ // \i The NXApp mainWindow method returns 0 if we're not the focused App.\ \i0 // \i See the beginning of this file for the answer.\ \i0 // \i I tried and tried, but ObjC refuses to compile a straight dereference \i0\fc1\cf1 \ if (document = [[ \b NXApp \b0 \b realMainWindow \b0 ] delegate]) \{\ \b\fc0\cf0 msgPrintRunPrintPanel \b0\fc1\cf1 = NO;\ [document \b print \b0 :self];\ \b\fc0\cf0 msgPrintRunPrintPanel \b0\fc1\cf1 = YES;\ *flag = YES;\ \} else \{\ *flag = NO;\ \}\ return 0;\ \}\ \ \ \fc0\cf0 //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Menu Delegate \b0 \ // \i The following code is ripped off of Draw.app. This is perfectly legal \i0 .\ //\ - (BOOL) \b menuItemUpdate \b0 :(MenuCell *) \b menuCell \b0 \ /*\ \i * Method called by all menu items which send their actions to the\ * First Responder. First, if the object which would respond were the\ * action sent down the responder chain also responds to the message\ * validateCommand:, then it is sent validateCommand: to determine\ * whether that command is valid now, otherwise, if there is a responder\ * to the message, then it is assumed that the item is valid.\ * The method returns YES if the cell has changed its appearance (so that\ * the caller (a Menu) knows to redraw it).\ \i0 */\ \{\ SEL action;\ id responder, target;\ BOOL enable;\ \ \b target \b0 = [menuCell \b target \b0 ];\ \b enable \b0 = [menuCell \b isEnabled \b0 ];\ if ( \b !target \b0 ) \{\ \b action \b0 = [menuCell \b action \b0 ];\ \b responder \b0 = [NXApp \b calcTargetForAction \b0 : \b action \b0 ];\ if ([ \b responder \b0 \b respondsTo \b0 :@selector( \b validateCommand \b0 :)]) \{\ return([ \b responder \b0 \b validateCommand \b0 : \b menuCell \b0 ]);\ \} else \{\ \b enable \b0 = \b responder \b0 ? YES : NO;\ \}\ \}\ \ if ([menuCell \b isEnabled \b0 ] != \b enable \b0 ) \{\ [menuCell \b setEnabled \b0 : \b enable \b0 ];\ return \b YES \b0 ;\ \} else \{\ return \b NO \b0 ;\ \}\ \}\ \ - (BOOL) \b validateCommand \b0 :(MenuCell *) \b menuCell \b0 \ \{\ SEL \b action \b0 = [menuCell \b action \b0 ];\ BOOL enable;\ \ if (action == @selector( \b saveAll: \b0 )) \{\ \b enable \b0 = [ \b etApp \b0 \b validateSaveAll \b0 ];\ if ([menuCell isEnabled] != enable) \{\ [menuCell setEnabled:enable];\ return YES;\ \} else \{\ return NO;\ \}\ \}\ if ((action == @selector( \b annotationAction: \b0 )) ||\ (action == @selector( \b import: \b0 )))\{\ id foo = [[[NXApp \b mainWindow \b0 ] \b delegate \b0 ] \b etDoc \b0 ];\ \b enable \b0 = foo && [foo \b acceptsAnnotation \b0 ];\ if ([menuCell isEnabled] != enable) \{\ [menuCell setEnabled:enable];\ return YES;\ \} else \{\ return NO;\ \}\ \}\ if (action == @selector( \b agentAction: \b0 )) \{\ \b enable \b0 = [[[NXApp \b mainWindow \b0 ] \b delegate \b0 ] \b etDoc \b0 ]? YES : NO;\ if ([menuCell isEnabled] != enable) \{\ [menuCell setEnabled:enable];\ return YES;\ \} else \{\ return NO;\ \}\ \}\ return NO;\ \}\ \ void \b initMenu \b0 (Menu * \b menu \b0 )\ /*\ \i * Sets the updateAction for every menu item which sends to the\ * First Responder (i.e. their target is nil). When autoupdate is on,\ * every event will be followed by an update of each of the menu items\ * which is visible. This keep all unavailable menu items dimmed out\ * so that the user knows what options are available at any given time.\ * Returns the activate menu if is found in this menu.\ \i0 */ \ \{\ int count;\ Matrix *matrix;\ MenuCell *cell;\ id matrixTarget, cellTarget;\ \ matrix = [menu itemList];\ [menu setAutoupdate:YES];\ matrixTarget = [matrix target];\ \ count = [matrix cellCount];\ while (count--) \{\ cell = [matrix cellAt:count :0];\ cellTarget = [cell target];\ if (!matrixTarget && !cellTarget) \{\ [ \b cell \b0 \b setUpdateAction \b0 :@selector( \b menuItemUpdate \b0 :) \b forMenu \b0 : \b menu \b0 ];\ \} else \b if \b0 ([ \b cell \b0 \b hasSubmenu \b0 ]) \{\ \b initMenu \b0 ( \b cellTarget \b0 );\ \}\ \}\ \}\ \ - \b annotationAction \b0 :sender\ \{ \ if ( \b ! \b0 [[[NXApp \b mainWindow \b0 ] \b delegate \b0 ] \b etDoc \b0 ])\ return \b nil \b0 ;\ \b if \b0 ([[[[NXApp mainWindow] delegate] etDoc] \b acceptsAnnotation \b0 ]) \{\ \b id it \b0 ;\ \ \b it \b0 = [[ \b etApp \b0 \b annotationByName \b0 :\ [ \b annotationTable \b0 \b valueForKey \b0 :\ NXUniqueString([[ \b sender \b0 \b selectedCell \b0 ] \b title \b0 ])]\ ]\ alloc];\ \ \b if \b0 ([ \b it \b0 \b respondsTo \b0 :@selector( \b initFromPboard \b0 : \b inDoc \b0 : \b linked \b0 :)]) \{\ [ \b it \b0 \b initFromPboard \b0 : \b nil \b0 \ \b inDoc \b0 :[[[NXApp \b mainWindow \b0 ] \b delegate \b0 ] \b etDoc \b0 ]\ linked:NO];\ [[[[NXApp mainWindow] delegate] etDoc] \b insertAnnotation \b0 : \b it \b0 ];\ \} \b else \b0 \{\ it = [it \b free \b0 ];\ NXLogError(" \b Annotation did not respond to initFromPboard::: \b0 ");\ NXBeep();\ \}\ \}\ return self;\ \}\ \ - \b agentAction \b0 :sender\ \{ \ if ( \b ! \b0 [[[NXApp \b mainWindow \b0 ] \b delegate \b0 ] \b etDoc \b0 ])\ return nil;\ [[[[NXApp mainWindow] delegate] etDoc]\ \b attachAgent \b0 :\ [[[ \b etApp \b0 \b agentByName \b0 :\ [ \b agentTable \b0 \b valueForKey \b0 :NXUniqueString([[ \b sender \b0 \b selectedCell \b0 ] \b title \b0 ])]]\ alloc] \b init \b0 :[[[[NXApp mainWindow] delegate] \b etDoc \b0 ] \b docInfo \b0 ]]];\ return self;\ \}\ \ @end }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.