// Doc.m
//
// Free software created 1 Feb 1992
// by Paul Burchard <burchard@math.utah.edu>.

#import "Doc.h"
#import "DocControl.h"
#import <objc/HashTable.h>
#import <appkit/appkit.h>
#import <stdlib.h>
#import <string.h>


@implementation Doc

static id convertFileNameToDoc;

+ (const char *)fileType
{
    return "";
}

+ (const char *)nibName
{
    return "Doc.nib";
}

+ (const char *)miniIconName
{
    return NULL;
}

+ (BOOL)backupOnSave
{
    return NO;
}

+ (const char *)defaultFolder
{
    return NXHomeDirectory();
}

+ initialize
{
    if(self != [Doc class]) return self;
    convertFileNameToDoc = [[HashTable alloc] initKeyDesc:"%" valueDesc:"@"];
    return self;
}

- init
{
    static count = 0;
    NXRect theFrame;
    NXSize theScreen;
    NXScreen *ignore;
    const char *iname;
    
    [super init];
    [NXApp loadNibSection:[[self class] nibName] owner:self];
    
    // Displace successive new windows down and right until edge of screen.
    [window getFrame:&theFrame andScreen:&ignore];
    [NXApp getScreenSize:&theScreen];
    if((NX_MAXX(&theFrame) + 20.0*count) > theScreen.width
    	|| (NX_Y(&theFrame) - 25.0*count) < 0)
	count = 0;
    NX_X(&theFrame) += 20.0*count;
    NX_Y(&theFrame) -= 25.0*count;
    count++;
    [window moveTo:NX_X(&theFrame) :NX_Y(&theFrame)];

    // Make window represent this Doc type.
    [window setDelegate:self];
    //!!![window setFreeWhenClosed:YES];
    if(iname = [[self class] miniIconName]) [window setMiniwindowIcon:iname];
    fileName = 0;
    [window makeKeyAndOrderFront:nil];
    return self;
}

- free
{
    [window free];
    if(fileName) [convertFileNameToDoc removeKey:fileName];
    return [super free];
}

- setFileName:(const char *)aName
{
    const char *aType;
    
//!!!
if(!aName && fileName) { [convertFileNameToDoc removeKey:fileName]; fileName = 0; }

    // Check if extension matches file type.
    if(!aName) return nil;
    if(!(aType = strrchr(aName, '/'))) aType = aName;
    if(aType = strrchr(aType, '.'))
    	{ if(strcmp(aType+1, [[self class] fileType]) != 0) return nil; }
    else
    	{ if(strcmp("", [[self class] fileType]) != 0) return nil; }

    // Re-index doc in filename table (don't overwrite existing Doc).
    if([[self class] docForFileName:aName]) return nil;
    if(fileName) [convertFileNameToDoc removeKey:fileName];
    fileName = NXUniqueString(aName);//!!! wasteful but avoid HashTable woes
    [convertFileNameToDoc insertKey:(void *)fileName value:(void *)self];

    // Re-title window.
    [window setTitleAsFilename:fileName];
    return self;
}

- (const char *)fileName
{
    return fileName;
}

+ docForFileName:(const char *)aName
{
    return (id)[convertFileNameToDoc valueForKey:(void *)aName];
}

- dump:sender
{
    // Implemented in subclass.
    if(!fileName) return nil;
    return self;
}

- load:sender
{
    // Implemented in subclass.
    if(!fileName) return nil;
    return self;
}

- textDidChange:sender
{
    [window setDocEdited:YES];
    return self;
}

- windowWillClose:sender
{
    // Check with delegate first.
    if(delegate && [delegate respondsTo:@selector(windowWillClose:)]
	&& ![delegate windowWillClose:sender])
	    return nil;
    
    // Give user chance to save or rethink if edited, else free doc.
    if(![[NXApp delegate] closeDoc:self andFree:NO]) return nil;//!!!
    return sender;
}

- window
{
    return window;
}

- setDelegate:anObject
{
    delegate = anObject;
    return self;
}

- delegate
{
    return delegate;
}

- forward:(SEL)aSelector :(marg_list)argFrame
{
    if([delegate respondsTo:aSelector])
        return [delegate performv:aSelector :argFrame];
    else return nil;
}

@end


