 
 /********************************************************************/
 /****                                                            ****/
 /****                                                            ****/
 /****    Program          : C-Plot.c                             ****/
 /****                                                            ****/
 /****    Version          :    03.34                             ****/
 /****                                                            ****/
 /****    Erstversion      : 14.08.1988                           ****/
 /****                                                            ****/
 /****    Letzte Änderung  : 20.10.1989                           ****/
 /****                                                            ****/
 /****    Compiliert mit   : siehe Make                           ****/
 /****                                                            ****/
 /****    Gelinkt mit      : siehe Make                           ****/
 /****                                                            ****/
 /********************************************************************/
 /****                                                            ****/
 /****                                                            ****/
 /****               Copyright by Rüdiger Dreier                  ****/
 /****                                                            ****/
 /****                                                            ****/
 /********************************************************************/
 
 /* Einbinden der Include-Files */
 
 #include "tool.h"
 #include "toolLibrary.h"
 #include <string.h>
 #include <devices/printer.h>
 #include <intuition/intuitionbase.h>
 #include <graphics/regions.h>
 #include <proto/mathieeedoubbas.h>
 #include <proto/mathieeedoubtrans.h>
 #include <proto/layers.h>
 
 /* Variablendeklaration */
 
 int GE=1,Groesse;/* Für die Genauigkeit der Zeichnung */
 /* Gibt an, ob Koordinatenkreuz neu gezeichnet werden muß   */
 BOOL KoordinatenKreuz_gezeichnet;
 
 struct LayersBase     *LayersBase;
 struct ViewPort       *viep;           /* Zeiger auf ViewPort        */
 struct IntuitionBase  *IntuitionBase;  /* Zeiger auf IntuitionBase   */
 struct Library        *ToolBase;
 extern struct Library *MathIeeeDoubBasBase;
 struct Library        *MathIeeeDoubTransBase;
 struct Window         *Window;         /* Zeiger auf Fenster         */
 struct RastPort       *RastPort;       /* Zeiger auf RastPort        */
 struct Screen         *Screen;         /* Zeiger auf Screen          */
 struct GfxBase        *GfxBase;        /* Zeiger auf Grafik-Library  */
 struct View           *View;
 struct BitMap         bitmap;
 struct Layer          *layer;
 struct Layer_Info     *layerinfo;
 struct info           msgInfo;
 
 /* Strings */
 UBYTE undo1[20];                              /* Für Gadget, Intervall und Konstanten */
 UBYTE undoFormel[MAXCHARS];                   /* Für Gadget, Formeleingabe            */
 UBYTE xmpstring[20],xmnstring[20];            /* Strings für Intervall                */
 UBYTE ympstring[20],ymnstring[20];            /* Strings für Intervall                */
 UBYTE KonAString[20],KonBString[20];          /* Strings für Konstanten               */
 UBYTE KonCString[20],KonDString[20];          /* Strings für Konstanten               */
 char  String1[]="-pi";
 
 SHORT XOffset,YOffset;
 extern UBYTE MinXText[20],MaxXText[20];       /* Strings für Gadget, IntervallText    */
 extern UBYTE MinYText[20],MaxYText[20];       /* Strings für Gadget, IntervallText    */
 
 /* 11 Strings je MAXCHARS Zeichen */
 UBYTE Formeln[11][MAXCHARS];
 char Formel[MAXCHARS];
 
 /* Variablen zur Überprüfung auf Mathe-Fehler    */
 extern LONG MatheFehler;
 
 /* Für Zugriff auf externe Daten und Funktionen  */
 extern struct NewWindow Fenster2,Fenster3;
 
 /* Für Zugriff auf externe Menudaten */
 extern struct Menu SecondMenu;
 extern char SubMenuTitle[10][16];
 
 /* Info-Struktur wird gefüllt, für schnelle      */
 /* Abfrage eines Events                          */
 
 /* Variablen, in denen wichtige Werte gespeichert werden                         */
 double xx,yy;                /* Punkte in x/y-Richtung                           */
 double xmp,xmn,ymp,ymn;      /* Intervallgrenzen                                 */
 double x0,y0;                /* Position der Achsen                              */
 double xm,ym;                /* Maßstab für x/y-Achse                            */
 struct Konstanten kon;
 
 /* Daten für Screen und Window */
 
 struct NewScreen Schirm=
  {
   0,0,640,256,2,2,1,HIRES,CUSTOMSCREEN,NULL,NULL,NULL,NULL
  };
 
 struct NewWindow Fenster=
  {
   0,1,640,255,0,1,MENUPICK|MOUSEMOVE|MOUSEBUTTONS|RAWKEY,
   BORDERLESS|ACTIVATE|REPORTMOUSE|SUPER_BITMAP,
   NULL,NULL,NULL,
   NULL,
   NULL,
   NULL,
   NULL,
   NULL,
   NULL,
   CUSTOMSCREEN
  };
 
 
 /* Setzt Punkt */
 
 VOID Pset(x1,y1)
 double x1,y1;
  {
   Move(RastPort,Fix(Add(x1,RUNDEN2))+Abstand,Fix(Add(y1,RUNDEN2))+Abstand);
   Draw(RastPort,Fix(Add(x1,RUNDEN2))+Abstand,Fix(Add(y1,RUNDEN2))+Abstand);
  }
 
 VOID DrawTo(x1,y1)
 double x1,y1;
  {
   Draw(RastPort,Fix(Add(x1,RUNDEN2))+Abstand,Fix(Add(y1,RUNDEN2))+Abstand);
  }
 
 /* Routine zum Zeichnen des Koordinatenkreuzes */
 
 VOID zeichne()
  {
   double i,dx,dy,x,y;
   LONG Zaehler;
   
   /* Setzt Farbe und Zeichenmodus */
   SetAPen(RastPort,1);
   SetDrMd(RastPort,JAM1);
   
   if(Groesse)
    {
     xx=969.0;               /* Definiert, wie viele Punkte für Grafik */
     yy=267.0;               /* genutzt werden sollen                  */
    }
   else
    {
     xx=609.0;               /* Definiert, wie viele Punkte für Grafik */
     yy=233.0;               /* genutzt werden sollen                  */
    }
   
   
   /* Berechnet Position der x/y-Achse */
   
   x0=Add(Mul(Div(Neg(xmn),Sub(xmp,xmn)),Sub(xx,1.0)),1.0);
   
   y0= Add(Mul(Div(ymp,Sub(ymp,ymn)),Sub(yy,1.0)),1.0);
   
   /* Bestimmt Zeichenmaßstab */
   xm=Div(Sub(xx,1.0),Sub(xmp,xmn));
   ym=Div(Sub(yy,1.0),Sub(ymp,ymn));
   
   /* Bestimmt Abstand zwischen 2 Skalenunterteilungen */
   dy=Div(Sub(ymp,ymn),10.0);
   dx=Div(Sub(xmp,xmn),10.0);
   
   /* Zeichnet nur, wenn nicht schon geschehen */
   if (!KoordinatenKreuz_gezeichnet)
    {
     /* Wenn y-Achse sichtbar, zeichnen */
     if(Cmp(x0,0.0)>=0 && Cmp(x0,xx)<1)
      {
       Line(x0,1.0,x0,yy);
      }
     
     /* Wenn x-Achse sichtbar, zeichnen */
     if(Cmp(y0,0.0)>=0 && Cmp(y0,yy)<1)
      {
       Line(1.0,y0,xx,y0);
      }
     
     /* Zeichnet Unterteilung der Achsen */
     
     
     for(Zaehler=0;Zaehler<=10;Zaehler++)
      {
       i=Add(xmn,Mul(dx,Flt(Zaehler)));
       if(Cmp(Abs(i),Div(dx,1000.0))==-1)i=0.0000;
       x=Add(x0,Mul(i,xm));
       Line(x,Sub(y0,3.0),x,Add(y0,3.0));
       Skalierung(i,0.0,i);
      }
     
     
     for(Zaehler=0;Zaehler<=10;Zaehler++)
      {
       i=Add(ymn,Mul(dy,Flt(Zaehler)));
       if(Cmp(Abs(i),Div(dy,1000.0))==-1)i=0.0000;
       y=Sub(y0,Mul(i,ym));
       Line(Sub(x0,5.0),y,Add(x0,5.0),y);
       Skalierung(0.0,i,i);
      }
     /* Koordinatenkreuz gezeichnet, wird beim nächsten Mal  */
     /* nicht mehr                                           */
     KoordinatenKreuz_gezeichnet=TRUE;
    }
  }
 
 
 /* Wertet Mausklick aus */
 
 VOID MenuWahl()
  {
   long menu,item,ENDE=1;
   unsigned short sub;
   
   while(ENDE)
    {
     /* Wartet auf Event */
     Wait(1L<<Window->UserPort->mp_SigBit);
     /* Arbeitet ab, bis keine Events mehr */
     while(EventAbfrage(Window,&msgInfo))
      {
       /* Verzweigt entsprechend der Events */
       switch(msgInfo.NachrichtenArt)
        {
         /* Menupunkt gewählt */
         case MENUPICK:
          {
           /* Wurde wirklich ein Menu gewählt ? */
           if (msgInfo.code!=MENUNULL)
            {
             /* Wenn ja, dann Menu-, Item- und SubItemNummer bestimmen */
             menu=MENUNUM(msgInfo.code);
             item=ITEMNUM(msgInfo.code);
             sub =SUBNUM (msgInfo.code);
             
             /* Entsprechend des Menus verzweigen */
             switch (menu)
              {
               case 1:
                {
                 /* Ein Punkt des ersten Menus wurde gewählt */
                 switch(item)
                  {
                   /* Entsprechend des Items verzweigen */
                   case 7:
                    {
                     /* Bestimmung der neuen Zeichengenauigkeit */
                     Genauigkeit();
                     break;
                    }
                   case 6:
                    {
                     /* Eingabe eines neuen Intervall */
                     do
                      {
                       TextFuerIntervall();     /* Gadget vorbereiten      */
                       /* Grenzen abfragen */
                       Grenzen(xmnstring,ymnstring,xmpstring,ympstring);
                       UmwandlungInIntervall(); /* Werte kopieren          */
                      }
                     while(Cmp(xmn,xmp)>=0 || Cmp(ymn,ymp)>=0);
                    }
                   case 5:
                    {
                     /* Schirm löschen */
                     Loeschen();
                     break;
                    }
                   case 4:
                    {
                     /* Routine zum Drucken */
                     drucken();
                     /* Farben wieder zurücksetzen */
                     SetColor();
                     break;
                    }
                   case 3:
                    {
                     /* Bereich mit Maus auswählen */
                     AusSchnitt(&xmn,&ymn,&xmp,&ymp); /* Funktion aufrufen   */
                     Loeschen(); /* Schirm löschen */
                     break;
                    }
                   case 2:
                    {
                     /* Eingabe der Werte für die Konstanten        */
                     TextFuerKonstanten();     /* Gadget vorbereiten */
                     /* Werte vom Anwender holen */
                     Grenzen(KonAString,KonCString,KonBString,KonDString);
                     UmwandlungInKonstanten(); /* Werte kopieren     */
                     
                     break;
                    }
                   case 1:
                    {
                     /* About */
                     /* Funktion, die Informationen über  */
                     /* das Programm und den Autor gibt   */
                     About();
                     break;
                    }
                   case 0:
                    {
                     /* Beenden des Programms */
                     ENDE=0;
                    }
                  }
                 break;
                }
               case 0:
                {
                 
                 /* Das nullte Menu wurde gewählt      */
                 switch (item)
                  {
                   /* Entsprechend des Items verzweigen */
                   case 6:
                    {
                     /* Funktionsterm ändern */
                     do
                      {
                       Funktionseingabe(Formeln[sub]); /* Holen der neuen Vorschrift */
                      }
                     while(AnzahlKlammern((char *)Formeln[sub]));
                     UpdateMenuText();               /* SubItemText erneuern       */
                     break;
                    }
                   case 5:
                    {
                     /* Entsprechend dem SubItem zeichnen   */
                     ZeichneFunktion(sub,0);
                     break;
                    }
                   case 4:
                    {
                     /* 1.Abl. zeichnen */
                     /* Entsprechend dem SubItem zeichnen   */
                     ZeichneFunktion(sub,1);
                     break;
                    }
                   case 3:
                    {
                     /* 2.Abl. zeichnen */
                     /* Entsprechend dem SubItem zeichnen   */
                     ZeichneFunktion(sub,2);
                     break;
                    }
                     /* Item 2 ist ---------- */
                   
                   case 1:
                    {
                     /* 1. Abl. symbolisch */
                     /* Entsprechend dem SubItem zeichnen   */
                     strcpy(Formel,Formeln[sub]);
                     strcpy(Formeln[10],Ableiten(0L,strlen(Formel)-1L));
                     ZeichneFunktion(10,0);
                     
                     break;
                    }
                   case 0:
                    {
                     /* 2. Abl. symbolisch */
                     strcpy(Formel,Formeln[sub]);
                     strcpy(Formel,Ableiten(0L,strlen(Formel)-1L));
                     strcpy(Formeln[10],Ableiten(0L,strlen(Formel)-1L));
                     ZeichneFunktion(10,0);
                    }
                  }
                 break;
                }
               case 2:
                {
                 switch(item)
                  {
                   case 0:
                    {
                     if(!Groesse)
                      {
                       Loeschen();
                       Groesse=GROSS;
                      };
                     break;
                    }
                   case 1:
                    {
                     if(Groesse)
                      {
                       Loeschen();
                       Groesse=KLEIN;
                      };
                    }
                  }
                }
              }
            }
          }
         case RAWKEY:
          {
           if(Groesse)
            {
             TastaturAbfrage();
            }
          }
        }
      }
    }
  }
 
 
 
 /* Hauptprogramm */
 
 VOID _main()
  {
   /* Einige Formeln vorschlagen */
   strcpy(Formeln[0],"sin(x)");
   strcpy(Formeln[1],"cos(x)");
   strcpy(Formeln[2],"tan(x)");
   strcpy(Formeln[3],"x^2");
   strcpy(Formeln[4],"x^3");
   strcpy(Formeln[5],"5*x");
   strcpy(Formeln[6],"x");
   strcpy(Formeln[7],"sqr(x)");
   strcpy(Formeln[8],"ln(x)");
   strcpy(Formeln[9],"log(x)");
   
   strcpy(xmpstring,&String1[1]);
   strcpy(xmnstring,String1);
   strcpy(ympstring,"1");
   strcpy(ymnstring,"-1");
   
   strcpy(KonAString,String1);
   strcpy(KonBString,String1);
   strcpy(KonCString,String1);
   strcpy(KonDString,String1);
   
   oeffne();                  /* Öffnen der Libraries, Screen, Fenster      */
   SetColor();                /* Farben setzen                              */
   UpdateMenuText();          /* SubMenuText erneuern                       */
   UmwandlungInIntervall();   /* Intervallstrings in double umwandeln       */
   UmwandlungInKonstanten();  /* Konstantenstrings in double umwandeln      */
   MenuWahl();                /* Menuwahl anspringen                        */
   ende();
  }
 
 
 /* Öffnet Libraries, Screen, Window */
 VOID oeffne()
  {
   if(!(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0)))ende();
   
   if(!(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0)))ende();
   
   if(!(ToolBase=OpenLibrary("tool.library",0)))ende();
   
   if(!(LayersBase = (struct LayersBase *)OpenLibrary("layers.library",0)))ende();
   
   if(!(MathIeeeDoubBasBase=OpenLibrary("mathieeedoubbas.library",0)))ende();
   
   if(!(MathIeeeDoubTransBase=OpenLibrary("mathieeedoubtrans.library",0)))ende();
   
   if(!(Screen=(struct Screen *)OpenScreen(&Schirm)))ende();
   
   InitBitMap(&bitmap,2,1000,MAXPIXELY);
   
   if(!(bitmap.Planes[0]=AllocRaster(1000,MAXPIXELY)))ende();
   Delay(5);
   if(!(bitmap.Planes[1]=AllocRaster(1000,MAXPIXELY)))ende();
   
   
   Fenster.Screen=Screen; /* Fenster soll auf Screen erscheinen */
   Fenster.BitMap=&bitmap;
   if(!(Window=(struct Window *)OpenWindow(&Fenster)))ende();
   
   /* Zuweisung von Variablen, Einfärben des Windows */
   RastPort=Window->RPort;            /* Variablenzuweisung       */
   SetMenuStrip(Window,&SecondMenu);  /* Menus verknüpfen         */
   viep=&Screen->ViewPort;            /* ViewPort-Zeiger füllen   */
   
   layer=RastPort->Layer;
   layerinfo=layer->LayerInfo;
   SetRast(RastPort,0);               /* Schirm löschen           */
   
   Fenster2.Screen=Screen;            /* Fenster2 auch auf Screen */
   Fenster3.Screen=Screen;
  }
 
 
 /* Routine, die alles wieder schließt */
 
 VOID ende()
  {
   /* Wenn offen -> schließen */
   if(Window)
    {
     ClearMenuStrip(Window);
     CloseWindow(Window);
    };
   if(bitmap.Planes[0])
    {
     FreeRaster(bitmap.Planes[0],1000,MAXPIXELY);
     bitmap.Planes[0]=0;
    }
   if(bitmap.Planes[1])
    {
     FreeRaster(bitmap.Planes[1],1000,MAXPIXELY);
     bitmap.Planes[1]=0;
    }
   
   if(Screen)CloseScreen(Screen);
   
   if(GfxBase)CloseLibrary((struct Library *)GfxBase);
   
   if(IntuitionBase)CloseLibrary((struct Library *)IntuitionBase);
   
   if(ToolBase)CloseLibrary((struct Library *)ToolBase);
   
   if(LayersBase)CloseLibrary((struct Library *)LayersBase);
   
   if(MathIeeeDoubBasBase)   
    {
     CloseLibrary(MathIeeeDoubBasBase);
     MathIeeeDoubBasBase=NULL;
    }
   if(MathIeeeDoubTransBase)
    {
     CloseLibrary(MathIeeeDoubTransBase);
     MathIeeeDoubTransBase=NULL;
    }
  }
 
 /* Zeichnet Linie von (x1,y1) - (x2,y2)   */
 /* Line ersetzt Funktion Line in Tool.lib */
 
 VOID Line(x1,y1,x2,y2)
 double x1,y1,x2,y2;
  {
   /* Zum Anfang bewegen und Linie ziehen */
   Move(RastPort,Fix(Add(x1,RUNDEN))+Abstand,Fix(Add(y1,RUNDEN))+Abstand);
   Draw(RastPort,Fix(Add(x2,RUNDEN))+Abstand,Fix(Add(y2,RUNDEN))+Abstand);
  }
 
 /* Beschriftet Koordinatenkreuz */
 VOID Skalierung(x,y,Wert)
 double x,y,Wert;
  {
   char buffer[11];
   long xx,yy,e;
   strcpy(buffer,UmwFtoS(&Wert,2));
   /* Beschriften von x- und y-Achse */
   if(!Tst(y))
    {
     e=strlen(buffer)<<2;
     xx=Fix(Add(Mul(x,xm),x0))-e+Abstand;
     yy=Fix(y0)+Abstand+12;
    }
   else
    {
     xx=Fix(x0)+Abstand+8;
     yy=Fix(Sub(y0,Mul(y,ym)))+Abstand+3;
    }
   
   Print(RastPort,buffer,1,xx,yy);
  }
 
 
 /* Wandelt Strings in double */
 
 /* Für Intervall */
 VOID UmwandlungInIntervall()
  {
   DOUBLE Var;
   xmp= *berechnen(xmpstring,&Var,&kon,&MatheFehler);
   xmn= *berechnen(xmnstring,&Var,&kon,&MatheFehler);
   ymp=(*berechnen(ympstring,&Var,&kon,&MatheFehler));
   ymn=(*berechnen(ymnstring,&Var,&kon,&MatheFehler));
   FehlerAbfrage();
   MatheFehler=0; /* Falls Fehler aufgetreten ist */
  }
 
 /* Für Konstanten */
 VOID UmwandlungInKonstanten()
  {
   DOUBLE Var;
   kon.k1=*berechnen(KonAString,&Var,&kon,&MatheFehler);
   kon.k2=*berechnen(KonBString,&Var,&kon,&MatheFehler);
   kon.k3=*berechnen(KonCString,&Var,&kon,&MatheFehler);
   kon.k4=*berechnen(KonDString,&Var,&kon,&MatheFehler);
   FehlerAbfrage();
   MatheFehler=0; /* Falls Fehler aufgetreten ist */
  }
 
 /* Erneuert SubMenuTexte */
 VOID UpdateMenuText()
  {
   /* Soll die SubMenuTitel mit den aktuellen Funktionsdefinitionen füllen */
   
   unsigned short i;
   ClearMenuStrip(Window);                   /* Menuverknüpfung aufheben  */
   for(i=0;i<=9;i++)
    {
     strcpy(SubMenuTitle[i],left(Formeln[9-i],14)); /* Ans Ziel kopieren         */
    }
   SetMenuStrip(Window,&SecondMenu);       /* Wieder verknüpfen         */
  }
 
 VOID SetRXOffset()
  {
   LONG dx,dy;
   if(YOffset<0)YOffset=0;
   
   if(XOffset<0)XOffset=0;
   
   if(YOffset>(MAXPIXELY-256))YOffset=MAXPIXELY-256;
   
   if(XOffset>(1000-640))XOffset=1000-640;
   
   dx=XOffset-(layer->Scroll_X);
   dy=YOffset-(layer->Scroll_Y);
   if(dx||dy)ScrollLayer(layerinfo,layer,dx,dy);
  }
 
 VOID TastaturAbfrage()
  {
   static short add=1;
   switch(msgInfo.code)
    {
     case 69:
      {
       /* ESC = Ursprung */
       XOffset=YOffset=0;
       add=1;
       break;
      }
     case 76:
      {
       /* Cursor up */
       YOffset-=add;
       add++;
       break;
      }
     case 77:
      {
       /* Cursor down */
       YOffset+=add;
       add++;
       break;
      }
     case 78:
      {
       /* Cursor right */
       XOffset+=add;
       add++;
       break;
      }
     case 79:
      {
       /* Cursor left */
       XOffset-=add;
       add++;
       break;
      }
     case 204:
     case 205:
     case 206:
     case 207:
      {
       /* Damit nicht zu schnell gescrollt wird... */
       add=1;
      }
    }
   SetRXOffset();
   if (add>10)add=10;
  }
 
 VOID Loeschen()
  {
   SetRast(RastPort,0);
   /* Koordinatenkreuz beim nächsten Mal neu zeichnen */
   KoordinatenKreuz_gezeichnet=FALSE;
   ScrollLayer(layerinfo,layer,(LONG)-(layer->Scroll_X),(LONG)-(layer->Scroll_Y));
  }
 
 
