/*

                              DISCLAIMER
                              ==========

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   

    If the software is modified by someone else and passed on, we, the authors
    want its recipients to know that what they have is not the original, so
    that any problems introduced by others will not reflect on the original
    authors' reputations.
*/                                            

/* Include files
*/
#include <stdio.h>
#include <phigs.h>
#include <phigs_defs.h>
#include <phigs_msgs.h>

#include "ptk.h"

/* Constants
*/
const matrix_label = 1;    

/* Globals
*/
   Pwstype          wstype;
   Pint             connid;                     
   PPlightsrcbundl  lightrec;
   Pint             nact;
   Pint             act[1];
   Pint             ndeact;
   Pint             deact[1];
   int              item,menu,err,indx;
   PR_nurb          nurb_rec,circle,sqr,tri;
   PR_nurb          nurb_rec2;
   Pmatrix3         mm,nurb_mat;
   float            lastscale, scalefac;
   float            angleX, angleY, angleZ;
   float            dax,day,daz;
   boolean          ldodax;
   boolean          lscale;               
   float            LastX, LastY, LastZ;
   boolean          shaded, cont_poly, wireframe, rotate_nurb, any_nurb;
   boolean          ltessalate, quit_demo;
   int              devstart;
   float            MaxDevX, MaxDevY;

   FILE             *fd;
   char             fname[256];
   char             *st1;
   Pint             curveapproxcrit;
   Pint             surfaceapproxcrit;
   PPapprox_value   approxval[2];
   int              istatus;

/* Function Prototypes
*/
void Initcommandmenu( void );
void InitPrimitivemenu( void );
void InitialiseMenu( void );
void InitValuators( void );
void nurb_rotate( void );
void Create_nurb_struct( void );
int get_menu_choice ( int *menu_number, int *choice_num );
void primitive( void );
int getstringinput( char *prompt, char *string );
void Pstart1( void );
void inqmaxdevicecoords(Pint wsid, Pfloat *maxdevx, Pfloat* maxdevy);

void set_printer(void);

                                                
main()
{
boolean printer_set=FALSE;
int picture_counter=0;
char file_name[20];

   /* Start of main body 
   */

   /* Initialise 
   */
   nrb_initialise();

   nrb_circle( &circle );
   nrb_extrude( &circle, ptk_vector3(0.0,0.0,2.0), &nurb_rec, &err);

   any_nurb    = FALSE ;
   rotate_nurb = FALSE ;
   quit_demo   = FALSE ;
   wireframe   = TRUE;
   cont_poly   = TRUE ;
   angleX      = 0.0;
   angleY      = 0.0;
   angleZ      = 0.0;
   LastZ       = 0.0;
   LastX       = angleX + 1.0;
   LastY       = 0.0;
   scalefac    = 0.1;
   lastscale   = scalefac;
   dax         = 1.0;
   day         = 2.0;

   curveapproxcrit   = PPCURV_CONST_SUBDIV_KNOTS;
   surfaceapproxcrit = PPSURF_CONST_SUBDIV_KNOTS;

   approxval[0].ivalue = 5;
   approxval[1].ivalue = 5;
   ltessalate = FALSE;
   ldodax     = TRUE;
   shaded     = FALSE ;

   /* create a light source - white light along the z-axis
   */      
   lightrec.type = PPLIGHT_TYPE_INFINITE;

   lightrec.record.infinite.colour_type = PCM_RGB;

   lightrec.record.infinite.colour_value.direct_colour.rgb.r = 1.0;
   lightrec.record.infinite.colour_value.direct_colour.rgb.g = 1.0;
   lightrec.record.infinite.colour_value.direct_colour.rgb.b = 1.0;

   lightrec.record.infinite.direction.x = -1.0;
   lightrec.record.infinite.direction.y = -1.0;
   lightrec.record.infinite.direction.z = -1.0;


   /* Start PHIGS up
   */
   popenphigs( 0,0 );

   /* Start the menus and the valuator devices
   */
   Pstart1();

   /* main loop 
   */
   while( ! quit_demo )
   {
      /* check for menu event 
      */
      get_menu_choice ( &menu,&item );

      /* Take appropiate action on each menu choice
      */
      switch( menu )
      {
         case 1 :
         switch( item ) 
         { 
            case 1 : 

               /* Quit
               */
               quit_demo = TRUE ;
               break; 

            case 2 : 

               /* capture screen to ddif file and exit
               */                
               getstringinput("File name(.ddif): ",fname);
               /* Pclosews(1);*/

               popenws( 2, fname, 250);
               ppsetlightsrcrep (2, 1, &lightrec);   
               ppoststruct( 2, 1, 0 );
               pclosews( 2 );
               quit_demo=TRUE;
               break;

            case 3 : 

               nrb_stats(stdout); 
               break;

            case 4 : 

               /* Nurb Dump 
               */
               nrb_dump(stdout, &nurb_rec);
               break;

            case 5 : 

               /* rotation to zero 
               */
               angleX = 0.0;
               angleY = 0.0;
               angleZ = 0.0;
               rotate_nurb = FALSE;
               Initcommandmenu();
               InitValuators();
               nurb_rotate();
               break;

             case 6 :

               /*  elevate 
               */
               if(  nurb_rec.pf_v.pf_nt > 1 )
               {
                  nrb_elevate( TRUE, &nurb_rec, &nurb_rec2 );
                  nrb_elevate( TRUE, &nurb_rec2, &nurb_rec );
               }
               else
               {
                  nrb_elevate( FALSE, &nurb_rec, &nurb_rec2 );
                  nrb_copy( &nurb_rec2, &nurb_rec);
               }
               Create_nurb_struct() ;
               break;

            case 7 :

               /* Big Knot sequence 
               */
               nrb_copy( &nurb_rec, &nurb_rec2 );
               nrb_deallocateknots( &nurb_rec.pf_u );

               nurb_rec.pf_u.pf_nt = 20;
               nurb_rec.pf_u.pf_n = nurb_rec.pf_u.pf_nt - nurb_rec.pf_u.pf_k;

               nrb_makeknots( 0.0, 1.0, &nurb_rec.pf_u );

               nrb_unionknots( &nurb_rec2.pf_u, &nurb_rec.pf_u, &nurb_rec.pf_u);
               nrb_osloc( &nurb_rec2, &nurb_rec);
               nrb_transpose( &nurb_rec );
               Create_nurb_struct() ;
               break;

            case 8 :
 
               /* Transpose the nurb 
               */
               nrb_transpose( &nurb_rec );
               Create_nurb_struct() ;
               break;

            case 9 :
 
               /* wireframe 
               */
               if( wireframe == TRUE )
                  wireframe = FALSE;
               else
                  wireframe = TRUE;

               Initcommandmenu();
               Create_nurb_struct() ;
               break;

            case 10 : 

               /* shaded 
               */
               if( shaded == TRUE )
                  shaded = FALSE;
               else
                  shaded = TRUE;

               Initcommandmenu();
               Create_nurb_struct() ;
               break;

            case 11 : 

               /* control polygon 
               */
               if( cont_poly == TRUE )
                  cont_poly = FALSE;
               else
                  cont_poly = TRUE;
               Initcommandmenu();
               Create_nurb_struct() ;
               break;

            case 12 :
   
               /* rotate on/off 
               * rotate_nurb = NOT rotate_nurb ;
               */
               Initcommandmenu();
               InitValuators();
               break;
   
            case 13 :

               /* Tessalate 
               */
               if( ltessalate == TRUE )
                  ltessalate = FALSE;
               else
                  ltessalate = TRUE;
               Initcommandmenu();
               Create_nurb_struct();
               break;

            case 14 : 

               /* Swap Dangle X and Dangle Y 
               */
               if( ldodax == TRUE )
                  ldodax = FALSE;
               else
                  ldodax = TRUE;

               Initcommandmenu();
               InitValuators();
               break;

            case 15 :

               /* Curve/Surface Approximation Vaule 
               */
               istatus = TRUE;
               while( istatus != FALSE )
               {
                  getstringinput("Curve ApproxCrit(Wkstn,Const,Knots,Metric,Chordal): ",fname);
                  istatus = readfile( fname, &curveapproxcrit );
               }
               istatus = TRUE;
               while( istatus != FALSE )
               {
                  getstringinput("Surface ApproxCrit(Wkstn,Const,Knots,Metric,Planar): ",fname);
                  istatus = readfile( fname, &surfaceapproxcrit );
               }
               istatus = TRUE;
               while( istatus != FALSE )
               {
                  getstringinput("Approximation value: ",fname);
                  istatus = readfile( fname, approxval[0].ivalue );
               }
               Create_nurb_struct();
               break;
            case 16:

               sprintf(file_name,"POST%d.PS",picture_counter++);

               /* Hardcopy
               */
               popenws ( 2, file_name, 61);

               if(!printer_set)
               {
                  set_printer();
                  printer_set=TRUE;
               }

               ppoststruct( 2,1, 1.0 );

/*               predrawallstruct( 2, PALWAYS );  */
               pclosews( 2);

               break;

            default :
               break;
            }    /*SWITCH*/
            break;

         case 2 :

            /* Different object selected
            */ 
            primitive();
            Create_nurb_struct();
            break;

         case 3 :

            /* Rotation
            */ 
            nurb_rotate();
            break;

         default :
            break;
      }

      /* Check the valuators for input
      */
      psampleval( 1, 1, &angleX );
      psampleval( 1, 2, &angleY );
      psampleval( 1, 3, &angleZ );
      psampleval( 1, 4, &scalefac);

      /*if( ldodax )
         psampleval( 1, 4, &dax );
      else                 
         psampleval( 1, 4, &day );
      */

      /* Rotate the nurb ?
      */
      if( rotate_nurb )
      {
         angleX = angleX + dax ;
         angleY = angleY + day ;
      }

      if(( LastX != angleX ) || ( LastY != angleY )  || 
         ( LastZ != angleZ ) || ( lastscale != scalefac ))
         nurb_rotate();

   } /* of while */

   /* Close down PHIGS
   */   
   pclosews( 1 );
   pclosephigs() ;
}  


void Initcommandmenu( void )
{   
Plimit3     commandmenubounds;
Pchoicerec  commandmenunames;
char        *choices[16];

   /* Make sure that the device is in request mode
   */
   psetchoicemode( 1, devstart, PREQUEST, PES_ECHO);

   /* Initialise the menu options
   */
   commandmenunames.choicepet1_datarec.number = 16;
   commandmenunames.choicepet1_datarec.title_string = "NURB Demonstrator";

   choices[0] = "QUIT";
   choices[1] = "Capture Screen";
   choices[2] = "Statistics";
   choices[3] = "Dump NURB";
   choices[4] = "Reset Rotation";
   choices[5] = "Elevate";
   choices[6] = "Refine Knot Vector";
   choices[7] = "Transpose";

   /* Test to see if the menus have the correct entries
   */
   if( wireframe )
      choices[8] = "Wireframe Off";
   else
      choices[8] = "Wireframe On";

   if( shaded )
      choices[9] = "Shading Off";
   else
      choices[9] = "Shading On";

   if( cont_poly )
      choices[10] = "Polygon Off";
   else
      choices[10] = "Polygon On";

   if( rotate_nurb )
      choices[11] = "Rotate Off";
   else
      choices[11] = "Rotate On";
   
   if( ltessalate )
      choices[12] = "Tessalate Off";
   else
      choices[12] = "Tessalate On";

   if( ldodax )
      choices[13] = "Specify DaY";
   else
      choices[13] = "Specify DaX";
    
   choices[14] = "Approx Crit/Value";
   choices[15] = "Hardcopy";

   commandmenunames.choicepet1_datarec.strings = choices;

   /* Initialise the menu echo area
   */
   commandmenubounds.xmin = MaxDevX - 0.12;
   commandmenubounds.xmax = MaxDevX - 0.06; 
   commandmenubounds.ymin = MaxDevY - 0.15;
   commandmenubounds.ymax = MaxDevY; 
   commandmenubounds.zmin = 0.0;
   commandmenubounds.zmax = 0.0;

   /* Initialise the menu 
   */
   pinitchoice3( 1,devstart,PCH_NOCHOICE,0,1,
                 &commandmenubounds, &commandmenunames );
   psetchoicemode( 1 ,devstart, PEVENT, PES_ECHO );

};

/* Initialise the Objects menu
*/
void InitPrimitivemenu( void )
{
Plimit3    PrimMenuBounds ;
Pchoicerec PrimMenuNames  ;
char        *choices[14];

   /* Make sure that the device is in request mode
   */
   psetchoicemode( 1, devstart+1, PREQUEST, PES_ECHO );    

   /* Initialise the menu options
   */
   choices[0]  = "Torus     ";
   choices[1]  = "Cylinder";
   choices[2]  = "Cone";
   choices[3]  = "Sphere";
   choices[4]  = "Cuboid";
   choices[5]  = "Tetrahedron";
   choices[6]  = "Triangular Prism";
   choices[7]  = "Pyramid";
   choices[8]  = "Vase";
   choices[9]  = "Circle";
   choices[10] = "Square";
   choices[11] = "Triangle";
   choices[12] = "Ruled Surface";
   choices[13] = "Read file";

   PrimMenuNames.choicepet1_datarec.strings = choices;

   PrimMenuNames.choicepet1_datarec.number = 14;
   PrimMenuNames.choicepet1_datarec.title_string = "NURB Primitives";

   /* Initialise the echo area
   */
   PrimMenuBounds.xmin = MaxDevX - 0.12;
   PrimMenuBounds.xmax = MaxDevX - 0.06;
   PrimMenuBounds.ymin = 0.0;
   PrimMenuBounds.ymax = MaxDevY - 0.15 - 0.07; 
   PrimMenuBounds.zmin = 0.0;
   PrimMenuBounds.zmax = 0.0; 

   /* Initialise the menu
   */
   pinitchoice3( 1, devstart+1, PCH_NOCHOICE, 0, 1,
                 &PrimMenuBounds, &PrimMenuNames);

   psetchoicemode( 1, devstart+1, PEVENT, PES_ECHO);    

}

/* set up the menu
*/
void InitialiseMenu( void )
{
   devstart = 6;

   Initcommandmenu();
   InitPrimitivemenu();
}

/* Initialise the valuator devices
*/
void InitValuators( void )
{
Pfloat   Value, initvalue;
Pvalrec  ValDataRec;
Plimit3  ValuatorArea;
float    highv, lowv;
Pint     promptecho;
Pfloat   quarter;

   /* Make sure that all the valuator devices are in request mode
   */
   psetvalmode( 1, 1, PREQUEST, PES_ECHO );
   psetvalmode( 1, 2, PREQUEST, PES_ECHO ); 
   psetvalmode( 1, 3, PREQUEST, PES_ECHO );
   psetvalmode( 1, 4, PREQUEST, PES_ECHO );

   /* Set the prompt echo type
   */
   promptecho = 2;

   ValDataRec.valpet2_datarec.high = 360.0;
   ValDataRec.valpet2_datarec.low  = -360.0;
   ValDataRec.valpet2_datarec.title_string = "Rotate X-Axis";
   initvalue = angleX;

   /* Divide the "y" space up into four and place the valuators 
   * in the quarters
   */
   quarter = MaxDevY / 4.0;

   ValuatorArea.xmin = MaxDevX - 0.05;
   ValuatorArea.xmax = MaxDevX;
   ValuatorArea.ymin = 0.0;
   ValuatorArea.ymax = quarter;
   ValuatorArea.zmin = 0.0;
   ValuatorArea.zmax = 0.0;

   pinitval3( 1, 1, initvalue, promptecho, &ValuatorArea, &ValDataRec );

   ValDataRec.valpet2_datarec.high = 360.0;
   ValDataRec.valpet2_datarec.low  = -360.0;
   ValDataRec.valpet2_datarec.title_string = "Rotate Y-Axis";
   initvalue = angleY;

   ValuatorArea.xmin = MaxDevX - 0.05;
   ValuatorArea.xmax = MaxDevX;
   ValuatorArea.ymin = quarter;
   ValuatorArea.ymax = 2.0 * quarter;
   ValuatorArea.zmin = 0.0;
   ValuatorArea.zmax = 0.0;

   pinitval3( 1, 2, initvalue, promptecho, &ValuatorArea, &ValDataRec);

   ValDataRec.valpet2_datarec.high = 360.0;
   ValDataRec.valpet2_datarec.low = -360.0;
   ValDataRec.valpet2_datarec.title_string = "Rotate Z-Axis";
   initvalue = angleZ;

   ValuatorArea.xmin = MaxDevX - 0.05;
   ValuatorArea.xmax = MaxDevX;
   ValuatorArea.ymin = 2.0 * quarter;
   ValuatorArea.ymax = 3.0 * quarter;
   ValuatorArea.zmin = 0.0;
   ValuatorArea.zmax = 0.0;

   pinitval3( 1, 3, initvalue, promptecho, &ValuatorArea, &ValDataRec);

   ValDataRec.valpet2_datarec.high = 1.5;
   ValDataRec.valpet2_datarec.low  = 0.0;
   ValDataRec.valpet2_datarec.title_string = "Scaling";
   initvalue = scalefac;

   ValuatorArea.xmin = MaxDevX - 0.05;
   ValuatorArea.xmax = MaxDevX;
   ValuatorArea.ymin = 3.0 * quarter;
   ValuatorArea.ymax = MaxDevY;
   ValuatorArea.zmin = 0.0;
   ValuatorArea.zmax = 0.0;

   pinitval3(1,4,initvalue, promptecho, &ValuatorArea, &ValDataRec);

   psetvalmode( 1, 1, PSAMPLE, PES_ECHO);
   psetvalmode( 1, 2, PSAMPLE, PES_ECHO);
   psetvalmode( 1, 3, PSAMPLE, PES_ECHO);
   psetvalmode( 1, 4, PSAMPLE, PES_ECHO);

}

/* Create a structure containing the nurb
*/
void Create_nurb_struct( void )
{
char buffer[256];
int  req_size;
int error_status;
Pvector3 point;

  if( ! any_nurb )
    any_nurb = TRUE;
  else
    pdelstruct( 1 );

    popenstruct (1);
    plabel( matrix_label );
    ptk_unitmatrix3 ( nurb_mat );
    point = ptk_vector3(scalefac,scalefac,scalefac);
    ptk_scale3 (&point, PREPLACE, nurb_mat );

    ptk_rotate3 ( angleZ, 3, PPOSTCONCATENATE , nurb_mat ); 
    ptk_rotate3 ( angleY, 2, PPOSTCONCATENATE , nurb_mat ); 
    ptk_rotate3 ( angleX, 1, PPOSTCONCATENATE , nurb_mat ); 
    point = ptk_vector3(0.5,0.5,0.5);
    ptk_shift3 (&point, PPOSTCONCATENATE , nurb_mat );
    psetglobaltran3 ( nurb_mat );

    if(  shaded )
    {                                                
	psetintstyle( PSOLID );
        psetintcolourind( 7 );

        /* remove hidden lines and surfaces, and fill
        */
        psethlhsrid( PPHLHSR_INDEX_NONE ); /* This could be wrong */

        ppsetintshadmethod( PPSHADE_NORMAL);
        ppsetintlightmethod( PPLIGHTING_DIFFUSE );

       /* inquire ws type and set appropraite HLHSR mode 
 	 1 - DECWindows,	2 - 3540
       */  

       pinqwsconntype( 1, 256, &error_status, buffer,
		   &connid, &req_size, &wstype);

      if(  wstype == 211 )
         psethlhsrmode( 1, PPHLHSR_MODE_NONE );
      else                
         psethlhsrmode( 1, PPHLHSR_MODE_PAINTERS );

      /* switch on the lights
      */
      nact = 1;
      act[0]  = 1;

      ndeact = 0;
      deact[0] = 0;

      ppsetlightsrcstate( nact, act, ndeact, deact );

    } /* of shaded */

    psetlinecolourind( 2 );

    if(  cont_poly )
      nrb_drawsnet( &nurb_rec );

    psetlinecolourind( 1 );

    if(  wireframe || shaded )
    {
      if( curveapproxcrit != PPCURV_IMP_DEP )
         ppsetcurvapproxcriteria( curveapproxcrit, approxval );
      if( surfaceapproxcrit != PPSURF_IMP_DEP )
         ppsetsurfapproxcriteria( surfaceapproxcrit, approxval );
      if( ltessalate)
         nrb_draws( &nurb_rec);
      else
         nrb_phigsplus( &nurb_rec );
    }
  pclosestruct();

  ppoststruct( 1,1, 1.0 );

  predrawallstruct( 1, PALWAYS );

} /* of create_nurb_struct */

/* Get input from the menus, if none then returns 0 
*/
int get_menu_choice ( int *menu_number, int *choice_num )
{

Pchoice      objectstatus;
int          EventWsid,EventDev;
Pevent       EventClass;


  objectstatus.status = PCH_NOCHOICE;
  EventClass.class = PI_NONE;

  *choice_num = 0;
  *menu_number = 0;
  pawaitevent( 0.001, &EventClass );

  switch( EventClass.class )
  {
  
   case PI_CHOICE : 
      pgetchoice( &objectstatus );
      if(  objectstatus.status != PCH_NOCHOICE )
      { 
         *menu_number = EventClass.dev - devstart + 1;
         *choice_num = objectstatus.choice;
      }
      break;

   case PI_VALUATOR : 
      if(  EventClass.dev == 1 )
         pgetval( &angleX );
      else if(  EventClass.dev == 2 )
         pgetval( &angleY );
      else if(  EventClass.dev == 3 ) 
         pgetval( &angleZ );
      else
         pgetval( &scalefac );
     
      menu = 3;
      break;
  
   default :
      break;
   
  } /* switch */

} /* of get_menu_choice */

/* rotate the nurb about the x or y axis 1 degree
*/
void nurb_rotate( void )
{
Pvector3 point;

   if( angleX > 360 ) angleX = 0;
   if( angleX < -360) angleX = 0;
   if( angleY > 360 ) angleY = 0;
   if( angleY < -360) angleY = 0;
   if( angleZ > 360 ) angleZ = 0;
   if( angleZ < -360) angleZ = 0;

   LastX = angleX;
   LastY = angleY;
   LastZ = angleZ;
   lastscale = scalefac;

   popenstruct( 1 );
   psetelemptr( 0 );
   psetelemptrlabel( matrix_label );
   poffsetelemptr( 1 );
      
   point = ptk_vector3(scalefac,scalefac,scalefac);
   ptk_scale3 (&point, PREPLACE, nurb_mat );
                                   
   ptk_rotate3( angleZ, 3, PPOSTCONCATENATE , nurb_mat ); 
   ptk_rotate3( angleY, 2, PPOSTCONCATENATE , nurb_mat ); 
   ptk_rotate3( angleX, 1, PPOSTCONCATENATE , nurb_mat ); 

   point = ptk_vector3(0.5,0.5,0.5);
   ptk_shift3(&point, PPOSTCONCATENATE , nurb_mat );

   pseteditmode( PEDIT_REPLACE );
   psetglobaltran3 ( nurb_mat );
   pclosestruct() ;  
   predrawallstruct( 1, PALWAYS );         
   pseteditmode( PEDIT_INSERT );
} /* of nurb_rotate */

/* Test to see which object was chosen to be displayed
*/
void primitive( void )
{
Pvector3 point;

   switch( item )
   {
      case 1 :
         /* torus 
         */
         nrb_torus( &nurb_rec ) ;  
         break;

      case 2 :

         /* cylinder 
         */
         nrb_circle( &circle );
         nrb_extrude( &circle, ptk_vector3(0.0,0.0,2.0), &nurb_rec, &err);
         break;
      case 3 : 

         /* cone 
         */
   	 nrb_circle( &circle ) ;
	 nrb_extrude( &circle, ptk_vector3 (0.0,0.0,2.0), &nurb_rec, &err );

         /* to make a cone we will force all x and y coordinates
	    to be the same point. 
         */           
  	 for( indx = 0 ; indx < nurb_rec.pf_u.pf_n ; indx++ )
  	 {
     	   nurb_rec.pf_ppp->pts[indx].x =  0.0 ; 
     	   nurb_rec.pf_ppp->pts[indx].y =  0.0 ;
         }                    
         break;

      case 4 : 

         /* sphere 
         */ 
         nrb_sphere( &nurb_rec );
         break;

      case 5 : 

         /* cuboid 
         */
 	 nrb_square( &sqr );
	 nrb_extrude( &sqr, ptk_vector3 (0.0,0.0,2.0), &nurb_rec, &err  );
         break;

      case 6 : 

         /* tetrahedron 
         */ 
         nrb_triangle( &tri );
	 nrb_extrude( &tri, ptk_vector3 (0.0,0.0,2.0), &nurb_rec, &err  );      
	 for( indx = 0 ; indx < nurb_rec.pf_u.pf_n  ; indx++ )    
  	 {
     	    nurb_rec.pf_ppp->pts[indx].x =  0.0 ; 
     	    nurb_rec.pf_ppp->pts[indx].y =  -0.67 ;
         }           
         break;

      case 7 : 

         /* tri prism 
         */ 
         nrb_triangle( &tri );
	 nrb_extrude( &tri, ptk_vector3 (0.0,0.0,2.0), &nurb_rec, &err  );
         break;

      case 8 : 

         /* pyramid 
         */
         nrb_square( &sqr );
         nrb_extrude( &sqr, ptk_vector3 (0.0,0.0,2.0), &nurb_rec, &err  );

	 /* to make a cone we will force all x and y coordinates
	 * to be the same point. 
         */   
	 for( indx = 0 ; indx < nurb_rec.pf_u.pf_n ; indx++ ) 
  	 {
     	    nurb_rec.pf_ppp->pts[indx].x =  0.0 ; 
     	    nurb_rec.pf_ppp->pts[indx].y =  0.0 ;
         }                    
         break;

      case 9 :
 
         /* vase 
         */
         nrb_vase( &nurb_rec );
         break;

      case 10 : 

         /* Circle 
         */
         nrb_circle( &nurb_rec );
         break;

      case 11 : 

         /* Square 
         */
         nrb_square( &nurb_rec ) ;
         break;

      case 12 : 

         /* triangle 
         */
         nrb_triangle( &nurb_rec ) ;
         break;

      case 13 : 

         /* Rule Surface 
         */
         nrb_square( &tri ) ;
         nrb_circle( &circle ) ;

         point = ptk_vector3(0.0,0.0,2.0);
         ptk_shift3( &point, PREPLACE, mm);
         nrb_xform( &circle,mm);
         nrb_ruled( &circle, &tri, &nurb_rec, &err);
         break;

      case 14 :

         /* Read from a file - STDIN for NOW 
         */
         getstringinput("Filename: ",fname);
         fd = fopen( fname, "r");
         if( fd != NULL )
         { 
            nrb_read( fd, &nurb_rec );
            nrb_dumpsummary( stdout, &nurb_rec );
            fclose( fd );
         }
         break;

   } /* switch */
}  


/* Initialise the menus etc..
*/
void Pstart1( void )
{                 
int wstype;
Pint       error_status;
char       buffer[256];
Pconnid    conn_id;
int        req_size;
Pdspsize   size;	/* display size */

   popenws ( 1, PHIGS$K_CONID_DEFAULT, PHIGS$K_WSTYPE_DEFAULT);

   /* Set the workstation update mode
   */
/*   psetdisplayupdatest( 1, PASAP, PUQUM ); */

   /* Get the device size
   */
   inqmaxdevicecoords ( 1, &MaxDevX, &MaxDevY );

   /* define menu
   */
   InitialiseMenu();
   InitValuators();

   ppsetlightsrcrep( 1, 1, &lightrec );   

   Create_nurb_struct();

}

/* Get keyboard input
*/
int getstringinput( char *prompt, char *string )
{
   printf( "%s", prompt );
   scanf( "%s", string );
}

/* Open a file
*/
int readfile( char *filename, Pint *data )
{
   FILE *file_status;

file_status = fopen( filename, "r" );   

   /* Check to see if open successful
   */
   if( file_status == NULL )
      return( FALSE );
   else
   {
      fprintf( file_status, "%d", data );
      fclose( file_status );
   }
   return( TRUE );
}
void set_printer(void)
{
float dc_x,dc_y;
float npc_x,npc_y;
float max_dc;	        /* max(dc_x, dc_y), used for npc-space	         */
Plimit3    viewport,	/* workstation viewport (use entire disp.surface)*/
	   window;      /* workstation window (npc coordinates)	         */

   /* Inquire maximum device coordinates
   */
   inqmaxdevicecoords ( 2, &dc_x, &dc_y);

   /* max_dc = max (dc_x, dc_y)						    
   */									    
   if( dc_x > dc_y)
      max_dc = dc_x;
   else
      max_dc = dc_y;

   /* Establish maximum normalized projection coordinates	
   */							
   npc_x = dc_x / max_dc;
   npc_y = dc_y / max_dc;

   /* Set workstation window in npc coordinates
   */
   window.xmin = window.ymin = 0.0;
   window.xmax = npc_x;
   window.ymax = npc_y;
   window.zmin = 0.0;
   window.zmax = 1.0;

   psetwswindow3 ( 2, &window);

   /* Set workstation viewport to use entire display surface
   */				
   viewport.xmin = viewport.ymin = 0.0;
   viewport.xmax = dc_x;
   viewport.ymax = dc_y;
   viewport.zmin = 0.0;
   viewport.zmax = 0.0;
   psetwsviewport ( 2, &viewport);

}
void inqmaxdevicecoords(Pint wsid, Pfloat *maxdevx, Pfloat* maxdevy)
{   
  Pint err, totsize;
  Pdspsize disprec;
  Pwstype wstype;
  Pchar *buffer;
  Pconnid connid;

  pinqwsconntype(wsid, 0, &err, buffer, &connid,
                 &totsize, &wstype);
  buffer = (Pchar *)malloc(totsize);
  pinqwsconntype(wsid, totsize, &err, buffer, &connid,
                 &totsize, &wstype);
  pinqdisplayspacesize(wstype, &err, &disprec);
  *maxdevx = disprec.device.x;
  *maxdevy = disprec.device.y;
  free(buffer);
} 
