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.