// Copyright 1998-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 "OASecureTextField.h"

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

RCS_ID("$Header: /Network/Developer/Source/CVS/OmniGroup/OmniAppKit/Widgets.subproj/OASecureTextField.m,v 1.5 1999/03/30 21:26:12 kc Exp $")

@implementation OASecureTextField

// Init and dealloc

- initWithFrame:(NSRect)aFrame;
{
    if (![super initWithFrame:aFrame])
        return nil;

    selectTextDisabled = NO;

    return self;
}

#ifndef YELLOW_BOX

- (void)dealloc;
{
    // In OPENSTEP 4.2, the NSSecureTextView field editor tries to talk to the last secure text field it was editing when it starts to be used to edit a new secure text field--regardless of whether that last one has been dealloced.  (This might be a side effect of our -stringValue hack below.)  If I knew how to clear its pointer to us, I'd do that, but I don't.  I could presumably also check to see whether we've ever been edited, but for now I'm just going to disable deallocation of OASecureTextFields:  we can ship with a leak, but not with this crasher.
    // Note that this bug does not occur on Rhapsody (at least, not on DR2).

    // [super dealloc];
}

#endif

// NSSecureTextField subclass

- (void)setFrameSize:(NSSize)newFrameSize;
{
    BOOL oldSelectTextDisabled;

    oldSelectTextDisabled = selectTextDisabled;
    selectTextDisabled = YES;
    [super setFrameSize:newFrameSize];
    selectTextDisabled = oldSelectTextDisabled;
}

- (void)selectText:(id)sender;
{
    if (selectTextDisabled)
        return;
    [super selectText:sender];
}

// -[NSSecureTextField stringValue] doesn't return the currently-entered value if you haven't yet left the field (i.e., made something else the first responder).  I'm working around that bug here by making the field resign its status as first responder (and then I'm cleaning up by making myself the first responder again).

- (NSString *)stringValue;
{
    NSWindow *window;
    NSResponder *firstResponder;

    window = [self window];
    firstResponder = [window firstResponder];

    // When we're selected, the first responder will be a private subview.
    if ([firstResponder isKindOfClass:[NSView class]] && [(NSView *)firstResponder isDescendantOf:self]) {
        NSRange selection;
        NSSelectionAffinity affinity;
        BOOL hadSelection;

        // Don't clobber the selection while extracting the value.
        if ([firstResponder isKindOfClass:[NSTextView class]]) {
            selection = [(NSTextView *)firstResponder selectedRange];
            affinity = [(NSTextView *)firstResponder selectionAffinity];
            hadSelection = YES;
        } else {
            affinity = NSSelectionAffinityDownstream; // appease compiler
            hadSelection = NO;
        }
            
        [window makeFirstResponder:nil];
        // Can't restore the private subview as the first responder because it may have been recycled.  Make ourselves the first responder instead.
        [window makeFirstResponder:self];

        // Restore the selection.
        if (hadSelection) {
            firstResponder = [window firstResponder];
            if ([firstResponder isKindOfClass:[NSTextView class]]) {
                [(NSTextView *)[window firstResponder] setSelectedRange:selection affinity:affinity stillSelecting:NO];
            }
        }
    }

    return [super stringValue];
}

@end
