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.