/*Amiga Computing*/
/*Code Clinic*/
/*A500 upwards*/

/*c source code   -  main program*/

#include "sums.h"

void main()
{
   /*opens libraries,screen and window*/
   IntuitionBase = (struct IntuitionBase *)
   OpenLibrary("intuition.library",LIBRARY_VERSION);/*open the library*/
   if (IntuitionBase == NULL) cleanup("no intuition library");
   GfxBase = (struct GfxBase *)
   OpenLibrary("graphics.library",0);/*open the library*/
   if (GfxBase == NULL) cleanup("no graphics library");
   InitBitMap(&ScreenBitMap,5,320,256);  /*set up a bitmap */
   for(i=0;i<5;i++)                      /*allocate screen for it*/
      {
        ScreenBitMap.Planes[i] = (PLANEPTR)AllocRaster(320,256);
        if (ScreenBitMap.Planes[i] == 0) exit(1);
        BltClear(ScreenBitMap.Planes[i],40*256,0); /*clear the a screen area*/
      }
   CustomScreen= (struct Screen *) OpenScreen(&NewScreenStructure);
   if (CustomScreen == 0) cleanup("no screen");      /*open the screen*/
   NewWindowStructure.BitMap = (struct BitMap *) &ScreenBitMap;
   NewWindowStructure.Screen = CustomScreen;        /*attach window to screen*/
   if ((MainWindow = (struct Window *)OpenWindow(&NewWindowStructure))  == NULL) 
   cleanup("cannot open main window");
  /*diverts the system error message to appear in front of MainWindow*/
   mproc=(struct Process *)FindTask(NULL);
   savewindow=(APTR *)mproc->pr_WindowPtr;
   mproc->pr_WindowPtr=(APTR)MainWindow;
   rp= (struct RastPort *)MainWindow->RPort;
  /*opens the console port*/
   error=InitConsole();
   if(error!=0) cleanup("no consoleport");
  d=&decx;            /*initialise pointers*/
  s=&sign;
  /*initialises cursor position and arrays*/
  
   for (i=0;i<399;i++)
       array[i] = 0;
   x = 20;
   y = 40; 
  /*handles the window input*/
   Handle_IDCMP();
  /*puts system error messages where they belong*/ 
  (APTR *)mproc->pr_WindowPtr = savewindow;
  /*flushes and closes console port*/  
   i=CheckIO(readrequest);
   if (i==FALSE) AbortIO(readrequest);
   DeletePort(readport);
   DeleteStdIO(readrequest);
  /*cleans up and exits*/ 
   cleanup(NULL); 
}

/*handle messages for window*/
void Handle_IDCMP()
   {
   APTR object;          
   for (quit_flag = FALSE;!quit_flag;)
      {
      if (1<<MainWindow->UserPort->mp_SigBit)
         {
      while (!(message=(struct IntuiMessage *)GetMsg(MainWindow->UserPort)))
             {/*processing*/
             }
         }
      class = message->Class;    
      code = message->Code;    
      object=message->IAddress;
      if (class!=RAWKEY)ReplyMsg((struct Message *) message);   
       /* (Clears message area,resets flags)*/
      switch ( class )
         {
         case MOUSEBUTTONS:
           quit_flag = TRUE;
           break;

         case RAWKEY:           /*key pressed*/   
           HandleRawKey();
           break;
        }                                                    /* end switch */
      }                                                      /* end forloop */
   }


void cleanup(errormsg)                                   
char *errormsg;
   {                                                   
     printf(errormsg);
     if (MainWindow != 0 ) CloseWindow(MainWindow);
     if (CustomScreen != 0 ) CloseScreen(CustomScreen);/*close screen*/
     for (i=0;i<5;i++)    /*free the screen memory*/
       {
          FreeRaster(ScreenBitMap.Planes[i],320,256);
       }
     if (GfxBase != 0 ) CloseLibrary(GfxBase);
     if (IntuitionBase !=0) CloseLibrary(IntuitionBase);/*close library*/
     exit(0);
    }


/*sets up dummy console port for RawKey Convert*/
int InitConsole()
{
   error=0;
   readport=CreatePort("conread",0);
   if (readport==0) return(1);
   readrequest=CreateStdIO(readport);
   if (readrequest==0) return(1);
   error=OpenDevice("console.device",-1,readrequest,0);
   ConsoleDevice=readrequest->io_Device;
   if (error!=0) return(error);
   return(0);
}

/*handles key code conversion*/

int KeyConvert(msg,buf)
struct IntuiMessage *msg;
char *buf;
{
   if (msg->Class!=RAWKEY) return(0);
   ievent.ie_Code=msg->Code;
   ievent.ie_Qualifier=msg->Qualifier;
   ievent.ie_position.ie_addr=* (APTR *)msg->IAddress;
   return(RawKeyConvert(&ievent,buf,10,NULL));
}


/*Converts RAWKEY code to ascii and processes it*/
/*RAWKEY from message converted, and string put in*/
/*buff[] Length of string returned*/
int HandleRawKey()
{
   int len,place;
   len= KeyConvert(message,&buff[0],10);
   ReplyMsg((struct Message *) message);
   if (len==1)                  /*one character only*/
     {
         if (buff[0]==0x1b)     /*escape key*/
            {  
               quit_flag = TRUE; 
               return(0);
             }
         if (buff[0]==0x7f)     /*delete key*/ 
            {
               x=x-8;
               aligntext();
               buff[0]=' ';
            } 
         if (buff[0]==0x09)      /*tab*/  
            {
                x = x+8;
                aligntext();
                return(0);
            }
         if (buff[0]==0x08)      /*backspace*/ 
            {
                x = x-8;
                aligntext();
                return(0);
            }
         if (buff[0]==0x0d)       /*carriage return & line feed*/  
            {
                x= 20;
                y=y+10;
                aligntext();
                return(0);
            }
         if (((*buff<48) || (*buff>57)) && (*buff !='.') 
           && (*buff != '-')&& (*buff != ' '))
                    return(0);
         Move(rp,x,y);           /*move to correct position*/
         Text(rp,buff,1);        /*display character*/
         place = (((y-40)/10)*10); /*put character in array*/
         place = place + ((x-20)/8);
         *(array+place) = buff[0];
         x = x+8;                /*calculate next position*/
         aligntext();
         return(0);
     }
     /*escape sequences*/
   if ((buff[1]==0x41)||(buff[1]==0x54)) 
         {                        /*cursor up*/
            y = y-10;
            aligntext();
            return(0);
          }
   if ((buff[1]==0x42)||(buff[1]==0x53)) 
         {                         /*cursor down*/
            y = y+10;
            aligntext();
            return(0);
         }
   if ((buff[1]==0x43)||(buff[1]==0x5a)||((buff[1]==0x20)&&(buff[2]==0x40)))
         {
            x=x+8;
            aligntext();
            return(0);
         }
   if ((buff[1]==0x44)||((buff[1]==0x20)&&(buff[2]==0x41)))
         {
            x=x-8;
            aligntext();
            return(0);
         }
           /*help key*/
   if((buff[1]==0x3f)&&(buff[2]==0x7e)) printf("help!\n");
           /*function keys*/
   
   if (fnkey(&buff[0],48,126,49,48,126)) 
   {                                 /*number and square*/
   strcpy(col1,"number       ");
   strcpy(col2,"square       ");
   for (i=0;i<20;i++)
     {
       fl=atof(array+10*i);
       strcpy(arrayout+20*i,ftoa(fl*fl,2));
     }
   display();
   }
   if (fnkey(&buff[0],49,126,49,49,126)) 
   {                              /*radius and circumference*/
   strcpy(col1,"radius       ");
   strcpy(col2,"circumference");
   for (i=0;i<20;i++)
     {
       fl=atof(array+10*i);
       strcpy(arrayout+20*i,ftoa(fl*2*PI,3));
     }
   display();
   }
   if (fnkey(&buff[0],50,126,49,50,126)) 
   {                              /*miles and kilometeres*/
   strcpy(col1,"miles        ");
   strcpy(col2,"kilometeres  ");
   for (i=0;i<20;i++)
     {
       fl=atof(array+10*i);
       fl=fl*MILEKILO;
       strcpy(arrayout+20*i,ftoa(fl,2));
     }
   display();
   }
   if (fnkey(&buff[0],51,126,49,51,126)) 
    {                                 /* centigrade and fahrenheit*/
   strcpy(col1,"centigrade   ");
   strcpy(col2,"fahrenheight ");
   for (i=0;i<20;i++)
     {
       fl=atof(array+10*i);
       fl=fl*1.8;
       strcpy(arrayout+20*i,ftoa(fl+32,2));
     }
   display();
   }
   if (fnkey(&buff[0],52,126,49,52,126)) 
    {                               /* pounds and kilos*/
   strcpy(col1,"pounds       ");
   strcpy(col2,"kilos        ");
   for (i=0;i<20;i++)
     {
       fl=atof(array+10*i);
       strcpy(arrayout+20*i,ftoa(fl*POUNDKILO,2));
     }
   display();
   }
   if (fnkey(&buff[0],53,126,49,53,126)) 
   {                               /* number and square root*/
   strcpy(col1,"number       ");
   strcpy(col2,"square root  ");
   for (i=0;i<20;i++)
     {
       fl=atof(array+10*i);
       fl2=sqrt(fl);
       strcpy(arrayout+20*i,ftoa(fl2,4));
     }
   display();
   }
   if (fnkey(&buff[0],54,126,49,54,126)) 
   {                            /*angle (in radians) and sine*/
   strcpy(col1,"radians      ");
   strcpy(col2,"sine         ");
   for (i=0;i<20;i++)
     {
       fl=atof(array+10*i);
       fl2=sin(fl);
       strcpy(arrayout+20*i,ftoa(fl2,10));
     }
   display();
   }
   if (fnkey(&buff[0],55,126,49,55,126)) 
  {                            /*angle (in radians) and cosine*/
   strcpy(col1,"radians      ");
   strcpy(col2,"cosine       ");
   for (i=0;i<20;i++)
     {
       fl=atof(array+10*i);
       fl2=cos(fl);
       strcpy(arrayout+20*i,ftoa(fl2,10));
     }
   display();
   }
   if (fnkey(&buff[0],56,126,49,56,126)) 
  {                               /*angle (in radians) and tangent*/
   strcpy(col1,"radians      ");
   strcpy(col2,"tangent      ");
   for (i=0;i<20;i++)
     {
       fl=atof(array+10*i);
       fl2=tan(fl);
       strcpy(arrayout+20*i,ftoa(fl2,10));
     }
   display();
   }
   if (fnkey(&buff[0],57,126,49,56,126)) 
  {                              /*number and log to base 10*/
   strcpy(col1,"number       ");
   strcpy(col2,"log base 10  ");
   for (i=0;i<20;i++)
     {
       fl=atof(array+10*i);
       fl2=0;
       if (fl >0) fl2=log10(fl);
       strcpy(arrayout+20*i,ftoa(fl2,10));
     }
   display();
   }
   aligntext();
   return(0);
}

void display()
{
   Move(rp,20,20);
   Text(rp,col1,strlen(col1));
   Move(rp,140,20);
   Text(rp,col2,strlen(col2));
   for (i=0;i<20;i++)
     {
       Move(rp,140,40+10*i);
       Text(rp,"                    ",20);
       Move(rp,140,40+10*i);
       Text(rp,arrayout+20*i,strlen(arrayout+20*i));
     }
   return;
}

/*checks for function key sequence*/
int fnkey(pointer,a,b,c,d,e)
char *pointer;
char a,b,c,d,e;
{
   long f;
   f=FALSE;
   if ((*(pointer+1)==a)&&(*(pointer+2)==b)) f=TRUE;
   if ((*(pointer+1)==c)&&(*(pointer+2)==d)&&(*(pointer+3)==e)) f=TRUE;
   return(f);
}

/* puts next character in position, taking care of line ends, etc*/
/*clears buffer*/
void aligntext()
{
   if (x <20) x = 20;
   if (x >91) {x=20; y = y+10;}
   if (y < 40) y = 40;
   if (y > 240) {x = 20; y = 40;}
   buff[1]=0;
   buff[2]=0;
   buff[0]=0;
   buff[3]=0;
   return;
}

/*routine to put the ASCII form of a floating point number
  in a buffer for display*/

char *ftoa(f,n)
double f;           /*floating point number*/
int n;             /*number of decimal places*/
{
  char *address;   /*pointer to string returned from fcvt() */
  int k;           /*loop variable*/
  for (k=0;k<31;k++) buffer2[k]=0;  /*clear character buffer*/

                    /* convert floating point to string
                     address points to string
                     f is floating point number
                     d is location for decimal point place
                     n is number of decimal places
                     s is location for sign*/
  address=fcvt(f,n,d,s);
                 
  if (*d>=0)        /*if there are no zeroes between the decimal point
                      and first character*/
     {              /*if the number is positive, copy the first part to
                       the buffer*/
         if (*s == 0)  strncpy(buffer2,address,*d);
         else        /*copy the signand first part to the buffer*/
            {
               strcpy(buffer2,"-");
               strncat(buffer2,address,*d);
            }
         strcat(buffer2,"."); /*copy decimal point to buffer*/
                              /*copy rest of string to buffer*/
         strncat(buffer2,address + *d,strlen(address)- *d);
         strcat(buffer2,'\0'); /*terminate the string*/
         return buffer2;       /*return address of buffer*/
     }
     if (*s == 0)  strcpy(buffer2,"."); /*copy decimal point to buffer*/
     else 
        {                               /*copy sign and decimal point*/
            strcpy(buffer2,"-.");
         }
     *d=-*d;                             /*copy the zeros*/
     for(k=0;k<*d;k++) strcat(buffer2,"0");
     if (n >*d)  strncat(buffer2,address,n-*d); /*rest of string*/
     strcat(buffer2,'\0');                /*terminate string*/
     return buffer2;                      /*return address of buffer*/
}  