/*Amiga Computing*/
/*Code Clinic*/
/*Oct1991- console port*/
/*A500 upwards*/

/*c source code   -  main program*/

#include "console.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");
  /*initialises cursor position and arrays*/
   for (i=0;i<799;i++) array[i] = ' ';
   x = 0;
   y = 20; 
  /*handles the window input*/
   Handle_IDCMP(); 
  /*displays characters input*/
   printf(array);
  /*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= 0;
                y=y+10;
                aligntext();
                return(0);
            }
         Move(rp,x,y);           /*move to correct psition*/
         Text(rp,buff,1);        /*display character*/
         place = (((y-20)/10)*20); /*put character in array*/
         place = place + (x/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)) SetAPen(rp,1);
   if (fnkey(&buff[0],49,126,49,49,126)) SetAPen(rp,2);
   if (fnkey(&buff[0],50,126,49,50,126)) SetAPen(rp,3);
   if (fnkey(&buff[0],51,126,49,51,126)) SetAPen(rp,4);
   if (fnkey(&buff[0],52,126,49,52,126)) SetAPen(rp,5);
   if (fnkey(&buff[0],53,126,49,53,126)) SetAPen(rp,6);
   if (fnkey(&buff[0],54,126,49,54,126)) SetAPen(rp,7);
   if (fnkey(&buff[0],55,126,49,55,126)) SetAPen(rp,8);
   if (fnkey(&buff[0],56,126,49,56,126)) SetAPen(rp,9);
   if (fnkey(&buff[0],57,126,49,56,126)) SetAPen(rp,10);
   aligntext();
   return(0);
}


/*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 <0) x = 0;
   if (x >312) {x=0; y = y+10;}
   if (y < 20) y = 20;
   if (y > 220) {x = 0; y = 20;}
   buff[1]=0;
   buff[2]=0;
   buff[0]=0;
   buff[3]=0;
   return;
}