/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : Icon library                                                */
/*    Fichier : icnDrive.c (icn's VTI (Compass) driver)                     */
/*                                                                          */
/*    (c) copyright 1991 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) : Vincent POUILLEY                      le : 13/09/1992     */
/*                                                                          */
/*    Modifie par : Vincent POUILLEY                    le : 08/12/1992     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/*    $Id: icnDrive.c,v 2.1.1.1 1993/09/23 16:04:30 sax Exp sax $               */
/*                                                                          */
/****************************************************************************/

#include <stdio.h>
#include "IconConst.h"
#include "ConvMacro.h"
#include MUT_H
#include ICN_H
#include IAC_H
#include ICU_H
#include <math.h>
#include <time.h>
#include <sys/types.h>
#include <sys/time.h>

#ident "@(#)Driver Compass icon v2.00 06/08/93 by Vincent POUILLEY"

#ifdef __STDC__
char HAlignToIcn(int align)
#else
char HAlignToIcn(align)
int align;
#endif
{
	switch (align)
	{
		case SAX_RIGHT :
			return 'R';
		case SAX_CENTER :
			return 'C';
		default :
			return 'L';
	}
}

#ifdef __STDC__
char VAlignToIcn(int align)
#else
char VAlignToIcn(align)
int align;
#endif
{
	switch (align)
	{
		case SAX_UP :
			return 'T';
		case SAX_CENTER :
			return 'C';
		default :
			return 'B';
	}
}

#ifdef __STDC__
char DirectionToIcn (int direction)
#else
char DirectionToIcn (direction)
int direction;
#endif
{
	return (direction == SAX_HORIZONTAL) ? 'H' : 'V';
}

#ifdef __STDC__
void icngetdate(char * date)
#else
void icngetdate(date)
char *date;
#endif
{
	time_t timer;
	char day[4], month[4];
	int year, nday, hour, minute, second;

	(void)time(&timer);
	(void)strcpy(date, ctime(&timer));
	(void)sscanf(date, "%s %s %d %d:%d:%d 19%d",
				 day, month, &nday, &hour, &minute, &second, &year);
	(void)sprintf(date, "%02d-%s-%02d %02d:%02d",
				  nday, month, year, hour, minute);
}

#ifdef __STDC__
int saveicnicon(IconGate_list * icon_gate)
#else
int saveicnicon(icon_gate)
IconGate_list * icon_gate;
#endif
{
	FILE * out;
	char filename[ICON_BUFSIZE], buf[ICON_BUFSIZE];
/* 	long height; */
	double scale;
	
	sprintf(filename, "%s/%s.%s", WORK_LIB, ICONGATE_MODELNAME(icon_gate), ICON_OUT);
	if ((out = (FILE *)fopen(filename, "r")) != NULL)
	{
		fclose (out);
		sprintf(buf,  "%s/%s.old.%s", WORK_LIB, ICONGATE_MODELNAME(icon_gate), ICON_OUT);
		if (link(filename, buf) != 0)
		{
			unlink(buf);
			link(filename, buf);
		}
		unlink(filename);
	}
	if ((out = (FILE *)fopen(filename, "w")) == NULL)
	{
		fprintf (stderr, "\n*** Icon Error *** saveicon (icn) impossible : Unable to write file %s\n", filename);
		return PROBLEM;
	}

	/*init temp variables */
/* 	height = ICONGATE_HEIGHT(icon_gate); */
	scale = ICONGATE_SCALE(icon_gate);

	/* write header */
	fprintf (out, "#cell1 %s any icon 5120 v7r5.6i\n", ICONGATE_MODELNAME(icon_gate));
	icngetdate(buf);
	fprintf (out, "# %s %s Sax_Icon * .\n", buf, buf);
	fprintf (out, "V 1\n");
	
	/* write instance information */
	fprintf (out, "I 0 0 F F F F 0\n");
	fprintf (out, "  %d %d \"Cell Name\" 1 %c%c %c\n",
			 UNSCALE_TO_INT(scale, ICONGATE_X_MODELNAME(icon_gate)) / SCALE_X,
/* 			 UNSCALE_TO_INT(scale, height - ICONGATE_Y_MODELNAME(icon_gate)) / SCALE_X, */
			 UNSCALE_TO_INT(scale, - ICONGATE_Y_MODELNAME(icon_gate)) / SCALE_X,
			 HAlignToIcn(ICONGATE_HALIGN_MODELNAME(icon_gate)),
			 VAlignToIcn(ICONGATE_VALIGN_MODELNAME(icon_gate)),
			 DirectionToIcn(ICONGATE_DIRECTION_MODELNAME(icon_gate)));
	fprintf (out, "  %d %d \"Label\" 1 %c%c %c\n",
			 UNSCALE_TO_INT(scale, ICONGATE_X_LABEL(icon_gate)) / SCALE_X,
/* 			 UNSCALE_TO_INT(scale, height - ICONGATE_Y_LABEL(icon_gate)) / SCALE_X, */
			 UNSCALE_TO_INT(scale, - ICONGATE_Y_LABEL(icon_gate)) / SCALE_X,
			 HAlignToIcn(ICONGATE_HALIGN_LABEL(icon_gate)),
			 VAlignToIcn(ICONGATE_VALIGN_LABEL(icon_gate)),
			 DirectionToIcn(ICONGATE_DIRECTION_LABEL(icon_gate)));
	fprintf (out, "  %d %d \"InstanceName\" 1 %c%c %c\n",
			 UNSCALE_TO_INT(scale, ICONGATE_X_INSNAME(icon_gate)) / SCALE_X,
/* 			 UNSCALE_TO_INT(scale, height - ICONGATE_Y_INSNAME(icon_gate)) / SCALE_X, */
			 UNSCALE_TO_INT(scale, - ICONGATE_Y_INSNAME(icon_gate)) / SCALE_X,
			 HAlignToIcn(ICONGATE_HALIGN_INSNAME(icon_gate)),
			 VAlignToIcn(ICONGATE_VALIGN_INSNAME(icon_gate)),
			 DirectionToIcn(ICONGATE_DIRECTION_INSNAME(icon_gate)));

	/* reverse all list */
	ICONGATE_LINES(icon_gate) = (IconLine_list *)reverse((chain_list *)ICONGATE_LINES(icon_gate));
	ICONGATE_SHAPES(icon_gate) = (IconShape_list *)reverse((chain_list *)ICONGATE_SHAPES(icon_gate));
	ICONGATE_CIRCLES(icon_gate) = (IconCircle_list *)reverse((chain_list *)ICONGATE_CIRCLES(icon_gate));
	ICONGATE_ARCS(icon_gate) = (IconArc_list *)reverse((chain_list *)ICONGATE_ARCS(icon_gate));
	ICONGATE_CONNECTORS(icon_gate) = (IconCon_list *)reverse((chain_list *)ICONGATE_CONNECTORS(icon_gate));
	/* write lines */
	{
		IconLine_list * iconline;
		
		for (iconline = ICONGATE_LINES(icon_gate); iconline; iconline = ICONLINE_NEXT(iconline))
		{
			fprintf (out, "L %d %d %d %d 0 0\n",
					 UNSCALE_TO_INT(scale, ICONLINE_X0(iconline)) / SCALE_X,
/* 					 UNSCALE_TO_INT(scale, height - ICONLINE_Y0(iconline)) / SCALE_X, */
					 UNSCALE_TO_INT(scale, - ICONLINE_Y0(iconline)) / SCALE_X,
					 UNSCALE_TO_INT(scale, ICONLINE_X1(iconline)) / SCALE_X,
/* 					 UNSCALE_TO_INT(scale, height - ICONLINE_Y1(iconline)) / SCALE_X); */
					 UNSCALE_TO_INT(scale, - ICONLINE_Y1(iconline)) / SCALE_X);
		}
	}
	
	/* write shapes */
	{
		IconShape_list * iconshape;
		IconComp_list * comp1, * comp2, * comp3, *comp4;
		
		for (iconshape = ICONGATE_SHAPES(icon_gate); iconshape; iconshape = ICONSHAPE_NEXT(iconshape))
		{
			/* perhaps it is a box */
			if ((ICONSHAPE_NBCOMP(iconshape) == 4) &&
				(ICONSHAPE_COMP_ISLINE(ICONSHAPE_FIRSTCOMP(iconshape))) &&
				(ICONSHAPE_COMP_ISLINE(ICONSHAPE_NEXTCOMP(ICONSHAPE_FIRSTCOMP(iconshape)))) &&
				(ICONSHAPE_COMP_ISLINE(ICONSHAPE_NEXTCOMP(ICONSHAPE_NEXTCOMP(ICONSHAPE_FIRSTCOMP(iconshape))))) &&
				(ICONSHAPE_COMP_ISLINE(ICONSHAPE_NEXTCOMP(ICONSHAPE_NEXTCOMP(ICONSHAPE_NEXTCOMP(ICONSHAPE_FIRSTCOMP(iconshape)))))))
			{
				comp1 = ICONSHAPE_FIRSTCOMP(iconshape);
				comp2 = ICONSHAPE_NEXTCOMP(ICONSHAPE_FIRSTCOMP(iconshape));
				comp3 = ICONSHAPE_NEXTCOMP(ICONSHAPE_NEXTCOMP(ICONSHAPE_FIRSTCOMP(iconshape)));
				comp4 = ICONSHAPE_NEXTCOMP(ICONSHAPE_NEXTCOMP(ICONSHAPE_NEXTCOMP(ICONSHAPE_FIRSTCOMP(iconshape))));
				if (((ICONSHAPE_Y_COMP(comp1) == ICONSHAPE_Y_COMP(comp2)) &&
					 (ICONSHAPE_X_COMP(comp2) == ICONSHAPE_X_COMP(comp3)) &&
					 (ICONSHAPE_Y_COMP(comp3) == ICONSHAPE_Y_COMP(comp4)) &&
					 (ICONSHAPE_X_COMP(comp4) == ICONSHAPE_X_COMP(comp1))) ||
					((ICONSHAPE_X_COMP(comp1) == ICONSHAPE_X_COMP(comp2)) &&
					 (ICONSHAPE_Y_COMP(comp2) == ICONSHAPE_Y_COMP(comp3)) &&
					 (ICONSHAPE_X_COMP(comp3) == ICONSHAPE_X_COMP(comp4)) &&
					 (ICONSHAPE_Y_COMP(comp4) == ICONSHAPE_Y_COMP(comp1))))
				{ /* it is a real box */
					fprintf (out, "B %d %d %d %d 0 0\n",
							 UNSCALE_TO_INT(scale, min (ICONSHAPE_X_COMP(comp1), ICONSHAPE_X_COMP(comp3))) / SCALE_X,
/* 							 UNSCALE_TO_INT(scale, height - (max(ICONSHAPE_Y_COMP(comp1), ICONSHAPE_Y_COMP(comp3)))) / SCALE_X, */
							 UNSCALE_TO_INT(scale, - (max(ICONSHAPE_Y_COMP(comp1), ICONSHAPE_Y_COMP(comp3)))) / SCALE_X,
							 UNSCALE_TO_INT(scale, max (ICONSHAPE_X_COMP(comp1), ICONSHAPE_X_COMP(comp3))) / SCALE_X,
/* 							 UNSCALE_TO_INT(scale, height - (min(ICONSHAPE_Y_COMP(comp1), ICONSHAPE_Y_COMP(comp3)))) /  SCALE_X); */
							 UNSCALE_TO_INT(scale, - (min(ICONSHAPE_Y_COMP(comp1), ICONSHAPE_Y_COMP(comp3)))) /  SCALE_X);
				}
				else /* it is not a legal box */
				{
					fprintf (out, "L %d %d %d %d 0\n",
							 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp1)) / SCALE_X,
/* 							 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp1)) / SCALE_X, */
							 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp1)) / SCALE_X,
							 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp2)) / SCALE_X,
/* 							 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp2)) / SCALE_X); */
							 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp2)) / SCALE_X);
					fprintf (out, "L %d %d %d %d 0\n",
							 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp2)) / SCALE_X,
/* 							 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp2)) / SCALE_X, */
							 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp2)) / SCALE_X,
							 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp3)) / SCALE_X,
/* 							 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp3)) / SCALE_X); */
							 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp3)) / SCALE_X);
					fprintf (out, "L %d %d %d %d 0\n",
							 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp3)) / SCALE_X,
/* 							 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp3)) / SCALE_X, */
							 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp3)) / SCALE_X,
							 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp4)) / SCALE_X,
/* 							 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp4)) / SCALE_X); */
							 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp4)) / SCALE_X);
					fprintf (out, "L %d %d %d %d 0\n",
							 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp4)) / SCALE_X,
/* 							 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp4)) / SCALE_X, */
							 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp4)) / SCALE_X,
							 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp1)) / SCALE_X,
/* 							 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp1)) / SCALE_X); */
							 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp1)) / SCALE_X);
				}
			}
			else /* general situation */
			{
				comp1 = ICONSHAPE_FIRSTCOMP(iconshape);
				comp2 = ICONSHAPE_NEXTCOMP(comp1);
				if (comp2 == NULL)
				{
					fprintf (stderr, "\n*** Icon Error *** saveicon (icn) impossible : Invalid arc component of shape\n");
					break;
				}
				while (comp1)
				{
					if (ICONSHAPE_COMP_ISLINE(comp1) || ICONSHAPE_COMP_ISARCEND(comp1))
					{
						fprintf (out, "L %d %d %d %d 0\n",
								 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp1)) / SCALE_X,
/* 								 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp1)) / SCALE_X, */
								 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp1)) / SCALE_X,
								 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp2)) / SCALE_X,
/* 								 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp2)) / SCALE_X); */
								 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp2)) / SCALE_X);
						comp1 = ICONSHAPE_NEXTCOMP(comp1);
						comp2 = ICONSHAPE_NEXTCOMP(comp2);
						if (comp2 == NULL)
							comp2 = ICONSHAPE_FIRSTCOMP(iconshape);
					}
					else
						if (ICONSHAPE_COMP_ISARCSTART(comp1)) /* arc */
						{
							int endboucle;
							double dx, dy, mx, my, fx, fy, a1, a2, b1, b2, cx, cy, r;

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif
							
							comp3 = comp2;
							endboucle = 0;
							while (ICONSHAPE_COMP_ISARCCOMP(comp3))
							{
								comp3 = ICONSHAPE_NEXTCOMP(comp3);
								if (comp3 == NULL)
								{
									if (endboucle)
									{
										fprintf (stderr,  "\n*** Icon Error *** saveicon (icn) impossible : Invalid arc component of shape\n");
										break;
									}
									else
									{
										endboucle = 1;
										comp3 = ICONSHAPE_FIRSTCOMP(iconshape);
									}
									
								}
							}
							if ((comp3 == comp2) || (!ICONSHAPE_COMP_ISARCEND(comp3)))
							{
								fprintf (stderr, "\n*** Icon Error *** saveicon (icn) impossible : Invalid arc component of shape\n");
								break;
							}
							dx = (double)ICONSHAPE_X_COMP(comp1);
							dy = (double)ICONSHAPE_Y_COMP(comp1);
							mx = (double)ICONSHAPE_X_COMP(comp2);
							my = (double)ICONSHAPE_Y_COMP(comp2);
							fx = (double)ICONSHAPE_X_COMP(comp3);
							fy = (double)ICONSHAPE_Y_COMP(comp3);
							
							if (dy != my)  
								a1 = - ((dx - mx)/(dy - my));
							else
								a1 = 1.;
							b1 = (dy + ((my-dy)/2.)) - (a1 * (dx + ((mx-dx)/2.)));
							
							if (my != fy)
								a2 = - ((mx - fx) / (my - fy));
							else
								a2 = 1.;
							b2 = (my + ((fy-my)/2.)) - (a2 * (mx + ((fx-mx)/2.)));
							
							if (a1==a2) 
							{        /* the three point are a straight line */
								fprintf (out, "L %d %d %d %d 0\n",
										 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp1)) / SCALE_X,
/* 										 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp1)) / SCALE_X, */
										 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp1)) / SCALE_X,
										 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp3)) / SCALE_X,
/* 										 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp3)) / SCALE_X); */
										 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp3)) / SCALE_X);
							}
							else
							{
								
								cx = (b2 - b1)/(a1 - a2);     
								cy = (a1 * cx) + b1; 
								
								if (dy==my)
								{ 
									cx = dx + ((mx-dx)/2.);
									cy = (a2 * cx) + b2;
								}
								
								if (dx==mx)
								{ 
									cy = dy + ((my-dy)/2.);
									cx = (cy - b2) / a2;
								}
								
								if (fy==my)
								{
									cx = mx + ((fx-mx)/2.); 
									cy = (a1 * cx) + b1;
								}
								
								if (fx==mx)
								{ 
									cy = my + ((fy-my)/2.); 
									cx = (cy - b1) / a1;
								}
								
								if ((dy==my) && (mx==fx))
								{ 
									cx = dx + ((mx-dx)/2.);
									cy = my + ((fy-my)/2.);
								}
								
								if ((dx==mx) && (my==fy)) 
								{
									cx = dy + ((my-dy)/2.);
									cy = mx + ((fx-mx)/2.);
								}
								
								/* Determining rayon of circle correspondant to the arc */
								r = sqrt((double)((double)(dx - cx) * (double)(dx - cx)) + 
										 (double)((double)(dy - cy) * (double)(dy - cy))); 
								a1 = atan2((dy - cy),(dx - cx));
								a1 = atan2((my - cy),(mx - cx)) - a1;
								a2 = atan2((fy - cy),(fx - cx)) - a1;
								if ((a2 - M_PI < 0.00001) || (a2 + M_PI < 0.00001))
									if (a1 > 0.)
										fprintf (out, "A %d %d %d %d %d 0 %d\n",
												 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp3)) / SCALE_X,
/* 												 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp3)) / SCALE_X, */
												 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp3)) / SCALE_X,
												 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp1)) / SCALE_X,
/* 												 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp1)) / SCALE_X, */
												 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp1)) / SCALE_X,
												 UNSCALE_TO_INT(scale, r) / SCALE_X, 0);
									else
										fprintf (out, "A %d %d %d %d %d 0 %d\n",
												 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp1)) / SCALE_X,
/* 												 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp1)) / SCALE_X, */
												 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp1)) / SCALE_X,
												 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp3)) / SCALE_X,
/* 												 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp3)) / SCALE_X, */
												 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp3)) / SCALE_X,
												 UNSCALE_TO_INT(scale, r) / SCALE_X, 0);
								if ((a1 < 0.) && (a2 < a1))
									fprintf (out, "A %d %d %d %d %d 0 %d\n",
											 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp1)) / SCALE_X,
/* 											 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp1)) / SCALE_X, */
											 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp1)) / SCALE_X,
											 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp3)) / SCALE_X,
/* 											 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp3)) / SCALE_X, */
											 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp3)) / SCALE_X,
											 UNSCALE_TO_INT(scale, r) / SCALE_X, 0);
								else if (((a2 > 0.) && (a1 < 0.)) || ((a2 > 0.) && (a1 > a2)))
									fprintf (out, "A %d %d %d %d %d 0 %d\n",
											 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp1)) / SCALE_X,
/* 											 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp1)) / SCALE_X, */
											 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp1)) / SCALE_X,
											 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp3)) / SCALE_X,
/* 											 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp3)) / SCALE_X, */
											 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp3)) / SCALE_X,
											 UNSCALE_TO_INT(scale, r) / SCALE_X, 1);
								else if ((a1 > 0.) && (a2 > a1))
									fprintf (out, "A %d %d %d %d %d 0 %d\n",
											 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp3)) / SCALE_X,
/* 											 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp3)) / SCALE_X, */
											 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp3)) / SCALE_X,
											 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp1)) / SCALE_X,
/* 											 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp1)) / SCALE_X, */
											 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp1)) / SCALE_X,
											 UNSCALE_TO_INT(scale, r) / SCALE_X, 0);
								else
									fprintf (out, "A %d %d %d %d %d 0 %d\n",
											 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp3)) / SCALE_X,
/* 											 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp3)) / SCALE_X, */
											 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp3)) / SCALE_X,
											 UNSCALE_TO_INT(scale, ICONSHAPE_X_COMP(comp1)) / SCALE_X,
/* 											 UNSCALE_TO_INT(scale, height - ICONSHAPE_Y_COMP(comp1)) / SCALE_X, */
											 UNSCALE_TO_INT(scale, - ICONSHAPE_Y_COMP(comp1)) / SCALE_X,
											 UNSCALE_TO_INT(scale, r) / SCALE_X, 1);
							}
							
							if (endboucle)
								break;
							comp1 = comp3;
							comp2 = ICONSHAPE_NEXTCOMP(comp1);
							if (comp2 == NULL)
								comp2 = ICONSHAPE_FIRSTCOMP(iconshape);
						} /* else if arc start */
						else /* comp is Arc Comp */
						{
							comp1 = ICONSHAPE_NEXTCOMP(comp1);
							comp2 = ICONSHAPE_NEXTCOMP(comp2);
							if (comp2 == NULL)
								comp2 = ICONSHAPE_FIRSTCOMP(iconshape);
						}
				} /* while */
			} /* general situation */
		} /* for iconshape */
	}

	/* write circles */
	{
		IconCircle_list * iconcircle;
		long rayon;
		
		for (iconcircle = ICONGATE_CIRCLES(icon_gate); iconcircle; iconcircle = ICONCIRCLE_NEXT(iconcircle))
		{
			rayon = (max(ICONCIRCLE_WIDTH(iconcircle), ICONCIRCLE_HEIGHT(iconcircle))) / 2;
			fprintf (out, "R %d %d %d 0 0\n",
					 UNSCALE_TO_INT(scale, ICONCIRCLE_X0(iconcircle) + rayon) / SCALE_X,
/* 					 UNSCALE_TO_INT(scale, height - (ICONCIRCLE_Y0(iconcircle) + rayon)) / SCALE_X, */
					 UNSCALE_TO_INT(scale, - (ICONCIRCLE_Y0(iconcircle) + rayon)) / SCALE_X,
					 UNSCALE_TO_INT(scale, rayon) / SCALE_X);
		}
	}
	
	/* write arcs */
	{
		IconArc_list * iconarc;
		double angle1, angle2;
		long xc, yc, r, x1, y1, x2, y2;
		
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

		for (iconarc = ICONGATE_ARCS(icon_gate); iconarc; iconarc = ICONARC_NEXT(iconarc))
		{
			r = UNSCALE_TO_INT(scale, (max(ICONARC_WIDTH(iconarc), ICONARC_HEIGHT(iconarc)))) / (2 * SCALE_X);
			xc = (UNSCALE_TO_INT(scale, ICONARC_X0(iconarc)) / SCALE_X) + r;
			yc = (UNSCALE_TO_INT(scale, ICONARC_Y0(iconarc)) / SCALE_X) + r;
			angle1 = ((double)(ICONARC_ANGLE1(iconarc)) * M_PI) / (180. * (double)(SCALE_X));
			angle2 = ((double)(ICONARC_ANGLE1(iconarc) + ICONARC_ANGLE2(iconarc)) * M_PI) / (180. * (double)(SCALE_X));
			x1 = xc + ROUND((double)(r) * cos (angle1));
/* 			y1 = (height / SCALE_X) - (yc - ROUND((double)(r) * sin (angle1))); */
 			y1 = - (yc - ROUND((double)(r) * sin (angle1)));
			x2 = xc + ROUND((double)(r) * cos (angle2));
/* 			y2 = (height / SCALE_X) - (yc - ROUND((double)(r) * sin (angle2))); */
			y2 = - (yc - ROUND((double)(r) * sin (angle2)));
			if (ICONARC_ANGLE2(iconarc) > 0)
			{
				fprintf (out, "A %d %d %d %d %d 0 %d\n", x1, y1, x2, y2, r, (ICONARC_ANGLE2(iconarc) > (180 * SCALE_X)) ? 1 : 0);
			}
			else
			{
				fprintf (out, "A %d %d %d %d %d 0 %d\n", x2, y2, x1, y1, r, (ICONARC_ANGLE2(iconarc) < (-180 * SCALE_X)) ? 1 : 0);
			}
		}
	}
	/* write connectors */
	{
		IconCon_list * iconcon;
		int id;
		
		for (iconcon = ICONGATE_CONNECTORS(icon_gate), id = 1;
			 iconcon;
			 iconcon = ICONCON_NEXT(iconcon), id++)
		{
			fprintf (out, "C %d %d %d %d %d \"%s\" 1 %c%c %c 0 0\n",
					 id, UNSCALE_TO_INT(scale, ICONCON_X(iconcon)) / SCALE_X,
/* 					 UNSCALE_TO_INT(scale, height - ICONCON_Y(iconcon)) / SCALE_X, */
					 UNSCALE_TO_INT(scale, - ICONCON_Y(iconcon)) / SCALE_X,
					 UNSCALE_TO_INT(scale, ICONCON_X_NAME(iconcon)) / SCALE_X,
/* 					 UNSCALE_TO_INT(scale, height - ICONCON_Y_NAME(iconcon)) / SCALE_X, */
					 UNSCALE_TO_INT(scale, - ICONCON_Y_NAME(iconcon)) / SCALE_X,
					 ICONCON_NAME(iconcon),
					 HAlignToIcn(ICONCON_HALIGN_NAME(iconcon)),
					 VAlignToIcn(ICONCON_VALIGN_NAME(iconcon)),
					 DirectionToIcn(ICONCON_DIRECTION_NAME(iconcon)));
		}
	}
	/* reverse all list */
	ICONGATE_LINES(icon_gate) = (IconLine_list *)reverse((chain_list *)ICONGATE_LINES(icon_gate));
	ICONGATE_SHAPES(icon_gate) = (IconShape_list *)reverse((chain_list *)ICONGATE_SHAPES(icon_gate));
	ICONGATE_CIRCLES(icon_gate) = (IconCircle_list *)reverse((chain_list *)ICONGATE_CIRCLES(icon_gate));
	ICONGATE_ARCS(icon_gate) = (IconArc_list *)reverse((chain_list *)ICONGATE_ARCS(icon_gate));
	ICONGATE_CONNECTORS(icon_gate) = (IconCon_list *)reverse((chain_list *)ICONGATE_CONNECTORS(icon_gate));

	/* write end of file, and close it */
	fprintf (out, "E\n");
	fclose (out);
	return OK;
} /* saveicnicon */
