/*
Pencil V1.0, Copyright 1994, 95 by Florian Marquardt.
This program may be distributed under the terms of the GNU general
public license (Start Pencil and select "Info>COPYING..." for a copy of the
license).
*/
// 29_10_94
#import "PencilText.h"
#import "PencilView.h"
#import <math.h>

extern BOOL globalOutlines;
extern id globalText; // used for drawing the text

#define M_180_PI 180.0/M_PI
extern void expandRect(NXRect *, float, float);
extern float angle(float x1,float y1,float x2,float y2);
#define TRANSFORMX(a,b) (tx+sx*cos(phi)*(a)-sy*sin(phi)*(b))
#define TRANSFORMY(a,b) (ty+sx*sin(phi)*(a)+sy*cos(phi)*(b))

extern read_brace_string(NXStream *stream, char *to);

// convert ( and ) to \( and \) (and other special characters)
// isn't very good for Ùðö etc. (--> \Ù\ð\ö, should be sort of \331 etc., don't know how
// to do it (must be somewhere in NS!))
void
convertToPSString(char *to, char *from)
{
	while(*from!=0) {
		if((*from>='*' && *from<='Z') || (*from>='^' && *from<='}'))
			*(to++)=*(from++);
		else
		{
			*(to++)='\\';
			*(to++)=*(from++);
		}
	}
	*to=0;
}

@implementation PencilText
- free
{
	if(rich) free(rich);
	return [super free];
}

- editText:(NXEvent *)te:(id)view:(id)flippedView
{
	static const NXSize maxsize={ 2000, 2000 };
	static const NXSize minsize={ 12, 12 };
	NXPoint pt;
	id text;

	pt=te->location;
	[flippedView convertPoint:&pt fromView:nil];
	if(text=[[view window] getFieldEditor:YES for:self])
	{
		[[view window] endEditingFor:[view window]];
		if(rich)
		{
		NXStream *stream;
		NXRect myframe;

		myframe=bounds;
		[view convertRect:&myframe toView:flippedView];
		[text moveTo:myframe.origin.x:myframe.origin.y];
		[text sizeTo:myframe.size.width:myframe.size.height];
		stream=NXOpenMemory(rich,length,NX_READONLY);
		[text readRichText:stream];
		NXClose(stream);
		}
		else
		{
		[text moveTo:pt.x:pt.y];
		[text sizeTo:12:12];
		[text setText:""];
		}
   		[text setCharFilter:NXEditorFilter];
		[text setEditable:YES];
		[text setDelegate:self];
		[text setHorizResizable:YES];
		[text setVertResizable:YES];
		[text setOpaque:YES];
		[text setMaxSize:&maxsize];
		[text setMinSize:&minsize];
		[text setMonoFont:NO];
		[text setFontPanelEnabled:YES];
		[text setAlignment:NX_LEFTALIGNED];
		[flippedView addSubview:text];
		[text display];
		[[view window] makeFirstResponder:text];
		[text selectText:self];
	}
	return self;
}

- textDidEnd:sender endChar:(unsigned short)why
{
NXStream *stream;
int maxlen;
id theview;
char *buf;

// GETTING THE rich-TEXT AND THE FRAME
if(rich) free(rich);
stream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
[sender writeRichText:stream];
NXGetMemoryBuffer(stream,&buf,&length,&maxlen);
if(rich=(char *)malloc(sizeof(char)*(length+1)))
	strcpy(rich,buf);
NXCloseMemory(stream, NX_FREEBUFFER);
[sender getFrame:&bounds];
[ [sender superview] convertRect:&bounds toView:theview=[[sender superview] superview]];
// CLEANING UP
[sender setCharFilter:NXFieldFilter];
[sender removeFromSuperview];
[theview richTextEnded:self];
[theview display:&bounds:1];
[theview displayCurrentGraphic];
return self;
}

- (BOOL)selected:(NXEvent *)te:(int *)cp:(id)view
{
	NXPoint pt;

	pt=te->location;
	[self transformPoint:&pt];
	if(pt.x>=bounds.origin.x && pt.y>=bounds.origin.y && pt.x<=bounds.size.width+bounds.origin.x && pt.y<=bounds.size.height+bounds.origin.y)
		return(YES);
	else
		return(NO);
}

- (BOOL)move:(NXEvent *)tte:(int *)cp:(id)view:(float)bsize
{
	return NO;
}

- calculateBoundingBox:(id)view
{
	return self;
}

- (void)draw:(NXRect *)re
{
	if(!re || NXIntersectsRect(&bounds, re))
	{
//	if(globalOutlines)
//	{
//	PSgsave();
//	if(translated)	PStranslate(tx,ty);
//	if(rotated)		PSrotate(M_180_PI*phi);
//	if(scaled)		PSscale(s,s);
//	PSsetlinewidth(0);
//	PSsetgray(.5);
//	PSrectstroke(bounds.origin.x,bounds.origin.y,bounds.size.width,bounds.size.height);
//	PSgrestore();
//	}
//	else
//	{
//	PSgsave();
//	if(translated)	PStranslate(tx,ty);
//	if(rotated)		PSrotate(M_180_PI*phi);
//	if(scaled)		PSscale(s,s);

if(rich)
{
NXStream *stream;

stream=NXOpenMemory(rich,length,NX_READONLY);
[globalText readRichText:stream];
NXClose(stream);
[[NXApp focusView] addSubview:globalText];
[globalText setFrame:&bounds];
[globalText display];
[globalText removeFromSuperview];
}
//	PSgrestore();
//	}
	}
}

- (void)rotateAroundCenter:(float)x:(float)y fromPoint:(NXPoint *)pt1 toPoint:(NXPoint *)pt2
{
	float dphi, dx, dy;

	dphi=angle(pt1->x-x,pt1->y-y,pt2->x-x,pt2->y-y);
	dx=bounds.origin.x-x;
	dy=bounds.origin.y-y;
	bounds.origin.x=x+cos(dphi)*dx-sin(dphi)*dy;
	bounds.origin.y=y+sin(dphi)*dx+cos(dphi)*dy;
}

- (void)scaleCenter:(float)cx:(float)cy by:(float)scx:(float)scy
{
	bounds.origin.x=cx+(bounds.origin.x-cx)*scx;
	bounds.origin.y=cy+(bounds.origin.y-cy)*scy;
	sx*=scx;
	sy*=scy;
}

- (void)drawPath
{
	DPSPrintf(DPSGetCurrentContext()," matrix currentmatrix ");
	if(translated)	PStranslate(tx,ty);
	if(rotated)		PSrotate(M_180_PI*phi);
	if(scaled)		PSscale(sx,sy);
	PSmoveto(bounds.origin.x,bounds.origin.y);
	PSrlineto(bounds.size.width,0);
	PSrlineto(0,bounds.size.height);
	PSrlineto(bounds.size.width,0);
	PSclosepath();
	DPSPrintf(DPSGetCurrentContext()," setmatrix\n");
}

- (void)drawControl:(NXRect *)re:(int)cp:(float)bsize
{
	[self draw:re];
	if(transformed)	{	PSgsave();
	if(translated)	PStranslate(tx,ty);
	if(rotated)		PSrotate(M_180_PI*phi);
	if(scaled)		PSscale(sx,sy);
	}
	PSsetlinewidth(0);
	PSsetgray(.5);
	PSrectstroke(bounds.origin.x,bounds.origin.y,bounds.size.width,bounds.size.height);
	if(transformed)	PSgrestore();
}

- addTranslation:(float)dtx:(float)dty
{
	bounds.origin.x+=dtx;
	bounds.origin.y+=dty;
	return self;
}

- makeCharacterPath:view:cp
{
	char *special;
	char *buf;
	
if(rich)
{
NXStream *stream;

stream=NXOpenMemory(rich,length,NX_READONLY);
[globalText readRichText:stream];
NXClose(stream);
}
	buf=(char *)malloc(sizeof(char)*(2+[globalText textLength]));
	special=(char *)malloc(sizeof(char)*(200+[globalText textLength]));
	// special=(char *)malloc(sizeof(char)*(200));
	[globalText getSubstring: buf start: 0 length: [globalText textLength]+1];
	sprintf(special,"/text (");
	convertToPSString(special+strlen(special), buf);
	sprintf(special+strlen(special), ") def\n/font (%s) def /fontsize %g def", [[globalText font] name], [[globalText font] pointSize]);
	
	[cp setMethodname:"charP"];
	[cp setDrawingMethod:"drawF"];
	[cp setFillMethod:"fill"];
	[cp setStrokeMethod:"stroke"];
	[cp setSpecialAttributes:special];
	[cp setColor1:NXConvertRGBToColor(0,0,0)];
	[cp setColor2:NXConvertRGBToColor(0,0,0)];
	[cp setLineWidth: .5];
	[cp initWithControlPt: bounds.origin.x: bounds.origin.y];
	free(special);
	free(buf);
	return self;
}

- write:(NXTypedStream *)stream
{
	[super write:stream];
	NXWriteTypes(stream,"*i",&rich,&length);
	return self;	
}

- read:(NXTypedStream *)stream
{
	[super read:stream];
	NXReadTypes(stream,"*i",&rich,&length);
	return self;
}

- (void)writeType:(NXStream *)to
{
	NXPrintf(to,"1");
}

#define WRITE_STRING(a) if((a) && strcmp(a,"")) NXPrintf(to, "{%s} ", a); else NXPrintf(to, "{} ")

- (void)writeDescription:(NXStream *)to
{
	[super writeDescription:to];
	NXPrintf(to," %d ", length);
	WRITE_STRING(rich);
}

#define NEWSTRING(a) read_brace_string(from, tmp); if(a) free(a); a=(char *)malloc(sizeof(char)*(strlen(tmp)+1)); strcpy(a,tmp)

- (void)initFromDescription:(NXStream *)from
{
	char tmp[3000];
	
	[super initFromDescription:from];
	NXScanf(from," %d", &length);
	NEWSTRING(rich);	
}
@end
