/* {(rm mdl ; cc -DUNIX -I. -s -n -O -Wc,-Nd4000 -Wc,-Ns4000 -Wc,-Nt50000 -DSYSV -DNLS16 -Dhp9000s300 -o mdl mdl.c mdllib.o  -L /usr/lib/X11R4 -L /usr/lib/Motif1.1 -lMrm -lXm -lXt -lX11 -lPW ; mdl test.mdl)& } */
/**---------------------------------------------------------------------
***	
***   file:      mdl.c
***
***   project:   Menu Description Language
***                     General purpose Menu generator.
***
***         (c) 1990 Rainer Kowallik
***
***-------------------------------------------------------------------*/

#include <stdio.h>
#include <sys/stat.h>
#define TMPDIRFILE "ram:mdltmpdir.tmp"

#ifdef AMIGA
#include <exec/types.h>
#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <workbench/icon.h>

extern struct WBStartup *WBenchMsg;
extern struct IconBase *IconBase;
#endif
#ifdef UNIX
#include <unistd.h>
#endif

#include <mdllib.h>

int    tmpnum=0;
char   resource[80];
char   *fn_command_str[160];
char   *var_name_str[160];
char   *var_value_str[160];
int    var_value_int[160];
char   language[80];
char   myname[80];
int    wl = -1;
int    wt = -1;

void tmpnam_(s)      /* due to a bug in the Lattice C 5.0 library ! */
char *s;
{
long int t;

   time(&t); t = t + tmpnum++;
   sprintf(s,"tmp%x",t);
}

/* --------------------------------------------------------
   Special callback function for mdl, executes string in
   fn_command_str[last_gadgetid]
   -------------------------------------------------------- */
void CallBack_mdl()
{
parse(fn_command_str[last_gadgetid]);
}


void main(argc,argv)
unsigned int argc;
char *argv[];
{
int n;
FILE *stream;
char mdlfile[80];
char c,s[80];
char cmdline[256];
FILE *tmp1;

#ifdef AMIGA
struct WBArg *Arg;
#endif


   strcpy(language,"ksh ");
   strcpy(mdlfile,argv[1]);
   if(argc > 0) strcpy(myname,argv[0]);



#ifdef AMIGA
   if(argc <= 1) {
      IconBase = (struct IconBase *) OpenLibrary("icon.library", 0L);
      Arg = WBenchMsg->sm_ArgList;
      strcpy(myname,Arg->wa_Name);
      Arg++;
      CurrentDir(Arg->wa_Lock);
      strcpy(mdlfile,Arg->wa_Name);
   }
#endif

   stream = fopen(mdlfile,"r");
   if(stream == NULL) {
      fprintf(stderr,"mdl: could not open command file>%s<\n",mdlfile);
      exit(0);
   }

/* the following is for two purposes: 
   1. Making a self detaching programm on an Amiga
   2. passing standard commandstrings from the mdl file
*/

   strcpy(cmdline,"");
   c = fgetc(stream);         /* an '-' in the first column of the first line */
   ungetc(c,stream);
   if(c == '-') {             /* signals a default command string */
      fgets(cmdline,80,stream); /* read default command string */
   }
   if((!checkopt(argc,argv,"-fork",s)) && (argc > 0)) {
      strcpy(s,cmdline);
      strcpy(cmdline," ");
      strcat(cmdline,myname); strcat(cmdline," ");
      for(n = 1; n < argc; n++) {
         strcat(cmdline,argv[n]);
         strcat(cmdline," ");
      }
      strcat(cmdline,"-fork ");
      strcat(cmdline,s);            /* add default options from mdl file */
#ifdef UNIX
      cmdline[0] = '(';
      strcat(cmdline,")&");
      system(cmdline);
#endif
#ifdef AMIGA
      amifork(cmdline);
#endif
      fclose(stream);
      exit(0);
   }


#ifdef UNIX
   strcpy(resource,mdlfile);  /* default resource file name is the mdl prog name */
   c = fgetc(stream);
   if(c == '{') { /* } create resource file: copy text enclosed in {} to TMPFILE */
      strcpy(resource,"mdl.tmp");
      sprintf(s,"/usr/lib/X11/app-defaults/%s",resource);
      tmp1 = fopen(s,"w");
      chmod(s,0666);
      n=1;
      while(!feof(stream)) {
         c = fgetc(stream);
         if(c == '{') n++;
         if(c == '}') n--;
         if(n == 0) break;
         fputc(c,tmp1);
      }
      fclose(tmp1);
   } else {
      ungetc(c,stream);
      sprintf(s,"/usr/lib/X11/app-defaults/%s",resource);
      tmp1 = fopen(s,"r");          /* check if resource file exists */
      if(tmp1 == NULL) {
         strcpy(resource,"mdl");    /* take mdl default resource file instead */
      } else {
         fclose(tmp1);
      }
   }

/* open display and read resource file (if any) */

   XtToolkitInitialize();
   app_context = XtCreateApplicationContext();
   if(!app_context) {
      printf("could not create application context\n");
      exit(0);
   }
   display = XtOpenDisplay (app_context, NULL, myname, resource, NULL, 0,
				 &argc, argv);
				 
	if (!display) {
		XtWarning ("mdl: Can't open display, exiting...");
		exit (0);
	}
#endif

  menu_init(argv,stream);
/* !!!! Debug !!!!
   sprintf(s,"fn_number = %d\n",fn_number);
   Help(s);
   !!!! Debug !!!! */
  fclose(stream);

#ifdef AMIGA
  my_window = (struct Window *) OpenWindow( my_new_window );
  SetMenuStrip( my_window, menu_bar );
  if(my_window == NULL)
  {
    fprintf(stderr,"could not open Window\n");
    close_gfx(my_window);
    exit(0);  
  }
  fin_flg = FALSE;
  MainLoop(my_window);
#endif

#ifdef UNIX
/* dont forget to activate the last menu entry */
   add_item(-1,-1,NEW_MENU,"empty",0,0);
	XtRealizeWidget (app_shell);
	XtAppMainLoop (app_context);
#endif

  exit(0);
}



/* ********************************************************************

   S T R I N G H A N D L I N G

   ******************************************************************** */

/* --------------------------------------------------
   reurns in s1 s2 from nth occurence of c up to c
   -------------------------------------------------- */

ExtractStr(s1,s2,n,c)
char s1[],s2[],c;
int n;
{
int m,i,l;
char c1;

   m=0; l=strlen(s2);
   i = 0;
   if(n > 0) {
      for(i=0;i<l;i++) {
          c1=s2[i];
          if(c1 == c) m++;
          if(m == n) break;
      }
      s1[0] = 0;
      if(c1 != c) return(-1);
      i++;
   }
   m=0;
   while(i<l) {
      c1 = s2[i++];
      if(c1 == c) break;
      s1[m++] = c1;
   }
   s1[m] = 0;
   if(strlen(s1)==0) return(-1);
   return(1);
}

/* --------------------------------------------------
   check if character is a bra '([{' or a ket ')]}'
   -------------------------------------------------- */
tstbra(c)
char c;
{
   if((c == '(') || (c == '[') || (c == '{')) return(1);
   if((c == ')') || (c == ']') || (c == '}')) return(-1);
   return(0);
}




/* --------------------------------------------------
    get parameter enclosed in brackets from file.
    any New line character will be substituted by the
    supplied character.
   -------------------------------------------------- */
fgetpar(stream,s,nl)
FILE *stream;
char nl,s[];
{
int n,cnt;
char c,bra,ket;

   n=0;
   while(n != 1) {
      if(feof(stream)) return(0);
      c = fgetc(stream);
      n = tstbra(c);
   }
   bra = c;
   if(bra == '(') {
      ket = ')';
   } else {
      ket = bra + 2;
   }
/* skip SPC and NL at start of line */
   c = 0;
   while(c < 33) c = fgetc(stream);
   ungetc(c,stream);
   n = 0; cnt = 1;
   while(!feof(stream)) {
      c = fgetc(stream);
      if(c == bra) cnt = cnt + 1;
      if(c == ket) cnt = cnt - 1;
      if(c == 10) {s[n++] = ' ' ; c = nl; }
      if(cnt == 0) break;
      s[n++] = c;
   }
   s[n] = 0; 
}

/* --------------------------------------------------
    get parameter enclosed in brackets from string.
   -------------------------------------------------- */
sgetpar(str,s,n,j)
char str[],s[];
int n,*j;
{
int m,i,l,cnt;
unsigned char c,bra,ket;

   l = strlen(str);
   i = *j;
   i = n; c=str[i];
   bra = 0; ket=' ';
   if(tstbra(c) == 1) {   
      bra = c;
      if(bra == '(') {
        ket = ')';
      } else {
        ket = bra + 2;
      }
      i = i + 1;
   }
   m = 0; cnt = 1;
   while(m < l) {
     c = str[i++];
     if(c == bra) cnt = cnt + 1;
     if(c == ket) cnt = cnt - 1;
     if((ket == ' ') && (tstbra(c) != 0)) cnt = cnt -1;
     if((ket == ' ') && (c < '0')) cnt = cnt -1;
     if(cnt <= 0) break;
     s[m++] = c;
   }
   if(tstbra(c)==-1) i++;
   s[m] = 0;
   *j = i-1;
   return(0);
}


/* ------------------------------------------------------
   reading file and start initializing menus
   ------------------------------------------------------ */
menu_init(argv,stream)
char *argv[];
FILE *stream;
{
int n,i;
int p1,p2;
int x = 200,
    y = 200,
    set_flg = 0;
float fx, fy;
char c,s[256],s1[128],s2[128],*cmd,title[80];
#ifdef UNIX
Arg args[10];
#endif
   cmd = (char *) malloc(8192);
   fx = 1.0; fy = 1.0;

   strcpy(title,"UNTITLED SHOULD CHANGE IT !");
   while(!feof(stream)) {         /* go through file */
      c=0;
      while(c < 33) {            /* skip NL CR SPC TAB ... */
         c = fgetc(stream);
         if(feof(stream)) {free(cmd); return(0);}
      }
      ungetc(c,stream);
      c = 33; s[0]=0; n=0;
      while((c > 32) && (c < 123)) {      /* read menu command */
         c = toupper(fgetc(stream));
         if((c == '(') || (c == '[') || (c == ' ') || (c == '{')) break;
         s[n++] = c;
      }
      ungetc(c,stream);
      s[n] = 0;
/* ----------- parse command and read following parameters ---------------- */
      if(strcmp(s,"SIZE") == 0) {      /* size of main window */
         fgetpar(stream,s,' ');
         ExtractStr(s1,s,0,',');      /* get x size */
         x = (int) (((float) atoi(s1)) * fx);
         ExtractStr(s1,s,1,',');      /* get y size */
         y = (int) (((float) atoi(s1)) * fy);
         n = ExtractStr(s1,s,2,',');      /* get y increment */
         if(n == 1) bas_y = atoi(s1);
         n = ExtractStr(s1,s,3,',');      /* get top edge */
         if(n == 1) wt = atoi(s1);
         n = ExtractStr(s1,s,4,',');      /* get left edge */
         if(n == 1) wl = atoi(s1);
         continue;
      }
      if(strcmp(s,"NAME") == 0) {      /* name of application */
         fgetpar(stream,s,' ');
         strcpy(title,s);
         continue;
      }
      if(strcmp(s,"FACTOR") == 0) {   /* scaling factor */
         fgetpar(stream,s,' ');
         ExtractStr(s1,s,0,',');      /* get x size */
         sscanf(s1,"%f",&fx);
         ExtractStr(s1,s,1,',');      /* get y size */
         sscanf(s1,"%f",&fy);
         continue;
      }
      if(strcmp(s,"LANGUAGE") == 0) {  /* command language for application */
         fgetpar(stream,s,' ');
         strcpy(language,s);
         continue;
      }
      if(set_flg == 0) {         /* open window */
         set_flg = 1;            /* should be done only once */
   /*   Create application shell.
   */

#ifdef AMIGA
         my_new_window = init_window(x,y,title,0,1);
         if(wl > 0)my_new_window->LeftEdge = wl;
         if(wt > 0)my_new_window->TopEdge = wt;
#endif
#ifdef UNIX
	n = 0;
	XtSetArg (args[n], XmNwidth, x);  n++;
	XtSetArg (args[n], XmNheight, y);  n++;
	app_shell = XtAppCreateShell (myname,resource,
				applicationShellWidgetClass, display, args, n);
	main_window = (Widget) CreateApplication (app_shell);
#endif
      }
      if(strcmp(s,"STARTUP") == 0) {  /* do initializing procedure */
         fgetpar(stream,cmd,10);
         parse(cmd);
         continue;
      }
      if(strcmp(s,"NEW_MENU") == 0) {      /* new entry on menu bar */
         fgetpar(stream,s,' ');         /* get name */
         add_item(-1,-1,NEW_MENU,s,0,0);
         fn_number++;
         continue;
      }
      if(strcmp(s,"MENU") == 0) {      /* new menu item */
         fgetpar(stream,s,' ');         /* get name */
         fgetpar(stream,cmd,10);      /* get action */
         add_item(-1,-1,MENU,s,0,0);
         fn_command[fn_number] = (void *)CallBack_mdl;
         fn_command_str[fn_number] = (char *) malloc(strlen(cmd)+1);
         strcpy(fn_command_str[fn_number],cmd);
         fn_number++;
         continue;
      }
      if(strcmp(s,"RADIO") == 0) {      /* start radio box */
         add_item(-1,-1,RADIO,"radio_box",0,0);
         fn_number++;
         continue;
      }
      if(strcmp(s,"TOGGLE") == 0) {      /* toggle button */
         fgetpar(stream,s,' ');         /* get name and position */
         fgetpar(stream,cmd,10);      /* get variable name */
         ExtractStr(s1,s,0,',');
         x = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         y = (int) (((float) atoi(s1)) * fy); /* get y position */
         ExtractStr(s1,s,2,',');       /* get name */
         add_item(x,y,TOGGLE,s1,0,0);
         var_name_str[fn_number] = (char *)malloc(strlen(cmd)+1);
         strcpy(var_name_str[fn_number],cmd);
         var_value[fn_number] = &var_value_int[fn_number];
         fn_number++;
         continue;
      }
      if(strcmp(s,"PUSH") == 0) {      /* push button */
         fgetpar(stream,s,' ');         /* get name and position */
         fgetpar(stream,cmd,10);      /* get command string */
         ExtractStr(s1,s,0,',');
         x = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         y = (int) (((float) atoi(s1)) * fy); /* get y position */
         ExtractStr(s1,s,2,',');       /* get name */
         add_item(x,y,PUSH,s1,0,0);
         fn_command[fn_number] = (void *)CallBack_mdl;
         fn_command_str[fn_number] = (char *) malloc(strlen(cmd)+1);
         strcpy(fn_command_str[fn_number],cmd);
         fn_number++;
         continue;
      }
      if(strcmp(s,"SCALEX") == 0) {      /* scale */
         fgetpar(stream,s,' ');         /* get name and position */
         fgetpar(stream,cmd,10);      /* get variable name */
         ExtractStr(s1,s,0,',');
         x = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         y = (int) (((float) atoi(s1)) * fy); /* get y position */
         ExtractStr(s2,s,2,',');       /* get name */
         ExtractStr(s1,s,3,',');
         p1 = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         p2 = (int) (((float) atoi(s1)) * fy); /* get y position */
         add_item(x,y,SCALEX,s2,p1,p2);
         var_value[fn_number] = &var_value_int[fn_number];
         var_name_str[fn_number] = (char *)malloc(strlen(cmd)+1);
         strcpy(var_name_str[fn_number],cmd);
         fn_number++;
         continue;
      }
      if(strcmp(s,"SCALEY") == 0) {      /* scale */
         fgetpar(stream,s,' ');         /* get name and position */
         fgetpar(stream,cmd,10);      /* get variable name */
         ExtractStr(s1,s,0,',');
         x = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         y = (int) (((float) atoi(s1)) * fy); /* get y position */
         ExtractStr(s2,s,2,',');       /* get name */
         ExtractStr(s1,s,3,',');
         p1 = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         p2 = (int) (((float) atoi(s1)) * fy); /* get y position */
         add_item(x,y,SCALEY,s2,p1,p2);
         var_value[fn_number] = &var_value_int[fn_number];
         var_name_str[fn_number] = (char *)malloc(strlen(cmd)+1);
         strcpy(var_name_str[fn_number],cmd);
         fn_number++;
         continue;
      }
      if(strcmp(s,"SCALEX11") == 0) {      /* scale */
         fgetpar(stream,s,' ');         /* get name and position */
         fgetpar(stream,cmd,10);      /* get variable name */
         ExtractStr(s1,s,0,',');
         x = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         y = (int) (((float) atoi(s1)) * fy); /* get y position */
         ExtractStr(s2,s,2,',');       /* get name */
         ExtractStr(s1,s,3,',');
         p1 = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         p2 = (int) (((float) atoi(s1)) * fy); /* get y position */
         add_item(x,y,SCALEX11,s2,p1,p2);
         var_value[fn_number] = &var_value_int[fn_number];
         var_name_str[fn_number] = (char *)malloc(strlen(cmd)+1);
         strcpy(var_name_str[fn_number],cmd);
         fn_number++;
         continue;
      }
      if(strcmp(s,"SCALEY11") == 0) {      /* scale */
         fgetpar(stream,s,' ');         /* get name and position */
         fgetpar(stream,cmd,10);      /* get variable name */
         ExtractStr(s1,s,0,',');
         x = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         y = (int) (((float) atoi(s1)) * fy); /* get y position */
         ExtractStr(s2,s,2,',');       /* get name */
         ExtractStr(s1,s,3,',');
         p1 = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         p2 = (int) (((float) atoi(s1)) * fy); /* get y position */
         add_item(x,y,SCALEY11,s2,p1,p2);
         var_value[fn_number] = &var_value_int[fn_number];
         var_name_str[fn_number] = (char *)malloc(strlen(cmd)+1);
         strcpy(var_name_str[fn_number],cmd);
         fn_number++;
         continue;
      }
      if(strcmp(s,"SELECTION") == 0) {      /* selection box */
         fgetpar(stream,s,' ');         /* get name and position */
         ExtractStr(s1,s,0,',');
         x = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         y = (int) (((float) atoi(s1)) * fy); /* get y position */
         n = 2; i = 0; s1[0] = 0;
         while(i != -1) {
            i = ExtractStr(s2,s,n++,',');    /* get name */
            if(i == 1) {
               if(s1[0] != 0) strcat(s1,",");
               strcat(s1,s2);
            }
         }
         add_item(x,y,SELECTION,s1,0,0);
         var_value_str[fn_number] = (char *)malloc(80);
         var_value[fn_number] = (int *)var_value_str[fn_number];
         fn_command[fn_number] = (void *)CallBack_mdl;
         fgetpar(stream,s2,' ');      /* get variable name */
         fgetpar(stream,cmd,10);      /* get command string */
         fn_command_str[fn_number] = (char *) malloc(strlen(cmd)+1);
         strcpy(fn_command_str[fn_number],cmd);
         var_name_str[fn_number] = (char *)malloc(strlen(s2)+1);
         strcpy(var_name_str[fn_number],s2);
         fn_number++;
         continue;
      }
      if(strcmp(s,"FILE_SELECT") == 0) {   /* selection box */
         fgetpar(stream,s,' ');         /* get name and position */
         fgetpar(stream,s2,' ');      /* get variable name */
         fgetpar(stream,cmd,10);      /* get command string */
         ExtractStr(s1,s,0,',');
         x = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         y = (int) (((float) atoi(s1)) * fy); /* get y position */
         ExtractStr(s1,s,2,',');       /* get name */
         add_item(x,y,FILE_SELECT,s1,0,0);
         var_value_str[fn_number] = (char *)malloc(80);
         var_value[fn_number] = (int *)var_value_str[fn_number];
         fn_command[fn_number] = (void *)CallBack_mdl;
         fn_command_str[fn_number] = (char *) malloc(strlen(cmd)+1);
         strcpy(fn_command_str[fn_number],cmd);
         var_name_str[fn_number] = (char *)malloc(strlen(s2)+1);
         strcpy(var_name_str[fn_number],s2);
         fn_number++;
         continue;
      }
      if(strcmp(s,"STRING_BOX") == 0) {      /* selection box */
         fgetpar(stream,s,' ');         /* get name and position */
         fgetpar(stream,s2,' ');      /* get variable name */
         fgetpar(stream,cmd,10);      /* get command string */
         ExtractStr(s1,s,0,',');
         x = (int) (((float) atoi(s1)) * fx); /* get x position */
         ExtractStr(s1,s,1,',');
         y = (int) (((float) atoi(s1)) * fy); /* get y position */
         ExtractStr(s1,s,2,',');       /* get name */
         add_item(x,y,STRING,s1,0,0);
         var_value_str[fn_number] = (char *)malloc(80); var_value_str[fn_number][0] = 0;
         var_value[fn_number] = (int *)var_value_str[fn_number];
         fn_command[fn_number] = (void *)CallBack_mdl;
         fn_command_str[fn_number] = (char *) malloc(strlen(cmd)+1);
         strcpy(fn_command_str[fn_number],cmd);
         var_name_str[fn_number] = (char *)malloc(strlen(s2)+1);
         strcpy(var_name_str[fn_number],s2);
         fn_number++;
         continue;
      }
      fprintf(stderr,"mdl: unknown command >%s<\n",s);
      c = 0;
      while(c != 10) {            /* try to synchronize */
         if(feof(stream)) {free(cmd); return(0);}
         c = fgetc(stream);
      }
   }
   free(cmd);
}

/* -------------------------------------------------------------
   parse a string:
   search for any occurence of $, and try to substitute
   the variable.
   Pass the string to the ksh and read the result
   ------------------------------------------------------------- */
parse(cstr)
char cstr[];
{
int i,n,m,l;
int flg;
char c,s[80],*str,*str2;
char execfile[80];
FILE *stream;

   str = (char *) malloc(8192); str2 = (char *) malloc(8192);
   tmpnam_(s);

#ifdef AMIGA
   strcpy(execfile,"ram:"); strcat(execfile,s);
#endif

#ifdef UNIX
   strcpy(execfile,s);
#endif
   strcpy(str,cstr);
   n = 0; l = strlen(str);
   while(n < l) {
      if(str[n] == '$') {      /* search for variable substitution */
         sgetpar(str,s,n+1,&i);
         flg = 0;
         for(m = 0; m < fn_number; m++) {      /* try to find menu variable */
            if(var_name_str[m] == NULL) continue;
            if(strcmp(s,var_name_str[m]) == 0 ) {   /* variable name found ! */
               flg = 1;
               if((var_funct[m] == STRING) || 
                  (var_funct[m] == SELECTION) ||
                  (var_funct[m] == FILE_SELECT)) {
                  strcpy(s,var_value_str[m]);      /* get replacement value */
               } else {
                  sprintf(s,"%d",var_value_int[m]);
               }
               break;
            }
         }
         if(flg == 0) {       /* try to find internal function */
            if(strcmp(s,"HELP") == 0) {
               flg = 1;
               sgetpar(str,s,i,&i);
               Help(s);
               strcpy(s," ");
            }
            if(strcmp(s,"EXIT") == 0) {
#ifdef AMIGA
               close_gfx(my_window);
#endif
               exit(0);
            }
            if(strcmp(s,"STRINGBOX") == 0) {
               flg = 1;
               sgetpar(str,s,i,&i);
               StringBox(s,s);
            }
            if(strcmp(s,"FILESELECT") == 0) {
               flg = 1;
               sgetpar(str,s,i,&i);
               FileSelect(s,s);
            }
         }
         if(flg == 1) {         /* replace variable name by string */
            m = 0;
            while(i < l) str2[m++] = str[i++];
            str2[m]=0;
            c = 32; m = 0;
            while(s[m] != 0) str[n++] = s[m++];
            str[n]=0;
            strcat(str,str2); l=strlen(str);
         }
      }
      n = n + 1;
   }
/* going to execute command. Output will be directed to a help window */
   if(str[0] == '!') {
      n = 0;
      while(str[n] != 0) {str[n] = str[n+1]; n++;} ; 
      ExecIO(str);
   } else {
      stream = fopen(execfile,"w");
      fprintf(stream,"%s\n",str);
      fclose(stream);

      strcpy(str,language);
      strcat(str," ");
      strcat(str,execfile);
      ExecIO(str);
      unlink(execfile);
   }

   free(str); free(str2);
   return(0);
}

/* add I/O redirection to command, execute command and display output */

ExecIO(cmd)
char cmd[];
{
int n,m,l;
char *s;
char *str;
char *resultfile;
FILE *stream;

#ifdef AMIGA
struct FileHandle *input, *output;
#endif

   str = (char *) malloc(8192);
   resultfile = (char *) malloc(80);
   s = (char *) malloc(80);

#ifdef AMIGA
   tmpnam_(s); strcpy(resultfile,"ram:"); strcat(resultfile,s);

   n = 0;
   while(cmd[n] != ' ') {str[n] = cmd[n]; n++;}
   str[n] = 0;
   m = 0; l = strlen(cmd);
   while(n <= l) s[m++] = cmd[n++];
   strcat(str," >"); strcat(str,resultfile);
   strcat(str," <CON:30/30/30/30/mdl-hilf");
   strcat(str,s);
input = (struct FileHandle *) Open("nil:",MODE_OLDFILE);
output = (struct FileHandle *) Open("nil:",MODE_NEWFILE);
   Execute(str,input,output);
Close(input);
Close(output);

   stream = fopen(resultfile,"r");
   n=fread(str,1,4094,stream); str[n]=0;
   fclose(stream);
#endif

#ifdef UNIX
   tmpnam_(resultfile);
   freopen(resultfile,"w",stdout);
   system(cmd);
   freopen(resultfile,"r",stdout);
   n=fread(str,1,8190,stdout); str[n]=0;
   freopen("/dev/syscon","w",stdout);
#endif

   unlink(resultfile);
   postparse(str);
   free(s); free(resultfile); free(str);
   return(0);
}


postparse(str)
char *str;
{
char *s1, *s2, *s3, *s4, *cmd;
int i,m,p;

   s1 = (char *) malloc(128);
   s2 = (char *) malloc(128);
   s3 = (char *) malloc(256);
   s4 = (char *) malloc(8192);
   cmd = (char *) malloc(128);

   p = 0; s4[0] = 0;
   while(str[p] != 0) {
      i = 0; while(str[p] != '\n') s3[i++] = str[p++];
      s3[i] = 0; p = p + 1;

      sscanf(s3,"%s %s %s",cmd,s1,s2);

      if(strcmp(cmd,"SET") == 0) { /* SET variable */
         for(m = 0; m < fn_number; m++) {      /* try to find menu variable */
            if(var_name_str[m] == NULL) continue;
            if(strcmp(s1,var_name_str[m]) == 0 ) {   /* variable name found ! */
               if(var_funct[m] == STRING) strcpy(var_value_str[m],s2);
               if(var_funct[m] == TOGGLE) var_value_int[m] = atoi(s2);
               if(var_funct[m] == SCALEX) var_value_int[m] = atoi(s2);
               if(var_funct[m] == SCALEY) var_value_int[m] = atoi(s2);
               if(var_funct[m] == SCALEX11) var_value_int[m] = atoi(s2);
               if(var_funct[m] == SCALEY11) var_value_int[m] = atoi(s2);
               s3[0] = 0;
               break;
            }
         }
      }
      if(strcmp(cmd,"EXIT") == 0) { /* EXIT menu */
#ifdef AMIGA
         close_gfx(my_window);
#endif
         free(cmd); free(s4); free(s3); free(s2); free(s1);
         exit(0);
      }
      if(strcmp(cmd,"CD") == 0) { /* CD */
         changedir(s1);
         free(cmd); free(s4); free(s3); free(s2); free(s1);
         return(0);
      }
      if(s3[0] != 0) {strcat(s4,s3); strcat(s4,"\n");}
   }
   if(s4[0] != 0) Help(s4);
   free(cmd); free(s4); free(s3); free(s2); free(s1);
}


changedir(str)
char *str;
{
#ifdef AMIGA
struct FileLock *pwd;

      pwd = (struct FileLock *) Lock(str,-2);
      if(pwd != NULL) {
         pwd = (struct FileLock *) CurrentDir(pwd);
         UnLock(pwd);
      }
#endif
#ifdef UNIX
      chdir(str);
#endif
return(0);
}


checkopt(argc,argv,s,sv)
int argc;
char *argv[],s[],sv[];
{
int   n,erg;

   erg=FALSE;
   for(n=1;n<argc;n++) {
      if(strcmp(argv[n],s)==0) {
         erg=TRUE;
         strcpy(sv,argv[n+1]);
      }
   }
   return(erg);
}

#ifdef AMIGA
amifork(str)
char *str;
{
struct FileHandle *input, *output;
char *s;

s = (char *) malloc(256);
strcpy(s,"run >nil: <nil: "); strcat(s,str);
input = (struct FileHandle *) Open("nil:",MODE_OLDFILE);
output = (struct FileHandle *) Open("nil:",MODE_NEWFILE);
   Execute(s,input,output);
Close(input);
Close(output);
free(s);
return(0);
}
#endif
