/*********************************************************************\

	File   		:	rsa_icon.c

	Date		:	24 08 1993
	Version		:	1

	Description :   Creation of the rsa icon.

\*********************************************************************/

/*---------------------------------------------------------\
                     includes
\---------------------------------------------------------*/

#include ICN_H
#include IAC_H
#include ICU_H

/*---------------------------------------------------------\
                     defines
\---------------------------------------------------------*/
/*
          ^
          |
          | Delta_Y
          |
          |
 Delta_X  v 1
<--------->|\
           | \
           |  \
           |   \ 
          7|    \2
           \6    |
          5/     |
           |    /3
           |   /
           |  /
           | /
          4|/


          ^
          |
          | Delta_Y
          |
          |
 Delta_X  v 1
<--------->|\
           | \
           |  \
           |   \ 
         13|    \2
           \12   |
         11/     |
           |     |
           |     |
         10|     |
           \9    |
          8/     |
           |    /3
           |   /
           |  /
           | /
          4|/

*/

#define GRID             10

#define DELTA_X          3
#define DELTA_Y          3

#define REAL_DELTA_X     ( DELTA_X * SCALE_X * GRID)
#define REAL_DELTA_Y     ( DELTA_Y * SCALE_X * GRID)

#define POINT__1_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT__1_Y       ( (  0 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__2_X       ( ( 12 + DELTA_X ) * SCALE_X * GRID )
#define POINT__2_Y       ( ( 12 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__3_X       ( ( 12 + DELTA_X ) * SCALE_X * GRID )
#define POINT__3_Y       ( ( 28 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__4_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT__4_Y       ( ( 40 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__5_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT__5_Y       ( ( 24 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__6_X       ( (  4 + DELTA_X ) * SCALE_X * GRID )
#define POINT__1_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT__1_Y       ( (  0 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__2_X       ( ( 12 + DELTA_X ) * SCALE_X * GRID )
#define POINT__2_Y       ( ( 12 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__3_X       ( ( 12 + DELTA_X ) * SCALE_X * GRID )
#define POINT__3_Y       ( ( 28 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__4_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT__4_Y       ( ( 40 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__5_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT__5_Y       ( ( 24 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__6_X       ( (  4 + DELTA_X ) * SCALE_X * GRID )
#define POINT__6_Y       ( ( 20 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__7_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT__7_Y       ( ( 16 + DELTA_Y ) * SCALE_X * GRID )

#define POINT__8_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT__8_Y       ( ( 32 + DELTA_Y ) * SCALE_X * GRID )
#define POINT__9_X       ( (  4 + DELTA_X ) * SCALE_X * GRID )
#define POINT__9_Y       ( ( 28 + DELTA_Y ) * SCALE_X * GRID )
#define POINT_10_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT_10_Y       ( ( 24 + DELTA_Y ) * SCALE_X * GRID )
#define POINT_11_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT_11_Y       ( ( 16 + DELTA_Y ) * SCALE_X * GRID )
#define POINT_12_X       ( (  4 + DELTA_X ) * SCALE_X * GRID )
#define POINT_12_Y       ( ( 12 + DELTA_Y ) * SCALE_X * GRID )
#define POINT_13_X       ( (  0 + DELTA_X ) * SCALE_X * GRID )
#define POINT_13_Y       ( (  8 + DELTA_Y ) * SCALE_X * GRID )

#define IN_A_1           ( (  8 + DELTA_Y ) * SCALE_X * GRID )
#define IN_B_1           ( ( 32 + DELTA_Y ) * SCALE_X * GRID )
#define IN_A_2           ( (  4 + DELTA_Y ) * SCALE_X * GRID )
#define IN_B_2           ( ( 20 + DELTA_Y ) * SCALE_X * GRID )
#define IN_C             ( ( 36 + DELTA_Y ) * SCALE_X * GRID )

#define RIGHT_BORDER     ( ( 12 + DELTA_X ) * SCALE_X * GRID )

#define OUT_1            ( ( 20 + DELTA_Y ) * SCALE_X * GRID )
#define OUT_2            ( ( 18 + DELTA_Y ) * SCALE_X * GRID )

#define CO               ( ( 22 + DELTA_Y ) * SCALE_X * GRID )

#define COUT_X           ( (  2 + DELTA_X ) * SCALE_X * GRID )
#define COUT_Y           ( (  2 + DELTA_Y ) * SCALE_X * GRID )
#define CIN_X            ( (  5 + DELTA_X ) * SCALE_X * GRID )
#define CIN_Y            ( (  5 + DELTA_Y ) * SCALE_X * GRID )
#define OVER_X           ( (  8 + DELTA_X ) * SCALE_X * GRID )
#define OVER_Y           ( (  8 + DELTA_Y ) * SCALE_X * GRID )
#define OTHER_X          ( ( 11 + DELTA_X ) * SCALE_X * GRID )
#define OTHER_Y          ( ( 11 + DELTA_Y ) * SCALE_X * GRID )

#define NOT_DIM          ( GRID * SCALE_X )

#define CON_DX           ( 1 * SCALE_X * GRID )
#define CON_DY           ( 2 * SCALE_X * GRID )

#define SYMBOL_CENTER_X  ( (  9 + DELTA_X ) * SCALE_X * GRID )
#define SYMBOL_CENTER_Y  ( ( 20 + DELTA_X ) * SCALE_X * GRID )
#define SYMBOL_DX        ( 1 * SCALE_X * GRID )
#define SYMBOL_DY        ( 1 * SCALE_X * GRID )

#define MODEL_X          ( 10 * SCALE_X * GRID )
#define MODEL_Y          ( 16 * SCALE_X * GRID )
#define INSTANCE_X       ( 10 * SCALE_X * GRID )
#define INSTANCE_Y       ( 30 * SCALE_X * GRID )
#define LABEL_X          ( 10 * SCALE_X * GRID )
#define LABEL_Y          ( 40 * SCALE_X * GRID )

/*---------------------------------------------------------\
                     other defines
\---------------------------------------------------------*/
#define DO_COUT_N       NAME("cout%s",(rsa_puiss(Bits-1)&1) ? "" : "_n")
#define DO_OVER_N       NAME("over%s",(rsa_puiss(Bits-2)&1) ? "" : "_n")

/*---------------------------------------------------------\
                     RsaVectorizeName
\---------------------------------------------------------*/
static char *RsaVectorizeName( Base, Bits, Msb0 )
char *Base;
int   Bits;
char  Msb0;
{
	static char Name[ 50 ];
	int begin;
	int end;

	if( Msb0 == 0 )
	{
		begin = Bits - 1;
		end   = 0;
	}
	else
	{
		begin = 0;
		end   = Bits - 1;
	}

	sprintf( Name, "%s[%d:%d]", Base, begin, end );

	return Name;

} /* fin de RsaVectorizeName */

/*---------------------------------------------------------\
                     create_rsa_icon
\---------------------------------------------------------*/
static rsa_icon ( ModelName, Bits, Msb0, Cin, Cout, Overn, Over, Not, Csa, Sub, AddSub )
char *ModelName;
int  Bits;
int  Msb0;
int  Cin;
int  Cout;
int  Overn;
int  Over;
int  Not;
int  Csa;
int  Sub;
int  AddSub;
{
	int TestParameters;
	IconGate_list *Icon;

	/* Testing the paraneters validity */
	TestParameters = 0;

	if( Csa    != 0 ) TestParameters ++;
	if( Sub    != 0 ) TestParameters ++;
	if( AddSub != 0 ) TestParameters ++;


	if( TestParameters > 1 )
	{
		fprintf( stderr, "Call the function 'create_rsa_icon' with invalid parameters !\n");
		return;
	}

	/* Creating the icon */
	Icon = addicongate( ModelName,
	                    MODEL_X,    MODEL_Y,    SAX_CENTER, SAX_CENTER, SAX_HORIZONTAL,
	                    INSTANCE_X, INSTANCE_Y, SAX_CENTER, SAX_CENTER, SAX_HORIZONTAL,
	                    LABEL_X,    LABEL_Y,    SAX_CENTER, SAX_CENTER, SAX_HORIZONTAL
	                   );

	if( Icon == NULL )
	{
		fprintf( stderr, "Function 'addicongate' return NULL pointer !\n");
		return;
	}

	if( Csa == 0 )
	{
		addiconline( Icon, POINT__1_X, POINT__1_Y, POINT__2_X, POINT__2_Y );
		addiconline( Icon, POINT__2_X, POINT__2_Y, POINT__3_X, POINT__3_Y );
		addiconline( Icon, POINT__3_X, POINT__3_Y, POINT__4_X, POINT__4_Y );
		addiconline( Icon, POINT__4_X, POINT__4_Y, POINT__5_X, POINT__5_Y );
		addiconline( Icon, POINT__5_X, POINT__5_Y, POINT__6_X, POINT__6_Y );
		addiconline( Icon, POINT__6_X, POINT__6_Y, POINT__7_X, POINT__7_Y );
		addiconline( Icon, POINT__7_X, POINT__7_Y, POINT__1_X, POINT__1_Y );

		/* Input */
		addiconline( Icon, 0, IN_A_1, REAL_DELTA_X, IN_A_1 );
		addiconline( Icon, 0, IN_B_1, REAL_DELTA_X, IN_B_1 );
		addiconcon( Icon, RsaVectorizeName( "a", Bits, Msb0 ),
		            0, IN_A_1, SAX_NORTH, IN, SAX_LEFT, SAX_UP, SAX_HORIZONTAL, 0, IN_A_1 - CON_DY );
		addiconcon( Icon, RsaVectorizeName( "b", Bits, Msb0 ),
		            0, IN_B_1, SAX_NORTH, IN, SAX_LEFT, SAX_UP, SAX_HORIZONTAL, 0, IN_B_1 - CON_DY );

	}
	else
	{
		addiconline( Icon, POINT__1_X, POINT__1_Y, POINT__2_X, POINT__2_Y );
		addiconline( Icon, POINT__2_X, POINT__2_Y, POINT__3_X, POINT__3_Y );
		addiconline( Icon, POINT__3_X, POINT__3_Y, POINT__4_X, POINT__4_Y );
		addiconline( Icon, POINT__4_X, POINT__4_Y, POINT__8_X, POINT__8_Y );
		addiconline( Icon, POINT__8_X, POINT__8_Y, POINT__9_X, POINT__9_Y );
		addiconline( Icon, POINT__9_X, POINT__9_Y, POINT_10_X, POINT_10_Y );
		addiconline( Icon, POINT_10_X, POINT_10_Y, POINT_11_X, POINT_11_Y );
		addiconline( Icon, POINT_11_X, POINT_11_Y, POINT_12_X, POINT_12_Y );
		addiconline( Icon, POINT_12_X, POINT_12_Y, POINT_13_X, POINT_13_Y );
		addiconline( Icon, POINT_13_X, POINT_13_Y, POINT__1_X, POINT__1_Y );

		/* Input */
		addiconline( Icon, 0, IN_A_2, REAL_DELTA_X, IN_A_2 );
		addiconline( Icon, 0, IN_B_2, REAL_DELTA_X, IN_B_2 );
		addiconline( Icon, 0, IN_C, REAL_DELTA_X, IN_C );

		addiconcon( Icon, RsaVectorizeName( "a", Bits, Msb0 ),
		            0, IN_A_2, SAX_NORTH, IN, SAX_LEFT, SAX_UP, SAX_HORIZONTAL, 5, IN_A_2 - CON_DY );
		addiconcon( Icon, RsaVectorizeName( "b", Bits, Msb0 ),
		            0, IN_B_2, SAX_NORTH, IN, SAX_LEFT, SAX_UP, SAX_HORIZONTAL, 5, IN_B_2 - CON_DY );
		addiconcon( Icon, RsaVectorizeName( "c", Bits, Msb0 ),
		            0, IN_C  , SAX_NORTH, IN, SAX_LEFT, SAX_UP, SAX_HORIZONTAL, 5, IN_C   - CON_DY );
	}

	addiconline( Icon, COUT_X, 0, COUT_X, COUT_Y );
	addiconcon( Icon, DO_COUT_N, COUT_X, 0, SAX_NORTH, OUT, SAX_LEFT, SAX_UP, SAX_HORIZONTAL, COUT_X, CON_DX );

	if( Cin != 0 )
	{
		addiconline( Icon, CIN_X, 0, CIN_X, CIN_Y);
		addiconcon( Icon, "cin", CIN_X, 0, SAX_NORTH, IN, SAX_LEFT, SAX_UP, SAX_HORIZONTAL, CIN_X, CON_DX );
	}

	if( ( Over != 0 ) || ( Overn != 0 ) )
	{
		addiconline( Icon, OVER_X, 0, OVER_X, OVER_Y);
		addiconcon( Icon, DO_OVER_N, OVER_X, 0, SAX_NORTH, OUT, SAX_LEFT, SAX_UP, SAX_HORIZONTAL, OVER_X, CON_DX );
	}

	if( Csa != 0 )
	{
		addiconline( Icon, OTHER_X, 0, OTHER_X, OTHER_Y);
		addiconcon( Icon, "coc", OTHER_X, 0, SAX_NORTH, IN, SAX_LEFT, SAX_UP, SAX_HORIZONTAL, OTHER_X, CON_DX );
	}

	if( AddSub != 0 )
	{
		addiconline( Icon, OTHER_X, 0, OTHER_X, OTHER_Y);
		addiconcon( Icon, "sub", OTHER_X, 0, SAX_NORTH, IN, SAX_LEFT, SAX_UP, SAX_HORIZONTAL, OTHER_X, CON_DX );
	}

	if( Cout == 0 )
	{
		if( Not == 0 )
		{
			addiconline( Icon, RIGHT_BORDER,                OUT_1,
			                   RIGHT_BORDER + REAL_DELTA_X, OUT_1 );
		}
		else
		{
			addiconcircle( Icon, RIGHT_BORDER, OUT_1 - (NOT_DIM / 2), NOT_DIM, NOT_DIM);
			addiconline( Icon, RIGHT_BORDER + NOT_DIM,      OUT_1,
			                   RIGHT_BORDER + REAL_DELTA_X, OUT_1 );
		}

		addiconcon( Icon, RsaVectorizeName( "s", Bits, Msb0 ), RIGHT_BORDER + REAL_DELTA_X, OUT_1, SAX_WEST, OUT,
		            SAX_RIGHT, SAX_UP, SAX_HORIZONTAL, RIGHT_BORDER + REAL_DELTA_X, OUT_1 - CON_DY );
	}
	else
	{
		if( Not == 0 )
		{
			addiconline( Icon, RIGHT_BORDER,                OUT_2,
			                   RIGHT_BORDER + REAL_DELTA_X, OUT_2 );
		}
		else
		{
			addiconcircle( Icon, RIGHT_BORDER, OUT_2 - (NOT_DIM / 2), NOT_DIM, NOT_DIM);
			addiconline( Icon, RIGHT_BORDER + NOT_DIM,      OUT_2,
			                   RIGHT_BORDER + REAL_DELTA_X, OUT_2 );
		}

		addiconcon( Icon, RsaVectorizeName( "s", Bits, Msb0 ), RIGHT_BORDER + REAL_DELTA_X, OUT_2, SAX_WEST, OUT,
		            SAX_RIGHT, SAX_UP, SAX_HORIZONTAL, RIGHT_BORDER + REAL_DELTA_X, OUT_2 - CON_DY );
	
		addiconline( Icon, RIGHT_BORDER, CO, RIGHT_BORDER + REAL_DELTA_X, CO );
		addiconcon( Icon, RsaVectorizeName( "co", Bits, Msb0 ), RIGHT_BORDER + REAL_DELTA_X, CO, SAX_WEST, OUT,
		            SAX_RIGHT, SAX_UP, SAX_HORIZONTAL, RIGHT_BORDER + REAL_DELTA_X, CO - CON_DY );
	}

	/* the symbol */
	if( ( Csa != 0 ) || (TestParameters == 0 ) )
	{
		addiconline( Icon, SYMBOL_CENTER_X - SYMBOL_DX, SYMBOL_CENTER_Y,
		                   SYMBOL_CENTER_X + SYMBOL_DX, SYMBOL_CENTER_Y);
		addiconline( Icon, SYMBOL_CENTER_X            , SYMBOL_CENTER_Y - SYMBOL_DY,
		                   SYMBOL_CENTER_X            , SYMBOL_CENTER_Y + SYMBOL_DY);
	}

	if( Sub != 0 )
	{
		addiconline( Icon, SYMBOL_CENTER_X - SYMBOL_DX, SYMBOL_CENTER_Y,
		                   SYMBOL_CENTER_X + SYMBOL_DX, SYMBOL_CENTER_Y);
	}

	if( AddSub != 0 )
	{
		addiconline( Icon, SYMBOL_CENTER_X - SYMBOL_DX, SYMBOL_CENTER_Y - SYMBOL_DY,
		                   SYMBOL_CENTER_X + SYMBOL_DX, SYMBOL_CENTER_Y - SYMBOL_DY);
		addiconline( Icon, SYMBOL_CENTER_X            , SYMBOL_CENTER_Y - SYMBOL_DY - SYMBOL_DY,
		                   SYMBOL_CENTER_X            , SYMBOL_CENTER_Y + SYMBOL_DY - SYMBOL_DY);
		addiconline( Icon, SYMBOL_CENTER_X - SYMBOL_DX, SYMBOL_CENTER_Y + SYMBOL_DY,
		                   SYMBOL_CENTER_X + SYMBOL_DX, SYMBOL_CENTER_Y + SYMBOL_DY);
	}

	update_icon( Icon );
   mbkenv();
	saveicon( Icon );
} /* fin de rsa_icon */

