This is WAISControl.m in view mode; [Download] [Up]
// WAISControl.m
//
// Free software created 1 Feb 1992
// by Paul Burchard <burchard@math.utah.edu>.
#import "WAISControl.h"
#import "Wais.h"
#import "QuestionDoc.h"
#import "SourceDoc.h"
#import "BrowserPane.h"
#import "IconWellControl.h"
#import "MailSpeaker.h"
#import <appkit/appkit.h>
#import <sys/file.h>
@implementation WAISControl
// ----------------------- PREFERENCES ------------------------ //
static NXDefaultsVector WAIStationDefaults =
{
{ "SystemFolder", "/LocalLibrary/WAIS" },
{ "SystemSourcesFolder", "/LocalLibrary/WAIS/sources" },
{ "UserFolder", "~/Library/WAIS" },
{ "UserSourcesFolder", "~/Library/WAIS/sources" },
{ "UserDocumentsFolder", "~/Library/WAIS/documents" },
{ "UserQuestionsFolder", "~/Library/WAIS/questions" },
{ "OpenOnRetrieval", "YES" },
{ "DocumentTypes", "" },
{ "MaxSearchResults", "30" },
{ "MailListAddress", "listserv@think.com" },
{ "MailListMessage", "ADD wais-talk\nADD wais-interest\nADD wais-discussion\n" },
{ "BugReportAddress", "burchard@math.utah.edu" },
{ "BugReportCC", "bug-wais@think.com" },
{ "BugReportSubject", "Comments on WAIStation.app " WAISTATION_VERSION " for NeXT" },
{ "BugReportMessage", "Please help us in making the WAIS software better.
Please answer candidly.
How was the installation on the NeXT?
How is the documentation?
Comments on the server code:
Comments on the NeXT interface:
Comments on the existing WAIS sources on the net:
What WAIS sources would you like to see:
Would you like to help? In what way?
General comments:
" },
{ NULL }
};
+ initialize
{
NXRegisterDefaults("WAIStation", WAIStationDefaults);
return self;
}
// Returns NXAtom-ized version of full folder name.
// Adds this name to the search path for the WaisClass (if not already there).
// Name will be inserted at beginning if where<0, at end if where>0.
// Note: subname may be NULL.
- (NXAtom)addToPath:WaisClass inPos:(int)where
subdir:(const char *)subname ofFolder:(const char *)name
{
char *buf;
const char *home;
NXAtom rtn;
int i, len, cnt;
id flist;
// Valid folder?
if(!name) return 0;
if(!(name[0]=='/' || (name[0]=='~' && name[1]=='/'))) return 0;
// Create buffer...
home = NXHomeDirectory();
len = 1 + strlen(name) + strlen("/");
if(home) len += strlen(home);
if(subname) len += strlen(subname);
buf = s_malloc(len);
if(!buf) return 0;
// Replace initial '~' with home directory.
if(name[0] == '~')
{
if(home) strcpy(buf, home);
strcat(buf, name+1);
}
else strcpy(buf, name);
len = strlen(buf);
// Append subfolder if any (fix trailing '/').
if(subname)
{
if(buf[len-1] != '/') strcat(buf, "/");
strcat(buf, subname);
}
else if(buf[len-1] == '/') buf[len-1] = 0;
// Append atomized version to WaisClass's path and return it.
rtn = NXUniqueString(buf); s_free(buf);
flist = [WaisClass folderList]; cnt = [flist count];
for(i=0; i<cnt; i++) if(rtn == *((NXAtom *)[flist elementAt:i])) break;
if(i >= cnt)
{
if(where > 0) [flist addElement:(void *)&rtn];
else [flist insert:(void *)&rtn at:0];
}
return rtn;
}
- createFolder:(const char *)name onError:(const char *)alertMsg
{
char cmd[2*MAXPATHLEN];
[Wais lockFileIO];
if(!name)
{
if(stringTable) NXRunAlertPanel(
[stringTable valueForStringKey:"WAIStation"],
[stringTable valueForStringKey:alertMsg],
[stringTable valueForStringKey:"OK"], NULL, NULL);
else { fprintf(stderr, "%s\n", alertMsg); fflush(stderr); }
[Wais unlockFileIO];
return nil;
}
if(0 == access(name, R_OK|W_OK|X_OK))
{ [Wais unlockFileIO]; return self; }
sprintf(cmd, "mkdirs \'%s\'", name);
system(cmd);
if(0 == access(name, R_OK|W_OK|X_OK))
{ [Wais unlockFileIO]; return self; }
if(stringTable) NXRunAlertPanel(
[stringTable valueForStringKey:"WAIStation"],
[stringTable valueForStringKey:alertMsg],
[stringTable valueForStringKey:"OK"], NULL, NULL);
else { fprintf(stderr, "%s\n", alertMsg); fflush(stderr); }
[Wais unlockFileIO];
return nil;
}
- usePrefs
{
const char *baseFolder, *thisFolder, *number;
const char *docTypes, *typeStart, *typeExten, *typeEnd, *typesDone;
char thisType[512], thisExten[512];
NXAtom folder;
unsigned int rank;
int limit;
// Set flag to open or not open docs as they are retrieved.
if(!NXGetDefaultValue("WAIStation", "OpenOnRetrieval")
|| 'Y'==*NXGetDefaultValue("WAIStation", "OpenOnRetrieval")
|| 'y'==*NXGetDefaultValue("WAIStation", "OpenOnRetrieval"))
isOpenOnRetrieval = YES;
else isOpenOnRetrieval = NO;
// Set class-wide search limit for questions.
if((number=NXGetDefaultValue("WAIStation", "MaxSearchResults"))
&& 1==sscanf(number, " %d ", &limit))
[WaisQuestion setSearchLimit:limit];
// Use document type ranking and file extension info.
if(docTypes = NXGetDefaultValue("WAIStation", "DocumentTypes"))
for(rank=1, typeStart=docTypes, typeExten=strchr(typeStart,'='),
typesDone=docTypes+strlen(docTypes),
typeEnd=(strchr(typeStart,',') ?
strchr(typeStart,','):typesDone);
typeStart && typeStart<typesDone;
rank++, typeStart=typeEnd+(typeEnd[0]==',' ? 1:0),
typeExten=strchr(typeStart,'='),
typeEnd=(strchr(typeStart,',') ?
strchr(typeStart,','):typesDone))
{
if(typeExten && typeExten<typeEnd)
{
strncpy(thisType, typeStart, typeExten-typeStart);
thisType[typeExten-typeStart] = 0;
strncpy(thisExten, typeExten+1, typeEnd-typeExten-1);
thisExten[typeEnd-typeExten-1] = 0;
[WaisDocument registerExtension:thisExten forType:thisType];
}
else
{
strncpy(thisType, typeStart, typeEnd-typeStart);
thisType[typeEnd-typeStart] = 0;
}
[WaisQuestion preferDocumentType:thisType withRank:rank];
}
// Create user directories if necessary and prepend to appropriate paths.
if(!(baseFolder = NXGetDefaultValue("WAIStation", "UserFolder")))
baseFolder = "~/Library/WAIS";
if(thisFolder = NXGetDefaultValue("WAIStation", "UserSourcesFolder"))
folder = [self addToPath:[WaisSource class] inPos:(-1)
subdir:NULL ofFolder:thisFolder];
else folder = [self addToPath:[WaisSource class] inPos:(-1)
subdir:"sources" ofFolder:baseFolder];
[self createFolder:folder
onError:"Can't create folder for WAIS sources"];
if(thisFolder = NXGetDefaultValue("WAIStation", "UserDocumentsFolder"))
folder = [self addToPath:[WaisDocument class] inPos:(-1)
subdir:NULL ofFolder:thisFolder];
else folder = [self addToPath:[WaisDocument class] inPos:(-1)
subdir:"documents" ofFolder:baseFolder];
[self createFolder:folder
onError:"Can't create folder for WAIS documents"];
if(thisFolder = NXGetDefaultValue("WAIStation", "UserQuestionsFolder"))
folder = [self addToPath:[WaisQuestion class] inPos:(-1)
subdir:NULL ofFolder:thisFolder];
else folder = [self addToPath:[WaisQuestion class] inPos:(-1)
subdir:"questions" ofFolder:baseFolder];
[self createFolder:folder
onError:"Can't create folder for WAIS questions"];
// Append system directories (if any) to appropriate paths.
if(thisFolder = NXGetDefaultValue("WAIStation", "SystemSourcesFolder"))
[self addToPath:[WaisSource class] inPos:1
subdir:NULL ofFolder:thisFolder];
else if(baseFolder = NXGetDefaultValue("WAIStation", "SystemFolder"))
[self addToPath:[WaisSource class] inPos:1
subdir:"sources" ofFolder:baseFolder];
return self;
}
- updatePrefs:sender
{
char number[128];
// Get new prefs from panel and save in database.
if([prefsIsOpenOnRetrieval state] != 0)
NXWriteDefault("WAIStation", "OpenOnRetrieval", "YES");
else NXWriteDefault("WAIStation", "OpenOnRetrieval", "NO");
sprintf(number, "%d", [prefsSearchLimit intValue]);
NXWriteDefault("WAIStation", "MaxSearchResults", number);
if([prefsDocumentTypes stringValue])
NXWriteDefault("WAIStation",
"DocumentTypes", [prefsDocumentTypes stringValue]);
if([prefsSystemFolder stringValue])
NXWriteDefault("WAIStation",
"SystemFolder", [prefsSystemFolder stringValue]);
if([prefsSystemSourcesFolder stringValue])
NXWriteDefault("WAIStation",
"SystemSourcesFolder", [prefsSystemSourcesFolder stringValue]);
if([prefsUserSourcesFolder stringValue])
NXWriteDefault("WAIStation",
"UserSourcesFolder", [prefsUserSourcesFolder stringValue]);
if([prefsUserDocumentsFolder stringValue])
NXWriteDefault("WAIStation",
"UserDocumentsFolder", [prefsUserDocumentsFolder stringValue]);
if([prefsUserQuestionsFolder stringValue])
NXWriteDefault("WAIStation",
"UserQuestionsFolder", [prefsUserQuestionsFolder stringValue]);
[self usePrefs];
return self;
}
- prefs:sender
{
const char *number;
int limit;
if(!prefsPanel) [NXApp loadNibSection:"Preferences.nib" owner:self];
if(!NXGetDefaultValue("WAIStation", "OpenOnRetrieval")
|| 'Y'==*NXGetDefaultValue("WAIStation", "OpenOnRetrieval")
|| 'y'==*NXGetDefaultValue("WAIStation", "OpenOnRetrieval"))
[prefsIsOpenOnRetrieval setState:1];
else [prefsIsOpenOnRetrieval setState:0];
if((number=NXGetDefaultValue("WAIStation", "MaxSearchResults"))
&& 1==sscanf(number, " %d ", &limit))
[prefsSearchLimit setIntValue:limit];
[prefsSearchLimit sendAction:[prefsSearchLimit action]
to:[prefsSearchLimit target]];
[prefsDocumentTypes
setStringValue:NXGetDefaultValue("WAIStation", "DocumentTypes")];
[prefsSystemFolder
setStringValue:NXGetDefaultValue("WAIStation", "SystemFolder")];
[prefsSystemSourcesFolder
setStringValue:NXGetDefaultValue("WAIStation", "SystemSourcesFolder")];
[prefsUserSourcesFolder
setStringValue:NXGetDefaultValue("WAIStation", "UserSourcesFolder")];
[prefsUserDocumentsFolder
setStringValue:NXGetDefaultValue("WAIStation", "UserDocumentsFolder")];
[prefsUserQuestionsFolder
setStringValue:NXGetDefaultValue("WAIStation", "UserQuestionsFolder")];
[prefsPanel update];
[prefsPanel makeKeyAndOrderFront:self];
return self;
}
+ (const char *)defaultFolder
{
if(NXGetDefaultValue("WAIStation", "UserFolder"))
return NXGetDefaultValue("WAIStation", "UserFolder");
else if(NXGetDefaultValue("WAIStation", "UserSourcesFolder"))
return NXGetDefaultValue("WAIStation", "UserSourcesFolder");
else return [[Wais folderList] elementAt:0];
}
// ----------------------- RETRIEVAL ------------------------ //
// Callback from retrieval thread to main thread.
- retrievalDone:data
{
int docAt, ok;
id doc, check_rtn;
if(!data || ![data isKindOf:[List class]]
|| ![[data objectAt:0] isKindOf:[Wais class]])
return nil;
doc = [data objectAt:0];
check_rtn = [data objectAt:1];
[data free];
// If successfully retrieved and user desires docs to be opened on
// retrieval, pop open doc.
if(check_rtn && isOpenOnRetrieval) [self openFile:[doc key] ok:&ok];
// Enable browser entry for doc if check_rtn non-nil, else remove it.
if(documentPaletteBrowser
&& (docAt=[documentPaletteBrowser indexOfEntry:[doc key]])>=0)
{
if(check_rtn) [documentPaletteBrowser setEntryEnabled:YES at:docAt];
else [documentPaletteBrowser removeEntryAt:docAt];
}
else if(sourcePaletteBrowser
&& (docAt=[sourcePaletteBrowser indexOfEntry:[doc key]])>=0)
{
if(check_rtn) [sourcePaletteBrowser setEntryEnabled:YES at:docAt];
else [sourcePaletteBrowser removeEntryAt:docAt];
}
return self;
}
any_t retrieval_thread(any_t rawArgs)
{
retrieval_args args = (retrieval_args)rawArgs;
id doc, src, check_rtn, data;
while(YES)
{
// Wait for retrieval requests to show up in list.
mutex_lock(args->requestMutex);
while([args->docList count] <= 0)
condition_wait(args->requestCondition, args->requestMutex);
doc = [args->docList objectAt:0];
mutex_unlock(args->requestMutex);
if(!doc) continue;
// Only one retrieval at a time, since same port may be used.
// If doc file describes a source, load it into Wais system.
// Else write auxiliary WAIS file to preserve access info.
check_rtn = [doc retrieve];
if(check_rtn)
{
if([doc valueForStringKey:":type"]
&& 0==strcmp([doc valueForStringKey:":type"], "WSRC"))
{
src = [[WaisSource alloc] initKey:[doc key]];
[src readWaisFile];
}
else [doc writeWaisFile];
}
// Report back:
// 1. Pop open retrieved doc if necessary.
// 2. Enable browser entry if successful, else remove it.
// (Use callback to main thread since AppKit is not thread-proof.
// Callback will free data list.)
// (Note: [NXApp delegate] = us.)
data = [[List alloc] init];
[data addObject:doc]; [data addObject:check_rtn];
[Wais callback:[NXApp delegate]
perform:@selector(retrievalDone:) with:data];
// Remove entry from request list.
mutex_lock(args->requestMutex);
[args->docList removeObjectAt:0];
mutex_unlock(args->requestMutex);
}
// Never reaches this.
return 0;
}
- restartThread
{
// Already running?
if(retrievalThread) return nil;
// Create and detach thread.
retrievalArgs.docList = retrievalList;
retrievalArgs.requestMutex = requestMutex = mutex_alloc();
retrievalArgs.requestCondition = requestCondition = condition_alloc();
retrievalThread = cthread_fork(retrieval_thread, (any_t)&retrievalArgs);
if(!retrievalThread) return nil;
cthread_detach(retrievalThread);
return self;
}
- terminateThread
{
int i;
// Try to abort the retrieval thread.
//!!! Zapping threads may screw up the mutex locking, so we don't
//!!! try to recycle old mutexes and conditions. Even if old thread stays
//!!! around, it's probably not doing much, so its freedom from the
//!!! new mutexes shouldn't be a problem.
if(!retrievalThread) return self;
thread_suspend(cthread_thread(retrievalThread));
cthread_abort(retrievalThread);
retrievalThread = 0;
requestMutex = 0;
requestCondition = 0;
[Wais waisNewLocks];
// Clear retrieval request list.
// Update palettes (removing disabled entries).
[retrievalList empty];
for(i=[documentPaletteBrowser count]-1; i>=0; i--)
if(![documentPaletteBrowser isEntryEnabledAt:i])
[documentPaletteBrowser removeEntryAt:i];
[documentPaletteBrowser update];
for(i=[sourcePaletteBrowser count]-1; i>=0; i--)
if(![sourcePaletteBrowser isEntryEnabledAt:i])
[sourcePaletteBrowser removeEntryAt:i];
[sourcePaletteBrowser update];
return self;
}
- cancelRetrievals:sender
{
[self terminateThread];
[self restartThread];
return self;
}
//!!! This method should be called before doing any operation that might
//!!! access a WaisDocument. If it is being retrieved, you should
//!!! not access it as that might collide with operations in the
//!!! retrieval thread.
- (BOOL)isDocumentBeingRetrieved:waisDoc
{
int docAt;
if(requestMutex) mutex_lock(requestMutex);
docAt = [retrievalList indexOf:waisDoc];
if(requestMutex) mutex_unlock(requestMutex);
if(docAt!=NX_NOT_IN_LIST && docAt>=0) return YES;
return NO;
}
- retrieveDocuments:(const char *)keyList
{
int docAt;
char *docKeys, *thisKey, *nextKey;
id doc, inBrowser;
BOOL isSource;
// Assumes keyList is TAB-separated list of keys.
if(!keyList || !retrievalThread) return nil;
if(!(docKeys = s_malloc(strlen(keyList) + 1))) return nil;
strcpy(docKeys, keyList);
for(thisKey=docKeys, nextKey=strchr(thisKey, '\t');
thisKey; thisKey=nextKey, nextKey=strchr(thisKey?thisKey:"", '\t'))
{
if(nextKey) *nextKey++ = 0;
// Check if doc is aleady retrieved or being retrieved (then ignore).
if(!(doc = [WaisDocument objectForKey:thisKey])) continue;
if([self isDocumentBeingRetrieved:doc] || [doc isRetrieved])
continue;
// Check if it is really a source.
isSource = NO;
inBrowser = documentPaletteBrowser;
if([doc valueForStringKey:":type"]
&& 0==strcmp([doc valueForStringKey:":type"], "WSRC"))
isSource = YES;
if(isSource) inBrowser = sourcePaletteBrowser;
// Enter into correct palette browser, but disabled.
if(inBrowser)
{
docAt = [inBrowser indexAddEntry:[doc key]];
[inBrowser setEntryEnabled:NO at:docAt];
[inBrowser update];
}
// Enter doc into queue and notify thead of retrieval request.
if(requestMutex) mutex_lock(requestMutex);
[retrievalList addObjectIfAbsent:doc];
if(requestMutex) mutex_unlock(requestMutex);
if(requestCondition) condition_signal(requestCondition);
}
s_free(docKeys);
return self;
}
- retrieveDocumentsFrom:sender
{
return [self retrieveDocuments:[sender stringValue]];
}
// ----------------------- PANEL SETUP ----------------------- //
- init
{
id Handlers;
[super init];
// Classify file types.
Handlers = [[List alloc] initCount:0];
[Handlers addObject:[QuestionDoc class]];
[Handlers addObject:[SourceDoc class]];
[super setDocHandlers:Handlers];
launchWithCreateDoc = YES;
// Keep track of retrieval threads.
retrievalList = [[List alloc] initCount:0];
retrievalThread = 0;
return self;
}
- free
{
if(retrievalThread) [self terminateThread];
[retrievalList free];
if(requestMutex) mutex_free(requestMutex);
if(requestCondition) condition_free(requestCondition);
return [super free];
}
- appDidInit:sender
{
char userInfo[1024];
char hostname[512];
[super appDidInit:sender];
// Enable Alert Panels for Wais classes.
[Wais setStringTable:stringTable];
// Set up according to preferences.
[self usePrefs];
// Set user registration string.
gethostname(hostname, 512); hostname[512-1] = 0;
sprintf(userInfo, "WAIStation.app %s, from host: %s, user: %s",
WAISTATION_VERSION, hostname, WAIS_USER);
[WaisSource registerUser:userInfo];
// Pop up source and doc palettes.
[self sourcePalette:self];
[self documentPalette:self];
[sourcePalettePanel makeKeyAndOrderFront:self];
// Start retrieval thread.
// Must be done after doc and source palette created if we want updates!
[self restartThread];
return self;
}
- help:sender
{
if(!helpPanel) [NXApp loadNibSection:"Help.nib" owner:self];
[helpPanel makeKeyAndOrderFront:self];
return self;
}
- info:sender
{
if(!infoPanel) [NXApp loadNibSection:"Info.nib" owner:self];
[infoPanel makeKeyAndOrderFront:self];
return self;
}
- bugReport:sender
{
//!!! Note the "MailSendDemo" port is undocumented.
id mailSpeaker = [[MailSpeaker alloc] init];
port_t mailPort = NXPortFromName("MailSendDemo", NULL);
if(!mailSpeaker || mailPort==PORT_NULL)
{ [mailSpeaker free]; return nil; }
[mailSpeaker setSendPort:mailPort];
[mailSpeaker openSend];
if(NXGetDefaultValue("WAIStation", "BugReportAddress"))
[mailSpeaker setTo:NXGetDefaultValue("WAIStation",
"BugReportAddress")];
if(NXGetDefaultValue("WAIStation", "BugReportCC"))
[mailSpeaker setCc:NXGetDefaultValue("WAIStation", "BugReportCC")];
if(NXGetDefaultValue("WAIStation", "BugReportSubject"))
[mailSpeaker setSubject:NXGetDefaultValue("WAIStation",
"BugReportSubject")];
if(NXGetDefaultValue("WAIStation", "BugReportMessage"))
[mailSpeaker setBody:NXGetDefaultValue("WAIStation",
"BugReportMessage")];
[mailSpeaker free];
port_deallocate(task_self(), mailPort);
return self;
}
- signMeUp:sender
{
//!!! Note the "MailSendDemo" port is undocumented.
id mailSpeaker = [[MailSpeaker alloc] init];
port_t mailPort = NXPortFromName("MailSendDemo", NULL);
if(!mailSpeaker || mailPort==PORT_NULL)
{ [mailSpeaker free]; return nil; }
[mailSpeaker setSendPort:mailPort];
[mailSpeaker openSend];
if(NXGetDefaultValue("WAIStation", "MailListAddress"))
[mailSpeaker setTo:NXGetDefaultValue("WAIStation", "MailListAddress")];
[mailSpeaker setSubject:"SUBSCRIBE"];
if(NXGetDefaultValue("WAIStation", "MailListMessage"))
[mailSpeaker setBody:NXGetDefaultValue("WAIStation",
"MailListMessage")];
[mailSpeaker free];
port_deallocate(task_self(), mailPort);
return self;
}
- sourcePalette:sender
{
int i, j, n, m;
BOOL quiet;
id srcList, srcPath;
const char **srcFolder;
if(!(srcPath = [WaisSource folderList])) return nil;
if(!sourcePalettePanel)
{
[NXApp loadNibSection:"SourcePalette.nib" owner:self];
[[sourcePaletteBrowser setAlphabetized:YES] setAbbreviated:YES];
[sourcePaletteBrowser setEditable:YES];
}
// Load all directories in source path (ignore missing ones).
[sourcePaletteBrowser clear];
quiet = [Wais isQuiet];
[Wais setQuiet:YES];
m = [srcPath count];
for(j=0; j<m; j++) if((srcFolder=(const char **)[srcPath elementAt:j])
&& (*srcFolder) && (srcList=[WaisSource loadFolder:*srcFolder]))
{
n = [srcList count];
for(i=0; i<n; i++)
[sourcePaletteBrowser addEntry:[[srcList objectAt:i] key]];
[srcList free];
}
[Wais setQuiet:quiet];
[sourcePaletteBrowser update];
[sourcePalettePanel orderFront:self];
if(!sourcePaletteIWC) sourcePaletteIWC =
[[IconWellControl alloc] initWindow:sourcePalettePanel];
return self;
}
- documentPalette:sender
{
int i, j, n, m;
BOOL quiet;
id docList, docPath;
const char **docFolder;
if(!(docPath = [WaisDocument folderList])) return nil;
if(!documentPalettePanel)
{
[NXApp loadNibSection:"DocumentPalette.nib" owner:self];
[[documentPaletteBrowser setAlphabetized:YES] setAbbreviated:YES];
[documentPaletteBrowser setEditable:YES];
}
// Load all directories in document path (ignore missing ones).
[documentPaletteBrowser clear];
quiet = [Wais isQuiet];
[Wais setQuiet:YES];
m = [docPath count];
for(j=0; j<m; j++) if((docFolder=(const char **)[docPath elementAt:j])
&& (*docFolder) && (docList=[WaisDocument loadFolder:*docFolder]))
{
n = [docList count];
for(i=0; i<n; i++)
{
if([self isDocumentBeingRetrieved:[docList objectAt:i]])
continue;
else if([[docList objectAt:i] isRetrieved])
[documentPaletteBrowser addEntry:[[docList objectAt:i] key]];
}
[docList free];
}
[Wais setQuiet:quiet];
[documentPaletteBrowser update];
[documentPalettePanel orderFront:self];
if(!documentPaletteIWC) documentPaletteIWC =
[[IconWellControl alloc] initWindow:documentPalettePanel];
return self;
}
// ----------------------- DELEGATED FILE OPS ------------------------ //
- (int)openFile:(const char *)fileName ok:(int *)flag
{
int rtn;
// Try to open in this application first, then in Workspace.
if([super handlerForFile:fileName])
{
if([super openForHandlerAt:(-1) name:fileName]) *flag = YES;
else *flag = NO;
rtn = 0;
}
else
{
[Wais lockTransaction];
[[NXApp appSpeaker] setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
rtn = [[NXApp appSpeaker] openFile:fileName ok:flag];
[Wais unlockTransaction];
}
return rtn;
}
- (int)removeFile:(const char *)fileName ok:(int *)flag
{
int rtn = 0;
char *auxFile = 0;
id doc = nil;
// If a WaisDocument, set it as unretrieved
// and delete the associated ".wais" file too.
if(!fileName) return (-1);
*flag = NO;
if(doc = [WaisDocument objectForKey:fileName])
{
auxFile = s_malloc(1+strlen(fileName)+strlen(".wais"));
if(!auxFile) return (-1);
strcpy(auxFile, fileName); strcat(auxFile, ".wais");
//!!! Potential thread conflict if doc is being retrieved.
// (But shouldn't be a problem since such entries are disabled.)
[doc setUnretrieved];
}
[Wais lockFileIO];
if(doc) rtn = unlink(auxFile);
if(rtn == 0) rtn = unlink(fileName);
else unlink(fileName);
[Wais unlockFileIO];
if(auxFile) s_free(auxFile);
if(rtn != 0) return rtn;
*flag = YES;
return 0;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.