/* 
   PXKCell.m

   NSCell for GNUstep GUI X/DPS Backend

   Copyright (C) 1996 Free Software Foundation, Inc.

   Author:  Pascal Forget <pascal@wsc.com>
   Date: January 1996
   
   This file is part of the GNUstep GUI X/DPS Backend.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
   
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   If you are interested in a warranty or support for this source code,
   contact Scott Christley <scottc@net-community.com> for more information.
   
   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ 

#include <gnustep/xdps/PXKCell.h>
#include <AppKit/NSControl.h>

NSMutableArray *_allCells; /* Contains all instances of the Cell class */

@implementation PXKCell

+ (void)initialize;
{
    if (!_allCells) {
	_allCells = [NSMutableArray array];
    }
}

- (NSSize)cellSizeForBounds:(NSRect)aRect;
{
    NSSize invalidSize;
    
    if ((aRect.size.width >= cell_size.width) &&
	(aRect.size.height >= cell_size.height)) {
	return aRect.size;
    } else {
	invalidSize.width = 0.0;
	invalidSize.height = 0.0;
	return invalidSize;
    }
}

- (NSComparisonResult)compare:(id)otherCell;
{
    if ((!otherCell) || ([otherCell isKindOfClass:[NSCell class]] == NO)) {
#if 0
	NSRaiseException(NSBadComparisonException); /* Right syntax? */
#else
	exit(-1); /* Crash the program */
#endif
    } else {
	return [[self stringValue] compare:[otherCell stringValue]];
    }
}

- (void)dealloc;
{
    [_allCells removeObject:self];
    [super dealloc];
}

- (NSRect)drawingRectForBounds:(NSRect)theRect;
{
    NSRect aRect;
    
    if (theRect.size.width >= cell_size.width) {
	aRect.size.width = theRect.size.width;
    } else {
	aRect.size.width = cell_size.width;
    }

    if (theRect.size.height >= cell_size.height) {
	aRect.size.height = theRect.size.height;
    } else {
	aRect.size.height = cell_size.height;
    }

    aRect.origin.x = theRect.origin.x;
    aRect.origin.y = theRect.origin.y;
    
    return aRect;
}

- (void)drawBorder;
{
    /* Not implemented yet */
}

- (void)drawImage;
{
    /* Not implemented yet */
}

#if 0
- (void)drawTextInRect:(NSRect)frame;
{
    /* Goofy implementation for testing only */
    
    int len1;
    int width;
    int font_height;
    int alignment = 0;
    XFontStruct *win_font;
#if 0
    fprintf(stdout, "Cell text frame: %d %d %d %d\n",
	    frame.origin.x, frame.origin.y,
	    frame.size.width, frame.size.height);
#endif    
    (void)load_font(&win_font);
    
    /* need length for both XTextWidth and XDrawString */
    len1 = [stringValue length];

    /* get string widths for centering */
    width = XTextWidth(win_font, [stringValue cString], len1);

    font_height = win_font->ascent + win_font->descent;

    /*
     * Wipe out the contents of the window by filling its
     * area with the backGroundColor (defined in NSView.h)
     */

    if (isOpaque) {
	XFillRectangle(NSDisplay, [_controlView xWindow], NSLightgrayGC,
		       frame.origin.x+2, frame.origin.y+2,
		       frame.size.width-4, frame.size.height-4);
    }
    
    if((alignment == NSALIGN_LEFT) && (width < frame.size.width)) {
	XDrawString(NSDisplay, [_controlView xWindow],
		    NSBlackGC,
		    frame.origin.x + 5,
		    frame.origin.y + font_height,
		    [stringValue cString], len1);
    } else if((alignment == NSALIGN_RIGHT) && ((width+5)<frame.size.width)) {
	XDrawString(NSDisplay, [_controlView xWindow],
		    NSBlackGC,
		    frame.origin.x + frame.size.width - 5 - width,
		    frame.origin.y + font_height,
		    [stringValue cString], len1);
    } else {

	if (width > (frame.size.width-4)) {
	    XDrawString(NSDisplay, [_controlView xWindow],
			NSBlackGC,
			frame.origin.x + frame.size.width - width-5, 
			frame.origin.y + font_height,
			[stringValue cString], len1);	    
	} else {
	    /* output text, centered on each line */
	    XDrawString(NSDisplay, [_controlView xWindow],
			NSBlackGC,
			frame.origin.x + (frame.size.width - width-6)/2, 
			frame.origin.y + font_height,
			[stringValue cString], len1);
	}
    }
}
#endif

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView;
{
#if 0
    if (image) {
	[self drawImage];
    }
    
    if (stringValue) {
	[self drawTextInRect:[self titleRectForBounds:cellFrame]];
    }
#endif
}

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView;
{
    [self drawBorder];
    [self drawInteriorWithFrame:cellFrame inView:controlView];
}

- (void)highlight:(BOOL)lit
	withFrame:(NSRect)cellFrame
	   inView:(NSView *)controlView;
{
    cell_highlighted = lit;
    [self drawWithFrame:cellFrame inView:controlView];
}

- (NSRect)imageRectForBounds:(NSRect)theRect;
{
    NSRect imageRect;

    if ([self isBordered] == NO) {
	imageRect.origin.x = theRect.origin.x;
	imageRect.origin.y = theRect.origin.y;
	imageRect.size.width = NSX_MAX(cell_size.width,theRect.size.width);
	imageRect.size.height = NSX_MAX(cell_size.width,theRect.size.height);
    } else {
	imageRect.origin.x = theRect.origin.x + 1.0;
	imageRect.origin.y = theRect.origin.y + 1.0;
	imageRect.size.width = NSX_MAX(cell_size.width - 2.0,
				       theRect.size.width - 2.0);
	imageRect.size.height = NSX_MAX(cell_size.width - 2.0,
					theRect.size.height - 2.0);
    }
    return imageRect;
}

- (id)initImageCell:(NSImage *)anImage;
{
    [super initImageCell:anImage];

    [_allCells addObject:self];
    
    return self;
}

- (id)initTextCell:(NSString *)aString;
{
    [super initTextCell:aString];
    
    [_allCells addObject:self];
    
    return self;
}

- (BOOL)isEntryAcceptable:(NSString *)aString;
{
    BOOL isNumeric = YES;   /* Int, float or double */
    BOOL isPositive = YES;  /* Numeric > 0 */
    BOOL isInt = YES;
    int i=0, count;
    const char *str;
    char c;
    int numberOfDots = 0;
    
    if ((entry_type == NSAnyType) || (aString == nil)) {
	return YES;
    } else {

	count = [aString length];

	str = [aString cString];

	if (entry_type == NSDateType) { /* VERY primitive date validation */
	    
	    for (i=0; i<count; i++) {
		c = str[i];
		if ((c=='k') ||
		    (c=='w') ||
		    (c=='x') ||
		    (c=='z') ||
		    (c<32) ||
		    (c>122))
		{
		    return NO;
		}
	    }
	    return YES;
	    
	} else {   /* Entry is of one of the numeric types */

	    /* Ignore leading blanks and TABS */

	    while (((c=str[i]) == ' ') || (c=='\t')) {
		i++;
	    }

	    /* See if the current char is a minus sign */

	    if (c == '-') {
		isPositive = NO;
	    }

	    for (; i<count; i++) {
		c = str[i];

		if (c == '.') {
		    numberOfDots++;
		    
		    if (numberOfDots > 1) {
			isNumeric = NO;
		    }
		} else {
		    
		    if ((c>'9') || (c < '0')) {
			isNumeric = NO;
		    }
		}
	    }

	    if (isNumeric &&
		isInt &&
		(((float)[aString intValue]) == [aString floatValue]))
	    {
		isInt = YES;
	    } else {
		isInt = NO;
	    }

	    if (entry_type == NSIntType) {
		if (isNumeric && isInt) {
		    return YES;
		} else {
		    return NO;
		}
	    } else if (entry_type == NSPositiveIntType) {
		if (isNumeric && isInt && isPositive) {
		    return YES;
		} else {
		    return NO;
		}
	    } else if (entry_type == NSFloatType) {
		if (isNumeric && (isInt == NO)) {
		    return YES;
		} else {
		    return NO;
		}
	    } else if (entry_type == NSPositiveFloatType) {
		if (isNumeric && (isInt == NO) && isPositive) {
		    return YES;
		} else {
		    return NO;
		}		
	    } else if (entry_type == NSDoubleType) {
		if (isNumeric && (isInt == NO)) {
		    return YES;
		} else {
		    return NO;
		}
	    } else if (entry_type == NSPositiveDoubleType) {
		if (isNumeric && (isInt == NO) && isPositive) {
		    return YES;
		} else {
		    return NO;
		}		
	    }	   
	}
    }
    return YES;
}

- (id)representedObject;
{
    return represented_object;
}

- (void)setRepresentedObject:(id)anObject;
{
    int i, count;
    NSCell *aCell;
    
    if (anObject == nil) {
	represented_object = nil; /* Set the instance variable, we're done. */
    } else {
	
	represented_object = anObject; /* Set the instance variable */
	
	count = [_allCells count];

	/*
	 * Look for an existing association between another cell
	 * and anObject
	 */
	
	for (i=0; i<count; i++) {
	    aCell = [_allCells objectAtIndex:i];
	
	    if ((aCell != self) && ([aCell representedObject] == anObject)) {
		[aCell setRepresentedObject:nil];
		return;
	    }
	}
    }
}

- (NSRect)titleRectForBounds:(NSRect)theRect;
{
#if 0
    fprintf(stdout, "Cell titleRectForBounds: %d %d %d %d\n",
	    theRect.origin.x, theRect.origin.y,
	    theRect.size.width, theRect.size.height);
#endif        
    /* Goofy implementation for testing only */
    return theRect;
}

@end
