This is Navigator.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 Navigator.m\ \b0 // \i \b SUMMARY \b0 : \b\i0 Implementation of the Navigator, which manages & locates eTDocs \b0 \ // \b\i SUPERCLASS \b0 : \i0 \b Object:Navigator \b0 \ // \b\i PROTOCOLS \b0 : \i0 \b <DocNotification> \b0 \ // \b\i INTERFACE \b0 : \i0 \b Navigator.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 viewPopup methods are unfinished.\ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b\i HISTORY \b0\i0 \ // 11/20/94: \b Split into 3 panels. \b0 \ // 10/31/94: \b Added the ability to inspect docInfos directly from the Nav. \b0 \ // 09/25/94: \b Revamped for eText5 \b0 \ // 08/21/93: \b Created. Gutless object \b0 \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Imported Interfaces \b0 \ //\ #import " \b Navigator.h \b0 "\ #import " \b Document \b0 .subproj/ \b eTDocInfoBrowserCell.h \b0 "\ #import " \b Kludges \b0 .subproj/ \b regexpr.h \b0 "\ \ \i @implementation Navigator\ \i0 //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Class Management \b0 \ //\ - \b init \b0 \{\ NXRect r;\ \ [NXApp \b loadNibSection \b0 :" \b Navigator.nib \b0 " owner:self withNames:NO];\ \ [navPanel \b setExcludedFromWindowsMenu \b0 :YES];\ [navPanel setFrameAutosaveName:"etNavigatorPanel"];\ [navPanel \b setFrameUsingName \b0 :"etNavigatorPanel"];\ \i \i0 // \i if ([userModel boolQuery:"NavigatorFloat"])\ \i0 // \i [navPanel setFloatingPanel:YES];\ \i0 [ \b navBrowser \b0 \b setDoubleAction \b0 :[navBrowser \b action \b0 ]];\ [navBrowser \b setAction \b0 :@selector( \b inspect: \b0 )];\ // \i This stupidity is documented in the NXBrowser Docs \i0 \ [navBrowser \b setMinColumnWidth \b0 :1];\ [navBrowser \b getFrame \b0 :&r];\ [navBrowser \b setMaxVisibleColumns \b0 :floor( \b NX_WIDTH \b0 (&r)/ \b 140 \b0 )];\ [navBrowser \b setMinColumnWidth \b0 : \b 140 \b0 ];\ \i [navBrowser setMaxVisibleColumns:10];\ \i0 [navBrowser getTitleFromPreviousColumn:YES];\ [ \b navBrowser setPathSeparator \b0 : \fc1\cf1 ' \b ` \b0 ' \fc0\cf0 ];\ [ \b navBrowser setCellClass \b0 : \fc1\cf1 [ \b eTDocInfoBrowserCell \b0 class] \fc0\cf0 ];\ [ \b navWell initLinkWell \b0 ];\ \ [btPanel \b setExcludedFromWindowsMenu \b0 :YES];\ [btPanel setFrameAutosaveName:"etHistoryPanel"];\ [btPanel \b setFrameUsingName \b0 :"etHistoryPanel"];\ [ \b btBrowser \b0 \b setDoubleAction \b0 :[btBrowser \b action \b0 ]];\ [btBrowser setAction:NULL];\ [ \b btBrowser setCellClass \b0 : \fc1\cf1 [ \b eTDocInfoBrowserCell \b0 class] \fc0\cf0 ];\ \b btList \b0 =[[List alloc] \b init \b0 ];\ \b btDirty \b0 = \b navDirty \b0 = \b YES \b0 ;\ \b shouldUseQP \b0 = \b NO \b0 ;\ \ [ \b navBrowser \b0 \b loadColumnZero \b0 ];\ return self;\ \}\ \ - \b free \b0 \{\ navPanel = [ \b navPanel \b0 free];\ btList = [ \b btList \b0 free];\ return self = [ \b super \b0 free];\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b User Interface \b0 \ //\ \ - \b showNavigator \b0 \{\ [ \b navPanel makeKeyAndOrderFront \b0 :self];\ [navPanel makeFirstResponder:navBrowser];\ return self;\ \}\ \ - \b showHistory \b0 \{\ [ \b btPanel makeKeyAndOrderFront \b0 :self];\ [btPanel makeFirstResponder:btBrowser];\ return self;\ \}\ \ - \b backtrack \b0 :sender \{\ // \i open the backtracked file -- make sure it eventually pops up in front, \i0 \ // \i even if the doc is already open. Q: will BTlist "bubble" this entry up? \i0 \ [ \b self \b0 \b navigate \b0 :sender];\ return self;\ \}\ \ - \b navigate \b0 :sender \{\ long dID;\ \ // \i open the navigated file -- make sure it eventually pops up in front,\ \i0 // \i even if the doc is already open. \i0 \ if (dID = [[ \b sender \b0 \b selectedCell \b0 ] \b docID \b0 ])\ [ \b etApp openID \b0 :dID];\ return self;\ \}\ \ - \b inspect \b0 :sender \{\ long dID;\ \ if (dID = [[ \b sender \b0 \b selectedCell \b0 ] \b docID \b0 ]) \{\ etfLink el;\ id theDI = [ \b eTDocInfo \b0 findDocInfo: \b dID \b0 ];\ \ [ \b inspector \b0 \b inspect \b0 :theDI];\ el.docID = [theDI docIDStr];\ el.docTitle = [theDI docTitle];\ el.anchorID = NXUniqueString("0");\ el.anchorTitle = [theDI docTitle];\ [ \b navWell \b0 \b setLink \b0 :&el];\ \} else \{\ [ \b navWell \b0 \b setLink \b0 :NULL];\ \}\ return self;\ \}\ \ - \b runQuery \b0 :sender \{\ \b shouldUseQP \b0 = \b YES \b0 ;\ [ \b navBrowser \b0 \b loadColumnZero \b0 ];\ return self;\ \}\ \ - \b reset \b0 :sender \{\ \b shouldUseQP \b0 = \b NO \b0 ;\ \b navDirty \b0 = \b YES \b0 ;\ return self;\ \}\ - \b touch \b0 \{\ \b btDirty \b0 = \b navDirty \b0 = \b YES \b0 ;\ return self;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Doc Notification \b0 \ //\ - \b docWillOpen \b0 :etDoc \{\ id theDocInfo = [etDoc docInfo];\ if ([ \b btList \b0 \b indexOf \b0 :[ \b theDocInfo docID \b0 ]] == \b NX_NOT_IN_LIST \b0 ) \{\ \b navDirty \b0 = YES;\ \b btDirty \b0 = YES;\ \} else \{\ [btList \b removeObject \b0 :[theDocInfo \b docID \b0 ]];\ \}\ [btList \b insertObject \b0 :[theDocInfo \b docID \b0 ] at: \b 0 \b0 ];\ \b btDirty \b0 = YES;\ return self;\ \}\ \ - \b docDidWrite \b0 :etDoc\{\ btDirty = \b YES \b0 ;\ navDirty = \b YES \b0 ;\ return self;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Filesystem Querying \b0 \ //\ - \b find \b0 :(const char *) \b regex \b0 \b inLibrary \b0 :(const char *) \b lib\ target \b0 :(id) target \b action \b0 :(SEL) action \{\ \b char \b0 \b temp \b0 [MAXPATHLEN];\ \ sprintf(temp, " \b %s \b0 ", [[NXBundle \b mainBundle \b0 ] \b directory \b0 ]);\ [self find:regex inDir:temp target:target action:action];\ sprintf(temp, " \b %s/Library/%s \b0 ", \b NXHomeDirectory \b0 (), \b lib \b0 );\ [self find:regex inDir:temp target:target action:action];\ sprintf(temp, " \b /LocalLibrary/%s \b0 ", \b lib \b0 );\ [self find:regex inDir:temp target:target action:action];\ sprintf(temp, " \b /NextLibrary/%s \b0 ", \b lib \b0 );\ [self find:regex inDir:temp target:target action:action];\ return self;\ \}\ \ - \b find \b0 :(const char *) \b regex \b0 \b inDir \b0 :(const char *) \b dir \b0 \ \b target \b0 :(id) target \b action \b0 :(SEL) action \{\ \b char \b0 * \b s \b0 , \b aPath \b0 [MAXPATHLEN];\ \b DIR \b0 * \b dirp \b0 ;\ struct \b direct \b0 * \b dp \b0 ;\ \ \b dirp \b0 = \b opendir \b0 ( \b dir \b0 );\ if (! \b dirp \b0 ) return \b nil \b0 ;\ if ( \b s \b0 = \b re_comp \b0 ( \b regex \b0 ))\ \{NXLogError(" \b Regex Compilation Error: \b0 %s", \b s \b0 ); return \b nil \b0 ;\}\ for ( \b dp \b0 = \b readdir \b0 ( \b dirp \b0 ); \b dp != NULL \b0 ; dp = readdir(dirp))\ if ( \b re_exec \b0 ( \b dp->d_name \b0 )==1) \{\ sprintf( \b aPath \b0 , "%s/%s", \b dir \b0 , \b dp->d_name \b0 );\ [ \b target perform \b0 : \b action \b0 \b with \b0 :(void *)NXUniqueString( \b aPath \b0 )];\ \}\ \b closedir \b0 ( \b dirp \b0 );\ return self;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b Database Management \b0 \ //\ \ - ( \b BOOL \b0 ) \b isParent \b0 :aDocInfo \{\ id \b theDocInfo \b0 ;\ HashTable * \b docInfoTable; \b0 \ long key;\ NXHashState state;\ \b BOOL \b0 \b isParent \b0 = \b NO \b0 ;\ NXAtom theQuery;\ \ docInfoTable = [ \b eTDocInfo docInfoTable \b0 ];\ state = [ \b docInfoTable \b0 \b initState \b0 ];\ \b theQuery \b0 = [aDocInfo \b docIDStr \b0 ];\ \b while \b0 (([docInfoTable \b nextState \b0 :&state key:(void **) &key\ value: (void**) &theDocInfo]) \b && \b0 ( \b !isParent \b0 ))\ if ([ \b theDocInfo \b0 \b searchFor \b0 :NXUniqueString( \b theQuery \b0 ) \ \b in \b0 :NXUniqueString( \b PARENT \b0 )])\ isParent = YES;\ \b return isParent \b0 ;\ \}\ \ - ( \b List \b0 *) \b btList \b0 \{\ static List* \b theList \b0 =nil;\ int i,j;\ id \b theDocInfo \b0 ;\ \ if (!theList) \b theList \b0 = [[ \b List \b0 alloc] \b init \b0 ];\ [ \b theList \b0 \b empty \b0 ];\ j = [btList count];\ for (i=0; i<j; i++) \{\ \b theDocInfo \b0 = [ \b eTDocInfo \b0 \b findDocInfo \b0 :[ \b btList \b0 objectAt: \b i \b0 ]];\ if ( \b theDocInfo \b0 )\ [ \b theList \b0 \b addObject \b0 :theDocInfo];\ else \{\ [ \b btList \b0 \b removeObjectAt \b0 :i];\ j--;\ i--;\ \}\ \}\ \b return \b0 \b theList \b0 ;\ \}\ \ - ( \b List \b0 *) \b query \b0 :(const char *) \b theQuery \b0 \b field \b0 :(const char *) \b theField \b0 \{\ id \b theDocInfo \b0 ;\ HashTable * \b docInfoTable; \b0 \ long key;\ NXHashState state;\ static List* \b theList \b0 =nil;\ \ if (!theList) \b theList \b0 = [[ \b List \b0 alloc] \b init \b0 ];\ [ \b theList \b0 \b empty \b0 ];\ docInfoTable = [ \b eTDocInfo docInfoTable \b0 ];\ \b state \b0 = [docInfoTable \b initState \b0 ];\ \b while \b0 ([docInfoTable \b nextState \b0 :&state key:(void **)&key\ value: (void**) & \b theDocInfo \b0 ])\ if ([ \b theDocInfo \b0 \b searchFor \b0 :NXUniqueString( \b theQuery \b0 )\ \b in \b0 :NXUniqueString( \b theField \b0 )])\ [ \b theList \b0 \b addObject \b0 : \b theDocInfo \b0 ];\ \b return \b0 \b theList \b0 ;\ \}\ \ - ( \b List \b0 *) \b queryByPanel \b0 \{\ id \b theDocInfo \b0 ;\ HashTable * \b docInfoTable; \b0 \ long key;\ NXHashState state;\ static List* \b theList \b0 =nil;\ const \b char \b0 *iqA, *iqD, *iqK, *iqC;\ \ if (!theList) \b theList \b0 = [[ \b List \b0 alloc] \b init \b0 ];\ [ \b theList \b0 \b empty \b0 ];\ docInfoTable = [ \b eTDocInfo docInfoTable \b0 ];\ \b state \b0 = [docInfoTable \b initState \b0 ];\ iqA = [ \b iqAuthor \b0 stringValue];\ iqD = [ \b iqDocTitle \b0 stringValue];\ iqK = [ \b iqKeyword \b0 stringValue];\ iqC = [ \b iqComments \b0 stringValue];\ \b while \b0 ([docInfoTable \b nextState \b0 :&state key:(void **)&key\ value: (void**) & \b theDocInfo \b0 ]) \{\ if ((*iqA && [ \b theDocInfo \b0 \b searchFor \b0 :iqA in: \b AUTHOR \b0 ]) ||\ (*iqD && [ \b theDocInfo \b0 \b searchFor \b0 :iqD in: \b DOCTITLE \b0 ]) ||\ (*iqK && [ \b theDocInfo \b0 \b searchFor \b0 :iqK in: \b KEYWORDS \b0 ]) ||\ (*iqC && [ \b theDocInfo \b0 \b searchFor \b0 :iqC in: \b COMMENTS \b0 ]))\ [ \b theList \b0 \b addObject \b0 : \b theDocInfo \b0 ];\ \}\ \b return \b0 \b theList \b0 ;\ \}\ \ //ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐ\ // \b AppKit Delegate \b0 \ //\ \ static int \b Navigator_docompare \b0 (eTDocInfo **x, eTDocInfo **y)\ \{\ return strcasecmp([*(eTDocInfo **)x docTitle],[*(eTDocInfo **)y docTitle]);\ \}\ - ( \b int \b0 ) \b browser \b0 :theBrowser \b fillMatrix \b0 :theMatrix \b inColumn \b0 :(int) col \{\ \b int \b0 \b rows \b0 ,i,count;\ id cell;\ List * \b result \b0 ;\ BOOL allLeaves=NO;\ \ \b if \b0 (theBrowser == \b btBrowser \b0 ) \{\ \b result \b0 = [self \b btList] \b0 ;\ \} else \b if \b0 ( \b col \b0 == \b 0 \b0 ) \{\ if ( \b shouldUseQP \b0 )\ \b result \b0 = [self \b queryByPanel \b0 ];\ \b \b0 else \b result \b0 = [self \b query \b0 :"^$" \b field \b0 : \b PARENT \b0 ]; \ \} \b else \b0 \{\ \b if \b0 ([[[ \b theBrowser \b0 matrixInColumn:col-1] \b selectedCell \b0 ] \b docID \b0 ]) \{\ \b result \b0 = [self \b query \b0 :[[[theBrowser matrixInColumn:col-1]\ selectedCell] \b docIDStr \b0 ] \b field \b0 : \b PARENT \b0 ]; \ \} \b else \b0 \{\ \b result \b0 = [self \b query \b0 :" \b * \b0 " \b field \b0 : " \b * \b0 "];\ \b allLeaves \b0 = \b YES \b0 ;\ \}\ \}\ \b if \b0 (theBrowser == \b navBrowser \b0 ) \{\ // \i Sort the list alphabetically \i0 \ \b qsort \b0 ( \b result \b0 ->dataPtr, \b result \b0 ->numElements,sizeof( \b id \b0 ),\ \b Navigator_docompare \b0 );\ \}\ \ \b count \b0 = [ \b result \b0 \b count \b0 ];\ \b if \b0 ((theBrowser == \b navBrowser \b0 ) \b && \b0 ( \b col \b0 == \b 0 \b0 ))\{\ \b rows \b0 = \b count+1 \b0 ;\ [theMatrix \b renewRows \b0 :rows cols:1];\ cell = [theMatrix cellAt:count :0];\ [ \b cell \b0 \b setListAllMode \b0 ]; // \i add the "All Known Documents" entry\ \i0 [cell setLeaf:NO];\ \} else \{\ rows = count;\ [theMatrix \b renewRows \b0 :rows cols:1];\ \}\ \ for (i=0; i <count; i++) \{\ \b cell \b0 = [theMatrix \b cellAt \b0 : \b i \b0 :0];\ [ \b cell \b0 \b setDocInfo \b0 :[ \b result \b0 \b objectAt \b0 : \b i \b0 ]];\ \b if \b0 ((theBrowser == \b btBrowser \b0 ) \b || \b0 \b allLeaves \b0 ) [cell \b setLeaf \b0 : \b YES \b0 ];\ \b else \b0 [cell \b setLeaf \b0 : \b ! \b0 [self \b isParent \b0 :[ \b result \b0 \b objectAt \b0 : \b i \b0 ]]];\ \}\ \b return \b0 \b rows \b0 ;\ \}\ \ - \b windowDidUpdate \b0 :sender \{\ static char navPath[2*MAXPATHLEN]; // \i I suspect the previous declaration of 3k on the stack (non-static) was smashing structures randomly. \i0 \ \ [navPanel \b disableFlushWindow \b0 ];\ if (navDirty) \{\ [ \b navBrowser \b0 \b getPath \b0 :navPath \b toColumn \b0 :([navBrowser \b lastColumn \b0 ]+1)];\ [ \b navBrowser \b0 \b loadColumnZero \b0 ];\ [ \b navBrowser \b0 \b setPath \b0 :navPath];\ navDirty = NO;\ \}\ if (btDirty) \{\ [ \b btBrowser \b0 \b loadColumnZero \b0 ];\ btDirty = NO;\ \}\ [[navPanel \b reenableFlushWindow \b0 ] \b flushWindow \b0 ];\ return self;\ \}\ \ \i @end }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.