// Mon Sep  2 12:09:44 MET DST 1996

#import "HTMLCells.h"

#import <appkit/appkit.h>

#define CLASS_VERSION 1

@implementation HRCell:Cell

+ initialize
 {   if (self == [HRCell class]) 
	{	/*
		 * **** Archiving: READ ME **** After bumping the CLASS_VERSION, it is
		 * considered common practice to add a comment line indicating the new
		 * version number, date, and modifier. Optionally, the reason for the
		 * change. There is no need to modify the setVersion message.
		 */
		// version 1: initial.  (db)
		[[self class] setVersion:CLASS_VERSION];
    }
	return self;
}


- initForText:(Text*) theText
{	if(!(self=[super init])) return nil;
	text=theText;
	return self;
}

// could be useful for unregistering¼
- free
{	return [super free];
}

- calcCellSize:(NXSize *)theSize
{	NXRect drawRect;
	[text getFrame:&drawRect];
	theSize->width=drawRect.size.width-12;
	theSize->height = 6;
    return self;
}

- drawInside: (const NXRect *)cellFrame inView:controlView
{	NXRect drawRect,clipRect;
	drawRect=*cellFrame;
	[self calcCellSize:&drawRect.size];
	[controlView getFrame:&clipRect];
	[controlView lockFocus];
	NX_WIDTH(&drawRect)+=(NX_X(&drawRect)+12);NX_X(&drawRect)=0;
	clipRect=drawRect;NX_X(&clipRect)-=1;NX_Y(&clipRect)-=1;
	NX_WIDTH(&clipRect)+=2;	NX_HEIGHT(&clipRect)=3;
	NXDrawGroove(&drawRect,&clipRect);
	[controlView unlockFocus];
	return self;
}

- highlight:(const NXRect *)cellFrame inView:controlView lit:(BOOL)flag;
{	return [self drawInside:cellFrame inView:controlView];
}

#define eventMask NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK
#define CLIP_Y(y, restraint0,restraintN) MAX(restraint0,MIN(restraintN,y))

- (BOOL)trackMouse:(NXEvent *)theEvent 
			inRect:(const NXRect *)cellFrame 
			ofView:controlView;
{	return NO;
}


@end


@implementation MiscTFTextFieldCell

- drawSelf: (const NXRect *)cellFrame inView:controlView
{	id erg;
	PSgsave();
	erg=[super drawSelf:cellFrame inView:controlView];
	PSgrestore();
	return erg;
}
- drawInside: (const NXRect *)cellFrame inView:controlView
{	if(afterDrag)
	{	afterDrag=NO;
		return self;
	} else return [super drawInside:cellFrame inView:controlView];
}

- (BOOL)trackMouse:(NXEvent *)theEvent 
			inRect:(const NXRect *)cellFrame 
			ofView:(Text*)controlView;
{	BOOL	erg;
 	NXRect frame=*cellFrame;
	if(  [controlView isKindOf:[Text class]])
	{	[[controlView window] disableFlushWindow];
		[[controlView superview] convertRect:&frame fromView:controlView];
		[[controlView sharedField] setCell:self];
		[[controlView sharedField] removeFromSuperview];
		[[controlView superview] addSubview:[controlView sharedField]];
		[[controlView sharedField] setFrame:&frame];
		[[controlView window] reenableFlushWindow];
		[[controlView sharedField] mouseDown:theEvent];
		afterDrag=YES;
		return NO;
	} else erg=[super trackMouse:theEvent inRect:cellFrame ofView:controlView];
	return erg;
}

-(void) setWidth:(NXCoord)aWidth
{	width=aWidth;
}
- calcCellSize:(NXSize *)theSize
{	[super calcCellSize:theSize];
	if(width) theSize->width=width;
    return self;
}

- highlight:(const NXRect *)cellFrame inView:controlView lit:(BOOL)flag;
{	return [self drawInside:cellFrame inView:controlView];
}

@end


@implementation MiscTFRadioCell

- initInText:(Text*)view
{	self=[self initIconCell:"FormRadio"];		//NXradio
	[self setAltIcon:		"FormRadioH"];		//NXradioH
	[self setBordered:NO];
	[self setHighlightsBy:NX_CONTENTS];
	[self setShowsStateBy:NX_CONTENTS];
	return self;
}
-(void) setCollegues:(List*) theCollegues
{	collegues=theCollegues;
}

- (BOOL)trackMouse:(NXEvent *)theEvent 
			inRect:(const NXRect *)cellFrame 
			ofView:(Text*)controlView;
{	if([self state]) return NO;
	else	// do some radio
	{	[collegues removeObject:self];
		[collegues makeObjectsPerform:@selector(setState:) with:(id)NO];
		[controlView display];
		[collegues addObject:self];
		return [super trackMouse:theEvent inRect:cellFrame ofView:controlView];
	}
}
#if 0
- setState:(BOOL) flag
{	return [super setState:flag];
}
#endif

@end
@implementation MiscTFCheckCell

- initInText:(Text*)view
{	self=[self initIconCell:"NXswitch"];
	[self setAltIcon:"NXswitch"];
	[self setBordered:NO];
	[self setHighlightsBy:NX_CONTENTS];
	[self setShowsStateBy:NX_CONTENTS];

	return self;
}

@end
@implementation MiscTFButtonCell

- initInText:(Text*)view
{	[self initTextCell:""];
	return self;
}

@end

@implementation MiscTFPopupCell

- initInText:(Text*)view
{	self=[self initTextCell:""];
	[self setIcon:"NXpopup"];
	[self setIconPosition:NX_ICONRIGHT];
	[self setHighlightsBy:NX_PUSHIN];
	[self setShowsStateBy:NX_PUSHIN];
	[self setAlignment:NX_LEFTALIGNED];
	text=view;

	return self;
}
-(void) setPopupList:(PopUpList*) theList
{	popupList=theList;
}
- takeTitleFrom:sender
{	[self setTitle:[[sender selectedCell] title]];
	[text display];
	return self;
}
- (BOOL)trackMouse:(NXEvent *)theEvent 
			inRect:(const NXRect *)cellFrame 
			ofView:(Text*)controlView;
{	NXRect frame=*cellFrame;
	if([controlView isKindOf:[Text class]])
	{	id newButton=NXCreatePopUpListButton(popupList);
		[[controlView window] disableFlushWindow];
		[[controlView superview] convertRect:&frame fromView:controlView];
	// register so that previous gets removed and freed
		[controlView setSharedButton:newButton];
		[[controlView superview] addSubview:newButton];
		[newButton setFrame:&frame];
		[[controlView window] reenableFlushWindow];
		[newButton mouseDown:theEvent];
		return NO;
	} else return [super trackMouse:theEvent inRect:cellFrame ofView:controlView];
}
-(void) setWidth:(NXCoord)aWidth
{	width=aWidth;
}
- calcCellSize:(NXSize *)theSize
{	[super calcCellSize:theSize];
	if(width) theSize->width=width;
    return self;
}
@end

@implementation TextBackgroundCell

- initFromImage:(NXImage*) theImg
{	if(!theImg) return nil;
	self=[super init];
	image=theImg;
	return self;
}

- calcCellSize:(NXSize *)theSize
{	theSize->width=2;theSize->height=2;
    return self;
}
- drawInside: (const NXRect *)cellFrame inView:controlView
{	NXRect clipRect;
	NXSize imgSiz={0,0};
	NXCoord		x,y;
	
	if(!image) return self;

	[controlView getFrame:&clipRect];

	[image getSize:&imgSiz];
	if(!imgSiz.width || !imgSiz.height) return self;

	[controlView lockFocus];
	for(y=imgSiz.height;y< NX_HEIGHT(&clipRect);y+=imgSiz.height)
	{	for(x=0;x< NX_WIDTH(&clipRect);x+=imgSiz.width)
		{	NXPoint currPoint={x,y};
			[image composite:NX_COPY toPoint:&currPoint];
		}
	} [controlView unlockFocus];
	return self;
}
- highlight:(const NXRect *)cellFrame inView:controlView lit:(BOOL)flag;
{	return nil;
}

@end


// this one displays the table-content cells in HTML-matrices
@implementation HTMLTextCell
//static id sharedText;
- sharedText
{	if(!displayHelper)
	{	NXRect someFrame={-1025,-1025,1024,1024};
		 displayHelper=[[Text alloc] initFrame:&someFrame];
		[displayHelper setDelegate:delegate];
		[displayHelper setEditable:NO];
		[displayHelper setVertResizable: YES];
		[displayHelper setHorizResizable:YES];
		[displayHelper setMaxSize:&someFrame.size];
	} if (_view && ![displayHelper isDescendantOf:[_view superview]])
		[[_view superview] addSubview:displayHelper];
	return displayHelper;
}
- sizeToFit
{	NXRect frame;
	if(!displayHelper || ![[self sharedText] textLength])
	{	if(!strchr([self stringValue],'<')) [[self sharedText] setText:[self stringValue]];
		else								[[self sharedText] setFromHTML:[self stringValue]];
		[[self sharedText] calcLine];
		[[self sharedText] sizeToFit];[[self sharedText] getFrame:&frame];
		size=frame.size;
	} return self;
}

- initWithHTML:(const char*) theHTML inView:(Matrix*) theMatrix
{	_view=theMatrix;
	[self initTextCell:theHTML];
	columnsSpanning=1;
	return self;
}
- setStringValue:(const char*) theStr
{	id erg=[super setStringValue:theStr];
	[self sizeToFit];
	return erg;
}
- calcCellSize:(NXSize *)theSize
{	*theSize=size;
	theSize->width/=columnsSpanning;
    return self;
}
- drawInside: (const NXRect *)cellFrame inView:controlView
 {	NXRect frame=*cellFrame;
	[[controlView superview] convertRect:&frame fromView:controlView];
	_view=controlView;
	if(!displayHelper)
	{	if(!strchr([self stringValue],'<')) [[self sharedText] setText:[self stringValue]];
		else								[[self sharedText] setFromHTML:[self stringValue]];
	}
	PSgsave();
	[[self sharedText] setFrame:&frame];
	[[self sharedText] display];
	PSgrestore();
	return NO;
}

- readRichText:(NXStream *)stream forView:view
{	char *buffer;
	int	  buflen;

	NXScanf(stream, "%f %f %d",&size.width,&size.height,&buflen);
	buffer=malloc(buflen+1);
	NXScanf(stream, "%s",buffer);
	//[self initWithHTML:buffer inView:view];
	free(buffer);

	return self;
}
- writeRichText:(NXStream *)stream forView:view
{	NXPrintf(stream, "%f %f %d %s",size.width,size.height,strlen([self stringValue]),[self stringValue]);
	return self;
}
-(void) setSize:(NXSize*) aSize {size=*aSize;}
-(void) setView:(Matrix*) aText {_view=aText;}
-(void) setDisplayHelper:(Text*) aText {displayHelper=aText;}
-(int)	columnsSpanning {return columnsSpanning;}
-(void)	setColumnsSpanning:(int) span {columnsSpanning=span;}
- copyFromZone:(NXZone*) aZone
{	HTMLTextCell *newCell=[super copyFromZone:aZone];
	[newCell setSize:&size];
	[newCell setStringValue:[self stringValue]];
	[newCell setView:_view];
	[newCell setDisplayHelper:nil];
	[newCell setColumnsSpanning:columnsSpanning];
	
	return newCell;
}
@end


@implementation MiscTFMatrixCell

- initWithMatrix:(Matrix *)aMatrix inView:controlView
{	matrix=aMatrix;
	return self;
}
- drawInside: (const NXRect *)cellFrame inView:controlView
 {	int x,y,maxX,maxY,xMove=0,spanning;
 	NXRect frame;
	[matrix getNumRows:&maxY numCols:&maxX];
	PSgsave();
	for(y=0;y< maxY;y++, xMove=0)
	{	for(x=0;x< maxX;x++)
		{	Cell *currCell=[matrix cellAt:y:x];
			[matrix getCellFrame:&frame at:y:x];NX_X(&frame)+=(NX_X(cellFrame)+xMove),
			NX_Y(&frame)+=NX_Y(cellFrame);	//relocation
			if((spanning=[currCell columnsSpanning]) >1)
			{	xMove+= NX_WIDTH(&frame)*(spanning-1);
				NX_WIDTH(&frame)*=spanning;
			} if([currCell stringValue] && strlen([currCell stringValue]))
				[(HTMLTextCell*)currCell drawSelf:&frame inView:controlView];
		}
	} PSgrestore();
	return NO;
}
- calcCellSize:(NXSize *)theSize
{	NXRect frame;
	[matrix getFrame:&frame];
	*theSize=frame.size;
    return self;
}

- free
{	if(matrix)
	{	[matrix free];
	}
	return [super free];
}

@end
