// Copyright 1997-1999 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 "OAApplication.h"

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>

#ifdef RHAPSODY
#import <OmniBase/system.h>  // for {s,g}et[e]{g,u}id
#endif

#import "OAAppkitQueueProcessor.h"

RCS_ID("$Header: /Network/Developer/Source/CVS/OmniGroup/OmniAppKit/OAApplication.m,v 1.9 1999/03/30 21:25:52 kc Exp $")

@implementation OAApplication


// This needed to be on for OOA in DR1.  It needs to be off for
// OmniCD in DR2.  This bug appears to be fixed in DR2.
#if 0 && defined(RHAPSODY)
+ (void)initialize;
{
    static BOOL initialized = NO;
    
    [super initialize];
    if (initialized)
        return;
    initialized = YES;

    // The Rhapsody/RDR workspace launches stuff with the wrong egid.  This causes DYLD to get cranky among other things.
    seteuid(getuid());
    setegid(getgid());
}
#endif

+ (void)setupOmniApplication;
{
    [OBPostLoader processClasses];
    [OFQueueProcessor startAppkitQueueProcessor];
}

+ (NSApplication *)sharedApplication;
{
    static OAApplication *omniApplication = nil;

    if (omniApplication)
        return omniApplication;

    omniApplication = (id)[super sharedApplication];
    [OAApplication setupOmniApplication];
    return omniApplication;
}

- (void)run;
{
    BOOL stillRunning = YES;

    exceptionCount = 0;
    exceptionCheckpointDate = [[NSDate alloc] init];
    do {
        NS_DURING {
            [super run];
            stillRunning = NO;
        } NS_HANDLER {
            if (++exceptionCount % 300 == 0) {
                if ([exceptionCheckpointDate timeIntervalSinceNow] > -3.0)
                    stillRunning = NO; // 300 exceptions in 3 seconds: abort
                [exceptionCheckpointDate release];
                exceptionCheckpointDate = [[NSDate alloc] init];
                exceptionCount = 0;
            }
            if (localException) {
                if (_appFlags._hasBeenRun)
                    [self handleRunException:localException];
                else
                    [self handleInitException:localException];
            }
        } NS_ENDHANDLER;
    } while (stillRunning && _appFlags._hasBeenRun);
}

- (void)sendEvent:(NSEvent *)event;
{
    [OFQueueProcessor disableAppkitQueueEventProcessing];
    NS_DURING {
        [super sendEvent:event];
    } NS_HANDLER {
        [OFQueueProcessor reenableAppkitQueueEventProcessing];
        if ([[localException name] isEqualToString:NSAbortModalException] || [[localException name] isEqualToString:NSAbortPrintingException])
            [localException raise];
        [self handleRunException:localException];
    } NS_ENDHANDLER;
    [OFQueueProcessor reenableAppkitQueueEventProcessing];
}

- (void)handleInitException:(NSException *)anException;
{
    NSLog(@"%@", [anException reason]);
}

- (void)handleRunException:(NSException *)anException;
{
    NSLog(@"%@", [anException reason]);
    NSRunAlertPanel(nil, @"%@", nil, nil, nil, [anException reason]);
}

@end
