/********************************************
**   De revolutionibus orbium coelestium   **
**             ( DeRev.MAIN.c )            **
**               (c) 1988 by               **
**             Jürgen  Brendel             **
********************************************/

#include <math.h>
#include <intuition/intuition.h>

#define MA   100   /* -- maximale Anzahl von Objekten -- */
#define M1   101
#define MENP 19    /* -- Anzahl der Menüpunkte -- */

int    count,code,code2,class,Jahre=0,xx,yy,
       xalt[M1], yalt[M1], p[161];
float  gm[M1],m[M1],x[M1],y[M1],x2[M1],y2[M1],
       Vx[M1],Vy[M1],Faktor,winkel,a,Vabl,xd,yd,
       Zeit,zeit2,gam,var2,fak,ystep,Tage=0.0;
char   string[40],buffer[71],undo[71],z,t,i,anz,start,
       bflag,vflag,uflag,tflag,jflag;

extern                save(), load();
extern long           *OpenLibrary();
extern struct Screen  *OpenScreen();
extern struct Window  *OpenWindow();
struct Screen         *screen;
struct Window         *window, *window2;
struct IntuitionBase  *IntuitionBase;
struct GfxBase        *GfxBase;
struct RastPort       *rport, *rport2;
struct IntuiMessage   *message;
struct IntuiText      mt[MENP];
struct MenuItem       mi[MENP];
struct Menu           menu =
{
  NULL,10,0,186,10,MENUENABLED,"(c) 1988 by J. Brendel",mi
};
struct StringInfo     strinf =
{
  (UBYTE *)&buffer,(UBYTE *)&undo,0,70,0,0,0,0,0,0,0,0,0
};
struct Gadget         strgad =
{
  NULL,3,11,517,10,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,
  STRGADGET,NULL,0,NULL,0,&strinf,NULL,0
};
struct NewScreen      hauptscreen =
{
  0,0,640,512,2,0,1,HIRES | LACE,
  CUSTOMSCREEN,NULL,NULL,NULL,NULL
};
struct NewWindow      hauptwindow =
{
  0,0,640,512,0,1, MENUPICK | MOUSEBUTTONS,
  BORDERLESS | ACTIVATE | SMART_REFRESH,
  NULL,NULL,NULL,NULL,NULL,10,10,640,512,CUSTOMSCREEN
};
struct NewWindow      parawindow =
{
  30,30,370,160,1,3,MOUSEBUTTONS,
  WINDOWDRAG | ACTIVATE,NULL,NULL,NULL,
  NULL,NULL,30,30,370,160,CUSTOMSCREEN
};
struct NewWindow      gragrawindow =
{
  30,0,520,512,1,3,CLOSEWINDOW,
  WINDOWCLOSE | WINDOWDRAG | ACTIVATE | GIMMEZEROZERO,
  NULL,NULL,(UBYTE *)"  GravoGrafik  ",
  NULL,NULL,30,0,520,512,CUSTOMSCREEN
};
struct NewWindow      lswindow =
{
  0,0,521,22,1,3,GADGETUP,WINDOWDRAG | ACTIVATE,
  &strgad,NULL,NULL,NULL,NULL,0,0,520,13,CUSTOMSCREEN
};

  /* -------------------- */
 /* ---- Funktionen ---- */
/* -------------------- */

void openall()
{
  /* ---- Libraries, Screen und Window öffnen ---- */

  if(!(IntuitionBase = (struct IntuitionBase *)
    OpenLibrary("intuition.library", 0))) exit(FALSE);
  if(!(GfxBase = (struct GfxBase *)
    OpenLibrary("graphics.library", 0)))
  { CloseLibrary(IntuitionBase); exit(FALSE); }
  if(!(screen = OpenScreen(&hauptscreen)))
  { CloseLibrary(IntuitionBase); CloseLibrary(GfxBase);
    exit(FALSE); }
  hauptwindow.Screen = parawindow.Screen =
       gragrawindow.Screen = lswindow.Screen = screen;
  if(!(window = OpenWindow(&hauptwindow)))
  { CloseScreen(screen); CloseLibrary(IntuitionBase);
    CloseLibrary(GfxBase); exit(FALSE); }
  rport=window->RPort;

  /* ---- Menüs installieren ---- */

  for(t=0; t<MENP; t++)
  {
    mi[t].NextItem = (t<(MENP-1)) ? &mi[t+1] : NULL;
    mi[t].LeftEdge = 0;     mi[t].TopEdge = t*16;
    mi[t].Width    = 178;   mi[t].Height  = 10;
    mi[t].Flags    = ITEMTEXT | ITEMENABLED | HIGHCOMP;
    mi[t].MutualExclude = NULL;
    mi[t].ItemFill      = (APTR) &mt[t];
    mi[t].Command       = NULL;  mi[t].SubItem = NULL;
    mi[t].NextSelect    = NULL;

    mt[t].FrontPen      = 0;     mt[t].BackPen   = 1;
    mt[t].TopEdge       = 1;     mt[t].LeftEdge  = 5;
    mt[t].DrawMode      = JAM2;  mt[t].ITextFont = NULL;
    mt[t].NextText      = NULL;
  }
  mt[0].IText = "Start";
  mt[1].IText = "Stop";
  mt[2].IText = "Neues Objekt";
  mt[3].IText = "Masse";
  mt[4].IText = "Position";
  mt[5].IText = "Geschwindigkeit";
  mt[6].IText = "Löschen";
  mt[7].IText = "Zeigen";
  mt[8].IText = "Zeitintervall";
  mt[9].IText = "Fixstern (JA)";
  mt[10].IText = "Vergrößerung";
  mt[11].IText = "Uhr";
  mt[12].IText = "Gravo - Grafik";
  mt[13].IText = "Neuer Nullpunkt";
  mt[14].IText = "Bildschirm löschen";
  mt[15].IText = "Laden";
  mt[16].IText = "Speichern";
  mt[17].IText = "Neu";
  mt[18].IText = "Ende";

  SetMenuStrip(window, &menu);
  SetRGB4(&(screen->ViewPort), 0,  0,  0,  7);
  SetRGB4(&(screen->ViewPort), 1,  3, 15,  3);
  SetRGB4(&(screen->ViewPort), 2, 15, 15, 15);
  SetRGB4(&(screen->ViewPort), 3, 15,  0,  0);
}

void startwerte()
{
  for(t=0; t<MA; t++)
  { m[t]=1.0e6; x[t]=0.0; y[t]=0.0; Vx[t]=0.0; Vy[t]=0.0; }

  m[1]=1.989e15; x[1] =   0.0;  y[1] =  0.0;  /* Sonne */
                Vx[1] =   0.0; Vy[1] =  0.0;
  m[2]=0.333e09; x[2] =  57.9;  y[2] =  0.0;  /* Merkur */
                Vx[2] =   0.0; Vy[2] = 47.9;
  m[3]=4.870e09; x[3] = 108.2;  y[3] =  0.0;  /* Venus */
                Vx[3] =   0.0; Vy[3] = 35.0;
  m[4]=5.977e09; x[4] = 149.6;  y[4] =  0.0;  /* Erde */
                Vx[4] =   0.0; Vy[4] = 29.765;
  m[5]=0.644e09; x[5] = 227.9;  y[5] =  0.0;  /* Mars */
                Vx[5] =   0.0; Vy[5] = 24.1;
  m[6]=1.899e12; x[6] = 778.3;  y[6] =  0.0;  /* Jupiter */
                Vx[6] =   0.0; Vy[6] = 13.1;
  m[7]=5.684e11; x[7] = 1427.0;  y[7] =  0.0; /* Saturn */
                Vx[7] =   0.0; Vy[7] = 9.6;
  m[8]=8.676e10; x[8] = 2870.0;  y[8] =  0.0; /* Uranus */
                Vx[8] =   0.0; Vy[8] = 6.9;
  m[9]=1.029e11; x[9] = 4496.0;  y[9] =  0.0; /* Neptun */
                Vx[9] =   0.0; Vy[9] = 5.4;
  start=2; mt[9].IText = "Fixstern (JA)"; uflag=0;
  Faktor=1.7e9; anz=0; Zeit=86400.0; zeit2=Zeit/3600.0;
  fak=50000000.0; ystep=1.0; gam=.00667*(Zeit/1.0e5);
}

void wertaufbereiten()
{
  gm[t]=gam*m[t];
  x2[t]=(x[t]*=1.0e9);  y2[t]=(y[t]*=1.0e9);
  Vx[t]*=(Zeit*1000.0); Vy[t]*=(Zeit*1000.0);
  xalt[t]=320+(int)(x[t]/Faktor);
  yalt[t]=256+(int)(y[t]/Faktor);
}

void ifuflag()
{
  if(uflag == 1)
  {
    SetAPen(rport, 2);
    if(tflag==1)
    {
      sprintf(string,"Tage: %.1f  ",Tage);
      Move(rport, 0, 8);
      Text(rport, (int)string, (int)(strlen(string)));
    }
    sprintf(string,"Jahre: %ld  ",Jahre);
    Move(rport, 290, 8);
    Text(rport, (int)string, (int)(strlen(string)));
  }
}

void clearscreen(neum)
char neum;
{
  Move(rport, 0, 0); ClearScreen(rport); ifuflag();
  SetAPen(rport,2);
  if(neum == 1)
    for(t=1; t<=anz; t++)
      WritePixel(rport, xalt[t], yalt[t]);
}

void print(s,aa,bb)
char *s;  int aa,bb;
{
  Move(rport2, (int)aa, (int)bb);
  Text(rport2, (int)s, (int)(strlen(s)));
}

void rec(s,aa,bb)
char *s;  int aa,bb; 
{
  int breite=19;
  if(aa == -1)
  { aa=310; bb=130; breite=27; s="OK"; }
  Move(rport2,(int)         aa, (int)     bb);
  Draw(rport2,(int)(aa+breite), (int)     bb);
  Draw(rport2,(int)(aa+breite), (int)(bb+19));
  Draw(rport2,(int)         aa, (int)(bb+19));
  Draw(rport2,(int)         aa, (int)     bb);
  print(s,aa+6,bb+12);
}

void button()
{
  message = (struct IntuiMessage *)GetMsg(window2->UserPort);
  code=message->Code; class=message->Class;
  for(count=0; count<8000; count++);
  if(class == MOUSEBUTTONS)
  {
    if(code == SELECTUP) bflag=0;
    if(code == SELECTDOWN) bflag=1;
  }
}

char booltest(wtitle,text)
char *wtitle, *text;
{
  parawindow.Title = wtitle; parawindow.Height = 110;
  rport2=(window2=OpenWindow(&parawindow))->RPort;
  vflag = 2; SetAPen(rport2, 2);
  rec("J",40,30); rec("N",40,60); SetAPen(rport2, 3);
  sprintf(string,"%s",text); print(string,88,57);
  while(vflag == 2)
  {
    button(); vflag = 2;
    if(bflag == 1)
    {
      xx=window2->MouseX; yy=window2->MouseY;
      if(xx>=40 && xx<=59 && yy>=30 && yy<=49) vflag=1;
      if(xx>=40 && xx<=59 && yy>=60 && yy<=79) vflag=0;
    }
  }
  for(count=0; count<10000; count++);
  CloseWindow(window2); parawindow.Height = 160;
  bflag = 0; return vflag;
}

float einst(kr,wtitle,text,schritt,sfak,sfak2,var,max,min,smax,kom,exp)
char kr, *wtitle, *text, kom, exp;
float schritt,sfak,sfak2,var,max,min,smax;
{
  float schritt2=schritt; int fl=0; char exflag;
  if(kr > 0) fl=22; if(kr == 1) text=" ( km/s ): ";
  if(kr == 2) text=" ( Mill. km ): ";
  parawindow.Title = wtitle;
  rport2=(window2=OpenWindow(&parawindow))->RPort;
  SetAPen(rport2, 2); rec("",-1,0);
  rec("+",40+fl,30); rec("-",40+fl,60);
  if(kr > 0) { rec("-",40,45); rec("+",84,45); }
  SetAPen(rport2, 3); exflag=0;
  while(exflag == 0)
  {
    button(); vflag=0;
    if(bflag == 1)
    {
      xx=window2->MouseX; yy=window2->MouseY;
      if(xx>=40+fl && xx<=59+fl && yy>=30 && yy<=49)
        { var+=(schritt*sfak); vflag=1; }
      if(xx>=40+fl && xx<=59+fl && yy>=60 && yy<=79)
        { var-=(schritt*sfak); vflag=1; }
      if(xx>=310 && xx<=337 && yy>=130 && yy<=159)
        exflag=1;
      if(kr > 0)
      {
        if(xx>=40 && xx<=59 && yy>=46 && yy<=65)
          { var2-=(schritt*sfak); vflag=1; }
        if(xx>=84 && xx<=103 && yy>=46 && yy<=65)
          { var2+=(schritt*sfak); vflag=1; }
      }
    }
    if(var > max) { var = min;  schritt = schritt2; }
    if(var < min) { var = max;  schritt = schritt2; }
    if(var2 > max) { var2 = min;  schritt = schritt2; }
    if(var2 < min) { var2 = max;  schritt = schritt2; }
    if(exp == 1 && schritt == schritt2)
    {
      schritt=1.0;
      while( (schritt*=10.0) < var ); schritt/=1.0e4;
    }
    if(kom > 0 && exp == 0)
    {
      if(kom == 2)
        sprintf(string,"%s%.3f      ",text,var/sfak);
      else
      {
        if(kr == 0)
          sprintf(string,"%s%.1f        ",text,var/sfak);
        if(kr == 1)
          sprintf(string,"Y%s%.3f      ",text,var/sfak);
        if(kr == 2)
          sprintf(string,"Y%s%.1f      ",text,var/sfak);
      }
    }
    else
      sprintf(string,"%s%.0f        ",text,var/sfak);
    if(exp == 1)
      sprintf(string,"%s%.3e   ",text,var/sfak);
    if(kr == 0) print(string,88,57);
    else
    {
      print(string,95,83);
      if(kr == 1)
        sprintf(string,"X%s%.3f      ",text,var2/sfak);
      if(kr == 2)
        sprintf(string,"X%s%.1f      ",text,var2/sfak);
      print(string,95,30);
    }
    if(vflag == 1)
    {
      schritt*=sfak2;
      if(schritt>smax) schritt=smax;
      if(( kr>0 && (xx>=40+fl && xx<=59+fl) ) || kr == 0 )
      {
        if(schritt*sfak > abs(var)/5.0 && yy>=60)
          schritt=abs(var)/5.0/sfak;
      }
      else
        if(schritt*sfak > abs(var2)/5.0 && xx<=40+fl)
          schritt=abs(var2)/5.0/sfak;
    }
    else
    {
      schritt=schritt2;
      if(exp == 1)
      {
        schritt=1.0;
        while( (schritt*=10.0) < var ); schritt/=1.0e4;
      }
    }
  }
  CloseWindow(window2); bflag=0; return var;
}

void lsgadwart()
{
  window2 = OpenWindow(&lswindow);
  class = GADGETDOWN;
  while(class != GADGETUP)
  {
    message = (struct IntuiMessage *)GetMsg(window2->UserPort);
    class = message->Class;
  }
  strcpy(undo,buffer); CloseWindow(window2);
}

void posinp(ob)
int ob;
{
  char naeheflag=1; int bp;
  bp = (int)(booltest(" Achtung! ",
              "Bildschirmposition? (J/N)"));
  for(count=1; count<10000; count++);
  while(naeheflag == 1)
  {
    if(bp == 1)
    {
      code = 0; class = 0; SetAPen(rport, 2);
      while(!(class == MOUSEBUTTONS && code == SELECTUP))
      {
        message = (struct IntuiMessage *)GetMsg(window->UserPort);
        class=message->Class; code=message->Code;
        xd=(float)((window->MouseX)-320);
        yd=(float)((window->MouseY)-256);
        sprintf(string," X ( Millionen km ): %.1f        ",
               xd*Faktor/1.0e9);
        Move(rport, 0, 8);
        Text(rport, (int)string, (int)(strlen(string)));
        sprintf(string,"   Y ( Millionen km ): %.1f       ",
               yd*Faktor/-1.0e9);
        Move(rport, 290, 8);
        Text(rport, (int)string, (int)(strlen(string)));
      }
      SetAPen(rport,0); RectFill(rport, 0, 0, 640, 9);
      ifuflag();
    }
    else
    { xd=x[ob]/Faktor; yd=y[ob]/Faktor; }
    var2=xd*Faktor/1.0e9;
    y[ob] = 1.0e9*einst(2,"  Position  ","",0.1,1.0,
     1.1,yd*Faktor/-1.0e9,1.0e6,-1.0e6,100000.0,1,0);
    x[ob]=var2*1.0e9; y[ob]=-y[ob]; naeheflag=0;
    for(t=1; t<anz; t++)
      if(abs(x[ob]-x[t]) < 100000000.0 && t!=ob &&
        abs(y[ob]-y[t]) < 100000000.0) naeheflag = 1;
  }
  SetAPen(rport, 0l);
  WritePixel(rport, xalt[ob], yalt[ob]);
}

void tausch(xt,yt)
int xt,yt;
{
  x[xt]=x[yt]; y[xt]=y[yt];
  x2[xt]=x2[yt]; y2[xt]=y2[yt];
  xalt[xt]=xalt[yt]; yalt[xt]=yalt[yt];
  Vx[xt]=Vx[yt]; Vy[xt]=Vy[yt];
  m[xt]=m[yt]; gm[xt]=gm[yt];
}

  /* --------------------- */
 /* --- Menü - Punkte --- */
/* --------------------- */

void bewegung()
{
  register char tt,ii;
  while(class != MENUPICK)
  {
    message = (struct IntuiMessage *)GetMsg(window->UserPort);
    class = message->Class;
    if(uflag == 1)
    {
      SetAPen(rport, 2); Tage+=zeit2/24.0;
      while(Tage>365.0) { Tage-=365.0; Jahre++; jflag=1; }
      if(Jahre>2000000000) Jahre=0;
      if(zeit2 < 8760.0 && tflag==1)
      {
        sprintf(string,"Tage: %.1f  ",Tage);
        Move(rport, 0, 8);
        Text(rport, (int)string, (int)(strlen(string)));
      }
      if(jflag == 1)
      {
        sprintf(string,"Jahre: %ld  ",Jahre);
        Move(rport, 290, 8); jflag=0;
        Text(rport, (int)string, (int)(strlen(string)));
      }
    }
    for(tt=start; tt<=anz; tt++)
    { x2[tt]=x[tt]; y2[tt]=y[tt]; }
    for(tt=start; tt<=anz; tt++)
    {
      SetAPen(rport,3); WritePixel(rport,xalt[tt],yalt[tt]);
      xalt[tt]=320+(int)(x[tt]/Faktor);
      yalt[tt]=256+(int)(y[tt]/Faktor);
      SetAPen(rport,2); WritePixel(rport,xalt[tt],yalt[tt]);
      y[tt]-=Vy[tt]; x[tt]-=Vx[tt];
      for(ii=1; ii<=anz; ii++)
      {
        if(ii!=tt)
        {
          xd=x[tt]-x2[ii]; yd=y[tt]-y2[ii]+1.0e-15;
          winkel=atan(yd/xd); xd/=1.0e6; yd/=1.0e6;
          Vabl = (xd>0.0) ? (gm[ii]/(xd*xd+yd*yd)) :
                            (-gm[ii]/(xd*xd+yd*yd));
          Vx[tt]+=cos(winkel)*Vabl*Zeit;
          Vy[tt]+=sin(winkel)*Vabl*Zeit;
        }
      }
    }
  }
}

void neu()
{
  float ber=1; posinp((int)(++anz));
  while( (ber*=10.0) < m[anz] ); ber/=1.0e10;
  m[anz] = einst(0,"  Masse  ","Trillionen Tonnen: ",
        ber,1.0,1.15,m[anz]/1.0e6,1.0e12,0.00001,1.0e11,0,1);
  m[anz]*=1.0e6; gm[anz]=gam*m[anz];
  Vy[anz]/=Zeit; var2=Vx[anz]/Zeit/-1000.0;
  Vy[anz] = einst(1,"  Geschwindigkeit  ","",0.001,
      1.0,1.15,Vy[anz]/1000.0,1.0e4,-1.0e4,1000.0,1,0);
  Vx[anz]=var2*Zeit*-1000.0; Vy[anz]*=1000.0*Zeit;
  x2[anz]=x[anz]; y2[anz]=y[anz];
  xalt[anz]=320+(int)(x[anz]/Faktor);
  yalt[anz]=256+(int)(y[anz]/Faktor);
  SetAPen(rport, 2); WritePixel(rport,xalt[anz],yalt[anz]);
}

void masse()
{
  float ber=1;
  int obn = (int)(einst(0,"  Masse  ","Objekt: ",
     1.0,1.0,1.0,1.0,(float)anz,1.0,1.0,0,0));
  while( (ber*=10.0) < m[obn] ); ber/=1.0e10;
  m[obn] = einst(0,"  Masse  ","Trillionen Tonnen: ",
       ber,1.0,1.15,m[obn]/1.0e6,1.0e12,0.00001,1.0e11,0,1);
  m[obn]*=1.0e6; gm[obn]=gam*m[obn];
}

void position()
{
  int obn = (int)(einst(0,"  Position  ","Objekt: ",
     1.0,1.0,1.0,1.0,(float)anz,1.0,1.0,0,0));
  posinp(obn); SetAPen(rport,2); x2[obn]=x[obn]; y2[obn]=y[obn];
  WritePixel(rport, (xalt[obn]=320+(int)(x[obn]/Faktor)),
    (yalt[obn]=256+(int)(y[obn]/Faktor)));
}

void geschw()
{
  int obn = (int)(einst(0,"  Geschwindigkeit  ","Objekt: ",
     1.0,1.0,1.0,1.0,(float)anz,1.0,1.0,0,0));
  Vy[obn]/=Zeit; var2=Vx[obn]/Zeit/-1000.0;
  Vy[obn] = einst(1,"  Geschwindigkeit  ","",0.001,
      1.0,1.15,Vy[obn]/1000.0,1.0e4,-1.0e4,1000.0,1,0);
  Vx[obn]=var2*Zeit*-1000.0; Vy[obn]*=1000.0*Zeit;
}

void loesch()
{
  int obn = (int)(einst(0,"  Löschen  ","Objekt: ",
     1.0,1.0,1.0,1.0,(float)anz,1.0,1.0,0,0));
  if(((int)(booltest(" Achtung! ",
                     "Wirklich löschen? (J/N)"))) == 1)
  {
    if(obn==1) { start=1; mt[9].IText="Fixstern (NEIN)"; }
    tausch(M1,obn); SetAPen(rport,0);
    WritePixel(rport,xalt[obn],yalt[obn]);
    if(obn < anz--)
    {
      for(t=obn; t<=anz; t++)
        tausch(t,t+1);
      tausch(anz+1,M1);
    }
  }
}

void zeig()
{
  int obn = (int)(einst(0,"  Zeigen  ","Objekt: ",
     1.0,1.0,1.0,1.0,(float)anz,1.0,1.0,0,0)); t=0;
  for(count=0; count<5500; count++)
  {
    SetAPen(rport, (int)t); t++; if(t>3) t=0;
    WritePixel(rport, xalt[obn], yalt[obn]);
  }
  SetAPen(rport,2); WritePixel(rport,xalt[obn],yalt[obn]);
}

void zeit()
{
  for(t=1; t<MA; t++) { Vx[t]/=Zeit; Vy[t]/=Zeit; }
  Zeit = einst(0,"  Zeit  ","Zeit (h): ",0.1,3600.0,
      1.1,Zeit,9.0e7,0.09,1000.0,1,0);
  for(t=1; t<MA; t++) { Vx[t]*=Zeit; Vy[t]*=Zeit; }
  gam=.00667*(Zeit/1.0e5); zeit2=Zeit/3600.0;
  for(t=1; t<MA; t++) gm[t]=gam*m[t];
}

void vergr()
{
  Faktor = einst(0,"  Vergrößerung  ","Mill. km pro Punkt: ",0.1,
       1.0,1.1,Faktor/1.0e9,1000.0,0.0,100.0,1,0);
  Faktor*=1.0e9; SetAPen(rport, 3);
  for(t=1; t<MA; t++)
  { xalt[t]=320+(int)(x[t]/Faktor);
    yalt[t]=256+(int)(y[t]/Faktor); }
}

void uhr()
{
  if(((int)(booltest(" Uhr ","Uhr? (J/N)"))) == 1)
  {
    uflag=1; tflag=0;
    if(((int)(booltest(" Uhr ",
           "Auf null setzen? (J/N)"))) == 1)
    { Tage=0.0; Jahre=0; }
    if(((int)(booltest(" Uhr ","Tage? (J/N)"))) == 1)
      tflag=1;
    SetAPen(rport,0); RectFill(rport,0,0,640,9);
    SetAPen(rport,2);
    if(tflag==1)
    {
      sprintf(string,"Tage: %.1f  ",Tage);
      Move(rport, 0, 8);
      Text(rport, (int)string, (int)(strlen(string)));
    }
    sprintf(string,"Jahre: %ld           ",Jahre);
    Move(rport, 290, 8); jflag=0;
    Text(rport, (int)string, (int)(strlen(string)));
  }
  else
  {
    SetAPen(rport, 0); RectFill(rport, 0, 0, 640, 9);
    uflag=0;
  }
}

void gragraf()
{
  register char ii; float y0,x0,v,xl,yl;
  register int yyy,xt,yt=425,xstart=96;
  fak = einst(0,"  Vergrößerung  ","Dehnungsfaktor: ",1.0,
     1.0,1.5,fak,500000000.0,1.0,10000000.0,0,0);
  ystep = 16.0/einst(0,"  Genauigkeit  ",
   "Schritte pro Zeile: ",1.0,1.0,1.0,ystep,16.0,1.0,1.0,0,0);
  if(window2=OpenWindow(&gragrawindow))
  {
    rport2=window2->RPort;
    for(yyy=1; yyy<=512; yyy+=16)
    {
      if((struct IntuiMessage *)GetMsg(window2->UserPort))
        goto gragraschluss;
      xl=(float)(2*xstart); yt+=2; yl=(float)yt;
      for(y0=(float)yyy; y0<=(float)yyy+16.0; y0+=ystep)
      {
        xt=1;
        for(x0=1.0; x0<=640.0; x0+=4.0)
        {
          v=0.0;
          for(ii=start; ii<=anz; ii++)
          {
            if(v < 5000.0)
            {
              xd=(x0-(float)320)*Faktor-x[ii]+1.0e-18;
              yd=(y0-(float)256)*Faktor-y[ii];
              winkel=atan(yd/xd); xd/=1.0e6; yd/=1.0e6;
              v+=((gm[ii]/(xd*xd+yd*yd))*fak/1.0e4);
            }
          }
          if(v > 800.0) v=800.0;
          p[xt]=(p[xt++]+(int)v)/2;
        }
      }
      for(xt=1, x0=1.0; x0<=640.0; x0+=4.0)
      {
        SetAPen(rport2, 0);
        Move(rport2, (int)(xl+1.0), yt+1);
        Draw(rport2, (int)(xl+1.0), yt-p[xt]+1);
        Move(rport2, (int)xl, (int)yl);
        xl=2.0*((float)xstart+x0/4.0); yl=(float)(yt-p[xt]);
        SetAPen(rport2, 3); Draw(rport2,(int)xl,(int)yl);
        p[xt++]=0;
      }
      Draw(rport2, (int)xl, yt); xstart-=3;
    }
    Wait(1 << window2->UserPort->mp_SigBit);
gragraschluss:
    CloseWindow(window2);
  }
  ystep=16.0/ystep;
}

void neunull()
{
  class = 0; SetAPen(rport, 2);
  while(!(class == MOUSEBUTTONS && code == SELECTUP))
  {
    message = (struct IntuiMessage *)GetMsg(window->UserPort);
    class=message->Class; code=message->Code;
    xx=(window->MouseX)-320; yy=(window->MouseY)-256;
    sprintf(string," X: %ld   ",xx);
    Move(rport, 0, 8);
    Text(rport, (int)string, (int)(strlen(string)));
    sprintf(string,"   Y: %ld   ",yy);
    Move(rport, 290, 8);
    Text(rport, (int)string, (int)(strlen(string)));
  }
  for(t=1; t<MA; t++)
  { x2[t]=(x[t]-=(float)xx*Faktor);
    y2[t]=(y[t]-=(float)yy*Faktor);
    xalt[t]-=xx; yalt[t]-=yy; }
  clearscreen(1);
}

void speichern()
{
  lswindow.Title = "  Save  "; lsgadwart(); save();
}

void laden()
{
  if((booltest(" Achtung! ",
     "Wirklich laden? (J/N)")) == 1)
  {
    lswindow.Title = "  Load  ";
    lsgadwart(); SetAPen(rport, 0);
    for(t=1; t<=anz; t++)
      WritePixel(rport, xalt[t], yalt[t]);
    load(); SetAPen(rport, 2);
    if(start == 2)
      mt[9].IText = "Fixstern (JA)";
    else
      mt[9].IText = "Fixstern (NEIN)";
    for(t=1; t<=anz; t++)
      WritePixel(rport, (xalt[t]=320+(int)(x[t]/Faktor)),
        (yalt[t]=256+(int)(y[t]/Faktor)));
  }
}

  /* ----------------------- */
 /* ---- Hauptprogramm ---- */
/* ----------------------- */

main()
{
  openall(); startwerte(); clearscreen(0); code=0; class=0;
  for(t=1; t<MA; t++) wertaufbereiten();

  while(1)
  {
    while(class != MENUPICK)
    { message = (struct IntuiMessage *)GetMsg(window->UserPort);
      code = message->Code; class=message->Class; }
    if (code == MENUNULL) { code = 0; class = 0; }
    else
    {
      class = 0;
      switch( ITEMNUM (code) )
      {
        case 0:                     /* Start */
          code2 = code; SetAPen(rport, 2);
          for(t=1; t<=anz; t++)
            WritePixel(rport, xalt[t], yalt[t]);
          bewegung();
          if((code = message->Code)==MENUNULL)
            code = code2;
          break;
        case 1:                     /* Stop */
          code = 0; break;
        case 2:                     /* Neues Objekt */
          code = 0; neu(); break;
        case 3:                     /* Masse */
          code = 0; if(anz>0) masse(); break;
        case 4:                     /* Position */
          code = 0; if(anz>0) position(); break;
        case 5:                     /* Geschwindigkeit */
          code = 0; if(anz>0) geschw(); break;
        case 6:                     /* Löschen */
          code = 0; if(anz>0) loesch(); break;
        case 7:                     /* Zeigen */
          code = 0; if(anz>0) zeig(); break;
        case 8:                     /* Zeitintervall */
          code = 0; zeit(); break;
        case 9:                     /* Fixstern (JA/NEIN) */
          code = 0;
          if(start == 1)
          { start=2; mt[9].IText = "Fixstern (JA)"; }
          else
          { start=1; mt[9].IText = "Fixstern (NEIN)"; }
          break;
        case 10:                     /* Vergrößerung */
          code = 0; vergr(); clearscreen(1); break;
        case 11:                    /* Uhr */
          code = 0; uhr(); break;
        case 12:                    /* Gravo - Grafik */
          code = 0; gragraf(); break;
        case 13:                    /* Neuer Nullpunkt */
          code = 0; neunull(); break;
        case 14:                    /* Bildschirm löschen */
          code = 0;
          if((booltest(" Achtung! ",
                       "Bildschirm löschen ? (J/N)")) == 1)
            clearscreen(1);
          break;
        case 15:                    /* Laden */
          code = 0; laden(); break;
        case 16:                    /* Speichern */
          code = 0; if(anz>0) speichern(); break;
        case 17:                    /* Neu */
          code = 0;
          if((booltest(" Achtung! ",
                       "Wirklich neu? (J/N)")) == 1)
          { startwerte();
            for(t=1; t<MA; t++) wertaufbereiten();
            clearscreen(); }
          break;
        case 18:                    /* Ende */
          code = 0;
          if((booltest(" Achtung! ",
                       "Wirklich beenden? (J/N)")) == 1)
          {
            ClearMenuStrip(window); CloseWindow(window);
            CloseScreen(screen); CloseLibrary(IntuitionBase);
            CloseLibrary(GfxBase); exit(TRUE);
          }
      }
    }
  }
}
