// Copyright 1997-2000 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import "OHHTMLDisplayProcessor.h"

#import <Foundation/Foundation.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>
#import <OmniAppKit/OmniAppKit.h>
#import <OWF/OWF.h>

#import "OHDocumentView.h"
#import "OHHTMLDocument.h"
#import "OHHTMLPageView.h"
#import "OHHTMLView.h"
#import "OHTextBuilder.h"

RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OmniHTML/Building.subproj/OHHTMLDisplayProcessor.m,v 1.11 2000/01/20 00:27:45 kc Exp $")

@implementation OHHTMLDisplayProcessor

+ (void)didLoad;
{
    [self registerProcessorClass:self fromContentType:[OWContentType contentTypeForString:@"ObjectStream/sgml"] toContentType:[OHDocumentView contentType] cost:1.0];
}

- initWithPipeline:(OWPipeline *)aPipeline;
{
    OFUserDefaults *defaults;
    OFZone *contentZone; /* TODO: Make this an ivar to eliminate zone dealloc race conditions? */

    if (![super initWithPipeline:aPipeline])
        return nil;

    defaults = [OFUserDefaults sharedUserDefaults];
    flags.contentAddedToPipeline = NO;
    flags.alwaysUsePreferenceColors = [defaults boolForKey:@"OHAlwaysUsePreferenceColors"];

    contentZone = [[pipeline contentCacheForLastAddress] contentZone];
    htmlDocument = [[OHHTMLDocument allocWithZone:[contentZone nsZone]] init];
    [htmlDocument setPipeline:aPipeline];
    textBuilder = [[OHTextBuilder allocWithZone:[self zone]] initWithHTMLOwner:htmlDocument];
    tableBuilder = nil;
    listRecursionLevel = 0;
    listIndex = -1;
    lastListFinalIndex = 1;
    listLabelType = LABEL_NONE;
    bulletImage = nil;
    definitionListIndent = -1;
    scriptBlockCount = 0;
    [textBuilder setTextBuilderObserver:self];

    return self;
}

- (void)dealloc;
{
    // These should have been cleared out in -process, -processAbort, or -process*Tag:
    OBASSERT(tableBuilder == nil);
    OBASSERT(currentForm == nil);
    OBASSERT(mapSet == nil);
    OBASSERT(currentMapName == nil);
    OBASSERT(currentShapes == nil);
    OBASSERT(currentAppletCell == nil);

    [textBuilder release];
    [htmlDocument release];
    [bulletImage release];

    [cachedFont release];
    [cachedPrefixString release];

    [super dealloc];
}

- (OHTextBuilder *)textBuilder;
{
    return textBuilder;
}

- (OHTextBuilder *)setTextBuilder:(OHTextBuilder *)aTextBuilder;
{
    OHTextBuilder *oldTextBuilder;

    if (textBuilder == aTextBuilder)
	return textBuilder;
    oldTextBuilder = [textBuilder autorelease];
    textBuilder = [aTextBuilder retain];
    return oldTextBuilder;
}

- (OHHTMLDocument *)htmlDocument;
{
    return htmlDocument;
}

// OWSGMLProcessor subclass

#ifdef DEBUG
- (void)processUnknownTag:(OWSGMLTag *)tag;
{
    NSLog(@"Ignoring unknown tag (%@)", [tag name]);
    [super processUnknownTag:tag];
}
#endif

- (void)processCData:(NSString *)cData;
{
    [textBuilder writeUnprocessedString:cData];
}

- (void)addContentToPipeline;
{
    OBPRECONDITION(!flags.contentAddedToPipeline);
    flags.contentAddedToPipeline = YES;
    [pipeline addContent:htmlDocument];
    [pipeline cacheContent];
    [pipeline startProcessingContent];
}

- (void)processBegin;
{
    [super processBegin];
    [self setStatusString:@"Rendering HTML page"];
}

- (void)process;
{
    [pipeline addContent:htmlDocument];
    [super process];
    [self endAnchor];
    [self endForm];
    [self endMapSet];
    [textBuilder endTextBuild];
    if (!flags.contentAddedToPipeline)
	[self addContentToPipeline];
    [textBuilder release];
    textBuilder = nil;
}

- (void)processAbort;
{
    [self endAnchor];
    [self endForm];
    [self endMapSet];
    [textBuilder endTextBuild];
    [textBuilder release];
    textBuilder = nil;
    [super processAbort];
}

// OHTextBuilderObserver protocol

- (void)textBuilderNoLongerPristine:(OHTextBuilder *)aTextBuilder;
{
    if ([pipeline contextObjectForKey:@"DisableIncrementalDisplay"] || flags.contentAddedToPipeline)
	return;
    [self addContentToPipeline];
}

// Debugging

- (NSMutableDictionary *)debugDictionary;
{
    NSMutableDictionary *debugDictionary;

    debugDictionary = [super debugDictionary];
    if (textBuilder)
	[debugDictionary setObject:textBuilder forKey:@"textBuilder"];
    if (htmlDocument)
	[debugDictionary setObject:htmlDocument forKey:@"htmlDocument"];

    [debugDictionary setIntValue:listRecursionLevel forKey:@"listRecursionLevel"];
    [debugDictionary setIntValue:listIndex forKey:@"listIndex"];
    [debugDictionary setIntValue:scriptBlockCount forKey:@"scriptBlockCount"];

    if (tableBuilder)
	[debugDictionary setObject:tableBuilder forKey:@"tableBuilder"];
    if (currentForm)
	[debugDictionary setObject:currentForm forKey:@"currentForm"];
    if (mapSet)
	[debugDictionary setObject:mapSet forKey:@"mapSet"];
    if (currentMapName)
	[debugDictionary setObject:currentMapName forKey:@"currentMapName"];
    if (currentShapes)
	[debugDictionary setObject:currentShapes forKey:@"currentShapes"];
    if (currentAppletCell)
	[debugDictionary setObject:currentAppletCell forKey:@"currentAppletCell"];

    return debugDictionary;
}

@end
