/* FKeys.c */ 
#include <exec/types.h> 
#include <stdio.h> 
#include <fcntl.h>
#include "ConsoleIO.h"
  /* things for function keys */
#define NUMKEYS 10		    /* number of function keys */
#define KEYSIZE 40		    /* maximum length of any one string */
#define BUFSIZE KEYSIZE * NUMKEYS   /* size of total buffer */
#define HEADER  '\x70'    /* first byte of file is version number (7.0) */
#define MAXOPTION 256               /* maximum length of option string */
#define CSI     '\x9b'		    /* Command Sequence Introducer */ 	
#define DEL	  127
#define LDK       128
#define LDX	  129
#define F10	  130

extern UBYTE *KeyBuf;

/*********************************************************************
**	  Some routines concerned with the function keys	    **
*********************************************************************/

extern void SetOptions();
extern int  GetOptions();
	       
/************* Attempt to load a Function-Key file ******************/

BOOL LoadKeys(keyfile)    /* returns (BOOL) success	*/

   char *keyfile;  /* the filename */
 {
      int fp;
      int i;
      short optsize;
      BOOL filefound = FALSE;
      BOOL goodfile  = TRUE;
      UBYTE c, opt[ MAXOPTION ];

   if ( (fp = open(keyfile, O_RDONLY)) == -1)
      return FALSE;
   i = read( fp, &c, sizeof( c ) );
   if ( i == sizeof( c ) && c == HEADER  )  /* gotta be a valid key file! */
     {
       filefound = TRUE;
       i = read( fp, &optsize, sizeof( optsize ) ); 
       if ( i != sizeof( optsize ) ||
            !((0 <= optsize) && (optsize < MAXOPTION)) )
	  goodfile = FALSE;
       else if ( read( fp, opt, optsize ) != optsize )
	  goodfile = FALSE;
       else
	 {
	    SetOptions( opt, optsize );
	    if ( read( fp, KeyBuf, BUFSIZE ) != BUFSIZE )
	       goodfile = FALSE;
	 }
      }
		
    close( fp );
    if ( !goodfile )
      {
	PutString( "Key Buffer file has been corrupted...\n." );
	PutString( "  Function Keys May be Invalid.\n" );
      }
	
    return filefound;    /* ahh, success? */
  }
/**************Save Function-Key file *****************/

BOOL SaveFKeys(filename)	/* returns (BOOL) success */
 char *filename;

{
    int fp;
    BOOL goodfile = TRUE;
    short optsize;
    UBYTE c = HEADER, opt[ MAXOPTION ];

    if ( ( fp = open( filename, O_WRONLY + O_CREAT )) == -1)
       return FALSE;

    if ( write( fp, &c, sizeof( c)) != sizeof( c ))
	goodfile = FALSE;
    else if ( ( optsize = GetOptions( opt, MAXOPTION )) > MAXOPTION)
      { 
	PutString( "Can't Happen: Too many options to save.\n" );  
	goodfile = FALSE;
      }
    else if ( write( fp, &optsize, sizeof( optsize )) != sizeof( optsize ))
        goodfile = FALSE;
    else if ( write( fp, opt, optsize ) != optsize )
	goodfile = FALSE;
    else if ( write( fp, KeyBuf, BUFSIZE ) != BUFSIZE )
	goodfile = FALSE;

    close( fp );
    if ( !goodfile )
       PutString( "Error writing file.\n");

    return goodfile;
 }

/************ Print the function-key number **************/
/*		format example: F7:			*/

static void PrintKeyNum(keynum)
    int keynum;
{
   keynum++;
   PutChar('F');
   if ((keynum == 10) || (keynum == 0))
      PutString("10: ");
   else
     {
       PutChar(keynum + '0');
       PutString(": ");
     }
}

/*********** Print a character from function-key string ************/

void keychar(key)
   UBYTE key;
 {
   if ((key > 129) && (key < 140 ))
     {
       PutChar('<');
       PrintKeyNum (key - 131);
       PutString ("\b>");
     }
   else
    {
      if ((key < ' ') || (key > DEL))         /* control character */
       {
         switch (key)
         { case 0:
	     PutChar('0');
	     break;
	   case '\b':
	     PutString("<BS>");
	     break;
	   case '\t':
	     PutString("<TAB>");
	     break;
          case '\n':
	     PutString("<NL>");
	     break;
          case '\r':
	     PutString("<CR>");
	     break;
          case 27:
	     PutString("<ESC>");
	     break;
          case LDK:
             PutString("<LOAD>");
             break;
          case LDX:
	     PutString("<LOADEX>");
	     break;
          default:
	     PutChar('^');
	     PutChar(key + 0x40);
          }				/* end switch(key) */
        }				/* end if control character */
      else PutChar(key);
    }					/* end if FKey execute */
  }

/************ Display Function-Key contents **********/

void DoContents()

{
   int x;
   UBYTE c, *offset;
   
 for (x=0; x < NUMKEYS; x++)
  {
    offset = KeyBuf + KEYSIZE * x;
    PrintKeyNum( x );
    while ( c = *offset++ )
      keychar(c);
    PutChar('\n');
   }
 }

/*******	Define a function-key string	*********/

void DefineString()
{
   UBYTE c, character;
   int keynum, count, offset, i;

   PutString( "\x9b33m\nFunction-Key String Definition:\n\n");
   if ( GetKey() != CSI )
     { PutString( "\naborted...\n\n\x9bm" );
       return;
     }
   else
     {
       character = GetKey();	    /* get the meat of the sequence */
       while ( GetKey() != '~' );   /* wait for sequence to end     */
     }
   if (!( (character >= '0') && (character <= '9') ))   /* isdigit? */
     {
	PutString( "aborted...\n\n\x9bm" );
	return;
      }
   else
      {
	 keynum = character - '0';
	 PrintKeyNum( keynum );
	 offset = KEYSIZE * keynum; /* find correct spot in buffer */
	 i = 0;
	 while ( (character = GetKey()) != CSI )	/* get the string */
	   { if (i<(KEYSIZE-1))
	     {
		if(character == 127)       /* DEL key is used as a special  */
		  {			   /* FKey 'CSI'. Takes the next    */
		    character = GetKey();  /* character as the function to  */
		    switch (character)	   /* be stored in the FKey string. */
		      { case 'l':
			  character = LDK; /* <LOAD> -- loads another FKey  */
			  break;	   /* definition file.		    */
			case 'L':
			  character = LDX; /* <LOADEX> -- takes the next    */
			  break;	   /* character as the FKey to be   */
					   /* executed AFTER loading the    */
					   /* specified file. ie...         */
					   /* <LOADEX>1key.file             */
					   /* will load key.file, then      */
					   /* execute FKey #1 as defined in */
					   /* key.file                      */
					   /* NOTE: 0 = FKey 10		    */
			default :
			  if ((character >= '0') && (character <= '9'))
			    character += 82;
			  break;
			}		/* end case */
		  }
	        KeyBuf[offset + (i++) ] = character;	/* store it	  */
	        keychar(character);  			/* display it, too */
	      }
	    }
	  while (GetKey() != '~' );	/* skip over rest of F-key	*/
	   	
	  while (i < KEYSIZE)
	    {
	       KeyBuf[offset+i] = '\0';	/* zero out the rest of		*/
	       i++;			/* that string's buffer		*/
	     }
	   PutString("\n\n");
	   PutString("\x9bm");
	  }	/* end else */
 }	/* end DefineString();	*/
