/* ------------------------------------------------------------------
   PWS16FNC written by R. Baines 6/90.

   This module handles all commands entered into PWS16PC.  In this
   module there is at least one function correlating to each command.
   The commands are kept in a dynamic array, thus allowing the user
   to generate aliases that map to existing commands (see init() in
   PWS16MN.C and config file).

   ------------------------------------------------------------------ */


/* includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <values.h>
#include <conio.h>
#include <process.h>
#include <mem.h>
#include "pwstruct.h"
#include "pwsglobl.h"
#include "proto.h"

/* Internal Files */
boolean openfile(void);

/* Globals shared ONLY with PWS16MN.C */
extern kmd_type *kmd;
extern boolean setchan;
extern boolean more;
extern boolean Snapshot;
extern boolean Shade;
extern char *tp[MAXTOK];                  /* token pointer */
extern int ki[MAXTOK];                    /* keyword idx */
extern int idx;

/* Internal Globals */
char *valstring[]= {"Y","YES","T","TRUE","ON","N","NO","F","FALSE","OFF"};
int value[]={1,1,1,1,1,0,0,0,0,0};
struct cmd_struct reset =
         {20,0,0,0,5,-1,-1,-1,0,0,0L,DAY_SEC,0,0,0,0,NUM_CHAN,
         {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},1,0,0,0,0,0,0,0,0,0};

/*---------------------------------------------------------------------

  DEFINE_COMMANDS  wrttien by. R. Baines 6/90
  function pointers are used to simplify parsing, this initializes
  vars so they can be used.  The order here is NOT the order they will
  end up in.  Later in the function INIT in PWS16MN, the list will be
  sorted.

  --------------------------------------------------------------------- */

void define_commands(void)
{
  int i;

  if (!(kmd = calloc(MAXKEY, sizeof(kmd_type)))) error(7);

  kmd[0].fnc = cmd_invalid;               /* invalid */
  kmd[1].fnc = cmd_input;                 /* input */
  kmd[2].fnc = cmd_units;                 /* units */
  kmd[3].fnc = cmd_spacecraft;            /* spacecraft */
  kmd[4].fnc = cmd_year;                  /* year */
  kmd[5].fnc = cmd_day;                   /* day */
  kmd[6].fnc = cmd_hour;                  /* hour */
  kmd[7].fnc = cmd_minute;                /* minute */
  kmd[8].fnc = cmd_span;                  /* span */
  kmd[9].fnc = cmd_min;                   /* min */
  kmd[10].fnc = cmd_max;                  /* max */
  kmd[11].fnc = cmd_cmin;                 /* Cmin */
  kmd[12].fnc = cmd_cmax;                 /* Cmax */
  kmd[13].fnc = cmd_fg;                   /* fg */
  kmd[14].fnc = cmd_fgonly;               /* fgonly */
  kmd[15].fnc = cmd_peaks;                /* peaks */
  kmd[16].fnc = cmd_nopeaks;              /* nopeaks */
  kmd[17].fnc = cmd_color;                /* color */
  kmd[18].fnc = cmd_snapshot;             /* snapshot */
  kmd[19].fnc = cmd_gray;                 /* gray */
  kmd[20].fnc = cmd_output;               /* output */
  kmd[21].fnc = cmd_filter;               /* filter */
  kmd[22].fnc = cmd_fmin;                 /* fmin */
  kmd[23].fnc = cmd_fmax;                 /* fmax */
  kmd[24].fnc = cmd_c01;                  /* c1 */
  kmd[25].fnc = cmd_c02;                  /* c2 */
  kmd[26].fnc = cmd_c03;                  /* c3 */
  kmd[27].fnc = cmd_c04;                  /* c4 */
  kmd[28].fnc = cmd_c05;                  /* c5 */
  kmd[29].fnc = cmd_c06;                  /* c6 */
  kmd[30].fnc = cmd_c07;                  /* c7 */
  kmd[31].fnc = cmd_c08;                  /* c8 */
  kmd[32].fnc = cmd_c09;                  /* c9 */
  kmd[33].fnc = cmd_c10;                  /* c10 */
  kmd[34].fnc = cmd_c11;                  /* c11 */
  kmd[35].fnc = cmd_c12;                  /* c12 */
  kmd[36].fnc = cmd_c13;                  /* c13 */
  kmd[37].fnc = cmd_c14;                  /* c14 */
  kmd[38].fnc = cmd_c15;                  /* c15 */
  kmd[39].fnc = cmd_c16;                  /* c16 */
  kmd[40].fnc = cmd_survey;               /* survey */
  kmd[41].fnc = cmd_window;               /* window */
  kmd[42].fnc = cmd_ignore;               /* reset */
  kmd[43].fnc = cmd_help;                 /* help */
  kmd[44].fnc = cmd_quit;                 /* quit */
  kmd[45].fnc = cmd_ignore;               /* - */
  kmd[46].fnc = cmd_run;		  /* run */
  kmd[47].fnc = cmd_shell;                /* shell */

  for (i=0; i<MAXKEY; i++)
     kmd[i].keyword = kp[i];

}




/* ---------------------------------------------------------------------

   FUNCTIONS BELOW  wrttien by. R. Baines 6/90
   there should be a function that correlates to each command that is
   entered by the user.  Each function below performs the operations
   the command given intends.


   --------------------------------------------------------------------- */

/* unknown keyword */
boolean cmd_invalid()
{
  char *cmnd;

  cmnd = tp[idx];
  printf ("Unknown keyword %s\n",cmnd);
  more = TRUE;
  return(FALSE);
}

/* choose input method */
boolean cmd_input(void)
{
   pws16_end();
   if (!findinput(tp[idx+1]))
	  error(17);
   pws16_begin();

   return(FALSE);
}


/* data units */
boolean cmd_units()
{
  char *param;

  boolean valid_param;
  valid_param = !(ki[idx+1]);
  param = tp[idx+1];

  if (valid_param)
     Cmd.units = atoi(param);

  if ((Cmd.units > 0) && (Cmd.units < 8))
   {
     Zmin = Defmin[Cmd.units];
     Zmax = Defmax[Cmd.units];
   }
   else
   {
     printf ("Invalid units=%s\n",param);
     more = TRUE;
   }
   return(FALSE);
}

/* spacecraft */
boolean cmd_spacecraft()
{
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
      Cmd.spacecraft=atoi(param);

   if (Cmd.spacecraft < 1 || Cmd.spacecraft > 2)
   {
     printf ("Invalid spacecraft=%s\n",param);
     more = TRUE;
   }
   return(FALSE);
}

/* year */
boolean cmd_year()
{
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
      Cmd.year=atoi(param);

   Cmd.year -= (Cmd.year > 1900) ? 1900: 0;
   if (Cmd.year < 77 || Cmd.year > 99)
   {
     printf ("Invalid year=%s\n",param);
     more = TRUE;
   }
   return(FALSE);
}

/* day of year */
boolean cmd_day()
{
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
      Cmd.day=atoi(param);

   if (Cmd.day < 1 || Cmd.day > 366)
   {
     printf ("Invalid day=%s\n",param);
     more = TRUE;
   }
   return(FALSE);
}

/* hour of day */
boolean cmd_hour()
{
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
      Cmd.hour=atoi(param);

   if (Cmd.hour < 0 || Cmd.hour > 23)
   {
     printf ("Invalid hour=%s\n",param);
     more = TRUE;
   }
   return(FALSE);
}

/* minute of hour */
boolean cmd_minute()
{
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
      Cmd.minute=atoi(param);

   if (Cmd.minute < 0 || Cmd.minute > 59)
   {
     printf ("Invalid minute=%s\n",param);
     more = TRUE;
   }
   return(FALSE);
}

/* time span in days, hours, minutes, or seconds */
boolean cmd_span()
{
   float span;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];

   if (valid_param)
   {
     span=atof(param);
     if (strchr(param,'D'))
        Cmd.span=span * (float) DAY_SEC;
     else if (strchr(param,'M'))
        Cmd.span=span * (float) MIN_SEC;
     else if (strchr(param,'S'))
        Cmd.span= span;
     else
        Cmd.span = span * (float) HOUR_SEC; /* default is hours */
   }
   if (Cmd.span <= 0L || Cmd.span > 3888000L)
   {
     printf ("Invalid span=%s\n",param);
     more = TRUE;
   }
   return(FALSE);
}

/* data minimum for scaling */
boolean cmd_min()
{
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
      Zmin=atof(param)*1000;

   if (Zmin >= Zmax)
      Zmin = Zmax-1000;

   return(FALSE);
}

/* data maximum for scaling */
boolean cmd_max()
{
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
      Zmax=atof(param)*1000;

   if (Zmax <= Zmin)
      Zmax = Zmin+1000;

   return(FALSE);
}

/* lowest frequency channel to plot */
boolean cmd_cmin()
{
   register int tmp, j;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
	 if (Cmin != (tmp=atoi(param)))
     {
	   Cmin= (tmp>0) ? ((tmp<NUM_CHAN) ? tmp : NUM_CHAN) : 1;

       if (Cmax>=Cmin)
		 for (j=0,tmp=Cmin;j<=Cmax-Cmin;j++,tmp++)
		  Cn[j]=tmp;
       else
		 for (j=0,tmp=Cmin;j<=Cmin-Cmax;j++,tmp--)
		  Cn[j]=tmp;

       for (;j<NUM_CHAN;j++)
         Cn[j]=0;

       setchan=TRUE;
     }

   return(FALSE);
}

/* highest frequency channel to plot */
boolean cmd_cmax()
{
   register int tmp, j;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
	 if (Cmax != (tmp=atoi(param)))
     {
	   Cmax= (tmp>0) ? ((tmp<NUM_CHAN) ? tmp : NUM_CHAN) : 1;

       if (Cmax>=Cmin)
		 for (j=0,tmp=Cmin;j<=Cmax-Cmin;j++,tmp++)
			Cn[j]=tmp;
       else
		 for (j=0,tmp=Cmin;j<=Cmin-Cmax;j++,tmp--)
			Cn[j]=tmp;

       for (;j<NUM_CHAN;j++)
          Cn[j]=0;

       setchan=TRUE;
     }

   return(FALSE);
}

/* gyrofrequency trace option */
boolean cmd_fg()
{
   int j;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (!valid_param)
      Cmd.fg=1;
   else
     for (j=0;j<10;j++)
     {
       if (!strcmp(valstring[j],param))
       {
         Cmd.fg = value[j];
         break;
       }
     }
   return(FALSE);
}

/* gyrofrequency only option */
boolean cmd_fgonly()
{
   int j;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (!valid_param)
      Cmd.fgonly=1;
   else
     for (j=0;j<10;j++)
     {
       if (!strcmp(valstring[j],param))
       {
         Cmd.fgonly=value[j];
         break;
       }
     }
   return(FALSE);
}

/* peaks option */
boolean cmd_peaks()
{
   int j;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (!valid_param)
      Cmd.peaks=1;
   else
     for (j=0;j<10;j++)
     {
       if (!strcmp(valstring[j],param))
       {
         Cmd.peaks=value[j];
         break;
       }
     }
   return(FALSE);
}

/* nopeaks option */
boolean cmd_nopeaks()
{
   int j;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (!valid_param)
      Cmd.peaks=0;
   else
     for (j=0;j<10;j++)
     {
       if (!strcmp(valstring[j],param))
       {
         Cmd.peaks=value[j];
         break;
       }
     }
   return(FALSE);
}

/* snapshot */
boolean cmd_snapshot()
{
   int j;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (!valid_param) {
	  label = pws16_snap_label;
	  plot = pws16_snap_plot;
   }
   else
      for (j=0;j<10;j++)
      {
       if (!strcmp(valstring[j],param)) {
	  if (value[j]) {
	     label = pws16_snap_label;
	     plot = pws16_snap_plot;
	  }
	  else /* No Snapshot */ {
	     label = pws16_label;
	     plot = pws16_plot;
	  }
		 break;
       }
   }
   return(FALSE);
}

/* Gray Toggle */
boolean cmd_gray()
{
   int j;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (!valid_param)
   {
      label = pws16_label;
      plot = pws16_gray_plot;
      Cmd.peaks=FALSE;
      Shade = TRUE;
      Pastel = FALSE;
   }
   else
     for (j=0;j<10;j++)
     {
       if (!strcmp(valstring[j],param))
       {
	  if (value[j])
	  {
	     label = pws16_label;
	     plot = pws16_gray_plot;
	     Cmd.peaks = FALSE;
	     Pastel = FALSE;
	  }
	  else /* No Shading */
	  {
	     label = pws16_label;
	     plot = pws16_plot;
             if (Pastel)
	        plot = pws16_gray_plot;
             else
	        Cmd.peaks = TRUE;
	  }
       Shade = value[j];
       break;
       }
     }
   return(FALSE);
}

/* Color Toggle */
boolean cmd_color()
{
   int j;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (!valid_param)
   {
      label = pws16_label;
      plot = pws16_gray_plot;
      Cmd.peaks=FALSE;
      Shade = TRUE;
      Pastel = TRUE;
   }
   else
     for (j=0;j<10;j++)
     {
       if (!strcmp(valstring[j],param))
       {
	  if (value[j]) {
	     label = pws16_label;
	     plot = pws16_gray_plot;
	     Cmd.peaks = FALSE;
	  }
	  else /* No Shading */ {
	     label = pws16_label;
	     plot = pws16_plot;
	     Cmd.peaks = TRUE;
	  }
       Shade = value[j];
       Pastel = value[j];
       break;
       }
     }
   return(FALSE);
}

/* select output device and determine number of time bins */
boolean cmd_output()
{
   char *param;

   param = tp[idx+1];
   if (strcmp(strupr(param), "FILE")==0)
	  return(!openfile());
   return(!(Cmd.numbin=pws16_device(param)));
}

/* turn filter on/off */
boolean cmd_filter()
{
   float filter_value;
   int j;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (!valid_param)
     Cmd.filter=100;

   /* else if param is a real number then process */
   else if ((isdigit(*param)) || (*param == '.'))
   {
     filter_value = atof(param);
     if ((filter_value*100 > MAXINT) || (filter_value < 0))
     {
       printf("Invalid value for filter, %s\n", param);
       more = TRUE;
     }
     else
       Cmd.filter = filter_value*100;
   }

   /* if not real number then look for yes, no, etc... */
   else
     for (j=0;j<10;j++)
     {
       if (!strcmp(valstring[j],param))
       {
         Cmd.filter=value[j];
         break;
       }
     }
   return(FALSE);
}

/* set min channel for filter select */
boolean cmd_fmin()
{
   int new_min;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
   {
     if (Cmd.fmin != (new_min=atoi(param)))
       Cmd.fmin= (new_min>0) ? ( (new_min<NUM_CHAN) ? new_min : NUM_CHAN ) : 0;
     if (Cmd.fmin > Cmd.fmax)
     {
       Cmd.fmin=Cmd.fmax;
       printf(" Invalid fmin, fmin set to %i\n", Cmd.fmin);
       more = TRUE;
     }
   }
   return(FALSE);
}

/* set max channel for filter */
boolean cmd_fmax()
{
   int new_max;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];

   if (valid_param)
   {
     if (Cmd.fmax != (new_max=atoi(param)))
       Cmd.fmax=new_max>0?(new_max<NUM_CHAN?new_max:NUM_CHAN):0;
     if (Cmd.fmin > Cmd.fmax)
     {
       Cmd.fmax=Cmd.fmin;
       printf(" Invalid fmax, fmax set to %i\n", Cmd.fmax);
       more = TRUE;
     }
   }
   return(FALSE);
}


/* setting channels manually */
boolean cmd_c01()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(0, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c02()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(1, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c03()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(2, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c04()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(3, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c05()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(4, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c06()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(5, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c07()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(6, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c08()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(7, atoi(tp[idx+1]));
	return(FALSE);

}

boolean cmd_c09()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(8, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c10()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(9, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c11()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(10, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c12()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(11, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c13()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(12, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c14()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(13, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c15()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(14, atoi(tp[idx+1]));
	return(FALSE);
}

boolean cmd_c16()
{
	if (!ki[idx+1]) /* if valid param */
	   channel(15, atoi(tp[idx+1]));
	return(FALSE);
}

/* survey option */
boolean cmd_survey()
{
   puts ("Sorry, SURVEY not yet implemented.");
   return(FALSE);
}

/* windows */
boolean cmd_window()
{
   float window_value;
   char *param;
   boolean valid_param;

   valid_param = !(ki[idx+1]);
   param = tp[idx+1];
   if (valid_param)
   {
     window_value = atof(param);
     if ((window_value*100 > MAXINT) || (window_value <=0))
     {
       printf("Invalid value for window, %s\n", param);
       more = TRUE;
     }
     else
       Cmd.window =  window_value*100;
   }
   return(FALSE);
}

/* reset option */
boolean cmd_reset()
{
   Cmd = reset;
   Zmin = Defmin[Cmd.units];
   Zmax = Defmax[Cmd.units];
   return(FALSE);
}

/* help/? option */
boolean cmd_help()
{
   FILE *fp;
   char line[LLEN];

   fp = fopen("pws16pc.hlp", "r+t");
   if (!fp)
   {
     puts("HELP is currently unavailable.\n");
     return(FALSE);
   }

   printf("\t\tPWS16 version %s written by L. Granroth\n", VERSION);
   while (fgets(line, LLEN, fp))
   {
     if (strstr(line, "#CONTINUE"))
       while(getch() != '\r');
     else
       printf(line);
   }

   fclose(fp);

   more = TRUE;
   return(FALSE);
}

/* end options */
boolean cmd_quit()
{
   return(TRUE);
}

/* replot graph --> ignore */
boolean cmd_ignore()
{
   return(FALSE);
}

/* run a program from inside this program */
boolean cmd_run(void)
{
   char pathname[128], *arguement[32], line[128];
   int i=1;

   printf("\nEnter Program:  ");
   gets(pathname);
   arguement[0] = pathname;

   printf("Enter Arguements: ");
   gets(line);

   arguement[i++] = strtok(line, " ");

   while (arguement[i++] = strtok(NULL, " "));

   if (spawnvp(P_WAIT, pathname, arguement) == -1)
      error(19);


   return(FALSE);
}

/* shell out to DOS */
boolean cmd_shell(void)
{
   char *shell, shell_default[]="COMMAND.COM";

   if (!(shell = getenv("COMSPEC")))
      shell = shell_default;

   if (spawnlp(P_WAIT, shell, shell, NULL) == -1)
      error(20);

   return(FALSE);
}


/* -----------------------------------------------------------------

   BELOW THREE functions are used by some of the above functions.

   ----------------------------------------------------------------- */


/* select filename to write to when OUTPUT = FILE; used by cmd_output */
boolean openfile(void)
{
   char filename[LLEN];

   do {
      if (fpOut)
	 fclose(fpOut);
      printf("Enter Name of OUTPUT File:  ");
      gets(filename);

   } while (fpOut=fopen(filename,"rt"));

   return (boolean) (fpOut=fopen(filename, "w+t"));
}

/* choose which input method; used by cmd_input */
boolean findinput(char *param)
{
   if (strcmp(param, "NET")==0) {
      pws16_begin = pws16_net_begin;
      pws16_command = pws16_net_command;
      pws16_data = pws16_net_data;
      pws16_end = pws16_net_end;
   }
   else if (strcmp(param, "FILE")==0) {
      pws16_begin = pws16_file_begin;
      pws16_command = pws16_file_command;
      pws16_data = pws16_file_data;
      pws16_end = pws16_file_end;
   }
   else if (strcmp(param, "SERVER")==0) {
      pws16_begin = pws16_server_begin;
      pws16_command = pws16_server_command;
      pws16_data = pws16_server_data;
      pws16_end = pws16_server_end;
   }
   else
      return(FALSE);

   return(TRUE);
}

/* parse out individual channel selection; used by cmd_c01 thru cmd_c16 */
boolean channel(int cn_idx, int cn_value)
{
   if (!setchan) {
      Cmin=0;
      Cmax=0;
      setmem(Cn, NUM_CHAN, 0);
      setchan=TRUE;
   }

   Cn[cn_idx]= (cn_value>1) ? ((cn_value<NUM_CHAN) ? cn_value : NUM_CHAN) : 1;

   return(FALSE);
}


/* ---------------------------------------------------------
   BELOW TWO functions used by init() in pws16mn.c

   - KMDCMP is for use with the sorting of the commands.
     KMDCMP is required to use QSORT().

   - KMDADD adds a command to the dynamic

   --------------------------------------------------------- */

int kmdcmp(const void *x, const void *y)
{
   kmd_type *a, *b;
   a = (kmd_type *) x;
   b = (kmd_type *) y;

   return(strcmp(a->keyword, b->keyword));
}


boolean kmdadd(char orgkmd[], char newkmd[])
{
   int i,j;

   for (i=1; i<MAXKEY; i++) {
      if (strcmp(kmd[i].keyword, orgkmd))
	 continue;

      for (j=0; j<LastKey; j++)
	 if (!strcmp(kmd[j].keyword, newkmd))
	    return(FALSE);

      kmd = realloc(kmd, sizeof(kmd[0])*(LastKey+1));
      kmd[LastKey].keyword =malloc(strlen(newkmd)+1);

      if (kmd && kmd[LastKey].keyword) {
	 strcpy(kmd[LastKey].keyword, newkmd);
         kmd[LastKey++].fnc = kmd[i].fnc;

         return(TRUE);
      }
      else
	 return(FALSE);
   }

   return(FALSE);
}
