/*  kurvemake  */
/* this is the name of the makefile */
/*******************************************************************/
/*                                                                 */
/*                            Kurve                                */
/*                                                                 */
/*                       Kurvendiskusion                           */
/*                                                                 */
/*                   © 89-92 by Henning Rink                       */
/*                                                                 */
/*                Version 2.001               12.09.1992           */
/*                                                                 */
/*                                                                 */
/* copyright notes -> see ReadMe                                   */
/*******************************************************************/

/*******************************************************************/
/*                                                                 */
/*                      REVISION HISTORY                           */
/*                                                                 */
/* Kurve V1.0                                           10.09.1989 */
/*                                                                 */
/* Kurve V1.5                                           20.02.1990 */
/* changed Parser 2.55 to 3.0                                      */
/* Parser now creates code for pseudo-stack-machine                */
/*                                                                 */
/* Kurve V1.6                                           21.10.1990 */
/* Updated whole programm for Aztec C 5.0a                         */
/* new Funktion-Requester                                          */
/* added zooming of coordinates                                    */
/*                                                                 */
/* Kurve V1.7                                           01.12.1990 */
/* new Parser 4.00 now generates 68000 machine code for IEEE64 libs*/
/* some minor changes in frequest.c                                */
/*                                                                 */
/* small changes in NeueF()                     V1.701  07.01.1991 */
/* changed DoReq()                                      07.01.1991 */
/* changed colours for WB 2.0 (got Kick36.141?) V1.702  19.01.1991 */
/* some minor changes at pseudo bugs            V1.703  10.03.1991 */
/* added UnZoom()                                       10.03.1991 */
/* changed line-clipping code                   V1.704  19.03.1991 */
/*                                                                 */
/* Kurve V1.71 27.04.1991                                          */
/* added screenprefs() and changed all? coordinates to             */
/* relative screen height and width                     27.04.1991 */
/*                                                                 */
/* V1.711 changed Drucken() because I got a formfeed between       */
/* close(fd[prt:]) (printing of the Text )                         */
/* and the OpenDevice(printer...) (prints RastPort)                */
/* this occur only with HP-Desk/Laserjet                27.05.1991 */
/* added ShowErr()                                      28.05.1991 */
/*                                                                 */
/* V1.712 some code improvements, menu style change     15.06.1991 */
/* no more dividing with constant floats->> multiply it!           */
/*                                                                 */
/* V1.713 small changes in all modules                  25.07.1991 */
/*                                                                 */
/* V1.714 changed Cross() and ZoomBox()                 10.08.1991 */
/*                                                                 */
/* V1.715 more 2.0 styling, translation german english             */
/* corrected  g-format error -->>checkstring()  18. and 24.08.1991 */
/*                                                                 */
/* V1.716 WB like cycling of ZoomBox                    24.09.1991 */
/*                                                                 */
/* V1.800 added changescreensize requester,             17.11.1991 */
/* changecolor request and some menu improvements                  */
/* Deleted Funktion(), Ableitung1() and  Ableitung2()              */
/* --> all drawing is done via DrawFunc()                          */
/* Inserted getcolors();  enabled Keystroke Activation  18.11.1991 */
/* of all Gadgets used in  Requesters                              */
/* inserted new mousepointer                            19.11.1991 */
/* added extLoadConfig and extSaveConfig to handle different       */
/* configuration files                          19. and 20.11.1991 */
/*                                                                 */
/* V1.801 found bug in tag structure; changed Draw->All 17.12.1991 */
/*                                                                 */
/* V1.802 ShowErr now does AutoRequest, added numerical (Simpson)  */
/* integration of the function from xmin to xmax        21.12.1991 */
/*                                                                 */
/* added #ifdef AztecVERSION500 to printpara() and checkstring()   */
/* in funkrequest.c, so checkstring is only compiled if you set    */
/* this define to AztecVERSION500 -> see checkstring()             */
/* changed some cast operators and includes.kur cause I'm using    */
/* now the Kick2.04 and AztecC52 includes               24.12.1991 */
/* some minor enhancements                              25.12.1991 */
/* placed file and screenrequest in fileandscreen.c     28.12.1991 */
/* V1.803 last Aztec 5.0d/e Version                     28.12.1991 */
/*                                                                 */
/* V1.900  new functionlist requester and new intervall requester  */
/* to deal with various number of functions  29.12.1991-06.02.1992 */
/* recursive drawfunc2()                                08.02.1992 */
/*                                                                 */
/* V1.901                                                          */
/* disabled load-save in Functionlist and found bug in disabling   */
/* Colors Menu if no palette requester is available     28.02.1992 */
/*                                                                 */
/* V1.902 bug in doreqreq found !!                      17.04.1992 */
/* now save and load settings always with the active function      */
/* bug in load - save functions found; load buffer was to small    */
/*                                                                 */
/* Changes for Version 2.000                                       */
/* doing CreateMenus()  disabled KickstartVersions<37   28.07.1992 */
/* changescreenmode-request with kick 2.0 look   01. to 03.08.1992 */
/* MouseCenterWin, new OK,Cancel Gadgets         03. to 04.08.1992 */
/* handlepattern, handleedit                     04. to 05.08.1992 */
/* changeintervall, asl filerequester                   06.08.1992 */
/* showerr now does EasyRequest()                       12.08.1992 */
/* min_open                                             13.08.1992 */
/* turboparser4.00 for 68881/82                         16.08.1992 */
/*                                                                 */
/* V2.001 small change in fileandscreen->gadgethandling 12.09.1992 */
/* improved handling of asl.requester some code cleanup 27.09.1992 */
/*******************************************************************/


/* externals in globdata.c  */

extern struct   NewWindow FirstNewWindow;
extern struct   NewWindow SecondNewWindow;
extern struct   NewWindow ThirdNewWindow;
extern struct   NewWindow FourthNewWindow;
extern struct   NewScreen FirstNewScreen; /* this is an ExtNewScreen !! */
extern struct   TextAttr  NormalAttr;
extern struct   IntuiText MemText;
extern struct   IntuiText DateText;
extern struct   IntuiText NameText;
extern unsigned char      funktion[]; /* init with LoadConfig()   25.07.1991 */
extern unsigned char      UndoBuffer[];
extern unsigned char      minx[];
extern unsigned char      maxx[];
extern unsigned char      miny[];
extern unsigned char      maxy[];
extern          char      *Days[],*Months[],*ErrorMessages[];
extern const    char      *coltoolname;
extern UWORD              mousedata[];
extern USHORT defscr;
extern struct EasyStruct  es1;


extern APTR     ScreenVI;
extern struct   Menu       *menu;
extern struct   NewMenu    menulist[];
extern struct   NewGadget  NewOKGadget;
extern struct   NewGadget  NewCancelGadget;
extern struct   Gadget     *nullgadget;

/* externals from funkrequest.c and parser.c */

extern  double  x;
extern  short   fehler;
extern  short   *point;
extern  void    FuncReq(void);
extern  void    ZoomBox(USHORT);
extern  void    UnZoom(void);
extern  void    printpara(unsigned char *,double);
extern  void    checkrights(char *);
extern  void    changecolor(void);
extern  void    changescreenmode(void);
extern  void    extLoadConfig(void);
extern  void    extSaveConfig(void);
extern  void    LoadConfig(char *);
extern  void    setcolors(void);
extern  void    delallfuncs(void);
extern  void    changeintervall(void);
extern  void    helpdruck(UBYTE **, long *);
extern  void    ReDrawFuncs(void);
extern  void    MouseCenterWin(struct NewWindow *,short,short);
extern  void    handlesave(void);
extern  void    setscreenprefs(void);

/* internal functions  */
void    Open_LIBS(void);
void    Close_LIBS(void);
void    Open_WINS(void);
void    Close_WINS(void);
void    About(void);
void    Drucken(void);
void    Ende(void);
void    NeueP(void);
void    DrawFunc(double (*)(double),long);
void    Clear(void);
void    Nullstellen(void);
void    Maxima(void);
void    Wendepunkte(void);
void    Cross(void);
void    Maus(void);
void    newton1(short);
void    newton2(short, double);
void    newton3(short, double);
short   openex(void);
void    closeex(short);
void    exaus(short,double,double,short);
double  f(double);
double  fa(double);
double  fa2(double);
double  fa3(double);
WORD    Menuauswertung(USHORT);
short   ShowErr(short,BOOL);
void    NumIntegrate(double (*)(double));
void    Cleardrawn(void);
void    DrawFunc2(double (*)(double),double,long);
void    Kickerror(void);
void    min_open(void);

/* more vars   */

double  (*numb)(void);
double  (*numb1)(void);
double  (*numb2)(void);
struct  FuncNode *FirstFunc;
struct  FuncNode *activeFunc;

extern struct        ExecBase   *SysBase;
struct ReqLib        *ReqBase;
struct IntuitionBase *IntuitionBase;
struct Library       *AslBase;
struct Library       *GadToolsBase;


struct Screen        *FirstScreen;
struct Window        *FirstWindow,*SecondWindow,*ThirdWindow,*FourthWindow;
struct IntuiMessage  *message;
struct GfxBase       *GfxBase;
struct RastPort      *rp,*rp2,*rp4;
struct Process       *process;
APTR                  oldwin;

double  xmin,xmax,ymin,ymax,xstep,xe,ye;
long    xnull,ynull;      /* Nullpunkte */
short   STEP=4;
long    ys,xs,yn,xn,xmouse,ymouse;   /* Startendkoordinaten für Zoombox  */
long    scrheight,scrwidth,winheightmax,scrmode;
short   flag=0;
UWORD   *mousemem;

extern struct IntuiText CopyrightText;
extern char   configfile[];
extern char   configpath[];
extern char   configdir[];
short array[1500];


union printerIO  /* look for Addison Wesley  Libraries&Devices  */
 {
   struct IOStdReq    ios;
   struct IODRPReq    iodrp;
   struct IOPrtCmdReq iopc;
 };



void    _cli_parse(){}
void    _wb_parse(){}


void main(void)
{
 register ULONG  MessageClass;
 USHORT   Code,paint=0;
 WORD     goon;

 if(SysBase->LibNode.lib_Version<37)  /* 28.07.1992 */
   Kickerror();


  xmin=sin(3.0)+sin(3.0);  /* Öffnen der Mathlibs   10.03.1991      */
                           /* bei einem Fehler bricht das Programm */
                           /* automatisch ab !!!                   */


 Open_LIBS();

 strcpy(&configpath[0],&configdir[0]);
 strcat(&configpath[0],&configfile[0]);

 LoadConfig(NULL);

 checkrights((char *)CopyrightText.IText);

 /* all screen configuration done !! */
 /* so lets open my screen and windows */

 Open_WINS();


   FOREVER
    {
      Wait(1L<<FirstWindow->UserPort->mp_SigBit);
      while(message=(struct IntuiMessage *)GetMsg(FirstWindow->UserPort))
       {
           MessageClass=message->Class;
           Code=message->Code;
           xmouse=message->MouseX;
           ymouse=message->MouseY;
           ReportMouse((long)FALSE,FirstWindow);
            
 
           if(MessageClass&MENUVERIFY)
             {
                   if(paint)
                    {
                      if(flag)
                       ZoomBox(2);
                       paint=0;
                       if(Code==MENUHOT)
                             message->Code=MENUCANCEL;
                    }
              }

           ReplyMsg((struct Message *)message);

          switch(MessageClass)
           {
              case MOUSEBUTTONS :
                 switch(Code)
                  {
                    case SELECTUP :
                        paint=0;
                        if(flag)
                           ZoomBox(paint);
                        break;
                    case SELECTDOWN : /* disabling menu messages  25.07.1991 */
                      if(!paint)
                         {
                             paint=1;
                             xs=xmouse;
                             ys=ymouse;
                         }
                        break;
                    }
              break;  

              case INTUITICKS:  /* added 24.09.1991 */
                   if(paint)
                     ZoomBox(paint);
                    break;

              case MOUSEMOVE :
                    if(paint)
                       ZoomBox(paint);
                    Maus();
                    break;

              case MENUPICK :
                  if(Code!=MENUNULL)
                   {
                    goon=Menuauswertung(Code); /* got an endless loop of */
                    while(goon)                /* NextSelect   so I must */
                     {     /* have a return value  from Menuauswertung   */
                           /* since doing CreateMenus()     28.07.1992   */
                       Code=ItemAddress(menu,(long)Code)->NextSelect;
                       if(Code!=MENUNULL)
                         goon=Menuauswertung(Code);
                       else
                         break;
                     }
                   }
                  break;

           }
           ReportMouse((long)TRUE,FirstWindow);
       }
    }
}



/******************************************/
/*                                        */
/*      Auswertung der Menunummer         */
/*                                        */
/******************************************/

WORD Menuauswertung(USHORT Menunummern)
{
  register USHORT Menu,MenuItem,SubItem;
  WORD     retval=TRUE;

  Menu=MENUNUM(Menunummern);
  MenuItem=ITEMNUM(Menunummern);
  SubItem=SUBNUM(Menunummern);


 SetDrMd(rp,(long)JAM1);

 switch(Menu)
  {
     case 0:
          switch(MenuItem)
             {
               case 0:
                    Cleardrawn();
                    Clear();
                    break;
               case 1:
                    About();
                    break;
               case 2:
                    if(ShowErr(16,TRUE))
                     Drucken();
                    break;
               case 3:
                    if(ShowErr(0,TRUE))
                    Ende();
                    break;
              }
          break;

     case 1:
          switch(MenuItem)
            {
               case 0:
                 FuncReq();
               break;

               case 1:
                 changeintervall();
                 break;

               case 2:
                 UnZoom();
               break;

               case 3:
                  switch(SubItem) /* Schrittweite einstellen  */
                   {
                     case 0:
                        STEP=1;
                        xstep=(xmax-xmin)/scrwidth;
                        break;
                     case 1:
                        STEP=2;
                        xstep=(xmax-xmin)/scrwidth*2.0;
                        break;
                     case 2:
                        STEP=4;
                        xstep=(xmax-xmin)/scrwidth*4.0;
                        break;
                     case 3:
                        STEP=8;
                        xstep=(xmax-xmin)/scrwidth*8.0;
                        break;
                    }
                 break;
               case 4:
                   changescreenmode();
                   retval=FALSE;
                   break;
               case 5:
                   changecolor();
                   break;
               case 6:
                   extLoadConfig();
                   retval=FALSE;
                   break;
               case 7:
                   extSaveConfig();
                   break;
            } 
          break;

     case 2:
          switch(MenuItem)
            {
              case 0:
                activeFunc->isdrawn|=0x01;
                DrawFunc(f,1L);
                break;
              case 1:
                activeFunc->isdrawn|=0x02;
                DrawFunc(fa,4L);
                break;
              case 2:
                activeFunc->isdrawn|=0x04;
                DrawFunc(fa2,5L);
                break;
              case 3:
                activeFunc->isdrawn|=0x07;
                DrawFunc(f,1L);
                DrawFunc(fa,4L);
                DrawFunc(fa2,5L);
                break;
              case 4:
                Clear();
                ReDrawFuncs();
                break;
            }
          break;
     case 3:
          switch(MenuItem)
           {
              case 0:
                Nullstellen();
                break;

              case 1:
                 Maxima();
                 break;

              case 2:
                Wendepunkte();
                break;

              case 3:
                NumIntegrate(f);
                break;
            }
          break;
   }
 SetDrMd(rp,(long)JAM1|COMPLEMENT);
return(retval);
}


void Open_LIBS(void)
 {
   extern struct Gadget FuncSaveGadget,FuncLoadGadget;


   if(!(AslBase=(struct Library *)  /* asl and gadtools  on 28.07.1992 */
       OpenLibrary((UBYTE *)"asl.library",37L)))
     {
      Close_LIBS();
      exit(0);
     }

   if(!(GadToolsBase=(struct Library *)
       OpenLibrary((UBYTE *)"gadtools.library",37L)))
     {
      Close_LIBS();
      exit(0);
     }


   ReqBase=(struct ReqLib *)OpenLibrary((UBYTE *)"req.library",0L);

   if(!(mousemem=AllocMem(72L,MEMF_CHIP)))
    {
     Close_LIBS();
     exit(0);
    }

   CopyMem((char *)&mousedata[0],(char *)mousemem,72L);

   if(!(GfxBase=(struct GfxBase *)
       OpenLibrary((UBYTE *)"graphics.library",37L)))
   {
       Close_LIBS();
       exit(0);
   }

   if (!(IntuitionBase = (struct IntuitionBase *)
         OpenLibrary((UBYTE *)"intuition.library", 37L)))
      {
         Close_LIBS();
         exit(0);
      }

}


void Close_LIBS(void)
 {
    if (mousemem)        FreeMem(mousemem,72L);
    if (AslBase)         CloseLibrary((struct Library *)AslBase);
    if (GadToolsBase)    CloseLibrary((struct Library *)GadToolsBase);
    if (ReqBase)         CloseLibrary((struct Library *)ReqBase);
    if (GfxBase)         CloseLibrary((struct Library *)GfxBase);
    if (IntuitionBase)   CloseLibrary((struct Library *)IntuitionBase);
 }

void Open_WINS(void)
 {
   BPTR fh;

   extern struct NewWindow ReqNewWindow,FuncReqNewWindow;

   if(!(FirstScreen=OpenScreen(&FirstNewScreen)))
       {
        if(ScreenVI)  /* do not call min_open on  programmstart */
          {           /* changed 13.08.1992                     */
            min_open();
            return();
           }
        else 
        {
         ShowErr(15,FALSE);
         Ende();
        }
       }

ScreenVI=GetVisualInfo(FirstScreen,TAG_DONE);  /* 28.07.1992 */

NewOKGadget.ng_VisualInfo=NewCancelGadget.ng_VisualInfo=ScreenVI;

FirstNewWindow.Screen=SecondNewWindow.Screen=ThirdNewWindow.Screen=\
FourthNewWindow.Screen=ReqNewWindow.Screen=FuncReqNewWindow.Screen=FirstScreen;

   if (!(FirstWindow = OpenWindow(&FirstNewWindow)))
      {
        ShowErr(15,FALSE);
        Ende();
      }

  process= (struct Process *) FindTask(NULL);
  oldwin=process->pr_WindowPtr;
  process->pr_WindowPtr=(APTR)FirstWindow;


  if(!(menu=CreateMenusA(menulist,NULL))) /* 28.07.1992 */
   {
     ShowErr(17,FALSE);
     Ende();
   }
  if(!LayoutMenusA(menu,ScreenVI,NULL))
   {
    ShowErr(17,FALSE);
    Ende();
   }

  if(!(SetMenuStrip(FirstWindow,menu))) /*  Menu aktivieren       */
   {                                    /* Test since 25.07.1991 */
     ShowErr(17,FALSE);
     Ende();
   }

  if(!ReqBase)
   {
    if(!(fh=Lock((UBYTE *)coltoolname,(long)ACCESS_READ)))
     {
       OffMenu(FirstWindow,(long)0x00a1);
     }
    else
     UnLock(fh);
   }

if (!(SecondWindow = OpenWindow(&SecondNewWindow)))
      {
        ShowErr(8,FALSE);
        Ende();
      }

 rp=FirstWindow->RPort;
 rp2=SecondWindow->RPort;

 SetAPen(rp,5L);
 SetBPen(rp,0L);
 SetAPen(rp2,1L);
 SetDrPt(rp,0xffff);
 SetDrMd(rp,(long)JAM1);

 setcolors();

 Cross();
 Maus();

 SetDrMd(rp,(long)JAM1|COMPLEMENT);
}


void Close_WINS(void)
{
  if (FirstWindow)   process->pr_WindowPtr=oldwin; /* Don't test oldwin!!  */
                                           /* test FirstWindow  10.03.1991 */

  if (FirstWindow->MenuStrip)  ClearMenuStrip(FirstWindow);
                            /* did only test FirstWindow before 25.07.1991 */

  if (menu)            FreeMenus(menu);
  if (FirstWindow)     CloseWindow(FirstWindow);
  if (SecondWindow)    CloseWindow(SecondWindow);
  if (FirstScreen)     
    {
     FreeVisualInfo(ScreenVI);
     CloseScreen(FirstScreen);
    }

  FirstScreen=FirstWindow=SecondWindow=menu=0L;

                                          /* BUG !!! if reopen windows with */
}                                         /* Open_WINS after Close_WINS AND */
                                          /* then ran out of mem, I close   */
                                          /* FirstWindow, but there is no   */
                                          /* FirstWindow!       25.12.1991  */


/******************************************/
/*                                        */
/*         Fenster mit Infotext           */
/*                                        */
/******************************************/

void About(void)
{
  ULONG MessageClass;
  struct RastPort *rp3;
  long memchip,memother;
  time_t z;
  UBYTE  speicher[40];
  struct tm  *zeit;
  short  offset;
 
  ThirdNewWindow.FirstGadget=NULL;

  time(&z);   /* Zeit als long Variable */
  zeit=localtime((const time_t *)&z);  /* long Variable in Zeitstructur wandeln */
  sprintf((char *)UndoBuffer,"%s %2d. %s %4d  %2d:%02d:%02d",Days[zeit->tm_wday],zeit->tm_mday,
          Months[zeit->tm_mon],zeit->tm_year+1900,
          zeit->tm_hour,zeit->tm_min,zeit->tm_sec);

  offset=200-TextLength(rp,(STRPTR)UndoBuffer,strlen((const char *)UndoBuffer))/2;

  DateText.IText=UndoBuffer;      /* Structuren vervollständigen  */
  DateText.LeftEdge=offset;

  memchip=AvailMem(MEMF_CHIP);
  memother=AvailMem(MEMF_FAST);

  sprintf((char *)speicher,"%ld chip mem, %ld other mem",memchip,memother);
  offset=200-TextLength(rp,(STRPTR)speicher,strlen((const char *)speicher))/2;

  MemText.IText=speicher;      /* Structuren vervollständigen  */
  MemText.LeftEdge=offset;
 
  MouseCenterWin(&ThirdNewWindow,0,0);

  if ((ThirdWindow = OpenWindow(&ThirdNewWindow))==NULL)
      ShowErr(9,FALSE);
  else
    {
    
     rp3=ThirdWindow->RPort;
     PrintIText(rp3,&NameText,0L,0L);
       FOREVER
         {
  
          if((message=(struct IntuiMessage *)
            GetMsg(ThirdWindow->UserPort))==NULL)
           {
             Wait(1L << ThirdWindow->UserPort->mp_SigBit);
             continue;
           }
            MessageClass=message->Class;
            ReplyMsg((struct Message *)message);
            switch(MessageClass)
              {
                 case MOUSEBUTTONS :
                 CloseWindow(ThirdWindow);
                 return();
               }
         }
    }
}


/******************************************/
/*                                        */
/*    Ausgabe des Windows und der         */
/*    Einstellungen auf den Drucker       */
/*                                        */
/******************************************/


void Drucken(void)
{
  struct  MsgPort    *printerPort;
  union   printerIO  *request;
  UBYTE               *memblock;
  long               len,col0,col2;


  helpdruck(&memblock,&len);   /* inserted 29.01.1992 */

  if(!len)
   return();

 SetPointer(FirstWindow,mousemem,16L,16L,0L,0L);

 if(printerPort=CreatePort(NULL,0L))
 {
  if(request=(union printerIO *)CreateExtIO(printerPort,
              sizeof(union printerIO)))
  {
  if(!(OpenDevice((UBYTE *)"printer.device",0L,(struct IORequest *)request,0L)))
   {
     /* old sprintf() deleted   29.01.1992 */

     request->ios.io_Message.mn_ReplyPort=printerPort;
     request->ios.io_Command=CMD_WRITE;
     request->ios.io_Data=(APTR)memblock;
     request->ios.io_Length=len;

     if(!(DoIO((struct IORequest *)request)))
      {
       col0=GetRGB4(FirstScreen->ViewPort.ColorMap,0L);
       col2=GetRGB4(FirstScreen->ViewPort.ColorMap,2L);
       SetRGB4(&FirstScreen->ViewPort,0L,15L,15L,15L);
       SetRGB4(&FirstScreen->ViewPort,2L,0L,0L,0L);

                  /* Einstellungen für einen RastPort-Dump */

       request->iodrp.io_Command= PRD_DUMPRPORT;
       request->iodrp.io_RastPort=rp;
       request->iodrp.io_ColorMap=FirstScreen->ViewPort.ColorMap;
       request->iodrp.io_Modes=FirstScreen->ViewPort.Modes;
       request->iodrp.io_SrcX=0;    /*       LeftEdge -- TopEdge  !!             */
       request->iodrp.io_SrcY=0;    /* so kann man auch einen Ausschnitt drucken */
       request->iodrp.io_SrcWidth=scrwidth;
       request->iodrp.io_SrcHeight=scrheight-10;
       request->iodrp.io_Special= SPECIAL_FULLROWS | SPECIAL_FULLCOLS | SPECIAL_ASPECT;

       if(DoIO((struct IORequest *)request))/* wartet bis Drucker fertig ist */
              fehler=10;                     /* SendIO würde im Programm fortfahren  */

      SetRGB4(&FirstScreen->ViewPort,0L,(col0>>8) & 0xf,(col0>>4) & 0xf,col0 & 0xf);
      SetRGB4(&FirstScreen->ViewPort,2L,(col2>>8) & 0xf,(col2>>4) & 0xf,col2 & 0xf);
     }
    CloseDevice((struct IORequest *)request);
   }
  DeleteExtIO((struct IORequest *)request);
  }
  DeletePort(printerPort);
 }

 ClearPointer(FirstWindow); /* 29.01.1992 */
 FreeMem(memblock,len);


}


void Ende(void)
{
 delallfuncs();
 Close_WINS();
 Close_LIBS();
 exit(0);
}


/**************************************************/
/*                                                */
/*    Einstellungen nach Neueingabe überprüfen    */
/*                                                */
/**************************************************/

void NeueP(void)
{
 register double help,xnd,ynd;

 xmin=atof((const char *)minx);
 xmax=atof((const char *)maxx);
 ymin=atof((const char *)miny);
 ymax=atof((const char *)maxy);

 if(xmin>xmax)  /*  X-Werte vertauscht  */
  {
    help=xmin;
    xmin=xmax;
    xmax=help;
  }
 if(ymin>ymax)   /*  Y-Werte vertauscht  */
  {
    help=ymin;
    ymin=ymax;
    ymax=help;
  }

  printpara(minx,xmin);  /* Werte nochmals reinschreiben ,um   */
  printpara(miny,ymin);  /* falsche Eingaben dem Benutzer beim */
  printpara(maxx,xmax);  /* nächsten Aufruf sichtbar zu machen */
  printpara(maxy,ymax);

  xstep=(xmax-xmin)/scrwidth*STEP;
 
  xe=scrwidth/(xmax-xmin);     /*  Schrittweite X         1Pixel  */
  xnd=xe*-xmin;                /*  Nullpunkt    X                 */

  ye=(scrheight-10)/(ymax-ymin);     /*  Schrittweite Y   1 Pixel */
  ynd=(scrheight-10)-ye*-ymin;       /*  Nullpunkt    Y           */

  xnull=xnd;              /* long Variablen mit Nullpunkt */
  ynull=ynd;


}

/*******************************************************************/
/*                                                                 */
/*               DrawFunc() is a revision of the old               */
/*                 Ableitung1() --> so Funktion(),                 */
/*                 Ableitung() and Ableitung2() is                 */
/*                      done with DrawFunc()                       */
/*              ->code size improvement of 860 bytes               */
/*                                                                 */
/*******************************************************************/

void DrawFunc(double (*calc)(double),long color)
{
  register  double y,x1;
  register  long   xp,yp;
  long      oldy;
  short            flag=0;
  UWORD     oldpattern;

   if(fehler)
    return();
   
   oldpattern=rp->LinePtrn;
   SetPointer(FirstWindow,mousemem,16L,16L,0L,0L);
   SetAPen(rp,color);
   SetDrPt(rp,activeFunc->FuncPattern);

   x1=xmin;
   y=calc(x1);
   yp=y*ye;
   yp=ynull-yp;

   xp=xmin*xe;

  if(yp>winheightmax)
     {
      yp=winheightmax;
      flag=1;
     }
  else
     if(yp<0L)
       {
         yp=0L;
         flag=1;
       }

  oldy=yp;
  Move(rp,0L,yp);

  for(;x1<xmax;x1 += xstep)
   {
     y=calc(x1);

     yp=-y*ye;
     yp+=ynull;
     xp=x1*xe;
     xp += xnull;

/*  more Line-Clipping                        */
/*  changed 19.03.1991 and 27.04.1991         */
/*  old Version draws a line to y=251 or y=-1 */
/*  this never caused a guru, but i thought   */
/*  my old A2000 A (built 23-Jun-87) machines */
/*  behavior is not like everyone's           */

     if(yp>winheightmax)
      {
       if(flag)
        Move(rp,xp,winheightmax);
       else
        {
         if(labs(yp-oldy)>(STEP<<2))
            DrawFunc2(calc,xstep,yp);
         Draw(rp,xp,winheightmax);
         flag=1;
        }
      }
     else
      {
       if(yp<0L)
         {
          if(flag)
            Move(rp,xp,0L);
          else
           {
             if(labs(yp-oldy)>(STEP<<2))
               DrawFunc2(calc,xstep,yp);
             Draw(rp,xp,0L);
             flag=1;
           }
         }
        else
          {
           if(labs(yp-oldy)>(STEP<<2))
              DrawFunc2(calc,xstep,yp);
            Draw(rp,xp,yp);
            flag=0;
          }
       }
     oldy=yp;
   }
  ClearPointer(FirstWindow);
  SetDrPt(rp,oldpattern);
}


/*******************************************************************/
/*                                                                 */
/*       DrawFunc2() draws one new step if delta y is to big       */
/*                         done 08.02.1992                         */
/*                                                                 */
/*******************************************************************/

void DrawFunc2(double (*calc)(double),double oldstep,long oldy)
{
  double   xold,step;
  register long   xp,yp;

   step=oldstep*0.5;

   xold=x;

   yp=-calc(x-step)*ye;
   yp+=ynull;
   xp=x*xe;      /* x is set while doing calc(x-step) */
   xp += xnull;

  if(yp>winheightmax)
      yp=winheightmax;
  else if(yp<0L)
        yp=0L;

  if(labs(yp-oldy)>(STEP<<2))
   DrawFunc2(calc,step,yp);

  Draw(rp,xp,yp);

  x=xold;
}


/*******************************************************************/
/*                                                                 */
/*             Cleardrawn clears the isdrawn Flag in               */
/*             struct FuncNode       done 23.01.1992               */
/*                                                                 */
/*******************************************************************/

void Cleardrawn(void)
{
 struct FuncNode *nodeptr;

 nodeptr=FirstFunc;

 do
  {
    nodeptr->isdrawn=0;
  }while(nodeptr=nodeptr->Next);
}

void Clear(void)   /*     Bildschirm löschen   */
{
 SetRast(rp,0L);
 Cross();
}


/******************************************/
/*                                        */
/*            Nullstellensuche            */
/*                                        */
/******************************************/

void Nullstellen(void)
{
   short n=0,sign,sign2;
   register    double dx,z;

   if(openex())
     return();

   Move(rp4,156L,20L);     /* Text ausgeben */
   Text(rp4,(UBYTE *)"Zero points",11L);

   x=xmin;
     sign=numb() < 0.0 ? 0 : 1;

   dx=(xmax-xmin)/scrwidth*4.0;  /* Schrittweite 4 Pixel  */

   for(;x<=xmax;x += dx)
    {
      sign2=numb() < 0.0 ? 0 : 1;

      if(sign != sign2 )
       {
           z=x;
           x -= dx*.5;
           n++;           /* Zähler der Nullstellen   */
           newton1(n);
           x = z;
           sign=sign2;
       }
     }

closeex(n);

}


/******************************************/
/*                                        */
/*        Ausgabewindow öffnen            */
/*                                        */
/******************************************/

short openex(void)
{
 
if (!(FourthWindow = OpenWindow(&FourthNewWindow)))
      {
        ShowErr(12,FALSE);
        return(1);
      }

   rp4=FourthWindow->RPort;
   SetAPen(rp4,6L);
   SetBPen(rp4,0L);
 return(0);
}


/******************************************/
/*                                        */
/*       Ausgabewindow schließen          */
/*                                        */
/******************************************/

void closeex(short n)
{
 long yoffset;

   yoffset=50+n*10;

   if(yoffset>(scrheight-15L))
     Move(rp4,184L,scrheight-18L);     /* Text ausgeben */
   else 
     Move(rp4,184L,yoffset);

   SetAPen(rp4,6L);
   Text(rp4,(UBYTE *)"End",3L);

   Wait(1L<<FourthWindow->UserPort->mp_SigBit);
   message=(struct IntuiMessage *)GetMsg(FourthWindow->UserPort);

   ReplyMsg((struct Message *)message);

   CloseWindow(FourthWindow);

}


/******************************************/
/*                                        */
/*     Ausgabe der gefundenen Stellen     */
/*                                        */
/******************************************/

void exaus(short n,double a,double b,short s)
{
    long offset=30+n*10;

    sprintf((char *)UndoBuffer,"y=%12.8f  at  x= %12.8e",a,b);
 
    if(offset>((scrheight/10)*10-30))
      {
        offset=(scrheight/10)*10-30;
        ScrollRaster(rp4,0L,10L,18L,32L,395L,scrheight-25L);
      }
    Move(rp4,20L,offset);
    SetAPen(rp4,1L);
    Text(rp4,(UBYTE *)UndoBuffer,strlen((const char *)UndoBuffer));
   
    if(s)
      {
        SetAPen(rp4,4L);
        Move(rp4,360L,offset);
        switch(s)
         {
           case 1:
              Text(rp4,(UBYTE *)"Max",3L);
              break;
           case 2:
              Text(rp4,(UBYTE *)"Min",3L);
              break;
           case 3:
              Text(rp4,(UBYTE *)"T",1L);
              break;
           case 4:
              Text(rp4,(UBYTE *)"S",1L);
              break;
         }
      }
}


/******************************************/
/*                                        */
/*    Ermitteln der Nullstelle            */
/*                                        */
/******************************************/

void newton1(short n)
{
  register  double x1,y1,y2;
  short q=0;

  x1=x;
  y1=numb();

  do
   {
     x += 1e-7;
     y2=numb();

     x1=x1-y1/((y2-y1)*1e7);
     
     x=x1;
     y1=numb();

     q++;
    }while((fabs(y1)>0.00001) && q<60);

     exaus(n,y1,x1,0);
}


/******************************************/
/*                                        */
/*          Maximasuche                   */
/*                                        */
/******************************************/

void Maxima(void)
{
 short n=0,sign,sign2;
 register double dx,z,x1;

  if(openex())
   return();

  SetAPen(rp4,6L);
  Move(rp4,140L,20L);
  Text(rp4,(UBYTE *)"Maxima & Minima",15L);

  x1=xmin;
  dx=(xmax-xmin)/scrwidth*8.0;
  sign=fa(x1)<0.0 ? 0 : 1;

  for(;x1<=xmax;x1 += dx)
   {
     sign2=fa(x1)<0.0 ? 0 : 1;
     if(sign != sign2)
      {
        z=x1;
        x1 -= dx*.5;
        n++;
        newton2(n,x1);
        x1=z;
        sign=sign2;
      }
    }
 closeex(n);

}


/******************************************/
/*                                        */
/*         Ermittlung des Maximas         */
/*                                        */
/******************************************/

void newton2(short n,double x1)
{
 register double y1,y;
 short q=0,s;

 y1=fa(x1);

 do
  {
    x1=x1-fa(x1)/fa2(x1);

    y1=fa(x1);
    q++;
  }while((fabs(y1)>0.001)&&q<60);

  x=x1;
  if(fa2(x1)<0.0)
    s=1;
  else
    s=2;
  y=numb();

  exaus(n,y,x1,s);

}


/******************************************/
/*                                        */
/*         Wendepunktsuche                */
/*                                        */
/******************************************/

void Wendepunkte(void)
{
 short n=0,sign,sign2;
 register double dx,z,x1;


 if(openex())
   return();

  SetAPen(rp4,6L);
  Move(rp4,144L,20L);
  Text(rp4,(UBYTE *)"Turning points",14L);

  x1=xmin;
  dx=(xmax-xmin)/scrwidth*8.0;
  sign=fa2(x1)<0.0 ? 0 : 1;

  for(;x1<=xmax;x1 += dx)
   {
    sign2=fa2(x1)<0.0 ? 0 : 1; 
     if(sign != sign2)
      {
        z=x1;
        x1 -= dx*.5;
        n++;
        newton3(n,x1);
        x1=z;
        sign=sign2;
      }
    }
 closeex(n);

}


/******************************************/
/*                                        */
/*       Ermittlung des Wendepunktes      */
/*                                        */
/******************************************/

void newton3(short n,double x1)
{
 register double y1,y;
 short q=0,s=3;

 y1=fa2(x1);

 do
  {
    x1=x1-fa2(x1)/fa3(x1);     /* x2=x1-f(x1)/f'(x1)  */

    y1=fa2(x1);
    q++;
  }while((fabs(y1)>0.001)&&q<60);
  
  x=x1;
  if(fabs(fa(x1))<0.1)
    s=4;
  y=numb();

  exaus(n,y,x1,s);
}


/******************************************/
/*                                        */
/*       Koordinatenkreuz zeichnen        */
/*                                        */
/******************************************/

void Cross(void)
 {
  register double z;
  register long   s;
  double   zadd;

  SetAPen(rp,2L);

                          /*   Achsen zeichnen   */

if(ynull>=0 && ynull<=winheightmax) /*      X-Achse        */
 {
  Move(rp,0L,ynull);
  Draw(rp,scrwidth-1L,ynull);

   zadd=pow(10.0,floor(log10(xmax-xmin)-0.7)); /* 20 minutes of thinking    */
   z=floor(xmin/zadd)*zadd+zadd;               /* 1h work, but great effect */
                                               /* changed 10.08.1991        */
                                               /* -0.7 gives 50 Steps       */
                                               /* -> 10^(1.7)=50.???        */
   do             /*   Einheiten zeichnen  */
    {
      s=xe*z+xnull;
      Move(rp,s,ynull-3L);         /* auf X-Achse   */
      Draw(rp,s,ynull+3L);
      z+=zadd;
    }while(z<=xmax);
 }

if(xnull>=0 && xnull<=scrwidth)    /*      Y-Achse        */
 {
   Move(rp,xnull,0L);
   Draw(rp,xnull,winheightmax);

   zadd=pow(10.0,floor(log10(ymax-ymin)-0.55));/* -0.55 gives me 35 steps */
   z=floor(ymin/zadd)*zadd+zadd;

   do
     {
       s=-ye*z+ynull;
       Move(rp,xnull-6L,s);         /* auf Y-Achse   */
       Draw(rp,xnull+6L,s);
       z+=zadd;
     }while(z<=ymax);
  }

}
/******************************************/
/*                                        */
/*                Function                */
/*                                        */
/******************************************/

double f(double r)  /* 17.11.1991 */
{
 x=r;
 return(numb());
}

/******************************************/
/*                                        */
/*             1. Ableitung               */
/*                                        */
/******************************************/

double fa(double r)
{
  register double x1,x2;

  x=r;

  if(numb1)
    return(numb1());

  x1=numb();
  x += 1e-6;
  x2 = numb();

  /*  (f(x+dx)-f(x))/dx  */

  return((x2-x1)*1e6);
}


/******************************************/
/*                                        */
/*             2. Ableitung               */
/*                                        */
/******************************************/

double fa2(double r)
{
  register double x1,x2; 
  double x3;

  x=r;

  if(numb2)
   return(numb2());

  x1=numb();
  x += 1e-5;
  x2=numb();
  x += 1e-5;
  x3=numb();

/*  f''(x)=(f(x+2dx)-2f(x+dx)+f(x))/dx^2 */

  return((x3-2.0*x2+x1)*1e10);

}


/******************************************/
/*                                        */
/*             3. Ableitung               */
/*                                        */
/******************************************/

double fa3(double r)
{
 register double x2,x3;
 double x1,x4;

 x=r;
 x1=numb();
 x += 1e-3;
 x2=numb();
 x += 1e-3;
 x3= numb();
 x += 1e-3;
 x4=numb();

 /* f'''(x)=(f(x+3dx)-3f(x+2dx)+3f(x+dx)-f(x))/dx^3  */

 return((x4-3.0*x3+3.0*x2-x1)*1e9);

}


/************************************************/
/*                                              */
/* abolute Koordinaten ins 2. Fenster schreiben */
/*                                              */
/************************************************/

void Maus(void)
{
 double mfy,mfx;
 char zahlx[15],zahly[15];

   mfy=(ynull-ymouse)/ye;       /*  x-Wert errechnen  */
   mfx=(xmouse-xnull)/xe;       /*  y-Wert errechnen  */

   sprintf(zahlx,"x= %-11.3e",mfx);
   sprintf(zahly,"y= %-11.3e",mfy);

      
    /* Text ausgeben */
   Move(rp2,4L,19L);
   Text(rp2,(UBYTE *)zahlx,14L);
   Move(rp2,4L,30L);
   Text(rp2,(UBYTE *)zahly,14L);

}


/*******************************************************************/
/*                                                                 */
/*           added this function cause I have a lott of            */
/*                 messages called in this form                    */
/*                                                                 */
/*                changed ShowErr on 12.08.1992                    */
/*       removed AutoRequest()   EasyRequest() is much better      */
/*******************************************************************/

short ShowErr(short num,BOOL extra)
{
  ULONG idcmp=0;

  fehler=0;    /* clear error number from parser  */

  if(extra)
    es1.es_GadgetFormat=(UBYTE *)"Ok|Cancel";
  else
    es1.es_GadgetFormat=(UBYTE *)"Ok";

   return(EasyRequestArgs(FirstWindow,&es1,&idcmp,&ErrorMessages[num]));
}


/*******************************************************************/
/*                                                                 */
/*      NumIntegrate() Integrates numerical the function f(x)      */
/*             from xmin to xmax via Simpson Integral              */
/*                                                                 */
/*******************************************************************/


void   NumIntegrate(double (*calc)(double))
{
 register  double f,x1;
 double    xs;
 short     n,i;
 ULONG     MessageClass;
 USHORT    code,qualifier;
 SHORT     GadgetID=0;
 char      str1[60],str2[30],str3[30];
 struct    Gadget  *gad;

 extern struct IntuiText    IntegralWin5Text,IntegralWin3Text;

 SetPointer(FirstWindow,mousemem,16L,16L,0L,0L);

  n=(xmax-xmin)/xstep;

  if(n&0x01)  /* first Version was n%2     25.12.1991 */
    n++;

   x1=xmin;
   xs=(xmax-xmin)/(n>>1);   /* double step rate !!   */

   f=calc(x1);
   x1+=xs*0.5;              /* the first step to n=1 */

   for(i=1;i<n;i+=2)
    {
      f+=4.0*calc(x1);      /* 4 times all not even parts */
      x1+=xs;
    }

   x1=xmin+xs; /* the step to n=2  */

   for(i=2;i<n;i+=2)
    {
     f+=2.0*calc(x1);       /* 2 times all even parts  */
     x1+=xs;
    }

    f=(f+calc(x1))*(xmax-xmin)/(3.0*n);

    sprintf(str1,"Xmin= %s  to  Xmax= %s",minx,maxx);
    printpara((unsigned char *)str2,f);
    sprintf(str3,"A= %s",str2);

    IntegralWin5Text.IText=(UBYTE *)str3;
    IntegralWin3Text.IText=(UBYTE *)str1;
    IntegralWin5Text.LeftEdge=200-(IntuiTextLength(&IntegralWin5Text)>>1);
    IntegralWin3Text.LeftEdge=200-(IntuiTextLength(&IntegralWin3Text)>>1);
                                  /* first version was lenght/2  25.12.1991 */

    NewOKGadget.ng_LeftEdge      =155;  /* 04.08.1992 */
    NewOKGadget.ng_TopEdge       =98;

    gad=CreateContext((struct Gadget **)&nullgadget);
    gad=CreateGadget((ULONG)BUTTON_KIND,gad,&NewOKGadget,
           GT_Underscore,(ULONG)'_',TAG_DONE);

    ThirdNewWindow.FirstGadget=nullgadget;

    ClearPointer(FirstWindow);
    MouseCenterWin(&ThirdNewWindow,0,30);
    if (!(ThirdWindow = OpenWindow(&ThirdNewWindow)))
       ShowErr(9,FALSE);
    else
     {
      rp4=ThirdWindow->RPort;
      PrintIText(rp4,&IntegralWin5Text,0L,0L);
      GT_RefreshWindow(ThirdWindow,NULL);
       FOREVER
        {
         Wait(1L << ThirdWindow->UserPort->mp_SigBit);
          while(message=(struct IntuiMessage *)GT_GetIMsg(ThirdWindow->UserPort))
          {
           MessageClass=message->Class;
           code=message->Code;
           qualifier=message->Qualifier;
           GT_ReplyIMsg(message);
           switch(MessageClass)
            {
                case IDCMP_REFRESHWINDOW: /*04.08.1992 */
                  GT_BeginRefresh(ThirdWindow);
                  PrintIText(rp4,&IntegralWin5Text,0L,0L);
                  GT_EndRefresh(ThirdWindow,(LONG)TRUE);
                  break;

                case VANILLAKEY:
                  switch(code)
                   {
                     case 'v':
                     if(!(qualifier&IEQUALIFIER_LCOMMAND))
                        break;
                     case 'O':
                     case 'o':
                      GadgetID=7;
                      break;
                   }
                  break;

                  case GADGETUP:  /* I've only one Gadget  */
                      GadgetID=7;
                      break;
 
                  default:
                      break;
            }
          }
        if( GadgetID == 7)
         break;
        }
      CloseWindow(ThirdWindow);
     }

if(nullgadget) FreeGadgets(nullgadget);

}


UBYTE  WRONGKICKVERSION[]=
{
 0,120,25,"Sorry, Kickstart Version greater 37.175 is needed!",0xff,
 0,184,55,"Press any mousebutton to continue!",0x00
};


void Kickerror(void)   /* 28.07.1992 */
{
 if (IntuitionBase = (struct IntuitionBase *)
     OpenLibrary((UBYTE *)"intuition.library", 0L))
  {
    DisplayAlert(0L,WRONGKICKVERSION,70L);
    CloseLibrary((struct Library *)IntuitionBase);
  }
 exit(0);
}


/*******************************************************************/
/*                                                                 */
/*          min_open() will try to open a 640*200 Screen           */
/*              if OpenScreen() from Open_WINS() fail              */
/* 13.08.1992                                                      */
/*******************************************************************/

void min_open(void)
{
 static BOOL recursive=0; /* or check 640*200 */


   if(AvailMem(MEMF_CHIP|MEMF_LARGEST)<55000L||recursive)
    {
      if(ShowErr(18,TRUE))
       {
         extSaveConfig();  /* sorry not able to open any screen  */
         handlesave();
        }
       Ende();
     }

  recursive=TRUE;
  scrmode=HIRES_KEY;
  scrheight=200;
  scrwidth=640;
  defscr=0;
  setscreenprefs();
  NeueP();
  Open_WINS();
  ShowErr(19,FALSE);
  recursive=FALSE;

}
