/*
      GW-Interface.c
      Graphics and user control for Geavity-Well
      Gary Teachout
      Copyright   July 1989
      lc -x -cs GW-Interface     To compile with Lattice 5.0
*/


 #include "GW-Include.h"


 void startup()
 {
   int   i  ;
   char  *p  ;


   IntuitionBase = ( struct IntuitionBase * )
                   OpenLibrary( "intuition.library" , 33 )  ;
   if ( ! IntuitionBase )
      cleanup()  ;

   GfxBase = ( struct GfxBase * )
             OpenLibrary( "graphics.library" , 33 )  ;
   if ( ! GfxBase )
      cleanup()  ;

   DiskfontBase = ( struct Library * )
                  OpenLibrary( "diskfont.library" , 33 )  ;
   if ( ! DiskfontBase )
      cleanup()  ;

   rfont = OpenDiskFont( &rtext )  ;
   if ( ! rfont )
      cleanup()  ;

   ns.Font = &stext  ;
   screen = OpenScreen( &ns )  ;
   if ( ! screen )
      cleanup()  ;

   for ( i = 0 ; i < 4 ; i ++ )
      SetRGB4( &screen->ViewPort , i ,    clut[ i ][ 0 ] ,
                                          clut[ i ][ 1 ] ,
                                          clut[ i ][ 2 ]  )  ;

   controlnw.Screen = screen  ;
   viewcontrolnw.Screen = screen  ;
   mainviewnw.Screen = screen  ;
   topviewnw.Screen = screen  ;
   rightviewnw.Screen = screen  ;

   for ( i = 0 ; i < 12 ; i ++ )
   {
      viewcongadg[ i ].GadgetID = i  ;
      viewcongadg[ i ].NextGadget = ( i < 11 ) ? &viewcongadg[ i + 1 ] : NULL ;
   }
   viewcontrolnw.FirstGadget = &viewcongadg[ 0 ]  ;

   for ( i = 0 ; i < 45 ; i ++ )
   {
      controlgadg[ i ].GadgetID = i  ;
      controlgadg[ i ].NextGadget = ( i < 44 ) ? &controlgadg[ i + 1 ] : NULL ;
   }
   controlnw.FirstGadget = &controlgadg[ 0 ]  ;

   for ( i = 0 ; i < 14 ; i ++ )
   {
      controlgadg[ 31 + i ].SpecialInfo = ( APTR ) &controlinfo[ i ]  ;
      controlinfo[ i ].UndoBuffer = undobuffer  ;
   }
   for ( i = 0 ; i < 4 ; i ++ )
   {
      controlinfo[ i ].MaxChars = 66  ;
      controlgadg[ 31 + i ].GadgetRender = ( APTR ) &textbox  ;
   }
   for ( i = 4 ; i < 14 ; i ++ )
   {
      controlinfo[ i ].MaxChars = 33  ;
      controlinfo[ i ].Buffer = &numberbuff[ i - 4 ][ 0 ]  ;
      controlgadg[ 31 + i ].GadgetRender = ( APTR ) &numberbox  ;
   }
   controlinfo[ 0 ].MaxChars = 100  ;
   controlinfo[ 0 ].Buffer = filename  ;
   controlinfo[ 1 ].Buffer = g.filecomment1  ;
   controlinfo[ 2 ].Buffer = g.filecomment2  ;
   controlinfo[ 3 ].Buffer = &g.objects[ g.objectnum ].name[ 0 ]  ;

   textbox.XY = &xytextbox[ 0 ]  ;
   numberbox.XY = &xynumbox[ 0 ]  ;

   control = OpenWindow( &controlnw )  ;
   if ( ! control )
      cleanup()  ;

   SetFont( control->RPort , rfont )  ;

   openmainview()  ;
   if ( ! mainview )
      cleanup()  ;

   SetAPen( control->RPort , BPEN )  ;
   Move( control->RPort , 90 , 10 )  ;
   Draw( control->RPort , 90 , 217 )  ;
   Draw( control->RPort , 638 , 217 )  ;

   SetBPen( control->RPort , LINEPEN )  ;
   SetAPen( control->RPort , DOTPEN )  ;
   for ( i = 0 ; i < 20 ; i ++ )
   {
      Move( control->RPort , 10 , 21 + ( i * 14 ) )  ;
      Text( control->RPort , &numbertext[ i * 3 ] , 4 )  ;
   }
   for ( i = 0 ; i < 11 ; i ++ )
   {
      Move( control->RPort , controlgadg[ 20 + i ].LeftEdge + 4 ,
                             controlgadg[ 20 + i ].TopEdge + 9 )  ;
      Text( control->RPort , controlgtext[ i ] , 8 )  ;
   }

   SetBPen( control->RPort , 0 )  ;
   SetAPen( control->RPort , DOTPEN )  ;
   Move( control->RPort , 58 , 21 + ( g.objectnum * 14 ) )  ;
   Text( control->RPort , "<-" , 2 )  ;
   Move( control->RPort , 48 , 21 + ( 0 * 14 ) )  ;
   Text( control->RPort , "*" , 1 )  ;
   Move( control->RPort , 48 , 21 + ( 1 * 14 ) )  ;
   Text( control->RPort , "*" , 1 )  ;
   Move( control->RPort , 48 , 21 + ( 2 * 14 ) )  ;
   Text( control->RPort , "*" , 1 )  ;
   for ( i = 0 ; i < 10 ; i ++ ) 
   {
      Move( control->RPort , controlgadg[ 31 + i ].LeftEdge + 5 ,
                             controlgadg[ 31 + i ].TopEdge - 7 )  ;
      Text( control->RPort , conlabel[ i ] , conlabellength[ i ] )  ;
   }
   Move( control->RPort , 150 , 23 )  ;
   Text(    control->RPort , 
            "Gravity Well   Celestial Motion Simulator" , 41 )  ;
   Move( control->RPort , 150 , 38 )  ;
   Text(    control->RPort , 
            "by  Gary Teachout   Freeware   Copyright 1989" , 45 )  ;
   Move( control->RPort , 130 , 197 )  ;
   Text( control->RPort , "Scale:" , 6 )  ;
   p = gcvt( g.scale , DBL_DIG , &ettext[ 0 ] )  ;
   Move( control->RPort , 234 , 197 )  ;
   Text( control->RPort ,  &ettext[ 0 ] , strlen( &ettext[ 0 ] ) )  ;
   Move( control->RPort , 130 , 211 )  ;
   Text( control->RPort , "Elaped Time:" , 12 )  ;
   Move( control->RPort , 88 , 346 )  ;
   Text( control->RPort , "X" , 1 )  ;
   Move( control->RPort , 88 , 360 )  ;
   Text( control->RPort , "Y" , 1 )  ;
   Move( control->RPort , 88 , 374 )  ;
   Text( control->RPort , "Z" , 1 )  ;

   menustrip[ 0 ].FirstItem = &menu0[ 0 ].item  ;
   menu0[ 0 ].item.ItemFill = ( APTR ) &menu0[ 0 ].text  ;
   menu0[ 0 ].text.ITextFont = &rtext  ;

   menustrip[ 1 ].FirstItem = &menu1[ 0 ].item  ;
   for ( i = 0 ; i < 5 ; i ++ )
   {
      menu1[ i ].item.ItemFill = ( APTR ) &menu1[ i ].text  ;
      menu1[ i ].text.ITextFont = &rtext  ;
      menu1[ i ].item.NextItem = ( i < 4 ) ? &menu1[ i + 1 ].item : NULL ;
   }

   menustrip[ 2 ].FirstItem = &menu2[ 0 ].item  ;
   for ( i = 0 ; i < 4 ; i ++ )
   {
      menu2[ i ].item.ItemFill = ( APTR ) &menu2[ i ].text  ;
      menu2[ i ].text.ITextFont = &rtext  ;
      menu2[ i ].item.NextItem = ( i < 3 ) ? &menu2[ i + 1 ].item : NULL ;
   }

   menustrip[ 0 ].NextMenu = &menustrip[ 1 ]  ;
   menustrip[ 1 ].NextMenu = &menustrip[ 2 ]  ;

   SetMenuStrip( control , &menustrip[ 0 ] )  ;

   openviewcontrol()  ;
   opentopview()  ;
   openrightview()  ;
   openviewcontrol()  ;

   set()  ;
 }


 void cleanup()  
 {
   if ( control )
   {
      ClearMenuStrip( control )  ;
      CloseWindow( control )  ;
   }

   if ( viewcontrol )
   {
      ClearMenuStrip( viewcontrol )  ;
      CloseWindow( viewcontrol )  ;
   }

   if ( mainview )
   {
      ClearMenuStrip( mainview )  ;
      CloseWindow( mainview )  ;
   }

   if ( topview )
   {
      ClearMenuStrip( topview )  ;
      CloseWindow( topview )  ;
   }

   if ( rightview )
   {
      ClearMenuStrip( rightview )  ;
      CloseWindow( rightview )  ;
   }

   if ( screen )
      CloseScreen( screen )  ;

   if ( rfont )
      CloseFont( rfont )  ;

   if ( DiskfontBase )
      CloseLibrary( DiskfontBase )  ;

   if ( GfxBase )
      CloseLibrary( GfxBase )  ;

   if ( IntuitionBase )
      CloseLibrary( IntuitionBase )  ;

   exit()  ;
 }


 void openmainview()
 {
   if ( mainview )
   {
      WindowToFront( mainview )  ;
   }
   else
   {
      mainview = OpenWindow( &mainviewnw )  ;
      if ( mainview )
      {
         SetMenuStrip( mainview , &menustrip[ 0 ] )  ;
         setupdisplay( mainview )  ;
      }
      else
      {
         DisplayBeep( screen )  ;
      }
   }
 }


 void opentopview()
 {
   if ( topview )
   {
      WindowToFront( topview )  ;
   }
   else
   {
      topview = OpenWindow( &topviewnw )  ;
      if ( topview )
      {
         SetMenuStrip( topview , &menustrip[ 0 ] )  ;
         setupdisplay( topview )  ;
      }
      else
      {
         DisplayBeep( screen )  ;
      }
   }
 }


 void openrightview()
 {
   if ( rightview )
   {
      WindowToFront( rightview )  ;
   }
   else
   {
      rightview = OpenWindow( &rightviewnw )  ;
      if ( rightview )
      {
         SetMenuStrip( rightview , &menustrip[ 0 ] )  ;
         setupdisplay( rightview )  ;
      }
      else
      {
         DisplayBeep( screen )  ;
      }
   }
 }


 void openviewcontrol()
 {
   long    i  ;

   if ( viewcontrol )
   {
      WindowToFront( viewcontrol )  ;
   }
   else
   {
      viewcontrol = OpenWindow( &viewcontrolnw )  ;
      if ( viewcontrol )
      {
         SetFont( viewcontrol->RPort , rfont )  ;
         SetMenuStrip( viewcontrol , &menustrip[ 0 ] )  ;
         SetBPen( viewcontrol->RPort , LINEPEN )  ;
         SetAPen( viewcontrol->RPort , DOTPEN )  ;
         for ( i = 0 ; i < 3 ; i ++ )
         {
            Move( viewcontrol->RPort , 14 , 86 + ( i * 16 ) )  ;
            Text( viewcontrol->RPort , "<" , 1 )  ;
            Move( viewcontrol->RPort , 78 , 86 + ( i * 16 ) )  ;
            Text( viewcontrol->RPort , ">" , 1 )  ;
         }            
         Move( viewcontrol->RPort , 18 , 22 + ( 0 * 16 ) )  ;
         Text( viewcontrol->RPort , " Follow " , 8 )  ;
         Move( viewcontrol->RPort , 18 , 22 + ( 1 * 16 ) )  ;
         Text( viewcontrol->RPort , " Center " , 8 )  ;
         Move( viewcontrol->RPort , 18 , 22 + ( 2 * 16 ) )  ;
         Text( viewcontrol->RPort , " Trails " , 8 )  ;
                
         Move( viewcontrol->RPort , 22 , 22 + ( 7 * 16 ) )  ;
         Text( viewcontrol->RPort , " Reset " , 7 )  ;
         Move( viewcontrol->RPort , 14 , 22 + ( 9 * 16 ) )  ;
         Text( viewcontrol->RPort , "IN" , 2 )  ;
         Move( viewcontrol->RPort , 62 , 22 + ( 9 * 16 ) )  ;
         Text( viewcontrol->RPort , "OUT" , 3 )  ;

         SetBPen( viewcontrol->RPort , 0 )  ;

         Move( viewcontrol->RPort , 18 , 22 + ( 3 * 16 ) )  ;
         Text( viewcontrol->RPort , "-Rotate-" , 8 )  ;
         Move( viewcontrol->RPort , 34 , 22 + ( 4 * 16 ) )  ;
         Text( viewcontrol->RPort , "Main" , 4 )  ;
         Move( viewcontrol->RPort , 38 , 22 + ( 5 * 16 ) )  ;
         Text( viewcontrol->RPort , "Top" , 3 )  ;
         Move( viewcontrol->RPort , 30 , 22 + ( 6 * 16 ) )  ;
         Text( viewcontrol->RPort , "Right" , 5 )  ;
         Move( viewcontrol->RPort , 26 , 22 + ( 8 * 16 ) )  ;
         Text( viewcontrol->RPort , "-Zoom-" , 6 )  ;
      }                            
      else
         DisplayBeep( screen )  ;
   }
 }


 void pixel( w , x , y )
   struct Window  *w  ;               
   double         x , y  ;
 {
   long     xx , yy  ;

   xx =     ( w->Width >> 1 ) 
         +  ( long ) ( g.scale * x * 200.0 )  ;
   yy =     ( w->Height >> 1 )
         -  ( long ) ( g.scale * y * 177.0 )  ;

   if (     ( xx > w->BorderLeft ) 
         && ( xx < ( w->Width - w->BorderRight ) )
         && ( yy > w->BorderTop ) 
         && ( yy < ( w->Height - w->BorderBottom ) ) )
   {
      WritePixel( w->RPort , xx , yy )  ; 
      WritePixel( w->RPort , xx + 1 , yy )  ; 
   }
 }


 void blankwindow( w )
   struct Window  *w  ;
 {
   if ( w )
   {
      SetAPen( w->RPort , 0 )  ;
      RectFill( w->RPort ,    w->BorderLeft - 1 ,
                              w->BorderTop - 1 ,
                              w->Width - w->BorderRight ,
                              w->Height - w->BorderBottom )  ;
   }
 }


 void line( w , x1 , y1 , x2 , y2 )
   struct Window  *w  ;
   double         x1 , y1 , x2 , y2  ;
 {
   long     xx1 , yy1 , xx2 , yy2  ;

   xx1 =    ( w->Width >> 1 ) 
         +  ( long ) ( g.scale * x1 * 200.0 )  ;
   yy1 =    ( w->Height >> 1 )
         -  ( long ) ( g.scale * y1 * 177.0 )  ;
   xx2 =    ( w->Width >> 1 ) 
         +  ( long ) ( g.scale * x2 * 200.0 )  ;
   yy2 =    ( w->Height >> 1 )
         -  ( long ) ( g.scale * y2 * 177.0 )  ;

   if (     ( xx1 > w->BorderLeft ) 
         && ( xx1 < ( w->Width - w->BorderRight ) )
         && ( yy1 > w->BorderTop ) 
         && ( yy1 < ( w->Height - w->BorderBottom ) )
         && ( xx2 > w->BorderLeft ) 
         && ( xx2 < ( w->Width - w->BorderRight ) )
         && ( yy2 > w->BorderTop ) 
         && ( yy2 < ( w->Height - w->BorderBottom ) ) )
   {
      Move( w->RPort , xx1 , yy1 )  ;
      Draw( w->RPort , xx2 , yy2 )  ;
   }
 }


 void linelong( w , x1 , y1 , x2 , y2 )
   struct Window  *w  ;
   long           x1 , y1 , x2 , y2  ;
 {
   if ( x1 < w->BorderLeft ) 
   {
      if ( x2 < w->BorderLeft ) 
         return  ;
      y1 = y1 +      ( double ) ( y2 - y1 )
                  /  ( x2 - x1 )
                  *  ( w->BorderLeft - x1 )  ;
      x1 = w->BorderLeft  ;
   }
   else if ( x1 > ( w->Width - w->BorderRight ) )
   {
      if ( x2 >  ( w->Width - w->BorderRight ) )
         return  ;
      y1 = y1 +      ( double ) ( y2 - y1 )
                  /  ( x2 - x1 )
                  *  ( w->Width - w->BorderRight - x1 )  ;
      x1 = w->Width - w->BorderRight  ;
   }

   if ( y1 < w->BorderTop )
   {
      if ( y2 < w->BorderTop )
         return  ;
      x1 = x1 +      ( double ) ( x2 - x1 )
                  /  ( y2 - y1 )
                  *  ( w->BorderTop - y1 )  ;
      y1 = w->BorderTop  ;
      if (     ( x1 < w->BorderLeft ) 
            || ( x1 > ( w->Width - w->BorderRight ) ) )
         return  ;
   }
   else if ( y1 > ( w->Height - w->BorderBottom ) )
   {
      if ( y2 > ( w->Height - w->BorderBottom ) )
         return  ;
      x1 = x1 +      ( double ) ( x2 - x1 )
                  /  ( y2 - y1 )
                  *  ( w->Height - w->BorderBottom - y1 )  ;
      y1 = w->Height - w->BorderBottom  ;
      if (     ( x1 < w->BorderLeft ) 
            || ( x1 > ( w->Width - w->BorderRight ) ) )
         return  ;
   }

   if ( x2 < w->BorderLeft ) 
   {
      y2 = y2 +      ( double ) ( y1 - y2 )
                  /  ( x1 - x2 )
                  *  ( w->BorderLeft - x2 )  ;
      x2 = w->BorderLeft  ;
   }
   else if ( x2 > ( w->Width - w->BorderRight ) )
   {
      y2 = y2 +      ( double ) ( y1 - y2 )
                  /  ( x1 - x2 )
                  *  ( w->Width - w->BorderRight - x2 )  ;
      x2 = w->Width - w->BorderRight  ;
   }

   if ( y2 < w->BorderTop )
   {
      x2 = x2 +      ( double ) ( x1 - x2 )
                  /  ( y1 - y2 )
                  *  ( w->BorderTop - y2 )  ;
      y2 = w->BorderTop  ;
   }
   else if ( y2 > ( w->Height - w->BorderBottom ) )
   {
      x2 = x2 +      ( double ) ( x1 - x2 )
                  /  ( y1 - y2 )
                  *  ( w->Height - w->BorderBottom - y2 )  ;
      y2 = w->Height - w->BorderBottom  ;
   }

   Move( w->RPort , x1 , y1 )  ;
   Draw( w->RPort , x2 , y2 )  ;
 }


 void interface()
 {
   struct FileHandle    *fh  ;
   struct filedata      *fd  ;
   long        i , s  ;
   struct dv   tv , vv  ;
   double      x , y  ;
   char        *p  ;

   if ( control )
   {
      while ( mes = GetMsg( control->UserPort ) )
      {
         readmes()  ;
         switch ( class )
         {
         case MENUPICK :
            handelmenu()  ;
            break   ;
         case GADGETUP :
            if (        ( iadd->GadgetID < 20 )
                     && (     g.objects[ iadd->GadgetID ].flags
                           || ( g.awaiting == NEWPOSITION )
                           || ( g.awaiting == NEWMASS )
                           || ( g.awaiting == NEWCREATE )
                           || ( g.awaiting == NEWVELOCITY ) ) )
            {
               Move( control->RPort , 58 , 21 + ( g.objectnum * 14 ) )  ;
               Text( control->RPort , "  " , 2 )  ;

               g.objectnum = iadd->GadgetID  ;

               Move( control->RPort , 58 , 21 + ( g.objectnum * 14 ) )  ;
               Text( control->RPort , "<-" , 2 )  ;

               setstrings()  ;

               if ( g.follow )
                  resetdisplay()  ;
            }
            else
            {
               switch ( iadd->GadgetID )
               {
               case 20 :
                  g.awaiting = NEWPOSITION  ;
                  screentitle( NEWPOSITION )  ;
                  break  ;
               case 21 :
                  g.awaiting = NEWVELOCITY  ;
                  screentitle( NEWVELOCITY )  ;
                  break  ;
               case 22 :
                  g.awaiting = NEWMASS  ;
                  screentitle( NEWMASS )  ;
                  break  ;
               case 23 : /* delete */
                  deleteobject( g.objectnum )  ;
                  resetdisplay()  ;
                  break  ;
               case 24 : /* zero M */
                  for ( tv = zerodv , x = 0.0 , i = 0 ; i < 20 ; i ++ )
                  {
                     if ( g.objects[ i ].flags && g.objects[ i ].mass )
                     {
                        scaledv(    &g.objects[ i ].velocity ,
                                    &g.objects[ i ].mass ,
                                    &vv )  ;
                        adddv( &tv , &vv , &tv )  ;
                        x = x + g.objects[ i ].mass  ;
                     }
                  }
                  if ( x )
                  {
                     x = 1 / x  ;
                     scaledv( &tv , &x , &tv )  ;
                     for ( i = 0 ; i < 20 ; i ++ )
                     {
                        if ( g.objects[ i ].flags )
                        {
                           subdv(   &g.objects[ i ].velocity ,
                                    &tv ,
                                    &g.objects[ i ].velocity )  ;
                        }
                     }
                  }
                  set()  ;
                  break  ;
               case 25 :
                  if ( g.awaiting > 1 )
                  {
                     g.awaiting = 0  ;
                     resetdisplay()  ;
                  }
                  g.awaiting = 0  ;
                  screentitle( 0 )  ;
                  g.stopflag = 0  ;
                  break  ;
               case 26 :        /*  load  */
                  Move( control->RPort , 200 , 62 )  ;
                  p = AllocMem( 4700 , MEMF_CHIP |MEMF_CLEAR )  ;
                  s = 1  ;
                  if ( p )
                  {
                     fh = Open( filename , MODE_OLDFILE )  ;
                     if ( fh )
                     {
                        ScreenToFront( screen )  ;

                        Text( control->RPort , 
                                 "Loading file                 " , 29 )  ;
                        fd = ( struct filedata * ) p  ;
                        i = Read( fh , p , 4700 )  ;
                        if ( i == 4700 )
                        {
                           for ( i = 0 ; i < 12 ; i ++ )
                              if ( fd->tag[ i ] != g.tag[ i ] )
                                 i = 20  ;
                           if ( i < 20 )
                           {
                              s = g.stopflag  ;
                              g = *fd  ;
                              for ( i = 0 ; i < 20 ; i ++ )
                              {
                                 Move(    control->RPort ,
                                          48 , 21 + ( i * 14 ) )  ;
                                 if ( g.objects[ i ].flags )
                                    Text( control->RPort , "*   " , 4 )  ;
                                 else
                                    Text( control->RPort , "    " , 4 )  ;
                              }
                              Move(    control->RPort ,
                                       58 , 21 + ( g.objectnum * 14 ) )  ;
                              Text( control->RPort , "<-" , 2 )  ;

                              screentitle( g.awaiting )  ;
                              setstrings()  ;
                              resetdisplay()  ;

                              Delay( 100 )  ;
                              Move( control->RPort , 200 , 62 )  ;
                              Text( control->RPort , 
                                 "                             " , 29 )  ;
                           }
                           else
                           {
                              Move( control->RPort , 200 , 62 )  ;
                              Text( control->RPort ,          
                                 "ERROR Not a Gravity Well file" , 29 )  ;
                           }
                        }
                        else
                        {
                           Move( control->RPort , 200 , 62 )  ;
                           Text( control->RPort , 
                                 "ERROR  While reading file    " , 29 )  ;
                        }

                        Close( fh ) ;
                     }
                     else
                        Text( control->RPort , 
                                 "ERROR  Could not open file   " , 29 )  ;

                     ScreenToFront( screen )  ;
                     FreeMem( p , 4700 )  ;
                  }
                  else
                     Text( control->RPort , 
                                 "ERROR  Out of memory         " , 29 )  ;

                  if ( g.stopflag && ( ! s ) )
                     stoploop()  ;

                  break  ;
               case 27 :        /*  save  */
                  Move( control->RPort , 200 , 62 )  ;
                  p = AllocMem( 4700 , MEMF_CHIP |MEMF_CLEAR )  ;
                  if ( p )
                  {
                     fh = Open( filename , MODE_NEWFILE )  ;
                     if ( fh )
                     {
                        ScreenToFront( screen )  ;
                        Text( control->RPort ,
                              "Saving file                  " , 29 )  ;
                        Move( control->RPort , 200 , 62 )  ;
                        fd = ( struct filedata * ) p  ;
                        *fd = g  ;
                        i = Write( fh , p , 4700 )  ;
                        if ( i == 4700 )
                        {
                           Delay( 100 )  ;
                           Text( control->RPort , 
                              "                             " , 29 )  ;
                        }
                        else
                           Text( control->RPort , 
                              "ERROR  While writing file    " , 29 )  ;
                          
                        Close( fh ) ;
                     }
                     else
                        Text( control->RPort ,
                              "ERROR  Could not open file   " , 29 )  ;

                     ScreenToFront( screen )  ;
                     FreeMem( p , 4700 )  ;
                  }
                  else
                     Text( control->RPort ,
                              "ERROR  Out of memory         " , 29 )  ;

                  break  ;
               case 28 :
                  for ( i = 0 ; i < 20 ; i ++ )
                     deleteobject( i )  ;
                  g.elapsedtime = 0.0  ;
                  g.timestep = 0.01  ;
                  g.magic = 100.0  ;
                  g.scale = 0.5  ;
                  g.trailson = 1  ;
                  g.follow = 0  ;
                  g.viewbasis = refobv  ;
                  g.viewoffset = zerodv  ;
                  g.filecomment1[ 0 ] = 0  ;
                  g.filecomment2[ 0 ] = 0  ;
                  setstrings()  ;
                  resetdisplay()  ;
                  if ( ! g.stopflag )
                  {
                     g.stopflag = 1  ;
                     stoploop()  ;
                  }
                  break  ;
               case 29 :
                  g.awaiting = NEWCREATE  ;
                  screentitle( NEWCREATE )  ;
                  break  ;
               case 30 :
                  create()  ;

                  g.timestep = atof( &numberbuff[ 0 ][ 0 ] )  ;
                  g.magic = atof( &numberbuff[ 1 ][ 0 ] )  ;

                  g.objects[ g.objectnum ].mass =
                              atof( &numberbuff[ 2 ][ 0 ] )  ;
                  g.objects[ g.objectnum ].radius =
                              atof( &numberbuff[ 3 ][ 0 ] )  ;

                  g.objects[ g.objectnum ].position.x =
                              atof( &numberbuff[ 4 ][ 0 ] )  ;
                  g.objects[ g.objectnum ].position.y =
                              atof( &numberbuff[ 6 ][ 0 ] )  ;
                  g.objects[ g.objectnum ].position.z =
                              atof( &numberbuff[ 8 ][ 0 ] )  ;

                  g.objects[ g.objectnum ].velocity.x =
                              atof( &numberbuff[ 5 ][ 0 ] )  ;
                  g.objects[ g.objectnum ].velocity.y =
                              atof( &numberbuff[ 7 ][ 0 ] )  ;
                  g.objects[ g.objectnum ].velocity.z =
                              atof( &numberbuff[ 9 ][ 0 ] )  ;

                  set()  ;
                  setstrings()  ;
                  resetdisplay()  ;

                  break  ;
               case 35 :
                  g.timestep = atof( &numberbuff[ 0 ][ 0 ] )  ;
                  p = gcvt( g.timestep , DBL_DIG , &numberbuff[ 0 ][ 0 ] )  ;
                  RefreshGadgets( &controlgadg[ 31 ] , control , NULL )  ;
                  break  ;
               case 36 :
                  g.magic = atof( &numberbuff[ 1 ][ 0 ] )  ;
                  p = gcvt( g.magic , DBL_DIG , &numberbuff[ 1 ][ 0 ] )  ;
                  RefreshGadgets( &controlgadg[ 31 ] , control , NULL )  ;
                  break  ;
               }
            }

            if ( g.awaiting > 1 )
            {
               g.follow = 0  ;
               resetdisplay()  ;
               if ( ! g.stopflag )
               {
                  g.stopflag = 1  ;
                  stoploop()  ;
               }
            }
            break   ;
         }
      }
   }
   if ( viewcontrol )
   {
      while ( mes = GetMsg( viewcontrol->UserPort ) )
      {
         readmes()  ;
         switch ( class )
         {
         case MENUPICK :
            handelmenu()  ;
            break  ;
         case CLOSEWINDOW :
            ClearMenuStrip( viewcontrol )  ;
            viewcontrolnw.LeftEdge = viewcontrol->LeftEdge  ;
            viewcontrolnw.TopEdge = viewcontrol->TopEdge  ;
            CloseWindow( viewcontrol )  ;
            viewcontrol = NULL  ;
            break  ;
         case GADGETUP :
            switch ( iadd->GadgetID )
            {
            case 0 :
               rotatedvpair10( &g.viewbasis.j , &g.viewbasis.i )  ;
               break  ;
            case 1 :
               rotatedvpair10( &g.viewbasis.i , &g.viewbasis.j )  ;
               break  ;
            case 2 :
               rotatedvpair10( &g.viewbasis.i , &g.viewbasis.k )  ;
               break  ;
            case 3 :
               rotatedvpair10( &g.viewbasis.k , &g.viewbasis.i )  ;
               break  ;
            case 4 :
               rotatedvpair10( &g.viewbasis.k , &g.viewbasis.j )  ;
               break  ;
            case 5 :
               rotatedvpair10( &g.viewbasis.j , &g.viewbasis.k )  ;
               break  ;
            case 6 :
               g.viewbasis = refobv  ;
               g.unviewbasis = refobv  ;
               break  ;
            case 7 :
               g.scale = g.scale * 1.6  ;
               p = gcvt( g.scale , DBL_DIG , &ettext[ 0 ] )  ;
               Move( control->RPort , 234 , 197 )  ;
               Text( control->RPort ,  &ettext[ 0 ] ,
                                       strlen( &ettext[ 0 ] ) )  ;
               Text( control->RPort , "                    " , 20 )  ;
               break  ;
            case 8 :
               g.scale = g.scale * 0.625  ;
               p = gcvt( g.scale , DBL_DIG , &ettext[ 0 ] )  ;
               Move( control->RPort , 234 , 197 )  ;
               Text( control->RPort ,  &ettext[ 0 ] ,
                                       strlen( &ettext[ 0 ] ) )  ;
               Text( control->RPort , "                    " , 20 )  ;
               break  ;
            case 9 :
               if ( g.trailson )
               {
                  g.trailson = 0  ;
                  resetdisplay()  ;
               }
               else
               g.trailson = 1  ;
               break  ;
            case 10 :
               if ( g.awaiting == NEWCENTER )
               {
                  screentitle( 0 )  ;
                  g.awaiting = 0  ;
               }
               else
               {
                  if ( g.follow )
                  {
                     g.follow = 0  ;
                     resetdisplay()  ;
                  }
                  else if ( g.awaiting )
                     resetdisplay()  ;
                  screentitle( NEWCENTER )  ;
                  g.awaiting = NEWCENTER  ;
               }
               break  ;
            case 11 :
               g.follow = ( g.follow ) ? 0 : 1  ;
               break  ;
            }
            if ( iadd->GadgetID != 10 )
            {
               if ( g.awaiting == NEWCENTER )
               {
                  screentitle( 0 )  ;
                  g.awaiting = 0  ;
               }
               resetdisplay()  ;
            }
            if ( iadd->GadgetID < 6 )
            {
               basis( &refobv.i , &g.viewbasis , &g.unviewbasis.i )  ;
               basis( &refobv.j , &g.viewbasis , &g.unviewbasis.j )  ;
               basis( &refobv.k , &g.viewbasis , &g.unviewbasis.k )  ;
            }
            break  ;
         }
         if ( ! viewcontrol )
            break  ;
      }
   }
   if ( mainview )
   {
      while ( mes = GetMsg( mainview->UserPort ) )
      {
         readmes()  ;
         switch ( class )
         {
         case MENUPICK :
            handelmenu()  ;
            break  ;
         case NEWSIZE :
            blankwindow( mainview )  ;
            setupdisplay( mainview )  ;
            break  ;
         case CLOSEWINDOW :
            ClearMenuStrip( mainview )  ;
            mainviewnw.LeftEdge = mainview->LeftEdge  ;
            mainviewnw.TopEdge = mainview->TopEdge  ;
            mainviewnw.Width = mainview->Width  ;
            mainviewnw.Height = mainview->Height  ;
            CloseWindow( mainview )  ;
            mainview = NULL  ;
            break  ;
         case MOUSEBUTTONS :
            if ( code == SELECTDOWN )
            {
               switch ( g.awaiting )
               {
               case NEWCENTER :
                  g.viewoffset.x =  g.viewoffset.x
                                 -  (     (     mousex
                                             -  ( mainview->Width >> 1 ) )
                                       /  ( g.scale * 200.0 ) )  ;
                  g.viewoffset.y =  g.viewoffset.y
                                 +  (     (     mousey
                                             -  ( mainview->Height >> 1 ) )
                                       /  ( g.scale * 177.0 ) )  ;
                  resetdisplay()  ;
                  break  ;
               case NEWPOSITION :
                  create()  ;
                  basis(   &g.objects[ g.objectnum ].position ,
                           &g.viewbasis ,
                           &tv )  ;
                  do
                  {
                     tv.x =      -g.viewoffset.x
                              +  (     (     mainview->MouseX 
                                          -  ( mainview->Width >> 1 ) )
                                    /  ( g.scale * 200.0 ) )  ;
                     tv.y =      -g.viewoffset.y
                              -  (     (     mainview->MouseY 
                                          -  ( mainview->Height >> 1 ) )
                                    /  ( g.scale * 177.0 ) )  ;
                     basis(   &tv ,
                              &g.unviewbasis ,
                              &g.objects[ g.objectnum ].position )  ; 
                     resetdisplay()  ;
                     Delay( 1 )  ;
                     if ( mes = GetMsg( mainview->UserPort ) )
                        readmes()  ;
                  } while (      ( class != MOUSEBUTTONS ) 
                              || ( code != SELECTUP ) ) ;
                  g.objects[ g.objectnum ].oldpos = 
                             g.objects[ g.objectnum ].position  ;
                  set()  ;
                  break  ;
               case NEWVELOCITY :
                  create()  ;
                  adddv(   &g.objects[ g.objectnum ].position ,
                           &g.objects[ g.objectnum ].velocity ,
                           &vv )  ;
                  basis(   &vv ,
                           &g.viewbasis ,
                           &tv )  ; 
                  do
                  {
                     tv.x =      -g.viewoffset.x
                              +  (     (     mainview->MouseX 
                                          -  ( mainview->Width >> 1 ) )
                                    /  ( g.scale * 200.0 ) )  ;
                     tv.y =      -g.viewoffset.y
                              -  (     (     mainview->MouseY 
                                          -  ( mainview->Height >> 1 ) )
                                    /  ( g.scale * 177.0 ) )  ;
                     basis(   &tv ,
                              &g.unviewbasis ,
                              &vv )  ; 
                     subdv(   &vv ,
                              &g.objects[ g.objectnum ].position ,
                              &g.objects[ g.objectnum ].velocity )  ; 
                     resetdisplay()  ;
                     Delay( 1 )  ;
                     if ( mes = GetMsg( mainview->UserPort ) )
                        readmes()  ;
                  } while (      ( class != MOUSEBUTTONS ) 
                              || ( code != SELECTUP ) ) ;
                  set()  ;
                  break  ;
               case NEWMASS :
                  create()  ;
                  basis(   &g.objects[ g.objectnum ].position ,
                           &g.viewbasis ,
                           &tv )  ; 
                  do
                  {
                     x =      -g.viewoffset.x
                           +  (     (     mainview->MouseX 
                                       -  ( mainview->Width >> 1 ) )
                                 /  ( g.scale * 200.0 ) )  ;
                     y =      -g.viewoffset.y
                           -  (     (     mainview->MouseY 
                                          -  ( mainview->Height >> 1 ) )
                                    /  ( g.scale * 177.0 ) )  ;
                     x = x - tv.x  ;
                     y = y - tv.y  ;
                     g.objects[ g.objectnum ].mass = sqrt( x * x + y * y )  ;
                     resetdisplay()  ;
                     Delay( 1 )  ;
                     if ( mes = GetMsg( mainview->UserPort ) )
                        readmes()  ;
                  } while (      ( class != MOUSEBUTTONS )
                              || ( code != SELECTUP ) ) ;
                  set()  ;
                  break  ;
               }
            }
            break  ;
         }
         if ( ! mainview )
            break  ;
      }
   }
   if ( topview )
   {
      while ( mes = GetMsg( topview->UserPort ) )
      {
         readmes()  ;
         switch ( class )
         {
         case MENUPICK :
            handelmenu()  ;
            break  ;
         case NEWSIZE :
            blankwindow( topview )  ;
            setupdisplay( topview )  ;
            break  ;
         case CLOSEWINDOW :
            ClearMenuStrip( topview )  ;
            topviewnw.LeftEdge = topview->LeftEdge  ;
            topviewnw.TopEdge = topview->TopEdge  ;
            topviewnw.Width = topview->Width  ;
            topviewnw.Height = topview->Height  ;
            CloseWindow( topview )  ;
            topview = NULL  ;
            break  ;
         case MOUSEBUTTONS :
            if ( code == SELECTDOWN )
            {
               switch ( g.awaiting )
               {
               case NEWCENTER :
                  g.viewoffset.x =  g.viewoffset.x
                                 -  (     (     mousex 
                                             -  ( topview->Width >> 1 ) )
                                       /  ( g.scale * 200.0 ) )  ;
                  g.viewoffset.z =  g.viewoffset.z
                                 -  (     (     mousey
                                             -  ( topview->Height >> 1 ) )
                                       /  ( g.scale * 177.0 ) )  ;
                  resetdisplay()  ;
                  break  ;
               case NEWPOSITION :
                  create()  ;
                  basis(   &g.objects[ g.objectnum ].position ,
                           &g.viewbasis ,
                           &tv )  ; 
                  do
                  {
                     tv.x =      -g.viewoffset.x
                              +  (     (     topview->MouseX 
                                          -  ( topview->Width >> 1 ) )
                                    /  ( g.scale * 200.0 ) )  ;
                     tv.z =      -g.viewoffset.z
                              +  (     (     topview->MouseY 
                                          -  ( topview->Height >> 1 ) )
                                    /  ( g.scale * 177.0 ) )  ;
                     basis(   &tv ,
                              &g.unviewbasis ,
                              &g.objects[ g.objectnum ].position )  ;
                     resetdisplay()  ;
                     Delay( 1 )  ;
                     if ( mes = GetMsg( topview->UserPort ) )
                        readmes()  ;
                  } while (      ( class != MOUSEBUTTONS )
                              || ( code != SELECTUP ) ) ;
                  g.objects[ g.objectnum ].oldpos =
                             g.objects[ g.objectnum ].position  ;
                  set()  ;
                  break  ;
               case NEWVELOCITY :
                  create()  ;
                  adddv(   &g.objects[ g.objectnum ].position ,
                           &g.objects[ g.objectnum ].velocity ,
                           &vv )  ;
                  basis(   &vv ,
                           &g.viewbasis ,
                           &tv )  ;
                  do
                  {
                     tv.x =      -g.viewoffset.x
                              +  (     (     topview->MouseX 
                                          -  ( topview->Width >> 1 ) )
                                    /  ( g.scale * 200.0 ) )  ;
                     tv.z =      -g.viewoffset.z
                              +  (     (     topview->MouseY 
                                          -  ( topview->Height >> 1 ) )
                                    /  ( g.scale * 177.0 ) )  ;
                     basis(   &tv ,
                              &g.unviewbasis ,
                              &vv )  ; 
                     subdv(   &vv ,
                              &g.objects[ g.objectnum ].position ,
                              &g.objects[ g.objectnum ].velocity )  ;
                     resetdisplay()  ;
                     Delay( 1 )  ;
                     if ( mes = GetMsg( topview->UserPort ) )
                        readmes()  ;
                  } while (      ( class != MOUSEBUTTONS )
                              || ( code != SELECTUP ) ) ;
                  set()  ;
                  break  ;
               case NEWMASS :
                  create()  ;
                  basis(   &g.objects[ g.objectnum ].position ,
                           &g.viewbasis ,
                           &tv )  ;
                  do
                  {
                     x =      -g.viewoffset.x
                           +  (     (     topview->MouseX
                                       -  ( topview->Width >> 1 ) )
                                 /  ( g.scale * 200.0 ) )  ;
                     y =      -g.viewoffset.z
                           +  (     (     topview->MouseY
                                       -  ( topview->Height >> 1 ) )
                                 /  ( g.scale * 177.0 ) )  ;
                     x = x - tv.x  ;
                     y = y - tv.z  ;
                     g.objects[ g.objectnum ].mass = sqrt( x * x + y * y )  ;
                     resetdisplay()  ;
                     Delay( 1 )  ;
                     if ( mes = GetMsg( topview->UserPort ) )
                        readmes()  ;
                  } while (      ( class != MOUSEBUTTONS )
                              || ( code != SELECTUP ) ) ;
                  set()  ;
                  break  ;
               }
            }
            break  ;
         }
         if ( ! topview )
            break  ;
      }
   }
   if ( rightview )
   {
      while ( mes = GetMsg( rightview->UserPort ) )
      {
         readmes()  ;
         switch ( class )
         {
         case MENUPICK :
            handelmenu()  ;
            break  ;
         case NEWSIZE :
            blankwindow( rightview )  ;
            setupdisplay( rightview )  ;
            break  ;
         case CLOSEWINDOW :
            ClearMenuStrip( rightview )  ;
            rightviewnw.LeftEdge = rightview->LeftEdge  ;
            rightviewnw.TopEdge = rightview->TopEdge  ;
            rightviewnw.Width = rightview->Width  ;
            rightviewnw.Height = rightview->Height  ;
            CloseWindow( rightview )  ;
            rightview = NULL  ;
            break  ;
         case MOUSEBUTTONS :
            if ( code == SELECTDOWN )
            {
               switch ( g.awaiting )
               {
               case NEWCENTER :
                  g.viewoffset.z =  g.viewoffset.z
                                 +  (     (     mousex 
                                             -  ( rightview->Width >> 1 ) )
                                       /  ( g.scale * 200.0 ) )  ;
                  g.viewoffset.y =  g.viewoffset.y
                                 +  (     (     mousey 
                                             -  ( rightview->Height >> 1 ) )
                                       /  ( g.scale * 177.0 ) )  ;
                  resetdisplay()  ;
                  break  ;
               case NEWPOSITION :
                  create()  ;
                  basis(   &g.objects[ g.objectnum ].position ,
                           &g.viewbasis ,
                           &tv )  ; 
                  do
                  {
                     tv.z =      -g.viewoffset.z
                              -  (     (     rightview->MouseX 
                                          -  ( rightview->Width >> 1 ) )
                                    /  ( g.scale * 200.0 ) )  ;
                     tv.y =      -g.viewoffset.y
                              -  (     (     rightview->MouseY 
                                          -  ( rightview->Height >> 1 ) )
                                    /  ( g.scale * 177.0 ) )  ;
                     basis(   &tv ,
                              &g.unviewbasis ,
                              &g.objects[ g.objectnum ].position )  ; 
                     resetdisplay()  ;
                     Delay( 1 )  ;
                     if ( mes = GetMsg( rightview->UserPort ) )
                        readmes()  ;
                  } while (      ( class != MOUSEBUTTONS ) 
                              || ( code != SELECTUP ) ) ;
                  g.objects[ g.objectnum ].oldpos = 
                             g.objects[ g.objectnum ].position  ;
                  set()  ;
                  break  ;
               case NEWVELOCITY :
                  create()  ;
                  adddv(   &g.objects[ g.objectnum ].position ,
                           &g.objects[ g.objectnum ].velocity ,
                           &vv )  ;
                  basis(   &vv ,
                           &g.viewbasis ,
                           &tv )  ;
                  do
                  {
                     tv.z =      -g.viewoffset.z
                              -  (     (     rightview->MouseX
                                          -  ( rightview->Width >> 1 ) )
                                    /  ( g.scale * 200.0 ) )  ;
                     tv.y =      -g.viewoffset.y
                              -  (     (     rightview->MouseY
                                          -  ( rightview->Height >> 1 ) )
                                    /  ( g.scale * 177.0 ) )  ;
                     basis(   &tv ,
                              &g.unviewbasis ,
                              &vv )  ; 
                     subdv(   &vv ,
                              &g.objects[ g.objectnum ].position ,
                              &g.objects[ g.objectnum ].velocity )  ;
                     resetdisplay()  ;
                     Delay( 1 )  ;
                     if ( mes = GetMsg( rightview->UserPort ) )
                        readmes()  ;
                  } while (      ( class != MOUSEBUTTONS )
                              || ( code != SELECTUP ) ) ;
                  set()  ;
                  break  ;
               case NEWMASS :
                  create()  ;
                  basis(   &g.objects[ g.objectnum ].position ,
                           &g.viewbasis ,
                           &tv )  ;
                  do
                  {
                     x =      -g.viewoffset.z
                           -  (     (     rightview->MouseX
                                       -  ( rightview->Width >> 1 ) )
                                 /  ( g.scale * 200.0 ) )  ;
                     y =      -g.viewoffset.y
                           -  (     (     rightview->MouseY
                                       -  ( rightview->Height >> 1 ) )
                                 /  ( g.scale * 177.0 ) )  ;
                     x = x - tv.z  ;
                     y = y - tv.y  ;
                     g.objects[ g.objectnum ].mass = sqrt( x * x + y * y )  ;
                     resetdisplay()  ;
                     Delay( 1 )  ;
                     if ( mes = GetMsg( rightview->UserPort ) )
                        readmes()  ;
                  } while (      ( class != MOUSEBUTTONS )
                              || ( code != SELECTUP ) ) ;
                  set()  ;
                  break  ;
               }
            }
            break  ;
         }
         if ( ! rightview )
            break  ;
      }
   }
   if (     ( g.awaiting != NEWPOSITION )
         && ( g.awaiting != NEWVELOCITY )
         && ( g.awaiting != NEWMASS )
         && ( g.awaiting != NEWCREATE )
         && ( ! g.objects[ g.objectnum ].flags ) )
   {
      for ( i = 0 ; ( ! g.objects[ i ].flags ) && ( i < 19 ) ; i ++ )
         ;
      if ( ( i == 19 ) && ( ! g.objects[ 19 ].flags ) )
         i = 0  ;

      Move( control->RPort , 58 , 21 + ( g.objectnum * 14 ) )  ;
      Text( control->RPort , "  " , 2 )  ;

      g.objectnum = i  ;

      Move( control->RPort , 58 , 21 + ( g.objectnum * 14 ) )  ;
      Text( control->RPort , "<-" , 2 )  ;

      setstrings()  ;
   }
 }


 void readmes()                                          
 {
   class = mes->Class  ;
   code = mes->Code  ;
   mousex = mes->MouseX  ;
   mousey = mes->MouseY  ;
   iadd = ( struct Gadget * ) mes->IAddress  ;
   ReplyMsg( mes )  ;
 }
 

 void handelmenu()
 {
   long     i  ;

   switch ( MENUNUM( code ) )
   {
   case 0 :
      if ( ITEMNUM( code ) == 0 )
         cleanup()  ;
      break  ;
   case 1 :
      switch ( ITEMNUM( code ) )
      {
      case 0 :
         openmainview()  ;
         break  ;
      case 1 :
         opentopview()  ;
         break  ;
      case 2 :
         openrightview()  ;
         break  ;
      case 3 :
         openviewcontrol()  ;
         break  ;
      case 4 :
         WindowToFront( control )  ;
         break  ;
      }
      break  ;
   case 2 :
      switch ( ITEMNUM( code ) )
      {
      case 0 :
         if ( g.awaiting > 1 )
         {
            g.awaiting = 0  ;
            resetdisplay()  ;
         }
         g.awaiting = 0  ;
         screentitle( 0 )  ;
         g.stopflag = 0  ;
         break  ;
      case 1 :
         if ( ! g.stopflag )
         {
            g.stopflag = 1  ;
            stoploop()  ;
         }
         break  ;
      case 2 :
         set()  ;
         break  ;
      case 3 :
         g.elapsedtime = 0  ;
         for ( i = 0 ; i < 20 ; i ++ )
         {
            g.objects[ i ].collision = 0  ;
            g.objects[ i ].mass = g.objects[ i ].startmass  ;
            g.objects[ i ].position = g.objects[ i ].startpos  ;
            g.objects[ i ].oldpos = g.objects[ i ].startpos  ;
            g.objects[ i ].velocity = g.objects[ i ].startvel  ;
         }
         resetdisplay()  ;
         break  ;
      }
      break  ;
   }
 }


 void stoploop()
 {
   ULONG    s  ;

   while ( g.stopflag )
   {
      s = 1 << control->UserPort->mp_SigBit  ;
      if ( viewcontrol )
         s |= 1 << viewcontrol->UserPort->mp_SigBit  ;
      if ( mainview )
         s |= 1 << mainview->UserPort->mp_SigBit  ;
      if ( topview )
         s |= 1 << topview->UserPort->mp_SigBit  ;
      if ( rightview )
         s |= 1 << rightview->UserPort->mp_SigBit  ;
      Wait( s )  ;
      interface()  ;
   }
 }


 void resetdisplay()
 {
   char  *p  ;

   blankwindow( mainview )  ;
   setupdisplay( mainview )  ;
   blankwindow( topview )  ;
   setupdisplay( topview )  ;
   blankwindow( rightview )  ;
   setupdisplay( rightview )  ;

   p = gcvt( g.elapsedtime , DBL_DIG , &ettext[ 0 ] )  ;
   Move( control->RPort , 234 , 211 )  ;
   Text( control->RPort , &ettext[ 0 ] , strlen( &ettext[ 0 ] ) )  ;
   Text( control->RPort , "                    " , 20 )  ;

   p = gcvt( g.scale , DBL_DIG , &ettext[ 0 ] )  ;
   Move( control->RPort , 234 , 197 )  ;
   Text( control->RPort ,  &ettext[ 0 ] , strlen( &ettext[ 0 ] ) )  ;
   Text( control->RPort , "                    " , 20 )  ;
 }


 void screentitle( n )  
   long  n  ;
 {
   SetWindowTitles( control , -1 , titletext[ n ] )  ;
   if ( viewcontrol )
      SetWindowTitles( viewcontrol , -1 , titletext[ n ] )  ;
   if ( mainview )
      SetWindowTitles( mainview , -1 , titletext[ n ] )  ;
   if ( topview )
      SetWindowTitles( topview , -1 , titletext[ n ] )  ;
   if ( rightview )
      SetWindowTitles( rightview , -1 , titletext[ n ] )  ;
 }


 void setupdisplay( w )
   struct Window  *w  ;
 {
   struct dv   np , vv ;
   long     xx , yy , tx , ty , ux , uy , i  ;

   if ( ! w )
      return  ;

   if ( g.awaiting > 1 )
   {
      basis( &g.objects[ g.objectnum ].position , &g.viewbasis , &np )  ;
      adddv( &np , &g.viewoffset , &np )  ;
      if ( w == mainview )
      {
         SetAPen( mainview->RPort , DOTPEN )  ;
         xx =     ( mainview->Width >> 1 )
               +  ( long ) ( g.scale * np.x * 200.0 )  ;
         yy =     ( mainview->Height >> 1 )
               -  ( long ) ( g.scale * np.y * 177.0 )  ;
         linelong( mainview , xx - 6 , yy , xx + 6 , yy )  ;
         linelong( mainview , xx , yy - 5 , xx , yy + 5 )  ;
         if ( g.awaiting == NEWVELOCITY )
         {
            SetAPen( mainview->RPort , LINEPEN )  ;
            for( i = 0 ; i < 20 ; i ++ )
            {
               if ( g.objects[ i ].flags && ( ! g.objects[ i ].collision ) )
               {
                  basis( &g.objects[ i ].position , &g.viewbasis , &np )  ;
                  adddv( &np , &g.viewoffset , &np )  ;
                  xx =     ( mainview->Width >> 1 )
                        +  ( long ) ( g.scale * np.x * 200.0 )  ;
                  yy =     ( mainview->Height >> 1 )
                        -  ( long ) ( g.scale * np.y * 177.0 )  ;
                  adddv(   &g.objects[ i ].position ,
                           &g.objects[ i ].velocity , &np )  ;
                  basis( &np , &g.viewbasis , &vv )  ;
                  adddv( &vv , &g.viewoffset , &vv )  ;
                  tx =     ( mainview->Width >> 1 ) 
                        +  ( long ) ( g.scale * vv.x * 200.0 )  ;
                  ty =     ( mainview->Height >> 1 )
                        -  ( long ) ( g.scale * vv.y * 177.0 )  ;
                  linelong( mainview , xx , yy , tx , ty )  ;
               }
            }
         }
         else if ( g.awaiting == NEWMASS )
         {
            SetAPen( mainview->RPort , LINEPEN )  ;
            for( i = 0 ; i < 20 ; i ++ )
            {
               if (     ( g.objects[ i ].flags )
                     && ( g.objects[ i ].mass )
                     && ( ! g.objects[ i ].collision ) )
               {
                  basis( &g.objects[ i ].position , &g.viewbasis , &np )  ;
                  adddv( &np , &g.viewoffset , &np )  ;
                  xx =     ( mainview->Width >> 1 )
                        +  ( long ) ( g.scale * np.x * 200.0 )  ;
                  yy =     ( mainview->Height >> 1 )
                        -  ( long ) ( g.scale * np.y * 177.0 )  ;
                  tx = ( long ) ( g.scale * g.objects[ i ].mass * 200.0 )  ;
                  ty = ( long ) ( g.scale * g.objects[ i ].mass * 177.0 )  ;
                  ux = ( long ) ( g.scale * g.objects[ i ].mass * 80.0 )  ;
                  uy = ( long ) ( g.scale * g.objects[ i ].mass * 70.0 )  ;
                  linelong(   mainview ,
                              xx + ux , yy + ty , xx - ux , yy + ty )  ;
                  linelong(   mainview ,
                              xx - ux , yy + ty , xx - tx , yy + uy )  ;
                  linelong(   mainview ,
                              xx - tx , yy + uy , xx - tx , yy - uy )  ;
                  linelong(   mainview ,
                              xx - tx , yy - uy , xx - ux , yy - ty )  ;
                  linelong(   mainview ,
                              xx - ux , yy - ty , xx + ux , yy - ty )  ;
                  linelong(   mainview ,
                              xx + ux , yy - ty , xx + tx , yy - uy )  ;
                  linelong(   mainview ,
                              xx + tx , yy - uy , xx + tx , yy + uy )  ;
                  linelong(   mainview ,
                              xx + tx , yy + uy , xx + ux , yy + ty )  ;
               }
            }
         }
      }
      if ( w == topview )
      {
         SetAPen( topview->RPort , DOTPEN )  ;
         xx =     ( topview->Width >> 1 )
               +  ( long ) ( g.scale * np.x * 200.0 )  ;
         yy =     ( topview->Height >> 1 )
               -  ( long ) ( g.scale * -np.z * 177.0 )  ;
         linelong( topview , xx - 6 , yy , xx + 6 , yy )  ;
         linelong( topview , xx , yy - 5 , xx , yy + 5 )  ;
         if ( g.awaiting == NEWVELOCITY )
         {
            SetAPen( topview->RPort , LINEPEN )  ;
            for( i = 0 ; i < 20 ; i ++ )
            {
               if ( g.objects[ i ].flags && ( ! g.objects[ i ].collision ) )
               {
                  basis( &g.objects[ i ].position , &g.viewbasis , &np )  ;
                  adddv( &np , &g.viewoffset , &np )  ;
                  xx =     ( topview->Width >> 1 )
                        +  ( long ) ( g.scale * np.x * 200.0 )  ;
                  yy =     ( topview->Height >> 1 )
                        -  ( long ) ( g.scale * -np.z * 177.0 )  ;
                  adddv(   &g.objects[ i ].position ,
                           &g.objects[ i ].velocity , &np )  ;
                  basis( &np , &g.viewbasis , &vv )  ;
                  adddv( &vv , &g.viewoffset , &vv )  ;
                  tx =     ( topview->Width >> 1 ) 
                        +  ( long ) ( g.scale * vv.x * 200.0 )  ;
                  ty =     ( topview->Height >> 1 )
                        -  ( long ) ( g.scale * -vv.z * 177.0 )  ;
                  linelong( topview , xx , yy , tx , ty )  ;
               }
            }
         }
         else if ( g.awaiting == NEWMASS )
         {
            SetAPen( topview->RPort , LINEPEN )  ;
            for( i = 0 ; i < 20 ; i ++ )
            {
               if (     ( g.objects[ i ].flags )
                     && ( g.objects[ i ].mass )
                     && ( ! g.objects[ i ].collision ) )
               {
                  basis( &g.objects[ i ].position , &g.viewbasis , &np )  ;
                  adddv( &np , &g.viewoffset , &np )  ;
                  xx =     ( topview->Width >> 1 )
                        +  ( long ) ( g.scale * np.x * 200.0 )  ;
                  yy =     ( topview->Height >> 1 )
                        -  ( long ) ( g.scale * -np.z * 177.0 )  ;
                  tx = ( long ) ( g.scale * g.objects[ i ].mass * 200.0 )  ;
                  ty = ( long ) ( g.scale * g.objects[ i ].mass * 177.0 )  ;
                  ux = ( long ) ( g.scale * g.objects[ i ].mass * 80.0 )  ;
                  uy = ( long ) ( g.scale * g.objects[ i ].mass * 70.0 )  ;
                  linelong(   topview ,
                              xx + ux , yy + ty , xx - ux , yy + ty )  ;
                  linelong(   topview ,
                              xx - ux , yy + ty , xx - tx , yy + uy )  ;
                  linelong(   topview ,
                              xx - tx , yy + uy , xx - tx , yy - uy )  ;
                  linelong(   topview ,
                              xx - tx , yy - uy , xx - ux , yy - ty )  ;
                  linelong(   topview ,
                              xx - ux , yy - ty , xx + ux , yy - ty )  ;
                  linelong(   topview ,
                              xx + ux , yy - ty , xx + tx , yy - uy )  ;
                  linelong(   topview ,
                              xx + tx , yy - uy , xx + tx , yy + uy )  ;
                  linelong(   topview ,
                              xx + tx , yy + uy , xx + ux , yy + ty )  ;
               }
            }
         }
      }
      if ( w == rightview )
      {
         SetAPen( rightview->RPort , DOTPEN )  ;
         xx =     ( rightview->Width >> 1 )
               +  ( long ) ( g.scale * -np.z * 200.0 )  ;
         yy =     ( rightview->Height >> 1 )
               -  ( long ) ( g.scale * np.y * 177.0 )  ;
         linelong( rightview , xx - 6 , yy , xx + 6 , yy )  ;
         linelong( rightview , xx , yy - 5 , xx , yy + 5 )  ;
         if ( g.awaiting == NEWVELOCITY )
         {
            SetAPen( rightview->RPort , LINEPEN )  ;
            for( i = 0 ; i < 20 ; i ++ )
            {
               if ( g.objects[ i ].flags && ( ! g.objects[ i ].collision ) )
               {
                  basis( &g.objects[ i ].position , &g.viewbasis , &np )  ;
                  adddv( &np , &g.viewoffset , &np )  ;
                  xx =     ( rightview->Width >> 1 )
                        +  ( long ) ( g.scale * -np.z * 200.0 )  ;
                  yy =     ( rightview->Height >> 1 )
                        -  ( long ) ( g.scale * np.y * 177.0 )  ;
                  adddv(   &g.objects[ i ].position , 
                           &g.objects[ i ].velocity , &np )  ;
                  basis( &np , &g.viewbasis , &vv )  ; 
                  adddv( &vv , &g.viewoffset , &vv )  ;
                  tx =     ( rightview->Width >> 1 ) 
                        +  ( long ) ( g.scale * -vv.z * 200.0 )  ;
                  ty =     ( rightview->Height >> 1 )
                        -  ( long ) ( g.scale * vv.y * 177.0 )  ;
                  linelong( rightview , xx , yy , tx , ty )  ;
               }
            }
         }
         else if ( g.awaiting == NEWMASS )
         {
            SetAPen( rightview->RPort , LINEPEN )  ;
            for( i = 0 ; i < 20 ; i ++ )
            {
               if (     ( g.objects[ i ].flags )
                     && ( g.objects[ i ].mass )
                     && ( ! g.objects[ i ].collision ) )
               {
                  basis( &g.objects[ i ].position , &g.viewbasis , &np )  ;
                  adddv( &np , &g.viewoffset , &np )  ;
                  xx =     ( rightview->Width >> 1 )
                        +  ( long ) ( g.scale * -np.z * 200.0 )  ;
                  yy =     ( rightview->Height >> 1 )
                        -  ( long ) ( g.scale * np.y * 177.0 )  ;
                  tx = ( long ) ( g.scale * g.objects[ i ].mass * 200.0 )  ;
                  ty = ( long ) ( g.scale * g.objects[ i ].mass * 177.0 )  ;
                  ux = ( long ) ( g.scale * g.objects[ i ].mass * 80.0 )  ;
                  uy = ( long ) ( g.scale * g.objects[ i ].mass * 70.0 )  ;
                  linelong(   rightview ,
                              xx + ux , yy + ty , xx - ux , yy + ty )  ;
                  linelong(   rightview ,
                              xx - ux , yy + ty , xx - tx , yy + uy )  ;
                  linelong(   rightview ,
                              xx - tx , yy + uy , xx - tx , yy - uy )  ;
                  linelong(   rightview ,
                              xx - tx , yy - uy , xx - ux , yy - ty )  ;
                  linelong(   rightview ,
                              xx - ux , yy - ty , xx + ux , yy - ty )  ;
                  linelong(   rightview ,
                              xx + ux , yy - ty , xx + tx , yy - uy )  ;
                  linelong(   rightview ,
                              xx + tx , yy - uy , xx + tx , yy + uy )  ;
                  linelong(   rightview ,
                              xx + tx , yy + uy , xx + ux , yy + ty )  ;
               }
            }
         }
      }
   }

   for ( i = 0 ; i < 20 ; i ++ )
   {
      if ( g.objects[ i ].flags && ( ! g.objects[ i ].collision ) )
      {
         if ( g.follow )
         {
            subdv(   &g.objects[ i ].position ,
                     &g.objects[ g.objectnum ].position , &vv )  ;
            basis( &vv , &g.viewbasis , &np )  ;
         }
         else
         {
            basis( &g.objects[ i ].position , &g.viewbasis , &np )  ;
            adddv( &np , &g.viewoffset , &np )  ;
         }
         SetAPen( w->RPort , DOTPEN )  ;
         if ( w == mainview )
            pixel( w , np.x , np.y )  ;
         if ( w == topview )
            pixel( w , np.x , -np.z )  ;
         if ( w == rightview )
            pixel( w , -np.z , np.y )  ;
      }
   }
 }


 void set()
 {
   long     i  ;

   g.elapsedtime = 0  ;
   for ( i = 0 ; i < 20 ; i ++ )
   {
      g.objects[ i ].startmass = g.objects[ i ].mass  ;
      g.objects[ i ].startpos = g.objects[ i ].position  ;
      g.objects[ i ].oldpos = g.objects[ i ].position  ;
      g.objects[ i ].startvel = g.objects[ i ].velocity  ;
      if ( g.objects[ i ].collision )
         deleteobject( i )  ;
   }
   setstrings()  ;
 }


 void create()
 {
   g.objects[ g.objectnum ].flags = 1  ;
   g.objects[ g.objectnum ].collision = 0  ;
   Move( control->RPort , 48 , 21 + ( g.objectnum * 14 ) )  ;
   Text( control->RPort , "*" , 1 )  ;
 }


 void setstrings()
 {
   char  *p  ;

   controlinfo[ 3 ].Buffer = &g.objects[ g.objectnum ].name[ 0 ]  ;
   p = gcvt(   g.timestep , DBL_DIG , &numberbuff[ 0 ][ 0 ] )  ;
   p = gcvt(   g.magic , DBL_DIG , &numberbuff[ 1 ][ 0 ] )  ;

   p = gcvt(   g.objects[ g.objectnum ].mass , DBL_DIG ,
               &numberbuff[ 2 ][ 0 ] )  ;
   p = gcvt(   g.objects[ g.objectnum ].radius , DBL_DIG ,
               &numberbuff[ 3 ][ 0 ] )  ;

   p = gcvt(   g.objects[ g.objectnum ].startpos.x , DBL_DIG ,
               &numberbuff[ 4 ][ 0 ] )  ;
   p = gcvt(   g.objects[ g.objectnum ].startpos.y , DBL_DIG ,
               &numberbuff[ 6 ][ 0 ] )  ;
   p = gcvt(   g.objects[ g.objectnum ].startpos.z , DBL_DIG ,
               &numberbuff[ 8 ][ 0 ] )  ;

   p = gcvt(   g.objects[ g.objectnum ].startvel.x , DBL_DIG ,
               &numberbuff[ 5 ][ 0 ] )  ;
   p = gcvt(   g.objects[ g.objectnum ].startvel.y , DBL_DIG ,
               &numberbuff[ 7 ][ 0 ] )  ;
   p = gcvt(   g.objects[ g.objectnum ].startvel.z , DBL_DIG ,
               &numberbuff[ 9 ][ 0 ] )  ;

   RefreshGadgets( &controlgadg[ 31 ] , control , NULL )  ;
 }


 void deleteobject( num )
   long num  ;
 {
   Move( control->RPort , 48 , 21 + ( num * 14 ) )  ;
   Text( control->RPort , " " , 1 )  ;
   g.objects[ num ].flags = 0  ;
   g.objects[ num ].collision = 0  ;
   g.objects[ num ].position = zerodv  ;
   g.objects[ num ].startpos = zerodv  ;
   g.objects[ num ].velocity = zerodv  ;
   g.objects[ num ].startvel = zerodv  ;
   g.objects[ num ].oldpos = zerodv  ;
   g.objects[ num ].mass = 0.0  ;
   g.objects[ num ].startmass = 0.0  ;
   g.objects[ num ].radius = 0.0  ;
   g.objects[ num ].name[ 0 ] = 0  ;
 }


 void endtrail( i , j )
   long  i , j  ;
 {
   struct dv   op , tv ;

   if ( g.trailson )
   {
      if ( mainview )
         SetAPen( mainview->RPort , LINEPEN )  ;
      if ( topview )
         SetAPen( topview->RPort , LINEPEN )  ;
      if ( rightview )
         SetAPen( rightview->RPort , LINEPEN )  ;
   }
   else
   {
      if ( mainview )
         SetAPen( mainview->RPort , 0 )  ;
      if ( topview )
         SetAPen( topview->RPort , 0 )  ;
      if ( rightview )
         SetAPen( rightview->RPort , 0 )  ;
   }
   if ( g.follow )
   {
      subdv(   &g.objects[ i ].oldpos ,
               &g.objects[ g.objectnum ].oldpos , &tv )  ;
      basis( &tv , &g.viewbasis , &op )  ;
   }
   else
   {
      basis( &g.objects[ i ].oldpos , &g.viewbasis , &tv )  ;
      adddv( &tv , &g.viewoffset , &op )  ;
   }
   if ( mainview )
      pixel( mainview , op.x , op.y )  ;
   if ( topview )
      pixel( topview , op.x , -op.z )  ;
   if ( rightview )
      pixel( rightview , -op.z , op.y )  ;
   if ( g.follow )
   {
      subdv(   &g.objects[ j ].oldpos ,
               &g.objects[ g.objectnum ].oldpos , &tv )  ;
      basis( &tv , &g.viewbasis , &op )  ;
   }
   else
   {
      basis( &g.objects[ j ].oldpos , &g.viewbasis , &tv )  ;
      adddv( &tv , &g.viewoffset , &op )  ;
   }
   if ( mainview )
      pixel( mainview , op.x , op.y )  ;
   if ( topview )
      pixel( topview , op.x , -op.z )  ;
   if ( rightview )
      pixel( rightview , -op.z , op.y )  ;
 }


 void updatedisplay()
 {
   struct dv   np[ 20 ] , op[ 20 ] , tv ;
   long  i  ;
   char  *p  ;

   if ( g.trailson )
   {
      if ( mainview )
         SetAPen( mainview->RPort , LINEPEN )  ;
      if ( topview )
         SetAPen( topview->RPort , LINEPEN )  ;
      if ( rightview )
         SetAPen( rightview->RPort , LINEPEN )  ;
   }
   else
   {
      if ( mainview )
         SetAPen( mainview->RPort , 0 )  ;
      if ( topview )
         SetAPen( topview->RPort , 0 )  ;
      if ( rightview )
         SetAPen( rightview->RPort , 0 )  ;
   }
   for ( i = 0 ; i < 20 ; i ++ )
   {
      if ( g.objects[ i ].flags && ( ! g.objects[ i ].collision ) )
      {

         if ( g.follow )
         {
            subdv(   &g.objects[ i ].position ,
                     &g.objects[ g.objectnum ].position , &tv )  ;
            basis( &tv , &g.viewbasis , &np[ i ] )  ;
            subdv(   &g.objects[ i ].oldpos ,
                     &g.objects[ g.objectnum ].oldpos , &tv )  ;
            basis( &tv , &g.viewbasis , &op[ i ] )  ;
         }
         else
         {
            basis( &g.objects[ i ].position , &g.viewbasis , &tv )  ;
            adddv( &tv , &g.viewoffset , &np[ i ] )  ;
            basis( &g.objects[ i ].oldpos , &g.viewbasis , &tv )  ;
            adddv( &tv , &g.viewoffset , &op[ i ] )  ;
         }
         if ( mainview )
            pixel( mainview , op[ i ].x , op[ i ].y )  ;
         if ( topview )
            pixel( topview , op[ i ].x , -op[ i ].z )  ;
         if ( rightview )
            pixel( rightview , -op[ i ].z , op[ i ].y )  ;
      }
   }
   if ( g.trailson )
   {
      if ( mainview )
         SetAPen( mainview->RPort , LINEPEN )  ;
      if ( topview )
         SetAPen( topview->RPort , LINEPEN )  ;
      if ( rightview )
         SetAPen( rightview->RPort , LINEPEN )  ;
      for ( i = 0 ; i < 20 ; i ++ )
      {
         if ( g.objects[ i ].flags && ( ! g.objects[ i ].collision ) )
         {
            if ( mainview )
               line( mainview ,  op[ i ].x , op[ i ].y ,
                                 np[ i ].x , np[ i ].y )  ;
            if ( topview )
               line( topview ,   op[ i ].x , -op[ i ].z ,
                                 np[ i ].x , -np[ i ].z )  ;
            if ( rightview )
               line( rightview , -op[ i ].z , op[ i ].y ,
                                 -np[ i ].z , np[ i ].y )  ;
         }
      }
   }
   if ( mainview )
      SetAPen( mainview->RPort , DOTPEN )  ;
   if ( topview )
      SetAPen( topview->RPort , DOTPEN )  ;
   if ( rightview )
      SetAPen( rightview->RPort , DOTPEN )  ;
   for ( i = 0 ; i < 20 ; i ++ )
   {
      if ( g.objects[ i ].flags && ( ! g.objects[ i ].collision ) )
      {
         if ( mainview )
            pixel( mainview , np[ i ].x , np[ i ].y )  ;
         if ( topview )
            pixel( topview , np[ i ].x , -np[ i ].z )  ;
         if ( rightview )
            pixel( rightview , -np[ i ].z , np[ i ].y )  ;
      }
   }
   p = gcvt( g.elapsedtime , DBL_DIG , &ettext[ 0 ] )  ;
   Move( control->RPort , 234 , 211 )  ;
   Text( control->RPort , &ettext[ 0 ] , strlen( &ettext[ 0 ] ) )  ;
   Text( control->RPort , "                " , 16 )  ;
 }


