/**************************************************************************/
/* Fraktal.c                                                   27.01.88   */
/* Version 4.0                                                            */
/*                                                                        */
/*                                                                        */
/* 1. Auswertung einer komplexen Nullstellen-Suche an Hand der Funktionen */
/*    (3)  z^5-1=0                                                        */
/*    (2)  z^4-1=0                                                        */
/*    (1)  z^3-1=0                                                        */
/* Untersuchung eines Attraktors  mit  entsprechender Farbinterpretation. */
/* (Farbe wird nach Anzahl der notwendigen Durchlaeufen bis zum Erreichen */
/* des Attraktors errechnet.)                                             */
/*    (3)   Attraktor z=.3090+i*.9510                                     */
/*          Attraktor z=-.8090+i*.5877                                    */
/*          Attraktor z=-.8090-i*.5877                                    */
/*          Attraktor z=.3090-i*.9510                                     */
/*          Attraktor z=1                                                 */
/*    (2)   Attraktor z=1                                                 */
/*          Attraktor z=i                                                 */
/*          Attraktor z=-1                                                */
/*          Attraktor z=-i                                                */
/*    (1)   Attraktor z=-.5+i*.866                                        */
/*          Attraktor z=-.5-i*.866                                        */
/*          Attraktor z=1                                                 */
/*                                                                        */
/* 2. Auswertung der komplexen Folge z^2-c=z                              */
/*    z(0)=0,c Bildpunkt -> Mandelbrodt-Ebene (Apfelmaennchen)            */
/*                                                                        */
/* 3. Auswertung der komplexen Folge z^3-c=z                              */
/*    z(0)=0,c Bildpunkt                                                  */
/*                                                                        */
/* 4. Auswertung der komplexen Folge z^4-c=z                              */
/*    z(0)=0,c Bildpunkt                                                  */
/*                                                                        */
/* 5. Auswertung der komplexen Folge z^5-c=z                              */
/*    z(0)=0,c Bildpunkt                                                  */
/*                                                                        */
/* 6. Auswertung der komplexen Folge z^2-c=z                              */
/*    z(0) Bildpunkt, c fest -> Julia-Menge                               */
/*                                                                        */
/* 7. Auswertung der komplexen Folge z^3-c=z                              */
/*    z(0) Bildpunkt, c fest                                              */
/*                                                                        */
/* 8. Auswertung der komplexen Folge z^4-c=z                              */
/*    z(0) Bildpunkt,c fest                                               */
/*                                                                        */
/* 9. Auswertung der komplexen Folge z^5-c=z                              */
/*    z(0) Bildpunkt, c fest                                              */
/*                                                                        */
/*                                                                        */
/* fuer Markt+Technik geschrieben von Heiko Knappe                        */
/*                                                                        */
/* Komplexe Dynamische Systeme                                            */
/**************************************************************************/


#include <exec/types.h>
#include <libraries/dos.h>
#include <math.h>
#include <intuition/intuition.h>
/* Einbinden des Definitionsfiles */
#include "fraktal.menu"

#define MIN 1e-10          /* kritischer Punkt? */

/* Variablen fuer die Uebergabe der frame-Werte                   */
extern float rxmin,rxmax,rymin,rymax;

/* Einbinden der externen Funktionen */
extern short save(),load(),frame();

char  funktion=0,resolution=0;/* welche Funktion? welche Aufloesung? */
char  anzcol;      /* Anzahl der Farben in der jeweiligen Aufloesung */
int   i;
float r1,r2,i1,i2;            /* Real- und Imaginaerteil der Folge   */
int   n,nmax=100,noff=0;      /* Iterationsschritte                  */
float emin=.001,emax=1000;    /* Abbruchkriterium                    */
float rmin=-1.5,rmax=1.5;     /* Grenzen des Bildes                  */
float imin=-1.5,imax=1.5;
float vrmin,vrmax,vimin,vimax;/* ViewPort-Definition                 */
float nsre[5],nsim[5];        /* Nullstellen                         */
float rst,ist;                /* Schrittweite                        */
short x=0,y=0,col;            /* x,y->Punktkoordinaten               */
float cre,cim,re,im,re1,re2,im1,im2,h1,h2,h3,h4;
                              /* cre,cim fuer Julia/Mandel           */
                              /* re,im laufender Re- und Im-Teil     */
                              /* re1,re2,im1,im2  -> Folgenglieder   */
                              /* h1,..h5 -> Hilfsvariable            */
float d[5];                   /* Abstaende zu den Nullstellen        */
char text[]="Komplexe Dynamische Systeme";
short x0=0,y0=0;              /* Koordinaten nach dem Laden          */
short width,height;           /* zum Rechnen                         */
short xs,ys,ye,fxoff,fyoff,yoff;
short bwf,britef,dreidf,pagef;/* Flags fuer Extra-Menu               */
int gridstep=10;              /* Anzahl der Gitterunterteilungen     */
int fak=1;                    /* Multiplikator fuer n bei 3d Ausgabe */


/***********************/
/* Hauptprogramm       */
/***********************/

main()
{
 emin*=emin,emax*=emax;
 open_things();
 for(;;)  /* solange Programm nicht beendet wird */
 {
    while((MyMessage=GetMsg(MyWindow->UserPort))==0);
    ReplyMsg(MyMessage);
    switch(MyMessage->Class)
    {
        case CLOSEWINDOW: close_things();
        case GADGETUP:    /* nur ein Gadget! */
                          strcpy(File,F);
                          for(i=0;File[i]!=' '&&i<80;++i);
                          File[i]=0;
                          strcpy(Fileh,File);
                          strcpy(Fileh+strlen(Fileh),".info");
                          break;
        case MENUPICK:    do_menu(MyMessage->Code);
                          break;
    }
 }
}


/***********************/
/* Initialisierung     */
/***********************/

open_things()
{
 IntuitionBase=OpenLibrary("intuition.library",0);
 if(IntuitionBase==0)
    close_things();
 GfxBase=OpenLibrary("graphics.library",0);
 if(GfxBase==0)
    close_things();
 MyWindow=OpenWindow(&MyNewWindow);
 if(MyWindow==0)
    close_things();
 SetMenuStrip(MyWindow,&MYFIRSTMENU);
 SetWindowTitles(MyWindow,MyNewWindow.Title,"von H. Knappe fÜr M&T 1987");
} 


close_things()
{
 if(IntuitionBase!=0) CloseLibrary(IntuitionBase);
 if(GfxBase!=0) CloseLibrary(GfxBase);
 if(MyWindow!=0) CloseWindow(MyWindow);
 exit();
} 

/* Screen des gewaehlten Formats oeffnen */
open_work()
{
 TOPEDGE=25;
 switch(resolution)
 {
    case 0:
      WIDTH=320;HEIGHT=250;DEPTH=5;FLAGS=0;anzcol=32;
      fxoff=10;fyoff=95;yoff=5;width=150;height=150;break;
    case 1:
      WIDTH=640;HEIGHT=250;DEPTH=4;FLAGS=HIRES;anzcol=16;
      fxoff=20;fyoff=95;yoff=5;width=450;height=150;break;
    case 2:
      WIDTH=320;HEIGHT=500;DEPTH=5;FLAGS=LACE;anzcol=32;
      fxoff=10;fyoff=190;yoff=10;width=100;height=200;break;
    case 3:
      WIDTH=640;HEIGHT=500;DEPTH=4;FLAGS=HIRES+LACE;anzcol=8;
      fxoff=20;fyoff=190;yoff=10;width=300;height=300;break;
    default: /* unsinnige Aufloesung */
      DisplayBeep(0);
      return(1);
 }
 if((resolution==2)||(resolution==3))
    TOPEDGE=50;
 if((DEPTH==5)&&(britef!=0))
 {
    DEPTH=6;  /* Extra_HalfBrite Modus setzen */
    anzcol=64;
    if(resolution==0) FLAGS=EXTRA_HALFBRITE;
    if(resolution==2) FLAGS=EXTRA_HALFBRITE+LACE;
 }
 MyScreen=OpenScreen(&MyNewScreen);
 set_colors();
 if(MyScreen==0)
 {
    DisplayBeep(0);
    return(1);
 }
 /* Oeffnen eines Screen fuellenden Windows */
 NewWorkWindow.Screen=MyScreen;
 WorkWindow=OpenWindow(&NewWorkWindow);
 if(WorkWindow==0)
 {
    DisplayBeep(0);
    close_work();
    return(1);
 }
 SetMenuStrip(WorkWindow,&WORKMENU);
 rp=WorkWindow->RPort;
 return(0);
}

close_work()
{
 x0=y0=0;
 BW=OFF,bwf=0;
 PAGE=OFF,pagef=0;
 if(WorkWindow!=0) CloseWindow(WorkWindow);
 if(MyScreen!=0) CloseScreen(MyScreen);
 WorkWindow=MyScreen=0;
}


set_colors()
{
 SHORT j;
 struct ViewPort *vp;

 vp=&(MyScreen->ViewPort);
 if((britef==0)||(resolution==1)||(resolution==3))
 { 
 SetRGB4(vp,0,0,0,0);      /* Hintergrund schwarz */
 for(i=1;i<anzcol/2;++i)
    SetRGB4(vp,i,(int)(15*((float)i*2/(float)anzcol)),0,0);
 for(i=anzcol/2;i<anzcol;++i)
    SetRGB4(vp,i,15-(int)(15*((float)i/(float)anzcol)),0,
            (int)(15*((float)i/(float)anzcol)));
 }
 else
 {  /* fuer Brite Modus Farben setzen */
    for(i=8,j=0;i<16;i+=2,++j)
    {
       SetRGB4(vp,j,0,0,i);
       SetRGB4(vp,j+4,i-1,0,i);
       SetRGB4(vp,j+8,i,0,i);
       SetRGB4(vp,j+12,i,0,0);
       SetRGB4(vp,j+16,0,i,0);
       SetRGB4(vp,j+20,i,i,0);
       SetRGB4(vp,j+24,0,i,i);
       SetRGB4(vp,j+28,i,i,i);
    }
 } 
}

set_bw()
{
 struct ViewPort *vp;

 vp=&(MyScreen->ViewPort);
 for(i=0;i<anzcol;i+=2) SetRGB4(vp,i,0,0,0); /* schwarz */
 for(i=1;i<anzcol;i+=2) SetRGB4(vp,i,15,15,15); /* weiss */
}


/***********************/
/* Menu-Abfrage        */
/***********************/

do_menu(MyCode)
USHORT MyCode;
{
 short menu=MENUNUM(MyCode),item=ITEMNUM(MyCode),subitem=SUBNUM(MyCode);
 long file;
 
 switch(menu)
 {
    case 0: /* Projekt Menu */
    switch(item)
    {
       case 0: /* Laden */
          if((file=Open(Fileh,MODE_OLDFILE))==0)
          {
             if(load(File,0)!=0)
             {
                DisplayBeep(0);  /* erfolgreich? */
                break;
             }
          }
          else
          {
             Read(file,&MyInfo,sizeof(MyInfo));
             Close(file);
             rmin=MyInfo.rmin,rmax=MyInfo.rmax;
             imin=MyInfo.imin,imax=MyInfo.imax;
             cim=MyInfo.cim,cre=MyInfo.cre;
             x0=MyInfo.mx,y0=MyInfo.my;
             emin=MyInfo.emin;   /* Quadrate abgespeichert! */
             emax=MyInfo.emax,nmax=MyInfo.nmax,noff=MyInfo.noff;
             funktion=MyInfo.mode,resolution=MyInfo.res;
             dreidf=MyInfo.dim;  /* 3d Modus? */
             britef=MyInfo.half_brite; /* HALF_BRITE? */
             if(MyInfo.mode<0||MyInfo.mode>ANZFUNK-1)
             {
                DisplayBeep(0);
                break; break;
             }
             set_menu();
             if(open_work()!=0) /* Konnte Work-Window geoeffnet werden? */
             {
                DisplayBeep(0);
                break; break;
             }
             else
             {
                ClearMenuStrip(MyWindow);
                if(load(File,MyScreen)!=0)
                   DisplayBeep(0);
                else
                {
                   set_colors();
                   fractal();
                }
                close_work();
                SetMenuStrip(MyWindow,&MYFIRSTMENU);
             }
          }
          break;
       case 1: /* Start */
          if(open_work()!=0) /* Konnte Work-Window geoeffnet werden? */
             break;
          else
          {
             ClearMenuStrip(MyWindow);
             fractal();
             close_work();
             SetMenuStrip(MyWindow,&MYFIRSTMENU);
          }
          break;
       case 2: /* Input */
          inpcon();
          break;
       case 3: /* Ende */
          close_things();
    }
    break;
    case 1: /* Format */
       resolution=item;
       set_resolution(resolution);
       break;
    case 2: /* Funktion */
       funktion=item;
       set_funktion(funktion);
       break;
    case 3: /* Extra */
    switch(item)
    {
       case 0: /* Brite */
          BRITE=OFF;
          if(britef==0)
          {
             BRITE=ON;
             britef=1;
          }
          else
             britef=0;
          break;
       case 1: /* 3-D */
          switch(subitem)
          {
             case 0: /* normal */
                DREIDN=DREIDI=OFF;
                if(dreidf==0||dreidf==2)
                {
                   DREIDN=ON;
                   dreidf=1;
                } 
                else
                   dreidf=0;
                break;
             case 1: /* invertiert */
                DREIDN=DREIDI=OFF;
                if(dreidf==0||dreidf==1)
                {
                   DREIDI=ON;
                   dreidf=2;
                } 
                else
                   dreidf=0;
                break;
          }
          break;
    }
    break;
    default: /* nichts ist eingetreten! */
    break;
 }
}

set_menu()
{
 set_resolution(resolution);
 set_funktion(funktion);
 set_brite(britef);
 set_3d(dreidf);
}

set_resolution(i)
short i;
{
 switch(i)
 {
    case 0: /* (320x250) 5 Planes */
       LORES=ON; MEDRES=HILORES=HIMEDRES=OFF;
       break;
    case 1: /* (640x250) 4 Planes */
       MEDRES=ON; LORES=HILORES=HIMEDRES=OFF;
       break;
    case 2: /* (320x500) 5 Planes */
       HILORES=ON; LORES=MEDRES=HIMEDRES=OFF;
       break;
    case 3: /* (640x500) 3 Planes */
       HIMEDRES=ON; LORES=MEDRES=HILORES=OFF;
       break;
 }
}

set_funktion(i)
short i;
{
 switch(i)
 {
    case 0: /* z^3-1=0 */
       F1=ON; F2=F3=F4=F5=F6=F7=F8=F9=F10=F11=F12=OFF;
       break;
    case 1: /* z^4-1=0 */
       F2=ON; F1=F3=F4=F5=F6=F7=F8=F9=F10=F11=F12=OFF;
       break;
    case 2: /* z^5-1=0 */
       F3=ON; F1=F2=F4=F5=F6=F7=F8=F9=F10=F11=F12=OFF;
       break;
    case 3: /* z^2-c=z */
       F4=ON; F1=F2=F3=F5=F6=F7=F8=F9=F10=F11=F12=OFF;
       break;
    case 4: /* z^3-c=z */
       F5=ON; F1=F2=F3=F4=F6=F7=F8=F9=F10=F11=F12=OFF;
       break;
    case 5: /* z^4-c=z */
       F6=ON; F1=F2=F3=F4=F5=F7=F8=F9=F10=F11=F12=OFF;
       break;
    case 6: /* z^5-c=z */
       F7=ON; F1=F2=F3=F4=F5=F6=F8=F9=F10=F11=F12=OFF;
       break;
    case 7: /* Julia */
       F8=ON; F1=F2=F3=F4=F5=F6=F7=F9=F10=F11=F12=OFF;
       break;
    case 8: /* 'Julia' z^3-c */
       F9=ON; F1=F2=F3=F4=F5=F6=F7=F8=F10=F11=F12=OFF;
       break;
    case 9: /* 'Julia' z^4-c */
       F10=ON; F1=F2=F3=F4=F5=F6=F7=F8=F9=F11=F12=OFF;
       break;
    case 10: /* 'Julia' z^5-c */
       F11=ON; F1=F2=F3=F4=F5=F6=F7=F8=F9=F10=F12=OFF;
       break;
    case 11:
       /* 'Erw.' Erweiterung zum einfachen Einbau einer eigenen Fkt. */
       F12=ON; F1=F2=F3=F4=F5=F6=F7=F8=F9=F10=F11=OFF;
       break;
 }
}

set_brite(i)
short i;
{
 BRITE=OFF;
 if(britef==1)
    BRITE=ON;
}

set_3d(i)
short i;
{
 DREIDN=DREIDI=OFF;
 switch(i)
 {
    case 1: DREIDN=ON;
            break;
    case 2: DREIDI=ON;
            break;
 }
}


/***********************/
/* Work-Window         */
/* bearbeiten          */
/***********************/

/* Welches Menue wurde im Work-Window angwewaehlt? */
/* Routine kehrt mit Werten von 1 bis 3 zurueck.   */
/* 0 -> kein Item angewaehlt!                      */
/* 1 -> Bild Speichern!                            */
/* 2 -> Work Fenster beenden!                      */
/* 3 -> Mousebutton gedrueckt!                     */
whats_up(class,code)
ULONG class;
USHORT code;
{
 USHORT menu,item;
 long file;
 
 switch(class)
 {                      
    case MENUPICK:       /* Menu wurde angewaehlt */
                   menu=MENUNUM(code);
                   item=ITEMNUM(code);
                   switch(menu)
                   {
                   case 0: /* Projekt-Menu? */
                      switch(item)
                      {
                         case 0: /* Speichern?    */
                         /* Speichern des Bildes im IFF-Format (kompr.) */
                         /* mit zuletzt eingegebener Name */
                         strcpy(File,F);
                         for(i=0;File[i]!=' '&&i<80;++i);
                         File[i]=0;
                         strcpy(Fileh,File);
                         strcpy(Fileh+strlen(Fileh),".info");
                         MyInfo.rmin=rmin,MyInfo.rmax=rmax;
                         MyInfo.imin=imin,MyInfo.imax=imax;
                         MyInfo.cim=cim,MyInfo.cre=cre;
                         MyInfo.mx=x,MyInfo.my=y;
                         MyInfo.emin=emin,MyInfo.emax=emax;
                         MyInfo.nmax=nmax,MyInfo.noff;
                         MyInfo.mode=funktion,MyInfo.res=resolution;
                         MyInfo.dim=dreidf; /* 3d Modus? */
                         MyInfo.half_brite=britef; /* HALF_BRITE? */
                         strcpy(MyInfo.text,text);
                         if(save(File,1,MyScreen)==0);
                         /* Bild kann nicht gespeichert werden!! */
                         /* Speichern des '.info' Files */
                         if((file=Open(Fileh,MODE_NEWFILE))!=0)
                         {
                            Write(file,&MyInfo,sizeof(MyInfo));
                            Close(file);
                         }
                         return(1);
                            break;
                         case 1: /* Cancel?       */
                            return(2);
                            break;
                      }
                      break;
                   case 1: /* Extra-Menu */
                      switch(item)
                      {
                         case 0: /* ganzer Screen? */
                            PAGE=OFF;
                            if(pagef==0)
                            {
                               pagef=1; PAGE=ON;
                               while(MyScreen->TopEdge>0)
                                  MoveScreen(MyScreen,0,-1);
                            }
                            else
                            {
                               pagef=0;
                               while(MyScreen->TopEdge<TOPEDGE)
                                  MoveScreen(MyScreen,0,1);
                            }
                            break;
                         case 1: /* Schwarz&Weiss an/aus */
                            BW=OFF;
                            if(bwf==0)
                            {
                               BW=ON;
                               bwf=1;
                               set_bw(); /* Schwarz-Weiss setzen */
                            }
                            else
                            {
                               set_colors(); /* Farben setzen */
                               bwf=0;
                            }
                            break;
                         case 2: /* Grid on/off */
                            if(dreidf==0)
                               grid(); /* Gitter zeichnen und warten */
                            break;
                         case 3: /* ViewPort einzeichnen */
                            if(dreidf==0)
                               draw_view();
                            break;
                      }
                      break;
                  }
    case MOUSEBUTTONS:   /* Taste wurde gedrueckt */
                   return(3);
                   break;
    default: /* ???? */
                   break;
 }
 return(0);
}

/* Eingabe von Werten ueber ein Consol-Fenster */
inpcon()
{
 int confile;
 char line[80];

 confile=Open("con:0/0/320/80/Eingabe-Fenster",MODE_OLDFILE);
 if(confile==0)
 {
    DisplayBeep(0); 
    close_();
 }
 while(inline(line,confile,80)!=0)
 {
    switch(line[0])
    {
       case 10 : /* Return-Zeile */
          break;
       case 'd': /* default-Werte seten */
          cim=cre=0,nmax=100,noff=0,rmin=imin=-1,rmax=imax=1,fak=1;
          emin=.001*.001,emax=1000*1000,gridstep=10,vrmin=vrmax=vimin=vimax=0;
          break;
       case 'f': /* Faktor fuer 3D-Ausgabe */
          fak=1;
          if(sscanf(line+1,"%d",&fak)!=1)
             printf("Eingabefehler:  -> %s",line);
          break;
       case 'c': /* cre,cim einlesen */
          cim=cre=0;
          if(sscanf(line+1,"%f,%f",&cre,&cim)!=2)
             printf("Eingabefehler:  -> %s",line);
          break;
       case 'n': /* nmax,noff einlesen */
          nmax=100,noff=0;
          if(sscanf(line+1,"%d,%d",&nmax,&noff)!=2)
             printf("Eingabefehler: -> %s",line);
          break;
       case 'r': /* rmin,rmax einlesen */
          rmin=-1,rmax=1;
          if(sscanf(line+1,"%f,%f",&rmin,&rmax)!=2)
             printf("Eingabefehler: -> %s",line);
          break;
       case 'i': /* imin,imax einlesen */
          imin=-1,imax=1;
          if(sscanf(line+1,"%f,%f",&imin,&imax)!=2)
             printf("Eingabefehler: -> %s",line);
          break;
       case 'e': /* emax,emin einlesen */
          emin=.001,emax=1000;
          if(sscanf(line+1,"%f,%f",&emin,&emax)!=2)
             printf("Eingabefehler: -> %s",line);
          emin*=emin,emax*=emax;
          break;
       case 'v': /* 'ViewPort' */
          vrmin=vrmax=vimin=vimax=0;
          if(sscanf(line+1,"%f,%f,%f,%f",&vrmin,&vrmax,&vimin,&vimax)!=4)
             printf("Eingabefehler: -> %s",line);
          if(vrmin>vrmax||vimin>vimax)
          {
             printf("Eingabefehler: -> %s",line);
             vrmin=vrmax=vimin=vimax=0;
          }
          break;
       case 'g':
          gridstep=10;
          if(sscanf(line+1,"%d",&gridstep)!=1)
             printf("Eingabefehler: -> %s",line);
          break;
       case 'a': /* Ausgabe der Parameter */
          ausgabe();
          break;
       case 'x': /* Ende der Eingabe */
          Close(confile);
          ausgabe();
          return(0);
       default : /* Fehler aufgetreten */
          printf("Eingabefehler: -> %s",line);
          break;
    }
 }
}

inline(c,handle,len) /* eine Zeile des Files einlesen */
char c[];
long *handle;
short len;
{
 short i=0,ende=0;

 while((i<len)&&(c[i-1]!=10)&&((ende=Read(handle,&c[i],1))!=0))
    ++i;
 c[i]=0;
 return(ende);
}

/* Ausgabe der aktuellen Parameter */
ausgabe()
{
 printf("\nParameter:\n nmax=%d noff=%d\n emin=%f emax=%f\n",
        nmax,noff,sqrt(emin),sqrt(emax));
 printf(" cre=%f cim=%f\n",cre,cim);
 printf(" Bereich [%f,%f] [%f,%f]\n",rmin,rmax,imin,imax);
 printf(" View [%f,%f] [%f,%f]\n",vrmin,vrmax,vimin,vimax);
 printf(" Gitter: %d\n",gridstep);
 printf(" 3D-Faktor: %d\n",fak);
}


/* Gitter im COMPLEMENT-Modus zeichnen */
grid()
{
 UBYTE *press,j;

 press=12574721;
 SetDrMd(rp,COMPLEMENT);
 for(j=0;j<2;++j)
 {
    for(i=1;i<gridstep;++i)
    {
       Move(rp,(short)(i*(float)width/(float)gridstep),0);
       Draw(rp,(short)(i*(float)width/(float)gridstep),height);
       Move(rp,0,(short)(i*(float)height/(float)gridstep));
       Draw(rp,width,(short)(i*(float)height/(float)gridstep));
    }
    if(j==0) while((*press&64)==64); /* nur ein Mal!!! */
    /* warten bis linker Mousebutton gedrueckt wird */
 }
 SetDrMd(rp,JAM1);
}

/* 'ViewFenster' im COMPLEMENT-Modus zeichnen */
draw_view()
{
 short x1view,y1view,x2view,y2view;
 UBYTE *press;

 press=12574721;
 x1view=(short)((vrmin-rmin)/rst),y1view=(short)((vimin-imin)/ist);
 x2view=(short)((vrmax-rmin)/rst),y2view=(short)((vimax-imin)/ist);
 if(x1view<0||x1view>width||y1view<0||y1view>height||
    x2view<0||x2view>width||y2view<0||y2view>height)
    return(FALSE);
 SetDrMd(rp,COMPLEMENT);
 RectFill(rp,x1view,y1view,x2view,y2view);
 while((*press&64)==64); /* warten bis linker Mousebutton gedrueckt wird */
 RectFill(rp,x1view,y1view,x2view,y2view);
 SetDrMd(rp,JAM1);
 return(TRUE);
}


/***********************/
/* Berechnungsroutine  */
/* fractal()           */
/***********************/

fractal()
{
 if(dreidf==0)
 {
    width=WIDTH;
    height=HEIGHT;
 }
 /* Definition der Bezugspunkte je nach Funktion */
 switch(funktion)
 {
    case 0: /* Newton 3 */
       nsre[0]=1,nsim[0]=0;                /* 1.Nullstelle  */
       nsre[1]=-.5,nsim[1]=.866;           /* 2.Nullstelle  */
       nsre[2]=-.5,nsim[2]=-.866;          /* 3.Nullstelle  */
       break;
    case 1: /* Newton 4 */
       nsre[0]=1,nsim[0]=0;                /* 1.Nullstelle  */
       nsre[1]=0,nsim[1]=1;                /* 2.Nullstelle  */
       nsre[2]=-1,nsim[2]=0;               /* 3.Nullstelle  */
       nsre[3]=0,nsim[3]=-1;               /* 4.Nullstelle  */
       break;
    case 2: /* Newton 5 */
       nsre[0]=.3090,nsim[0]=.9510;         /* 1.Nullstelle */
       nsre[1]=-.8090,nsim[1]=.5877;        /* 2.Nullstelle */
       nsre[2]=-.8090,nsim[2]=-.5877;       /* 3.Nullstelle */
       nsre[3]=.3090,nsim[3]=-.9510;        /* 4.Nullstelle */
       nsre[4]=1,nsim[4]=0;                 /* 5.Nullstelle */
       break;
    default: /* sonst Konvergenzuntersuchung gegen (0,0) */
       nsre[0]=nsim[0]=0;
       break;
 }
 if(x0==width) x0=0;
 if(y0==height) y0=0;
 rst=(rmax-rmin)/width,ist=(imax-imin)/height;
 for(x=x0;x<width;++x)
 {
    for(re=rmin+x*rst,y=y0;y<height-1;++y)
    {
       im=imin+y*ist;
       n=y0=0;   /* nach dem Laden y0 zuruecksetzen */        
       /* wurde Menu angewaehlt ? */
       if((WorkMessage=GetMsg(WorkWindow->UserPort))!=0)
       {
          ReplyMsg(WorkMessage);
          /* Frame bei 3D Modus nicht moeglich!! */
          if((WorkMessage->Class!=MOUSEBUTTONS)||(dreidf==0))
             i=whats_up(WorkMessage->Class,WorkMessage->Code);
          else i=0;
          if(i==2) return(0);
          if(i==3) 
          {
             if(frame(MyScreen,rmin,imin,rmax,imax)==0)
             {
                /* neue Koordinaten wurden eingegeben             */
                SetRast(rp,0);  /* Screen loeschen!               */
                rmin=rxmin,rmax=rxmax;
                imin=rymin,imax=rymax;
                rst=(rmax-rmin)/width,ist=(imax-imin)/height;
                y=height,x=0;   /* neues Bild starten             */
                break; break;
             }
          }
       }
       if(dreidf==0)
       {
          SetAPen(rp,anzcol-1);
          WritePixel(rp,x,y);
       }
       switch(funktion)
       {
          case 0: /* Newton 3 */
             newton3();
             break;
          case 1: /* Newton 4 */
             newton4();
             break;
          case 2: /* Newton 5 */
             newton5();
             break;
          case 3: /* Mandel */
             mandel();
             break;
          case 4: /* z^3-c */
             z_3();
             break;
          case 5: /* z^4-c */
             z_4();
             break;
          case 6: /* z^5-c */
             z_5();
             break;
          case 7: /* Julia-Menge */
             julia();
             break;
          case 8: /* 'Julia-Menge' z^3-c */
             julia_3();
             break;
          case 9: /* 'Julia-Menge' z^4-c */
             julia_4();
             break;
          case 10: /* 'Julia-Menge' z^5-c */
             julia_5();
             break;
          case 11: /* Erweiterung */
             erweiterung();
             break;
       }
       col=n%(anzcol-2)+1;
       if((n==nmax||n<noff)&&dreidf==0) col=0; /* nmax -> schwarz */
       if(dreidf==2) n=nmax-n; /* Mode invertiert */
       n*=fak;
       SetAPen(rp,col);
       if(dreidf==0)
          WritePixel(rp,x,y);
       else
       {  /* 3D Ausgabe */
          xs=x+fxoff+(height-y);
          ys=fyoff+y;
          ye=ys-n-yoff;
          if(ye<0) ye=0;
          Move(rp,xs,ys);
          Draw(rp,xs,ye);
          SetAPen(rp,anzcol-col);
          WritePixel(rp,xs,ye);
       }
    }
 }
 /* Bild fertig berechnet. Warten bis Menue angewaehlt */
 while((i=ende())==0);
 if(i==2) fractal();
}


/***********************/
/* newton5             */
/* z^5-1=0             */
/***********************/

newton5()
{
 for(n=0,re1=re,im1=im;n<nmax;++n)
 {
    if((re1+im1)!=0)
    {
       h1=re1*re1-im1*im1;
       h2=h1*h1-4*re1*re1*im1*im1;
       h1=4*h1*re1*im1;
       h3=h1*h1+h2*h2;
       if(h3<MIN)          /* Absturzgefahr              */
          break;
       re2=(4*re1+h2/h3)/5,im2=(4*im1-h1/h3)/5;
       re1=re2,im1=im2;
    }
    else /* Null? */
       break;
    /* Abstaende des neuen Folgenglieds zu den einzelnen */
    /* Attraktoren, das heisst Nullstellen.              */
    for(i=0;i<5;++i)
    {
       h1=re1-nsre[i],h2=im1-nsim[i];
       d[i]=h1*h1+h2*h2;
    }
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin||d[1]<emin||d[2]<emin||d[3]<emin||d[4]<emin)
       break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax||d[1]>emax||d[2]>emax||d[3]>emax||d[4]>emax)
       break;
 }
}


/***********************/
/* newton4             */
/* z^4-1=0             */
/***********************/

newton4()
{
 for(n=0,re1=re,im1=im;n<nmax;++n)
 {
    h1=re1*re1-im1*im1,h2=h1*re1-2*re1*im1*im1;
    h1=h1*im1+2*re1*re1*im1;
    h3=h1*h1+h2*h2;
    if(h3>MIN)
    {
       re2=(3*re1+h2/h3)/4,im2=(3*im1-h1/h3)/4;
       re1=re2,im1=im2;
    }
    else /* Null? */
       break;
    /* Abstaende des neuen Folgenglieds zu den einzelnen */
    /* Attraktoren, das heisst Nullstellen.              */
    for(i=0;i<4;++i)
    {
        h1=re1-nsre[i],h2=im1-nsim[i];
        d[i]=h1*h1+h2*h2;
    }
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin||d[1]<emin||d[2]<emin||d[3]<emin)
       break;
    /* Attraktor Unendlich?                              */
       if(d[0]>emax||d[1]>emax||d[2]>emax||d[3]>emax)
       break;
 }
}


/***********************/
/* newton3             */
/* z^3-1=0             */
/***********************/

newton3()
{
 for(n=0,re1=re,im1=im;n<nmax;++n)
 {
    h1=re1*re1+im1*im1;
    if(h1>MIN)
    {
       re2=(2*re1+(re1*re1-im1*im1)/(h1*h1))/3;
       im2=(2*im1-(2*re1*im1)/(h1*h1))/3;
       re1=re2,im1=im2;
    }
    else /* Null? */
       break;
    /* Abstaende des neuen Folgenglieds zu den einzelnen */
    /* Attraktoren, das heisst Nullstellen.              */
    for(i=0;i<3;++i)
    {
       h1=re1-nsre[i],h2=im1-nsim[i];
       d[i]=h1*h1+h2*h2;
    }
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin||d[1]<emin||d[2]<emin)
       break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax||d[1]>emax||d[2]>emax)
       break;
 }
}


/***********************/
/* mandel              */
/* z^2-c=z             */
/***********************/

mandel()
{
 for(n=re1=im1=0,cre=re,cim=im;n<nmax;++n)
 {
    im2=2*re1*im1-cim,re2=re1*re1-im1*im1-cre;
    im1=im2,re1=re2;
    d[0]=im1*im1+re1*re1;
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin)  break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax)  break;
 }
}


/***********************/
/* z^3-c=z             */
/***********************/

z_3()
{
 for(n=re1=im1=0,cre=re,cim=im;n<nmax;++n)
 {
    im2=3*re1*re1*im1-im1*im1*im1-cim,re2=re1*re1*re1-3*im1*im1*re1-cre;
    im1=im2,re1=re2;
    d[0]=im1*im1+re1*re1;
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin)  break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax)  break;
 }
}


/***********************/
/* z^4-c=z             */
/***********************/

z_4()
{
 for(n=re1=im1=0,cre=re,cim=im;n<nmax;++n)
 {
    h1=3*re1*re1*im1-im1*im1*im1,h2=re1*re1*re1-3*im1*im1*re1;
    im2=re1*h1+im1*h2-cim,re2=re1*h2-im1*h1-cre;
    im1=im2,re1=re2;
    d[0]=im1*im1+re1*re1;
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin)  break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax)  break;
 }
}


/***********************/
/* z^5-c=z             */
/***********************/

z_5()
{
 for(n=re1=im1=0,cre=re,cim=im;n<nmax;++n)
 {
    h1=3*re1*re1*im1-im1*im1*im1,h2=re1*re1*re1-3*im1*im1*re1;
    h3=re1*h1+im1*h2,h4=re1*h2-im1*h1;
    im2=re1*h3+im1*h4-cim,re2=re1*h4-im1*h3-cre;
    im1=im2,re1=re2;
    d[0]=im1*im1+re1*re1;
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin)  break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax)  break;
 }
}


/***********************/
/* Julia-Mengen        */
/* z^2-c=z             */
/***********************/

julia()
{
 /* cre und cim wie vorgewaehlt */
 for(n=0,re1=re,im1=im;n<nmax;++n)
 {
    im2=2*re1*im1-cim,re2=re1*re1-im1*im1-cre;
    im1=im2,re1=re2;
    d[0]=im1*im1+re1*re1;
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin)  break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax)  break;
 }
}

/***********************/
/* 'Julia'-Mengen      */
/* z^3-c=z             */
/***********************/

julia_3()
{
 /* cre und cim wie vorgewaehlt */
 for(n=0,re1=re,im1=im;n<nmax;++n)
 {
    im2=3*re1*re1*im1-im1*im1*im1-cim,re2=re1*re1*re1-3*im1*im1*re1-cre;
    im1=im2,re1=re2;
    d[0]=im1*im1+re1*re1;
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin)  break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax)  break;
 }
}


/***********************/
/* 'Julia'-Mengen      */
/* z^4-c=z             */
/***********************/

julia_4()
{
 /* cre und cim wie vorgewaehlt */
 for(n=0,re1=re,im1=im;n<nmax;++n)
 {
    h1=3*re1*re1*im1-im1*im1*im1,h2=re1*re1*re1-3*im1*im1*re1;
    im2=re1*h1+im1*h2-cim,re2=re1*h2-im1*h1-cre;
    im1=im2,re1=re2;
    d[0]=im1*im1+re1*re1;
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin)  break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax)  break;
 }
}


/***********************/
/* 'Julia'-Mengen      */
/* z^5-c=z             */
/***********************/

julia_5()
{
 /* cre und cim wie vorgewaehlt */
 for(n=0,re1=re,im1=im;n<nmax;++n)
 {
    h1=3*re1*re1*im1-im1*im1*im1,h2=re1*re1*re1-3*im1*im1*re1;
    h3=re1*h1+im1*h2,h4=re1*h2-im1*h1;
    im2=re1*h3+im1*h4-cim,re2=re1*h4-im1*h3-cre;
    im1=im2,re1=re2;
    d[0]=im1*im1+re1*re1;
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin)  break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax)  break;
 }
}


/***********************/
/* Erweiterung         */
/***********************/

erweiterung()
{
 /* cre und cim wie vorgewaehlt */
 for(n=0,re1=re,im1=im;n<nmax;++n)
 {
    d[0]=im1*im1+re1*re1;
    /* Ist der Attraktor erreicht?                       */
    if(d[0]<emin)  break;
    /* Attraktor Unendlich?                              */
    if(d[0]>emax)  break;
 }
}


/* Warten und Testen ob Menu richtig angewaehlt! */
/* Rueckkehr mit 0 -> Cancel nicht angewaehlt    */
/*               1 -> Cancel angewaehlt          */
/*               2 -> Bereich angewaehlt         */
ende()
{
 while((WorkMessage=GetMsg(WorkWindow->UserPort))==0);
 ReplyMsg(WorkMessage);
 if((WorkMessage->Class!=MOUSEBUTTONS)||(dreidf==0))
    i=whats_up(WorkMessage->Class,WorkMessage->Code);
 else i=0;
 if(i==2) return(1);
 if(i==3)
 {
    if(frame(MyScreen,rmin,imin,rmax,imax)==0)
    {
       /* neue Koordinaten wurden eingegeben             */
       SetRast(rp,0);  /* Screen loeschen!               */
       rmin=rxmin,rmax=rxmax;
       imin=rymin,imax=rymax;
       rst=(rmax-rmin)/width,ist=(imax-imin)/height;
       x=y=x0=y0=0;
       return(2);
    }
 }
 return(0);
}

