Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
441 lines (356 sloc) 10 KB
// HyperText Access method manager Object HyperManager.m
// --------------------------------------
//
//
// History:
// Oct 90 Written TBL
//
#import "HyperManager.h"
@implementation HyperManager
#import "HyperText.h"
#import "HTUtils.h"
#import "HTParse.h"
#import "HTAccess.h"
#import "WWWPageLayout.h"
#define THIS_TEXT (HyperText *)[[[NXApp mainWindow] contentView] docView]
extern char * WWW_nameOfFile(const char * name); /* In file access */
/* Exported to everyone */
int WWW_TraceFlag =0; /* Exported to everyone */
char * appDirectory; /* Name of the directory containing the application */
/* Private to this module
*/
PRIVATE FileAccess * fileAccess = nil;
+ new
{
self = [super new];
accesses = [List new]; // Create and clear list
return self;
}
- traceOn:sender { WWW_TraceFlag = 1; return self;}
- traceOff:sender { WWW_TraceFlag = 0; return self;}
- manager {return nil; } // we have no manager
- setManager {return nil; } // we have no manager
- (const char *) name
{
return "any";
}
// Access Management functions
//
- registerAccess:(HyperAccess *)access
{
if (!accesses) accesses=[List new];
if (TRACE) printf(
"HyperManager: Registering access `%s'.\n", [access name]);
if (0==strcmp([access name], "file"))
fileAccess = (FileAccess*)access; /* We need that one */
return [accesses addObject:access];
}
// Load an anchor from some access loadAnchor:
// -------------------------------
//
// This implementation simply looks for an access with the right name.
// It also checks whether in fact the anchor
// is already loaded and linked, and that the address string is not null.
//
// On exit:
// If a duplicate node is found, that anchor is returned
// If there is no success, nil is returned.
// Otherwise, the anchor is returned.
- loadAnchor:(Anchor *)anAnchor Diagnostic:(int)diagnostic
{
char * s=0;
const char *addr;
int i;
HyperAccess * access;
if ([anAnchor node]) {
return [[anAnchor node] nodeAnchor]; /* Already loaded and linked. */
if (TRACE) printf("HyperManger: Anchor already has a node.\n");
}
addr = [anAnchor address];
if (!addr) {
if (TRACE) printf("HyperManger: Anchor has no address - can't load it.\n");
return nil; /* No address? Can't load it. */
}
if (TRACE) printf("HyperManager: Asked for `%s'\n", addr);
s= HTParse(addr, "", PARSE_ACCESS);
for(i=0; i<[accesses count]; i++) {
access = [accesses objectAt:i];
if (0==strcmp(s, [access name])) {
id status;
HyperText * HT;
if(TRACE) printf("AccessMgr: Loading `%s' using `%s' access.\n",
[anAnchor address], [access name]);
free(s);
status = [access loadAnchor:anAnchor Diagnostic:diagnostic];
if (!status) return nil;
// The node may have become an index: update the existence
// state of the panel.
HT = [anAnchor node];
if ([HT isIndex]) {
[[keywords window] makeKeyAndOrderFront:self];
} else {
[[keywords window] close];
// [[keywords window] orderOut:self]; @@ bug?
}
return status;
}
}
// Error: No access. Print useful error message.
{
char got[100];
char *format;
format = *s ?
"Invalid access prefix for `%s'\n Can be one of %s but not `%s:'.\n"
: "No access prefix specified for `%s'\n Accesses are: %s .\n";
for(i=0; i<[accesses count]; i++) {
sprintf(got, "%s: ",[[accesses objectAt:i] name]);
}
printf(format,[anAnchor address], got, s);
NXRunAlertPanel(NULL,format,
NULL,NULL,NULL,
[anAnchor address], got, s);
}
free(s);
return nil;
}
//______________________________________________________________________________
// Open or search by name
// -----------------------
//
//
- accessName:(const char *)arg
Diagnostic:(int)diagnostic
{
return [[Anchor newAddress:arg] selectDiagnostic:diagnostic];
}
// Search with a given diagnostic level
//
// This involves making a special address string, being the index address
// with a ? sign followed by a "+" separated list of keywords.
//
- searchDiagnostic:(int)diagnostic
{
char addr[256];
char keys[256];
char *p, *q;
HyperText * HT = THIS_TEXT;
if (!HT) return nil;
strcpy(addr, [[HT nodeAnchor] address]);
if ((p=strchr(addr, '?'))!=0) *p=0; /* Chop off existing search string */
strcat(addr,"?");
strcpy(keys, [keywords stringValueAt:0]);
q =HTStrip(keys); /* Strip leading and trailing */
for(p=q; *p; p++)
if (WHITE(*p)) {
*p='+'; /* Separate with plus signs */
while (WHITE(p[1])) p++; /* Skip multiple blanks */
if (p[1]==0) *p = 0; /* Chop a single trailing space */
}
strcat(addr, keys); /* Make combined node name */
return [self accessName:HTStrip(addr) Diagnostic:diagnostic];
}
// N A V I G A T I O N
// Realtive moves
// --------------
//
// These navigate around the web as though it were a tree, from the point of
// view of the user's browsing order.
- back:sender { return [Anchor back]; }
- next:sender { return [Anchor next]; }
- previous:sender { return [Anchor previous]; }
// Go Home
// -------
//
// This accesses the default page of text for the user or, failing that,
// for the system.
//
- goHome:sender
{
return [fileAccess openMy:"default.html" diagnostic:0];
}
// Load Help information
// ---------------------
//
//
- help:sender
{
return [fileAccess openMy:"help.html" diagnostic:0];
}
// Go to the Blank Page
// --------------------
//
//
- goToBlank:sender
{
return [fileAccess openMy:"blank.html" diagnostic:0];
}
// Application Delegate Methods
// ============================
// On Initialisation, Load Initial File
// ------------------------------------
-appDidInit:sender
{
if (TRACE) printf("HyperManager: appDidInit\n");
// StrAllocCopy(appDirectory, NXArgv[0]);
// if (p = strrchr(appDirectory, '/')) p[1]=0; /* Chop home slash */
// if (TRACE) printf("WWW: Run from %s\n", appDirectory);
[Anchor setManager:self];
return [self goHome:self];
}
// Accept that we can open files from the workspace
- (BOOL)appAcceptsAnotherFile:sender
{
return YES;
}
// Open file from the Workspace
//
- (int)appOpenFile:(const char *)filename type:(const char *)aType
{
char * name = WWW_nameOfFile(filename);
HyperText * HT = [self accessName:name Diagnostic:0];
free(name);
return (HT!=0);
}
// Open Temporary file
//
// @@ Should unlink(2) the file when we have done with it!
- (int)appOpenTempFile:(const char *)filename type:(const char *)aType
{
char * name = WWW_nameOfFile(filename); /* No host */
HyperText * HT = [self accessName:name Diagnostic:0];
free(name);
return (HT!=0);
}
// Actions:
// -------
- search:sender
{
return [self searchDiagnostic:0];
}
- searchRTF:sender
{
return [self searchDiagnostic:1];
}
- searchSGML:sender
{
return [self searchDiagnostic:2];
}
// Direct open buttons:
- open:sender
{
return [self accessName:[openString stringValueAt:0] Diagnostic:0];
}
- openRTF:sender
{
return [self accessName:[openString stringValueAt:0] Diagnostic:1];
}
- openSGML:sender
{
return [self accessName:[openString stringValueAt:0] Diagnostic:2];
}
// Save a hypertext back to its original server
// --------------------------------------------
- save:sender
{
HyperText * HT = THIS_TEXT;
id status = [(HyperAccess *)[HT server] saveNode:HT];
if (status) [[HT window] setDocEdited:NO];
return status;
}
// Save all hypertexts back
// -------------------------
- saveAll:sender
{
List * windows = [NXApp windowList];
id cv;
int i;
int n = [windows count];
for(i=0; i<n ; i++){
Window * w = [windows objectAt:i];
if (cv=[w contentView])
if ([cv respondsTo:@selector(docView)])
if ([w isDocEdited]) {
HyperText * HT = [[w contentView] docView];
if ([(HyperAccess *)[HT server] saveNode:HT])
[w setDocEdited: NO];
}
}
return self;
}
// Close all unedited windows except this one
// ------------------------------------------
//
- closeOthers:sender
{
Window * thisWindow = [NXApp mainWindow];
List * windows = [[NXApp windowList] copy];
{
int i;
id cv; // Content view
int n = [windows count];
for(i=0; i<n; i++){
Window * w = [windows objectAt:i];
if (w != thisWindow)
if (cv=[w contentView])
if ([cv respondsTo:@selector(docView)]) {
if (![w isDocEdited]) {
if (TRACE) printf(" Closing window %i\n", w);
[w performClose:self];
}
}
}
[windows free]; /* Free off copy of list */
return self;
}
}
// Print Postscript code for the main window
// -----------------------------------------
- print:sender
{
return [THIS_TEXT printPSCode:sender];
}
// Run the page layout panel
//
- runPagelayout:sender
{
PageLayout * pl = [WWWPageLayout new];
[pl runModal];
return self;
}
// HyperText delegate methods
//
// This one has been passed from a window
// to the hypertext which is its delegate,
// to the access server module of that hypertext,
// to this access manager.
//
// When a hypertext windown becomes a key window, the search
// panel is turned on or off depending on whether a search can be done,
// and the default address in the "open using full reference" panel
// is set to the address of the current hypertext.
//
- hyperTextDidBecomeMain: sender
{
if ([sender isIndex]) {
[[keywords window] makeKeyAndOrderFront:self];
} else {
[[keywords window] close];
// [[keywords window] orderOut:self]; bug?
}
[openString setStringValue: [[sender nodeAnchor] address] at:0];
return self;
}
// Panel delegate methods
//
// The only windows to which this object is a delegate
// are the open and search panels. When they become key,
// we ensure that the text is selected.
- windowDidBecomeKey:sender
{
if (sender == [openString window])
[openString selectTextAt:0]; // Preselect the text
else if (sender == [keywords window])
[keywords selectTextAt:0]; // Preselect the text
return self;
}
@end