/* :ts=8 */
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "general.h"
#include "globals.h"
#include "intui.h"
#include "spl_math.h"
#include "spl_util.h"
#include "spl_gfx.h"


	/* Constants and macros used by the clipping routine:	*/
#define OutCode_Top	0x01
#define OutCode_Bottom	0x02
#define OutCode_Right	0x04
#define OutCode_Left	0x08

	/* Compute 'OutCode' for position (X,Y) and return it in C	*/
#define Compute_OutCode(X, Y, C)				\
	C = 0;						\
	if (Y > YMax)      C  = OutCode_Top;		\
        else if (Y < YMin) C  = OutCode_Bottom;		\
	if (X > XMax)      C |= OutCode_Right;		\
        else if (X < XMin) C |= OutCode_Left
	

	/* Clip and draw line (X0,Y0) - (X1,Y1) in view V.		*/
#define ViewClipDrawLine(V, X0, Y0, X1, Y1)		\
	ClipDrawLine(X0, Y0, X1, Y1, 			\
		Views[V].X_Min, Views[V].X_Max,		\
		Views[V].Y_Min, Views[V].Y_Max)

void ClipDrawLine(short X0, short Y0, short X1, short Y1, 
	 	  short XMin, short XMax, short YMin, short YMax)
/************************************************************************/
/*                                                                      */
/* Clip and draw the line from (X0, Y0) - (X1, Y1) to the rectangle 	*/
/* given by (XMin, YMin) - (XMax, YMax).				*/
/*                                                                      */
/* This is the Cohen-Sutherland algorithm as described in 		*/
/* Computer graphics p. 113 - 117.					*/
/*                                                                      */
/************************************************************************/
{
    Boolean_T 	Accept, Done;
    long	OutCode0, OutCode1, OutCodeOut;
    int		X, Y;

    Accept = Done = FALSE;

    Compute_OutCode(X0, Y0, OutCode0);
    Compute_OutCode(X1, Y1, OutCode1);

    do {

	if (OutCode0 == 0 && OutCode1 == 0) Accept = Done = TRUE;
   	else if ((OutCode0 & OutCode1) != 0) Done = TRUE;
   	else {

	    /* Failed both tests, so calculate the line segment to 	*/
	    /* clip: from an outside point to an intersection with 	*/
	    /* clip edge.						*/

	    /* At least one  endpoint is outside the clip rectangle,	*/
	    /* pick it.							*/

	    if (OutCode0 != 0) OutCodeOut = OutCode0;
            else	       OutCodeOut = OutCode1;

	    /* Now find intersection point:			 	*/

	    if (OutCodeOut & OutCode_Top) {

		/* Divide line at top of clip rectangle			*/
		if (Y0 == Y1) Done = TRUE;
		else {
		    X = X0 + (X1 - X0) * (YMax - Y0) / (Y1 - Y0);
		    Y = YMax;
		}
	    } else if (OutCodeOut & OutCode_Bottom) {

		/* Divide line at bottom of clip rectangle		*/
		if (Y0 == Y1) Done = TRUE;
		else {
		    X = X0 + (X1 - X0) * (YMin - Y0) / (Y1 - Y0);
		    Y = YMin;
		}

	    } else if (OutCodeOut & OutCode_Right) {

		/* Divide line at right of clip rectangle		*/
		if (X0 == X1) Done = TRUE;
		else {
		    X = XMax;
		    Y = Y0 + (Y1 - Y0) * (XMax - X0) / (X1 - X0);
		}

	    } else if (OutCodeOut & OutCode_Left) {

		/* Divide line at left of clip rectangle		*/
		if (X0 == X1) Done = TRUE;
		else {
		    X = XMin;
		    Y = Y0 + (Y1 - Y0) * (XMin - X0) / (X1 - X0);
		}
	    } /* if .. else .. */

	    /* Now we move outside point to intersection point to clip,	*/
	    /* and get ready for next pass.				*/

	    if (OutCodeOut == OutCode0) {

		X0 = X;
		Y0 = Y;
		Compute_OutCode(X0, Y0, OutCode0);

	    } else {

		X1 = X;
		Y1 = Y;
		Compute_OutCode(X1, Y1, OutCode1);

 	    } /* if .. else .. */

	} /* if .. else .. */

    } while (!Done);

    if (Accept) {

	/* Draw from (X0, Y0) to (X1, Y1) */

    	Move(Windows[Id_Active_Window].RastPort, X0, Y0);
    	Draw(Windows[Id_Active_Window].RastPort, X1, Y1);
	
    } /* if */

} /* ClipDrawLine */


void Modify_Scale(double Factor)
/************************************************************************/
/*                                                                      */
/* Modify the scale factor.						*/
/*                                                                      */
/************************************************************************/
{
    X_Scale_Factor *= Factor;
    Y_Scale_Factor *= Factor;
    Max_Dist = 5.0 / Y_Scale_Factor;

} /* Modify_Scale */

void Transformation_Init()
/************************************************************************/
/*                                                                      */
/* Initialize all transformation parameters.				*/
/*                                                                      */
/************************************************************************/
{
    Vector_T 	Initial_Offset		= { 0.0, 0.0, 0.0 };

    Y_Scale_Factor	= 0.5;
    X_Scale_Factor	= Aspect_Ratio * Y_Scale_Factor;
    Modify_Scale(1.0);	

    Compute_Rotation_Matrix(M_Rotation, Rotation_Vector);
    Set_Offset(Initial_Offset, -1);

} /* Transformation_Init */

void Set_Offset(Vector_T Pos, short View_Id)
/************************************************************************/
/*                                                                      */
/* Set the offset to Pos. View_Id designates the view in which the 	*/
/* offset is changed (-1 => all views).					*/
/*                                                                      */
/************************************************************************/
{
    switch (View_Id) {

    case -1: 				/* All views	*/
        Offset[0] = Pos[0]; 
        Offset[1] = Pos[1]; 
        Offset[2] = Pos[2]; 
	break;

    case 0: 				/* Y - Z	*/
        Offset[1] = Pos[1]; 
        Offset[2] = Pos[2]; 
	break;

    case 1: 				/* X - Z	*/
        Offset[0] = Pos[0]; 
        Offset[2] = Pos[2]; 
	break;

    case 2: 				/* X - Y	*/
        Offset[0] = Pos[0]; 
        Offset[1] = Pos[1]; 
	break;  

    } /* switch */

} /* Set_Offset */

void Move_Offset(short Direction, short View_Id)
/************************************************************************/
/*                                                                      */
/* Move offset in the view given by View_Id in the direction given by	*/
/* Direction (0: Up, 1: Down, 2: Right, 3: Left).			*/
/*                                                                      */
/* The distance moved depends on the current scale factor.		*/
/*                                                                      */
/************************************************************************/
{
    double 	Delta;
    Vector_T	New_Offset;

    Vec2Op(New_Offset, =, Offset);

    Delta = 100.0 / Y_Scale_Factor;

    switch (Direction) {
    case 0:	/* Up */
        switch (View_Id) {
	case 0: New_Offset[2] = Offset[2] + Delta; break;
	case 1: New_Offset[2] = Offset[2] + Delta; break;
	case 2: New_Offset[1] = Offset[1] + Delta; break;
	} /* switch */
	break;

    case 1:	/* Down */
        switch (View_Id) {
	case 0: New_Offset[2] = Offset[2] - Delta; break;
	case 1: New_Offset[2] = Offset[2] - Delta; break;
	case 2: New_Offset[1] = Offset[1] - Delta; break;
	} /* switch */
	break;

    case 2:	/* Right */
        switch (View_Id) {
	case 0: New_Offset[1] = Offset[1] + Delta; break;
	case 1: New_Offset[0] = Offset[0] + Delta; break;
	case 2: New_Offset[0] = Offset[0] + Delta; break;
	} /* switch */
	break;

    case 3:	/* Left */
        switch (View_Id) {
	case 0: New_Offset[1] = Offset[1] - Delta; break;
	case 1: New_Offset[0] = Offset[0] - Delta; break;
	case 2: New_Offset[0] = Offset[0] - Delta; break;
	} /* switch */
	break;

    } /* Switch */

    Set_Offset(New_Offset, -1);

} /* Move_Offset */

void Snap_To_Grid(Vector_T Pos)
/************************************************************************/
/*                                                                      */
/* Snap the point Pos to the grid.					*/
/*                                                                      */
/************************************************************************/
{
    double Size2;

    Size2 = Grid_Size / 2.0;

    Pos[0] = SGN(Pos[0]) * Grid_Size * ( (int)((ABS(Pos[0]) + Size2) / Grid_Size));
    Pos[1] = SGN(Pos[1]) * Grid_Size * ( (int)((ABS(Pos[1]) + Size2) / Grid_Size));
    Pos[2] = SGN(Pos[2]) * Grid_Size * ( (int)((ABS(Pos[2]) + Size2) / Grid_Size));

} /* Snap_To_Grid */

short Screen_To_World(int Screen_X, int Screen_Y, Vector_T Pos)
/************************************************************************/
/*                                                                      */
/* Convert the screen coordinates (Screen_X, Screen_Y) to a world coor-	*/
/* dinate, and return id of the view where (Screen_X, Screen_Y) is.	*/
/*                                                                      */
/* NOTICE: This function can only find two of the three world coordi-	*/
/*	   nates. The third will not be modified by this routine.	*/
/*                                                                      */
/************************************************************************/
{
    if ((What_Mask & What_X) &&
	Screen_X >= Views[V_X].X_Min && 
        Screen_X <= Views[V_X].X_Max &&
        Screen_Y >= Views[V_X].Y_Min && 
	Screen_Y <= Views[V_X].Y_Max) {  	/* View X: Y-Z	*/

	Pos[1] = (Screen_X - Views[V_X].X_Center) / X_Scale_Factor + 
	    							Offset[1];
	Pos[2] = (Views[V_X].Y_Center - Screen_Y) / Y_Scale_Factor + 
	    							Offset[2];
	return(V_X);

    } /* if */

    if ((What_Mask & What_Y) &&
	Screen_X >= Views[V_Y].X_Min &&  
        Screen_X <= Views[V_Y].X_Max &&
	Screen_Y >= Views[V_Y].Y_Min && 
	Screen_Y <= Views[V_Y].Y_Max) { 	/* View Y: X-Z	*/

	Pos[0] = (Screen_X - Views[V_Y].X_Center) / X_Scale_Factor + 
	    							Offset[0];
	Pos[2] = (Views[V_Y].Y_Center - Screen_Y) / Y_Scale_Factor + 
	    							Offset[2];
	return(V_Y);

    } /* if */

    if ((What_Mask & What_Z) &&
	Screen_X >= Views[V_Z].X_Min &&  
        Screen_X <= Views[V_Z].X_Max &&
        Screen_Y >= Views[V_Z].Y_Min && 
	Screen_Y <= Views[V_Z].Y_Max) {  	/* View Z: X-Y	*/

	Pos[0] = (Screen_X - Views[V_Z].X_Center) / X_Scale_Factor + 
	    							Offset[0];
	Pos[1] = (Views[V_Z].Y_Center - Screen_Y) / Y_Scale_Factor + 
	    							Offset[1];
	return(V_Z);

    } /* if */

    if ((What_Mask & What_P) &&
 	Screen_X >= Views[V_P].X_Min && 
        Screen_X <= Views[V_P].X_Max &&
	Screen_Y >= Views[V_P].Y_Min && 
	Screen_Y <= Views[V_P].Y_Max) {  	/* View P: Persp*/

	/* Points can't be selected in persp view (yet) */
	return(-1);

    } /* if */

    return(-1);

} /* Screen_To_World */

void World_To_Screen(Vector_T Pos, short *X0, short *Y0, 
			           short *X1, short *Y1, 
				   short *X2, short *Y2)
/************************************************************************/
/*                                                                      */
/* Convert the world coordinate in Pos to screen coordinates for the 	*/
/* three 'flat' views.							*/
/*                                                                      */
/* This function is called all the time, so it is a good place for opti-*/
/* mization.								*/
/*                                                                      */
/************************************************************************/
{
    Vector_T	P;

    Vec3Op(P, =, Pos, -, Offset);

    *X0 = Views[V_X].X_Center + P[1] * X_Scale_Factor;	/* X : Y - Z */
    *Y0 = Views[V_X].Y_Center - P[2] * Y_Scale_Factor;

    *X1 = Views[V_Y].X_Center + P[0] * X_Scale_Factor;	/* Y : X - Z */
    *Y1 = Views[V_Y].Y_Center - P[2] * Y_Scale_Factor;

    *X2 = Views[V_Z].X_Center + P[0] * X_Scale_Factor;	/* Z : X - Y */
    *Y2 = Views[V_Z].Y_Center - P[1] * Y_Scale_Factor;

} /* World_To_Screen */

void World_To_Persp(Vector_T Pos, short *X, short *Y)
/************************************************************************/
/*                                                                      */
/* Convert the world coordinate in Pos to screen coordinates for the 	*/
/* perspective view.							*/
/*                                                                      */
/* This function is called all the time, so it is a good place for opti-*/
/* mization.								*/
/*                                                                      */
/************************************************************************/
{
    Vector_T	P, RP;

    Vec3Op(P, =, Pos, -, Offset);

    Matrix_MultV(RP, M_Rotation, P);

    *X = Views[V_P].X_Center +  RP[0] * X_Scale_Factor;
    *Y = Views[V_P].Y_Center -  RP[2] * Y_Scale_Factor;

} /* World_To_Persp */

void Unmark_All()
/************************************************************************/
/*                                                                      */
/* Unmark all splines, knots and points.				*/
/*                                                                      */
/************************************************************************/
{
    short    i;
    short    Point_Id;
    Spline_T *Spline;
    Knot_T   *Knot;


    for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {

	if (Spline->Nbr_Knots > 0) {

	    Do_Unmark(*Spline);

	    for (i = 0, Knot = Spline->First; 
		 i < Spline->Nbr_Knots; i++, Knot = Knot->Next) 
					Do_Unmark(*Knot);
	} /* if */

    } /* for */

    for (Point_Id = 0; Point_Id < Max_Nbr_Points; Point_Id++) 
					Do_Unmark(Points[Point_Id]);

} /* Unmark_All */

void Mark_Selected_Segments()
/************************************************************************/
/*                                                                      */
/* Mark the currently selected segments.				*/
/*                                                                      */
/************************************************************************/
{
    Knot_T      *Knot, *Begin_Knot, *End_Knot;

    Unmark_All();

    if (Select_Spline == NULL || Select_Knot == NULL) return;

    if (Select_Spline->Nbr_Knots < 2) return;

    if (Select_Spline->Nbr_Knots < 5) {

	Begin_Knot = Select_Spline->First;
	if (Select_Spline->Loop) 
	     End_Knot   = Select_Spline->Last->Next;
	else End_Knot   = Select_Spline->Last;

    } else {

	Begin_Knot = Select_Knot;
	if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;
	if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;

	End_Knot = Select_Knot;
	if (End_Knot->Next) End_Knot = End_Knot->Next;
	End_Knot = End_Knot->Next;

    } /* if .. else .. */

		/* Loop from Begin_Knot to End_Knot (exclusive)	*/

    Knot = Begin_Knot;
    do {

	Do_Mark(*Knot);
	Knot = Knot->Next;

    } while (Knot != End_Knot);

} /* Mark_Selected_Segments */

void Mark_Connected_Segments(short Point_Id)
/************************************************************************/
/*                                                                      */
/* Mark segments connected to point Point_Id.				*/
/*                                                                      */
/************************************************************************/
{
    Spline_T    *Spline;
    Knot_T	*K, *Knot, *Begin_Knot, *End_Knot;
    short	i;

    if (!Is_Point_Id_Ok(Point_Id)) return;

    Unmark_All();

    for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {

	if (Spline->Nbr_Knots < 2) continue;

	Knot = NULL;
	for (i = 0, K = Spline->First; i < Spline->Nbr_Knots; 
						i++, K = K->Next)
	   if (K->Point_Id == Point_Id) Knot = K;

	if (Knot == NULL) continue;


        if (Spline->Nbr_Knots < 5) {

	    Begin_Knot = Spline->First;
	    if (Spline->Loop) End_Knot = Spline->Last->Next;
	    else  	      End_Knot = Spline->Last;

        } else {

	    Begin_Knot = Knot;
	    if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;
	    if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;

	    End_Knot = Knot;
	    if (End_Knot->Next) End_Knot = End_Knot->Next;
	    End_Knot = End_Knot->Next;

	} /* if .. else .. */

		/* Loop from Begin_Knot to End_Knot (exclusive)	*/

        Knot = Begin_Knot;
        do {

	    Do_Mark(*Knot);
	    Knot = Knot->Next;

        } while (Knot != End_Knot);

    } /* for */

} /* Mark_Connected_Segments */

void Compute_Segment(Spline_T *Spline, Knot_T *Knot)
/************************************************************************/
/*                                                                      */
/* Compute a spline segment.						*/
/*                                                                      */
/* This function is using a brute force iterative evaluation, it would	*/
/* be much better to use a forward difference method as described in	*/
/* Computer Graphics p. 511 - 514.					*/
/* Oh well, maybe another time...					*/
/*                                                                      */
/************************************************************************/
{
    Matrix4_T	M_Precomp;
    Vector4_T	Pos;
    double 	Step_T;
    double 	T;
    Byte_T	NX, NY, NZ, NP;

    NX = NY = NZ = NP = 0;

    if (Spline->Nbr_Knots < 2) return;

    Step_T = 1.0 / Spline_Resolution;

    Precompute_Kochanek_Bartels(M_Precomp, Spline, Knot);


    for (T = 0.0; T <= 1.0; T += Step_T) {

	Compute_Position(Pos, T, M_Precomp);

	World_To_Screen(Pos,&Knot->ViewX[NX][0],  &Knot->ViewX[NX][1],
			    &Knot->ViewY[NY][0],  &Knot->ViewY[NY][1],
			    &Knot->ViewZ[NZ][0],  &Knot->ViewZ[NZ][1]);

	World_To_Persp(Pos, &Knot->ViewP[NP][0], &Knot->ViewP[NP][1]);

		/* Simple clipping: The line must be entirely within the*/
		/* views.						*/

	if (Views[V_X].X_Min < Knot->ViewX[NX][0] &&
	    Views[V_X].Y_Min < Knot->ViewX[NX][1] &&
	    Views[V_X].X_Max > Knot->ViewX[NX][0] &&
	    Views[V_X].Y_Max > Knot->ViewX[NX][1]) NX++;

	if (Views[V_Y].X_Min < Knot->ViewY[NY][0] &&
	    Views[V_Y].Y_Min < Knot->ViewY[NY][1] &&
	    Views[V_Y].X_Max > Knot->ViewY[NY][0] &&
	    Views[V_Y].Y_Max > Knot->ViewY[NY][1]) NY++;

	if (Views[V_Z].X_Min < Knot->ViewZ[NZ][0] &&
	    Views[V_Z].Y_Min < Knot->ViewZ[NZ][1] &&
	    Views[V_Z].X_Max > Knot->ViewZ[NZ][0] &&
	    Views[V_Z].Y_Max > Knot->ViewZ[NZ][1]) NZ++;

	if (Views[V_P].X_Min < Knot->ViewP[NP][0] &&
	    Views[V_P].Y_Min < Knot->ViewP[NP][1] &&
	    Views[V_P].X_Max > Knot->ViewP[NP][0] &&
	    Views[V_P].Y_Max > Knot->ViewP[NP][1]) NP++;


    } /* for */

    Knot->NX = NX;
    Knot->NY = NY;
    Knot->NZ = NZ;
    Knot->NP = NP;

} /* Compute_Segment */


void Compute_Marked_Segments()
/************************************************************************/
/*                                                                      */
/* Compute vectors for all marked segments.				*/
/*                                                                      */
/************************************************************************/
{
    int		i;
    Spline_T	*Spline;
    Knot_T	*Knot;
    int		Nbr_Knots;

    for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {

        if ((Nbr_Knots = Spline->Nbr_Knots) < 1) continue;

	for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots; 
						i++, Knot = Knot->Next) {
	
	    if (Is_Marked(*Spline) || Is_Marked(*Knot) ) {

	    	Compute_Segment(Spline, Knot);

	     } /* if */

	} /* for */


    } /* for */

} /* Compute_Marked_Segments */


void Compute_Spline(Spline_T *Spline)
/************************************************************************/
/*                                                                      */
/* Compute vectors for a given spline.					*/
/*                                                                      */
/************************************************************************/
{
    Knot_T	*Knot;
    int		i;
    int	  	Nbr_Knots;

    if ((Nbr_Knots = Spline->Nbr_Knots) < 1) return;


    for (i = 0, Knot = Spline->First; i < Nbr_Knots; i++, Knot = Knot->Next) {

	if (!Is_Hidden(Points[Knot->Point_Id]))
			Compute_Segment(Spline, Knot);

    } /* for */

} /* Compute_Spline */


void Compute_Splines()
/************************************************************************/
/*                                                                      */
/* Compute vectors for all splines.          				*/
/*                                                                      */
/************************************************************************/
{
    Spline_T *Spline;

    Set_Pointer(TRUE);

    for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {

	Compute_Spline(Spline);

    } /* for */

    Set_Pointer(FALSE);

} /* Compute_Splines */

void Draw_Segment(Spline_T *Spline, Knot_T *Knot, int Pen, long What)
/************************************************************************/
/*                                                                      */
/* Draw a spline segment.						*/
/*                                                                      */
/* The segment must have been 'computed' before calling this function.	*/
/*                                                                      */
/************************************************************************/
{
    Knot_T	*Next_Knot;

    What &= What_Mask;

	/* If either of the endpoints is hidden, 		*/
	/* then don't draw the segment 				*/

    Next_Knot = Knot->Next;
    if (Next_Knot == NULL) return;

    if (Is_Hidden(Points[Next_Knot->Point_Id]) || 
	Is_Hidden(Points[Knot->Point_Id]) ) return;

    SetAPen(Windows[Id_Active_Window].RastPort, Pen);


    if ( (What & What_SX) && (Knot->NX > 1) ) {
       	Move(Windows[Id_Active_Window].RastPort, Knot->ViewX[0][0], 
				       Knot->ViewX[0][1]);
	PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NX-1, 
					&Knot->ViewX[1][0]);
    } /* if */

    if ( (What & What_SY) && (Knot->NY > 1) ) {
	Move(Windows[Id_Active_Window].RastPort, Knot->ViewY[0][0], 
				       Knot->ViewY[0][1]);
	PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NY-1, 
					&Knot->ViewY[1][0]);
    } /* if */

    if ( (What & What_SZ) && (Knot->NZ > 1) ) {
	Move(Windows[Id_Active_Window].RastPort, Knot->ViewZ[0][0], 
	    			       Knot->ViewZ[0][1]);
	PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NZ-1, 
					&Knot->ViewZ[1][0]);
    } /* if */

    if ( (What & What_SP) && (Knot->NP > 1) ) {

       	Move(Windows[Id_Active_Window].RastPort, Knot->ViewP[0][0], 
				       Knot->ViewP[0][1]);
	PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NP-1, 
					&Knot->ViewP[1][0]);

    } /* if */

} /* Draw_Segment */

void Draw_Marked_Segments(Draw_Mode_T Mode, long What)
/************************************************************************/
/*                                                                      */
/* Draw all marked segments.						*/
/*                                                                      */
/************************************************************************/
{
    Spline_T 	*Spline;
    Knot_T	*Knot;
    int		i;
    short	Nbr_Knots;
    int		Pen;

    switch (Mode) {

    case DM_Normal: /* Normal draw */
    	Pen = Pen_Segment;
    	Windows[Id_Active_Window].RastPort->Mask    = 0xff;
    	SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
        break;

    case DM_Erase: /* Delete	   */
    	Pen = Pen_Background;
    	Windows[Id_Active_Window].RastPort->Mask    = 0xff;
    	SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
        break;

    case DM_Plane: /* Draw in plane 3 */
    	Pen = Pen_Plane;
    	Windows[Id_Active_Window].RastPort->Mask    = 0x08;
    	SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
        break;

    } /* switch */

    for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {

	if ((Nbr_Knots = Spline->Nbr_Knots) < 2) continue;

	for (i = 0, Knot = Spline->First; 
	     i < Nbr_Knots && Knot->Next != NULL; i++, Knot = Knot->Next) {

	    if (Is_Marked(*Spline) || Is_Marked(*Knot) ) {

	        if (Mode == DM_Normal) {

	            Pen = Pen_Segment;

	            if (Select_Spline == Spline) {

	   		if (Select_Knot == Knot || 
	       	    	    Select_Knot == Knot->Next) Pen = Pen_Segment_Selected;

	            } /* if */

	    	} /* if */
	    	Draw_Segment(Spline, Knot, Pen, What);
    		Draw_Knot(Spline, Knot,  Mode, What);

	    } /* if */

	} /* for */

    } /* for */

    Draw_Knot(Select_Spline, Select_Knot,  Mode, What);

} /* Draw_Marked_Segments */

void Draw_Spline(Spline_T *Spline , Draw_Mode_T Mode, long What)
/************************************************************************/
/*                                                                      */
/* Draw a spline.							*/
/*                                                                      */
/************************************************************************/
{
    Knot_T	*Knot;
    int		i;
    short	Nbr_Knots;
    int		Pen;

    if (Spline == NULL) return;
    if ((Nbr_Knots = Spline->Nbr_Knots) < 1) return;

    switch (Mode) {

    case DM_Normal: /* Normal draw */
    	Pen = Pen_Segment;
    	Windows[Id_Active_Window].RastPort->Mask    = 0xff;
    	SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
        break;

    case DM_Erase: /* Delete	   */
    	Pen = Pen_Background;
    	Windows[Id_Active_Window].RastPort->Mask    = 0xff;
    	SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
        break;

    case DM_Plane: /* Draw in plane 3 */
    	Pen = Pen_Plane;
    	Windows[Id_Active_Window].RastPort->Mask    = 0x08;
    	SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
        break;

    } /* switch */


    for (i = 0, Knot = Spline->First; 
	 i < Nbr_Knots && Knot->Next != NULL; i++, Knot = Knot->Next) {

	if (Mode == DM_Normal) {

	    Pen = Pen_Segment;

	    if (Select_Spline == Spline) {

	   	if (Select_Knot == Knot || 
	       	    Select_Knot == Knot->Next)  Pen = Pen_Segment_Selected;

	    } /* if */

	} /* if */

	Draw_Segment(Spline, Knot, Pen, What);
        Draw_Knot(Spline, Knot, Mode, What);


    } /* for */

    Draw_Knot(Spline, Knot, Mode, What);

} /* Draw_Spline */


void Draw_Splines(Draw_Mode_T Mode, long What)
/************************************************************************/
/*                                                                      */
/* Draw all splines.							*/
/*                                                                      */
/************************************************************************/
{
    Spline_T *Spline;

    for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {

	Draw_Spline(Spline, Mode, What);

    } /* for */

} /* Draw_Splines */

void Draw_Origin(Draw_Mode_T Mode, long What)
/************************************************************************/
/*                                                                      */
/* Draw the origin.							*/
/*                                                                      */
/************************************************************************/
{
    short 	Xx0, Yx0, Xy0, Yy0, Xz0, Yz0, Xp0, Yp0;
    short 	Xx1, Yx1, Xy1, Yy1, Xz1, Yz1, Xp1, Yp1;
    Vector_T	Vector;
    double	Size;
    int		Pen;

    What &= What_Mask;

    switch (Mode) {

    case DM_Normal:
	Pen = Pen_Segment;
        SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
        Windows[Id_Active_Window].RastPort->Mask    = 0xff;
	break;

    case DM_Erase:
	Pen = Pen_Background;
        SetDrMd(Windows[Id_Active_Window].RastPort, JAM2);
        Windows[Id_Active_Window].RastPort->Mask    = 0xff;
	break;

    case DM_Plane:
	Pen = Pen_Plane;
        SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
        Windows[Id_Active_Window].RastPort->Mask    = 0x08;
	break;

    } /* switch */

    World_To_Screen(Origin, &Xx0, &Yx0, &Xy0, &Yy0, &Xz0, &Yz0);
    World_To_Persp(Origin,  &Xp0, &Yp0);

    Size = 10.0 / Y_Scale_Factor;

						/* X - Axis	*/
    Vector[0] = Origin[0] + Size;
    Vector[1] = Origin[1];
    Vector[2] = Origin[2];

    World_To_Screen(Vector, &Xx1, &Yx1, &Xy1, &Yy1, &Xz1, &Yz1);
    World_To_Persp(Vector,  &Xp1, &Yp1);

    if (Mode == DM_Normal) Pen = Pen_Axis_X;
    SetAPen(Windows[Id_Active_Window].RastPort, Pen);
	
    if (What & What_X) ViewClipDrawLine(V_X, Xx0, Yx0, Xx1, Yx1);
    if (What & What_Y) ViewClipDrawLine(V_Y, Xy0, Yy0, Xy1, Yy1);
    if (What & What_Z) ViewClipDrawLine(V_Z, Xz0, Yz0, Xz1, Yz1);
    if (What & What_P) ViewClipDrawLine(V_P, Xp0, Yp0, Xp1, Yp1);

						/* Y - Axis	*/
    Vector[0] = Origin[0];
    Vector[1] = Origin[1] + Size;
    Vector[2] = Origin[2];

    World_To_Screen(Vector, &Xx1, &Yx1, &Xy1, &Yy1, &Xz1, &Yz1);
    World_To_Persp(Vector,  &Xp1, &Yp1);

    if (Mode == DM_Normal) Pen = Pen_Axis_Y;
    SetAPen(Windows[Id_Active_Window].RastPort, Pen);

    if (What & What_X) ViewClipDrawLine(V_X, Xx0, Yx0, Xx1, Yx1);
    if (What & What_Y) ViewClipDrawLine(V_Y, Xy0, Yy0, Xy1, Yy1);
    if (What & What_Z) ViewClipDrawLine(V_Z, Xz0, Yz0, Xz1, Yz1);
    if (What & What_P) ViewClipDrawLine(V_P, Xp0, Yp0, Xp1, Yp1);

						/* Z - Axis	*/
    Vector[0] = Origin[0];
    Vector[1] = Origin[1];
    Vector[2] = Origin[2] + Size;

    World_To_Screen(Vector, &Xx1, &Yx1, &Xy1, &Yy1, &Xz1, &Yz1);
    World_To_Persp(Vector,  &Xp1, &Yp1);

    if (Mode == DM_Normal) Pen = Pen_Axis_Z;
    SetAPen(Windows[Id_Active_Window].RastPort, Pen);

    if (What & What_X) ViewClipDrawLine(V_X, Xx0, Yx0, Xx1, Yx1);
    if (What & What_Y) ViewClipDrawLine(V_Y, Xy0, Yy0, Xy1, Yy1);
    if (What & What_Z) ViewClipDrawLine(V_Z, Xz0, Yz0, Xz1, Yz1);
    if (What & What_P) ViewClipDrawLine(V_P, Xp0, Yp0, Xp1, Yp1);

} /* Draw_Origin */

void Draw_Grid(long What)
/************************************************************************/
/*                                                                      */
/* Draw the grid if it is active.					*/
/*                                                                      */
/************************************************************************/
{
    Vector_T 	Grid;
    short	X0x, Y0x, X0y, Y0y, X0z, Y0z;    
    short	X1x, Y1x, X1y, Y1y, X1z, Y1z;    
    short	X, Y;
    int		Dx, Dy;
    long	i;

    if (!Grid_Active) return;

    Vec2Op(Grid, =, Offset);

    Snap_To_Grid(Grid);
    World_To_Screen(Grid, &X0x, &Y0x, &X0y, &Y0y, &X0z, &Y0z);    

    Grid[0] = Offset[0] + Grid_Size;
    Grid[1] = Offset[1] + Grid_Size;
    Grid[2] = Offset[2] + Grid_Size;
    Snap_To_Grid(Grid);
    World_To_Screen(Grid, &X1x, &Y1x, &X1y, &Y1y, &X1z, &Y1z);    

    Dx = ABS(X1x - X0x);	/* Size of grid in screen coordinates */
    Dy = ABS(Y1x - Y0x);

    if (Dx < 5 || Dx > 100 || Dy < 5 || Dy > 100) return;



    i = (X0x - Views[V_X].X_Min) / Dx; X0x -= (i * Dx);
    i = (Y0x - Views[V_X].Y_Min) / Dy; Y0x -= (i * Dy);

    i = (X0y - Views[V_Y].X_Min) / Dx; X0y -= (i * Dx);
    i = (Y0y - Views[V_Y].Y_Min) / Dy; Y0y -= (i * Dy);

    i = (X0z - Views[V_Z].X_Min) / Dx; X0z -= (i * Dx);
    i = (Y0z - Views[V_Z].Y_Min) / Dy; Y0z -= (i * Dy);

    SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
    Windows[Id_Active_Window].RastPort->Mask    = 0xff;
    SetAPen(Windows[Id_Active_Window].RastPort, Pen_Grid);

    What &= What_Mask;

    if (What & What_X) {

	for (X = X0x; X < Views[V_X].X_Max; X += Dx) {
	    for (Y = Y0x; Y < Views[V_X].Y_Max; Y += Dy) {
		WritePixel(Windows[Id_Active_Window].RastPort, X, Y);
	    }
	}

    } /* if */

    if (What & What_Y) {

	for (X = X0y; X < Views[V_Y].X_Max; X += Dx) {
	    for (Y = Y0y; Y < Views[V_Y].Y_Max; Y += Dy) {
		WritePixel(Windows[Id_Active_Window].RastPort, X, Y);
	    }
	}
    } /* if */

    if (What & What_Z) {

	for (X = X0z; X < Views[V_Z].X_Max; X += Dx) {
	    for (Y = Y0z; Y < Views[V_Z].Y_Max; Y += Dy) {
		WritePixel(Windows[Id_Active_Window].RastPort, X, Y);
	    }
	}
    } /* if */

} /* Draw_Grid */

void Draw_Box(Vector_T Min_Pos, Vector_T Max_Pos, Vector_T R_Vector,
					Draw_Mode_T Mode, long What)
/************************************************************************/
/*                                                                      */
/* Draw a box after it has been rotated as defined by R_Vector.		*/
/* If R_Vector == NULL no rotation is performed.			*/
/*                                                                      */
/************************************************************************/
{
    Matrix_T	R_Matrix;
    Vector_T	Tmp;
    Vector_T	Corners[8];
    short 	X[8][4], Y[8][4];
    int		Pen;
    int		i;


    What &= What_Mask;

    switch (Mode) {

    case DM_Normal:
        Pen = Pen_Segment;
        SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
        Windows[Id_Active_Window].RastPort->Mask    = 0xff;
	break;

    case DM_Erase:
        Pen = Pen_Background;
        SetDrMd(Windows[Id_Active_Window].RastPort, JAM2);
        Windows[Id_Active_Window].RastPort->Mask    = 0xff;
	break;

    case DM_Plane:
    	Pen = Pen_Plane;
    	Windows[Id_Active_Window].RastPort->Mask    = 0x08;
    	SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
	break;

    } /* switch */

    SetAPen(Windows[Id_Active_Window].RastPort, Pen);


	/* The eight corners:	*/
    Vec3Scalar(Corners[0], = , Min_Pos[0], Min_Pos[1], Min_Pos[2]);
    Vec3Scalar(Corners[1], = , Max_Pos[0], Min_Pos[1], Min_Pos[2]);
    Vec3Scalar(Corners[2], = , Min_Pos[0], Max_Pos[1], Min_Pos[2]);
    Vec3Scalar(Corners[3], = , Max_Pos[0], Max_Pos[1], Min_Pos[2]);
    Vec3Scalar(Corners[4], = , Min_Pos[0], Min_Pos[1], Max_Pos[2]);
    Vec3Scalar(Corners[5], = , Max_Pos[0], Min_Pos[1], Max_Pos[2]);
    Vec3Scalar(Corners[6], = , Min_Pos[0], Max_Pos[1], Max_Pos[2]);
    Vec3Scalar(Corners[7], = , Max_Pos[0], Max_Pos[1], Max_Pos[2]);

    if (R_Vector != NULL) {

         Compute_Rotation_Matrix(R_Matrix, R_Vector);

	for (i = 0; i < 8; i++) {

	    Vec3Op(Corners[i], =, Corners[i], -, Origin);
            Matrix_MultV(Tmp, R_Matrix, Corners[i]);
	    Vec3Op(Corners[i], =, Tmp, +, Origin);

    	} /* for */

    } /* if */

    if (What & What_K3)
	for (i = 0; i < 8; i++)
            World_To_Screen(Corners[i], &X[i][0], &Y[i][0], 
					&X[i][1], &Y[i][1], 
					&X[i][2], &Y[i][2]);
    if (What & What_KP)
	for (i = 0; i < 8; i++)
            World_To_Persp(Corners[i], &X[i][3], &Y[i][3]);


    if (What & What_KX) {


	ViewClipDrawLine(V_X, X[0][0], Y[0][0], X[1][0], Y[1][0]);
	ViewClipDrawLine(V_X, X[1][0], Y[1][0], X[3][0], Y[3][0]);
	ViewClipDrawLine(V_X, X[3][0], Y[3][0], X[2][0], Y[2][0]);
	ViewClipDrawLine(V_X, X[2][0], Y[2][0], X[0][0], Y[0][0]);

	ViewClipDrawLine(V_X, X[4][0], Y[4][0], X[5][0], Y[5][0]);
	ViewClipDrawLine(V_X, X[5][0], Y[5][0], X[7][0], Y[7][0]);
	ViewClipDrawLine(V_X, X[7][0], Y[7][0], X[6][0], Y[6][0]);
	ViewClipDrawLine(V_X, X[6][0], Y[6][0], X[4][0], Y[4][0]);

	ViewClipDrawLine(V_X, X[0][0], Y[0][0], X[4][0], Y[4][0]);
	ViewClipDrawLine(V_X, X[1][0], Y[1][0], X[5][0], Y[5][0]);
	ViewClipDrawLine(V_X, X[2][0], Y[2][0], X[6][0], Y[6][0]);
	ViewClipDrawLine(V_X, X[3][0], Y[3][0], X[7][0], Y[7][0]);

    } /* if */

    if (What & What_KY) {

	ViewClipDrawLine(V_Y, X[0][1], Y[0][1], X[1][1], Y[1][1]);
	ViewClipDrawLine(V_Y, X[1][1], Y[1][1], X[3][1], Y[3][1]);
	ViewClipDrawLine(V_Y, X[3][1], Y[3][1], X[2][1], Y[2][1]);
	ViewClipDrawLine(V_Y, X[2][1], Y[2][1], X[0][1], Y[0][1]);

	ViewClipDrawLine(V_Y, X[4][1], Y[4][1], X[5][1], Y[5][1]);
	ViewClipDrawLine(V_Y, X[5][1], Y[5][1], X[7][1], Y[7][1]);
	ViewClipDrawLine(V_Y, X[7][1], Y[7][1], X[6][1], Y[6][1]);
	ViewClipDrawLine(V_Y, X[6][1], Y[6][1], X[4][1], Y[4][1]);

	ViewClipDrawLine(V_Y, X[0][1], Y[0][1], X[4][1], Y[4][1]);
	ViewClipDrawLine(V_Y, X[1][1], Y[1][1], X[5][1], Y[5][1]);
	ViewClipDrawLine(V_Y, X[2][1], Y[2][1], X[6][1], Y[6][1]);
	ViewClipDrawLine(V_Y, X[3][1], Y[3][1], X[7][1], Y[7][1]);

    } /* if */

    if (What & What_KZ) {

	ViewClipDrawLine(V_Z, X[0][2], Y[0][2], X[1][2], Y[1][2]);
	ViewClipDrawLine(V_Z, X[1][2], Y[1][2], X[3][2], Y[3][2]);
	ViewClipDrawLine(V_Z, X[3][2], Y[3][2], X[2][2], Y[2][2]);
	ViewClipDrawLine(V_Z, X[2][2], Y[2][2], X[0][2], Y[0][2]);

	ViewClipDrawLine(V_Z, X[4][2], Y[4][2], X[5][2], Y[5][2]);
	ViewClipDrawLine(V_Z, X[5][2], Y[5][2], X[7][2], Y[7][2]);
	ViewClipDrawLine(V_Z, X[7][2], Y[7][2], X[6][2], Y[6][2]);
	ViewClipDrawLine(V_Z, X[6][2], Y[6][2], X[4][2], Y[4][2]);

	ViewClipDrawLine(V_Z, X[0][2], Y[0][2], X[4][2], Y[4][2]);
	ViewClipDrawLine(V_Z, X[1][2], Y[1][2], X[5][2], Y[5][2]);
	ViewClipDrawLine(V_Z, X[2][2], Y[2][2], X[6][2], Y[6][2]);
	ViewClipDrawLine(V_Z, X[3][2], Y[3][2], X[7][2], Y[7][2]);

    } /* if */

    if (What & What_KP) {


	ViewClipDrawLine(V_P, X[0][3], Y[0][3], X[1][3], Y[1][3]);
	ViewClipDrawLine(V_P, X[1][3], Y[1][3], X[3][3], Y[3][3]);
	ViewClipDrawLine(V_P, X[3][3], Y[3][3], X[2][3], Y[2][3]);
	ViewClipDrawLine(V_P, X[2][3], Y[2][3], X[0][3], Y[0][3]);

	ViewClipDrawLine(V_P, X[4][3], Y[4][3], X[5][3], Y[5][3]);
	ViewClipDrawLine(V_P, X[5][3], Y[5][3], X[7][3], Y[7][3]);
	ViewClipDrawLine(V_P, X[7][3], Y[7][3], X[6][3], Y[6][3]);
	ViewClipDrawLine(V_P, X[6][3], Y[6][3], X[4][3], Y[4][3]);

	ViewClipDrawLine(V_P, X[0][3], Y[0][3], X[4][3], Y[4][3]);
	ViewClipDrawLine(V_P, X[1][3], Y[1][3], X[5][3], Y[5][3]);
	ViewClipDrawLine(V_P, X[2][3], Y[2][3], X[6][3], Y[6][3]);
	ViewClipDrawLine(V_P, X[3][3], Y[3][3], X[7][3], Y[7][3]);

    } /* if */

} /* Draw_Box */

void Draw_Knot(Spline_T *Spline, Knot_T *Knot, Draw_Mode_T Mode, long What)
/************************************************************************/
/*                                                                      */
/* Draw a knot.								*/
/* Don't drow it in DM_Plane mode.					*/
/*                                                                      */
/************************************************************************/
{
    short 	Xx, Yx, Xy, Yy, Xz, Yz, Xp, Yp;
    int	 	Point_Id;
    int		Pen;

    What &= What_Mask;

    if (Spline == NULL || Knot == NULL) return;

    Point_Id = Knot->Point_Id;

    if (Is_Hidden(Points[Point_Id])) return;

    switch (Mode) {

    case DM_Normal:
	if (Point_Id == Select_Point_Id)        Pen = Pen_Knot_Primary;
        else if (Is_Selected(Points[Point_Id])) Pen = Pen_Knot_Selected;
        else			       	        Pen = Pen_Knot;
        SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
        Windows[Id_Active_Window].RastPort->Mask    = 0xff;
	break;

    case DM_Erase:
        Pen = Pen_Background;
        SetDrMd(Windows[Id_Active_Window].RastPort, JAM2);
        Windows[Id_Active_Window].RastPort->Mask    = 0xff;
	break;

    case DM_Plane:
	return;

    } /* switch */

    SetAPen(Windows[Id_Active_Window].RastPort, Pen);


    if (What & What_K3)
        World_To_Screen(Points[Point_Id].Pos, &Xx, &Yx, &Xy, &Yy, &Xz, &Yz);
    if (What & What_KP)
        World_To_Persp(Points[Point_Id].Pos,  &Xp, &Yp);

#define DRAW_DOT
#ifdef DRAW_DOT

	/* Draw knots as dots	*/
    if (What & What_KX) {

		/* Clipping */
	if (Views[V_X].X_Min < Xx && Views[V_X].Y_Min < Yx &&
	    Views[V_X].X_Max > Xx && Views[V_X].Y_Max > Yx) {


	    WritePixel(Windows[Id_Active_Window].RastPort, Xx, Yx);

	} /* if */
    } /* if */

    if (What & What_KY) {
	if (Views[V_Y].X_Min < Xy && Views[V_Y].Y_Min < Yy &&
	    Views[V_Y].X_Max > Xy && Views[V_Y].Y_Max > Yy) {

	    WritePixel(Windows[Id_Active_Window].RastPort, Xy, Yy);

	} /* if */
    } /* if */

    if (What & What_KZ) {
	if (Views[V_Z].X_Min < Xz && Views[V_Z].Y_Min < Yz &&
	    Views[V_Z].X_Max > Xz && Views[V_Z].Y_Max > Yz) {

	    WritePixel(Windows[Id_Active_Window].RastPort, Xz, Yz);

	} /* if */

    } /* if */

    if (What & What_KP) {

	if (Views[V_P].X_Min < Xp && Views[V_P].Y_Min < Yp &&
	    Views[V_P].X_Max > Xp && Views[V_P].Y_Max > Yp) {

	    WritePixel(Windows[Id_Active_Window].RastPort, Xp, Yp);

	} /* if */

    } /* if */

#else

	/* Draw knots as small crosses	*/
    if (What & What_KX) {


		/* Clipping */
	if (Views[V_X].X_Min < Xx - 2 && Views[V_X].Y_Min < Yx - 2 &&
	    Views[V_X].X_Max > Xx + 2 && Views[V_X].Y_Max > Yx + 2) {

	    Move(Windows[Id_Active_Window].RastPort, Xx - 2, Yx);
	    Draw(Windows[Id_Active_Window].RastPort, Xx + 2, Yx);
	    Move(Windows[Id_Active_Window].RastPort, Xx    , Yx - 2);
	    Draw(Windows[Id_Active_Window].RastPort, Xx    , Yx + 2);

	} /* if */
    } /* if */

    if (What & What_KY) {
	if (Views[V_Y].X_Min < Xy - 2 && Views[V_Y].Y_Min < Yy - 2 &&
	    Views[V_Y].X_Max > Xy + 2 && Views[V_Y].Y_Max > Yy + 2) {

	    Move(Windows[Id_Active_Window].RastPort, Xy - 2, Yy);
	    Draw(Windows[Id_Active_Window].RastPort, Xy + 2, Yy);
	    Move(Windows[Id_Active_Window].RastPort, Xy    , Yy - 2);
	    Draw(Windows[Id_Active_Window].RastPort, Xy    , Yy + 2);

	} /* if */
    } /* if */

    if (What & What_KZ) {
	if (Views[V_Z].X_Min < Xz - 2 && Views[V_Z].Y_Min < Yz - 2 &&
	    Views[V_Z].X_Max > Xz + 2 && Views[V_Z].Y_Max > Yz + 2) {

	    Move(Windows[Id_Active_Window].RastPort, Xz - 2, Yz);
	    Draw(Windows[Id_Active_Window].RastPort, Xz + 2, Yz);
	    Move(Windows[Id_Active_Window].RastPort, Xz    , Yz - 2);
	    Draw(Windows[Id_Active_Window].RastPort, Xz    , Yz + 2);

	} /* if */

    } /* if */

    if (What & What_KP) {

	if (Views[V_P].X_Min < Xp - 2 && Views[V_P].Y_Min < Yp - 2 &&
	    Views[V_P].X_Max > Xp + 2 && Views[V_P].Y_Max > Yp + 2) {

	    Move(Windows[Id_Active_Window].RastPort, Xp - 2, Yp);
	    Draw(Windows[Id_Active_Window].RastPort, Xp + 2, Yp);
	    Move(Windows[Id_Active_Window].RastPort, Xp    , Yp - 2);
	    Draw(Windows[Id_Active_Window].RastPort, Xp    , Yp + 2);

	} /* if */

    } /* if */
#endif

} /* Draw_Knot */


void Draw_Knots(Draw_Mode_T Mode, long What)
/************************************************************************/
/*                                                                      */
/* Draw all knots.							*/
/*                                                                      */
/************************************************************************/
{
    int	     i;
    Spline_T *Spline;
    Knot_T   *Knot;

    What &= What_Mask;

    if ( (What & What_K) == 0) return;

    for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {

        if (Spline->Nbr_Knots < 1) continue;

        for (i = 0, Knot = Spline->First; 
	     i < Spline->Nbr_Knots; i++, Knot = Knot->Next) 
				Draw_Knot(Spline, Knot, Mode, What);

    } /* for */

} /* Draw_Knots */

void Draw_All(long What)
/************************************************************************/
/*                                                                      */
/* Draw all splines, knots, grid and the origin.			*/
/*                                                                      */
/************************************************************************/
{
    Set_Pointer(TRUE);

    Draw_Grid(What);
    Draw_Splines(DM_Normal, What);
    Draw_Origin(DM_Normal, What);

    Set_Pointer(FALSE);

} /* Draw_All */
