/* {(rm mdl ; cc -s -n -O -Wc,-Nd4000 -Wc,-Ns4000 -Wc,-Nt50000 -DSYSV -DNLS16 -Dhp9000s300 -o mdl mdl.c -lXm -lXt -lX11 -lPW  ; mdl lise.mdl)& } */
/**---------------------------------------------------------------------
***	
***	file:		mdl.c
***
***	project:	Menu Description Language
***                     General purpose Menu generator.
***
***			(c) 1990 Rainer Kowallik
***
***-------------------------------------------------------------------*/


/*  include files  */
#include <stdio.h>
#include <setjmp.h>

#include <X11/Intrinsic.h>
#include <X11/IntrinsicP.h>
#include <X11/CoreP.h>
#include <X11/Shell.h>
#include <Xm/Xm.h>
#include <Xm/BulletinB.h>
#include <Xm/CascadeB.h>
#include <Xm/Frame.h>
#include <Xm/Label.h>
#include <Xm/MainW.h>
#include <Xm/MessageB.h>
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/RowColumn.h
#include <Xm/ScrollBar.h>
#include <Xm/ScrolledW.h>
#include <Xm/ToggleBG.h>
#include <Xm/Scale.h>
#include <Xm/SelectioB.h>


#define	PUSH		1
#define	TOGGLE		2
#define	SCALEX		3
#define SCALEY		4
#define	DIALOG		5
#define	MENU		6
#define	NEW_MENU	7
#define	FILE_SELECT	8
#define	BOARD		9
#define BULLETIN	10
#define	SELECTION	11
#define	MESSAGE		12
#define	RADIO		13
#define	ROWCOL		14
#define	SCALEX11	15
#define SCALEY11	16


/*  functions defined in this program  */

void main();
void activateCB(); /* Callback for the PushButton */


/*  global variables  */

Display		*display	= NULL; /*  dsplay		*/
Widget		app_shell	= NULL;	/*  shell widget	*/
Widget		main_window	= NULL;	/*  MainWindow		*/
Widget		menu_bar	= NULL;	/*  MenuBar		*/
Widget		menu_pane	= NULL;	/*  MenuPane		*/
Widget		cascade		= NULL;	/*  CascadeButton	*/
Widget		frame		= NULL;	/*  Frame		*/
Widget		swindow		= NULL;	/*  ScrolledWindow	*/
Widget		row_column	= NULL;	/*  RowColumn		*/
Widget		button		= NULL;	/*  PushButtonGadget	*/
Widget		hsb		= NULL;
Widget 		vsb		= NULL;	/*  ScrollBars		*/
Widget		radio		= NULL;	/*  Radio button Widget */
Widget		dialog_box	= NULL;

int 	fn_number = 0;
char 	*fn_command[160];
char	var_name[80][160];
char	var_value[80][160];
Widget 	Wtoggle[160];
int	toggle_var[160];
int 	toggle_ptr = 0;
Widget	Wscale[160];
int	scale_var[160];
int	scale_ptr = 0;
int	selector[160];
int	selector_ptr = 0;
int	acc_x=0;			/* accumulated x	*/
int	acc_y=0;			/* accumulated y	*/
int	bas_y=5;			/* base scale for y-increment */
char	menu_name[80];			/* store menu bar name */
char	return_string[80];		/* string returned from dialog box */
char	resource[80];
jmp_buf	ugly;

/* -------------------------------------------------------------- 
    Create default application windows and widgets
   -------------------------------------------------------------- */
Widget CreateApplication (parent) 
Widget		parent;		/*  parent widget	*/
{
Arg		args[10];	/*  arg list		*/
register int	n;		/*  arg count		*/


	/*	Create MainWindow.
	*/
	n = 0;
	main_window = XmCreateMainWindow (parent, "main1", args, n);
	XtManageChild (main_window);

	/*	Create MenuBar in MainWindow.
	*/
	n = 0;
	menu_bar = XmCreateMenuBar (main_window, "menu_bar", args, n); 
	XtManageChild (menu_bar);

	/*	Create Frame MainWindow and ScrolledWindow in Frame.
	*/
	n = 0;
	XtSetArg (args[n], XmNmarginWidth, 2);  n++;
	XtSetArg (args[n], XmNmarginHeight, 2);  n++;
	XtSetArg (args[n], XmNshadowThickness, 1);  n++;
	XtSetArg (args[n], XmNshadowType, XmSHADOW_OUT);  n++;
	frame = XmCreateFrame (main_window, "frame", args, n);
	XtManageChild (frame);

	n = 0;
	XtSetArg (args[n], XmNscrollBarDisplayPolicy, XmAS_NEEDED);  n++;
	XtSetArg (args[n], XmNscrollingPolicy, XmAUTOMATIC);  n++;
	swindow = XmCreateScrolledWindow (frame, "swindow", args, n);
	XtManageChild (swindow);

	n = 0;
	XtSetArg (args[n], XmNpacking, XmPACK_NONE);  n++;
	XtSetArg (args[n], XmNorientation, XmVERTICAL);  n++; 
	row_column = XmCreateRowColumn (swindow, "row_column", args, n);
	XtManageChild (row_column);

	/*	Set MainWindow areas and add tab groups
	*/
	XmMainWindowSetAreas (main_window, menu_bar, NULL, NULL, NULL,
			frame);
	n = 0;
	XtSetArg (args[n], XmNhorizontalScrollBar, &hsb);  n++;
	XtSetArg (args[n], XmNverticalScrollBar, &vsb);  n++;
	XtGetValues (main_window, args, n);
	if (hsb) XmAddTabGroup (hsb);
	if (vsb) XmAddTabGroup (vsb);
	XmAddTabGroup (row_column);
	return(main_window);
}


/* -------------------------------------------------------------
 	Dialog Box Creation Functions:
		Help(char message[]);
		FileSelect(char dir[]);
		StringBox(char title[]);
   ------------------------------------------------------------- */
/*-------------------------------------------------------------
**	CreateHelp		- create help window
*/
Widget	CreateHelp (message) 
	char message[];
{
	Widget		knopf;
	Widget		message_box;	/*  Message Dialog 	*/
	Arg		args[20];	/*  arg list		*/
	register int	n;		/*  arg count           */
	XmString	title_string = NULL;
	XmString	message_string = NULL;
	XmString	knopf_string = NULL;


	message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
	knopf_string = XmStringCreateLtoR ("Close", XmSTRING_DEFAULT_CHARSET);
	title_string = XmStringCreateLtoR ("Message:", XmSTRING_DEFAULT_CHARSET);

	/*	Create MessageBox dialog.
	*/
	n = 0;
	XtSetArg (args[n], XmNdialogTitle, title_string);  n++;
	XtSetArg (args[n], XmNokLabelString, knopf_string);  n++;
	XtSetArg (args[n], XmNmessageString, message_string);  n++;
	message_box = XmCreateMessageDialog (main_window, "helpbox", args, n);

	knopf = XmMessageBoxGetChild (message_box, XmDIALOG_CANCEL_BUTTON);
	XtUnmanageChild (knopf);
	knopf = XmMessageBoxGetChild (message_box, XmDIALOG_HELP_BUTTON);
	XtUnmanageChild (knopf);


	/*	Free strings and return MessageBox.
	*/
	if (title_string) XtFree (title_string);
	if (message_string) XtFree (message_string);
	if (knopf_string) XtFree (knopf_string);
	return (message_box);
}

Help(message)
char message[];
{
Widget w;
w = CreateHelp(message);
XtManageChild(w);
}

/*-------------------------------------------------------------
**	CreateStringBox		- create string input window
*/
Widget	CreateStringBox (title) 
	char title[];
{
	Widget		knopf;
	Arg		args[20];	/*  arg list		*/
	register int	n;		/*  arg count		*/

	XmString	title_string = NULL;


	title_string = XmStringCreateLtoR (title, XmSTRING_DEFAULT_CHARSET);

	/*	Create MessageBox dialog.
	*/
	n = 0;
	XtSetArg (args[n], XmNdialogTitle, title_string);  n++;
	dialog_box = XmCreatePromptDialog (main_window, "stringbox", args, n);

	XtAddCallback (dialog_box, XmNokCallback,activateCB, -1);

	/*	Free strings and return MessageBox.
	*/
	if (title_string) XtFree (title_string);
	return (dialog_box);
}

/* TRICK TRICK TRICK TRICK TRICK TRICK TRICK TRICK TRICK TRICK TRICK TRICK

   Since Xwindows only works from within the XtMainloop (building boxes,
   watching mouse actions ...) it seemd to be impossible to write
   JUST a function, which returns anything from a box, and then continues
   with the program. The only way around this is a very dirty trick:
   we store the address of our function with setjmp before giving controll
   to XtMainloop, and after processing in our callback routine, longjmp
   goes back to were we started.

   TRICK TRICK TRICK TRICK TRICK TRICK TRICK TRICK TRICK TRICK TRICK TRICK */

StringBox(message,rtstr)
char message[],rtstr[];
{
Widget w;
w = CreateStringBox(message);
if(setjmp(ugly)==0) {
   XtManageChild(w);
   XtMainLoop ();
} else {
   strcpy(rtstr,return_string);
}
}

/*-------------------------------------------------------------
**	CreateFileSelect	- create file selection window
*/
Widget	CreateFileSelect (dir) 
	char dir[];
{
	Widget		knopf;
	Arg		args[10];	/*  arg list		*/
	register int	n;		/*  arg count		*/

	XmString	title_string = NULL;


	title_string = XmStringCreateLtoR (dir, XmSTRING_DEFAULT_CHARSET);

	/*	Create MessageBox dialog.
	*/
	n = 0;
	XtSetArg (args[n], XmNdialogTitle, title_string);  n++;
	dialog_box = XmCreateFileSelectionDialog (main_window,
			 "fsel_box", args, n);

	XtAddCallback (dialog_box, XmNokCallback,activateCB, -1);

	knopf = XmFileSelectionBoxGetChild (dialog_box, XmDIALOG_HELP_BUTTON);
	XtUnmanageChild (knopf);


	/*	Free strings and return MessageBox.
	*/
	if (title_string) XtFree (title_string);
	return (dialog_box);
}

FileSelect(message,rtstr)
char message[],rtstr[];
{
Widget w;
w = CreateFileSelect(message);
if(setjmp(ugly)==0) {
   XtManageChild(w);
   XtMainLoop ();
} else {
   strcpy(rtstr,return_string);
}
}



/* -------------------------------------------------------------
    add an item to the menu list
   ------------------------------------------------------------- */
add_item(x,y,type,text,p1,p2)
int x,y,type,p1,p2;
char text[];
{
int i,m;
Widget button;
Widget knopf;
XmString label_string;
Arg	args[10]; /*  arg list		*/
register int n;	/*  arg count		*/
char s1[80];
XmString item[80];

/* check, if position has to be adjusted */
   if(x != -1) acc_x = x;
   if(y != -1) acc_y = y;

/* do string parsing for SELECTION box */
   extract_str(s1,text,0,',');
	label_string = 
           XmStringCreateLtoR(s1, XmSTRING_DEFAULT_CHARSET);
	n = 0;
	XtSetArg (args[n], XmNlabelString, label_string);  n++;
   i=1; m=1;
   while(m>0) {
      m = extract_str(s1,text,i,',');
      if(strlen(s1)==0) break;
      item[i-1] = XmStringCreateLtoR(s1,XmSTRING_DEFAULT_CHARSET);
      i++;
   }
   item[i-1] = NULL;

/* set position */
	XtSetArg (args[n], XmNx,acc_x); n++;
	XtSetArg (args[n], XmNy,acc_y); n++;

   switch(type) {

   case PUSH:
	XtSetArg (args[n], XmNlabelType, XmSTRING);  n++; 
	button = XmCreatePushButtonGadget(row_column,text , args, n);
	XtAddCallback (button, XmNactivateCallback, 
          activateCB, (caddr_t)fn_number);
	acc_y = acc_y + (8 * bas_y);
	break;

   case TOGGLE:
	if(radio==NULL) radio = row_column;
	button = XmCreateToggleButtonGadget(radio,text , args, n);
	toggle_var[toggle_ptr] = fn_number;
	Wtoggle[toggle_ptr++] = button;
	acc_y = acc_y + (5 * bas_y);
	break;

   case SCALEX:
	XtSetArg (args[n], XmNtitleString, label_string);  n++;
	XtSetArg (args[n], XmNorientation, XmHORIZONTAL);  n++;
	XtSetArg (args[n], XmNshowValue, True);  n++;
	XtSetArg (args[n], XmNminimum,p1);  n++;
	XtSetArg (args[n], XmNmaximum,p2);  n++;
	button = XmCreateScale(row_column,text , args, n);
	scale_var[scale_ptr] = fn_number;
	Wscale[scale_ptr++] = button;
	acc_y = acc_y + (15 * bas_y);
	break;

   case SCALEY:
	XtSetArg (args[n], XmNtitleString, label_string);  n++;
	XtSetArg (args[n], XmNorientation, XmVERTICAL);  n++;
	XtSetArg (args[n], XmNshowValue, True);  n++;
	XtSetArg (args[n], XmNminimum,p1);  n++;
	XtSetArg (args[n], XmNmaximum,p2);  n++;
	button = XmCreateScale(row_column,text , args, n);
	scale_var[scale_ptr] = fn_number;
	Wscale[scale_ptr++] = button;
	acc_y = acc_y + (30 * bas_y);
	break;

   case SCALEY11:
	XtSetArg (args[n], XmNtitleString, label_string);  n++;
	XtSetArg (args[n], XmNorientation, XmVERTICAL);  n++;
	XtSetArg (args[n], XmNshowValue, True);  n++;
	XtSetArg (args[n], XmNminimum,p1);  n++;
	XtSetArg (args[n], XmNmaximum,p2);  n++;
	XtSetArg (args[n], XmNheight,(p2-p1));  n++;
	button = XmCreateScale(row_column,text , args, n);
	scale_var[scale_ptr] = fn_number;
	Wscale[scale_ptr++] = button;
	acc_y = acc_y + (30 * bas_y);
	break;

   case SCALEX11:
	XtSetArg (args[n], XmNtitleString, label_string);  n++;
	XtSetArg (args[n], XmNorientation, XmHORIZONTAL);  n++;
	XtSetArg (args[n], XmNshowValue, True);  n++;
	XtSetArg (args[n], XmNminimum,p1);  n++;
	XtSetArg (args[n], XmNmaximum,p2);  n++;
	XtSetArg (args[n], XmNwidth,(p2-p1));  n++;
	button = XmCreateScale(row_column,text , args, n);
	scale_var[scale_ptr] = fn_number;
	Wscale[scale_ptr++] = button;
	acc_y = acc_y + (15 * bas_y);
	break;

   case SELECTION:
	XtSetArg (args[n], XmNtitleString, label_string);  n++;
	XtSetArg (args[n], XmNlistLabelString, label_string);  n++;
	XtSetArg (args[n], XmNminimizeButtons,True);  n++;
	XtSetArg (args[n], XmNlistItemCount,i-1);  n++;
	XtSetArg (args[n], XmNlistItems,item); n++;
	button = XmCreateSelectionBox(row_column,text , args, n);
	knopf = XmMessageBoxGetChild (button, XmDIALOG_CANCEL_BUTTON);
	XtUnmanageChild (knopf); /* get rid of unneeded buttons */
	XtAddCallback (button, XmNokCallback, 
          activateCB, (caddr_t)fn_number);
	selector[selector_ptr++] = fn_number;
	acc_y = acc_y + (75 * bas_y);
	break;

   case RADIO:
	radio = XmCreateRadioBox(row_column,text, args, n);
	XtManageChild (radio);
	return(0);
	break;

   case FILE_SELECT:
	XtSetArg (args[n], XmNtitleString, label_string);  n++;
	XtSetArg (args[n], XmNlistLabelString, label_string);  n++;
	button = XmCreateFileSelectionBox(row_column,text , args, n);
	knopf = XmFileSelectionBoxGetChild (button, XmDIALOG_CANCEL_BUTTON);
	XtUnmanageChild (knopf); /* get rid of unneeded buttons */
	knopf = XmFileSelectionBoxGetChild (button, XmDIALOG_HELP_BUTTON);
	XtUnmanageChild (knopf);
	XtAddCallback (button, XmNokCallback, 
          activateCB, (caddr_t)fn_number);
	selector[selector_ptr++] = fn_number;
	acc_y = acc_y + (90 * bas_y);
	break;

   case MENU:
	button = XmCreatePushButton (menu_pane, label_string, args, n);
	XtAddCallback (button, XmNactivateCallback, 
 		activateCB, (caddr_t)fn_number);
	break;

   case NEW_MENU:
	n = 0;
	label_string = 
           XmStringCreateLtoR(menu_name, XmSTRING_DEFAULT_CHARSET);
	XtSetArg (args[n], XmNlabelString, label_string);  n++;
	XtSetArg (args[n], XmNsubMenuId, menu_pane);  n++;
	XtSetArg(args[n], XmNlabelString,
		label_string);
	cascade = XmCreateCascadeButton (menu_bar,label_string,args,n);
	XtManageChild (cascade);
	n = 0;
	menu_pane = XmCreatePulldownMenu (menu_bar, "menu_pane", args, n);
	strcpy(menu_name,text);
	return(0);
	break;
   default:
	return(0);
	break;
   }
   
/*  start managing button */
	  XtManageChild(button);
}


/*------------------------------------------------------------- */
void main (argc,argv)
unsigned int argc;
char *argv[];
{
Arg	args[10]; /*  arg list		*/
register int n;	/*  arg count		*/
FILE *stream, *tmp1;
char c,tempfile[80];
int pid;

   pid=fork();
   if(pid!=0) exit(0); /* avoid waiting of shell */

/*  initialize toolkit  */
	XtToolkitInitialize();

/* create resource file from supplied file if possible */
	strcpy(resource,"");
	stream = fopen(argv[1],"r");
	if(stream == NULL) {
		fprintf(stderr,"mdl: could not open command file>%s<\n",argv[1]);
		exit(0);
	}
	c = fgetc(stream);
	if(c == '{') {		/* copy text enclosed in {} to TMPFILE */
	   strcpy(resource,"mdl.tmp");
	   tmp1 = fopen("/usr/lib/X11/app-defaults/mdl.tmp","w");
	   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);
	}

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

	display = XtOpenDisplay (NULL, NULL, argv[0], resource, NULL, 0,
				 &argc, argv);
	if (display == NULL) {
		XtWarning ("mdl: Can't open display, exiting...");
		exit (0);
	}

	menu_init(argv,stream);
	fclose(stream);

/* dont forget to activate the last menu entry */
   add_item(-1,-1,NEW_MENU,"empty",0,0);

	XtRealizeWidget (app_shell);
	XtMainLoop ();
}


/*-------------------------------------------------------------
**	activateCB - callback for button
*/
void activateCB (w, client_data, call_data) 
Widget	w;		/*  widget id		*/
caddr_t	client_data;	/*  data from application   */
caddr_t	call_data;	/*  data from widget class  */
{
int	fn;
int	n,m,i;
char	*cbstr;
char	rtstr[80];

/* first read all toggle buttons */
   for(n=0;n<toggle_ptr;n++) {
      i=XmToggleButtonGadgetGetState(Wtoggle[n]);
      sprintf(rtstr,"%d",i);
      m=toggle_var[n];
      strcpy(var_value[m],rtstr);
   }
      
/* now read all sliders */
   for(n=0;n<scale_ptr;n++) {
      XmScaleGetValue(Wscale[n],&i);
      sprintf(rtstr,"%d",i);
      m=scale_var[n];
      strcpy(var_value[m],rtstr);
   }



   fn=(int)client_data;

/* process callback from dialog box */
   if(fn<0) {
          {
             XmSelectionBoxCallbackStruct *scb =
                (XmSelectionBoxCallbackStruct *) call_data;
             XmStringGetLtoR(scb->value, XmSTRING_DEFAULT_CHARSET, &cbstr);
          }
          strcpy(return_string,cbstr);
	  XtUnmanageChild(dialog_box);
          longjmp(ugly,1);
   }



/* if call from selection box, the catch string */
   for(n=0;n<selector_ptr;n++) {
      if(selector[n] == fn) {
          {
             XmSelectionBoxCallbackStruct *scb =
                (XmSelectionBoxCallbackStruct *) call_data;
             XmStringGetLtoR(scb->value, XmSTRING_DEFAULT_CHARSET, &cbstr);
             strcpy(var_value[fn],cbstr);
          }
      }
   }
   parse(fn_command[fn]);
}

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

	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
   -------------------------------------------------- */

extract_str(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,m,i,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;
}

/* ------------------------------------------------------
   reading file and start initializing menus
   ------------------------------------------------------ */
menu_init(argv,stream)
char *argv[];
FILE *stream;
{
int m,i;
int p1,p2;
int x = 100,
    y = 100,
    set_flg = 0;
char c,s[256],s1[128],s2[128],cmd[8192];
Arg	args[10]; /*  arg list		*/
register int n;	/*  arg count		*/


   while(!feof(stream)) {			/* go through file */
      c=0;
      while(c < 33) {				/* skip NL CR SPC TAB ... */
         c = fgetc(stream);
         if(feof(stream)) 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,' ');
         extract_str(s1,s,0,',');		/* get x */
         x = atoi(s1);
         extract_str(s1,s,1,',');		/* get y */
         y = atoi(s1);
         n = extract_str(s1,s,2,',');		/* get y increment */
         if(n == 1) bas_y = atoi(s1);
         continue;
      }
      if(set_flg == 0) {			/* open window */
         set_flg = 1;				/* should be done only once */
	/*	Create application shell.
	*/

	n = 0;
	XtSetArg (args[n], XmNwidth, x);  n++;
	XtSetArg (args[n], XmNheight, y);  n++;
	app_shell = XtAppCreateShell (argv[0],resource,
				applicationShellWidgetClass, display, args, n);

	/*	Create and realize main application window.
	*/
	main_window = CreateApplication (app_shell);
      }
      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] = (char *) malloc(strlen(cmd)+1);
         strcpy(fn_command[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 */
         extract_str(s1,s,0,','); x = atoi(s1);	/* get x position */
         extract_str(s1,s,1,','); y = atoi(s1);	/* get y position */
         extract_str(s1,s,2,','); 		/* get name */
         add_item(x,y,TOGGLE,s1,0,0);
         strcpy(var_name[fn_number],cmd);
         fn_number++;
         continue;
      }
      if(strcmp(s,"PUSH") == 0) {		/* push button */
         fgetpar(stream,s,' ');			/* get name and position */
         fgetpar(stream,cmd,10);		/* get command string */
         extract_str(s1,s,0,','); x = atoi(s1);	/* get x position */
         extract_str(s1,s,1,','); y = atoi(s1);	/* get y position */
         extract_str(s1,s,2,','); 		/* get name */
         add_item(x,y,PUSH,s1,0,0);
         fn_command[fn_number] = (char *) malloc(strlen(cmd)+1);
         strcpy(fn_command[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 */
         extract_str(s1,s,0,','); x = atoi(s1);	/* get x position */
         extract_str(s1,s,1,','); y = atoi(s1);	/* get y position */
         extract_str(s2,s,2,','); 		/* get name */
         extract_str(s1,s,3,','); p1 = atoi(s1); /* get minimum */
         extract_str(s1,s,4,','); p2 = atoi(s1); /* get maximum */
         add_item(x,y,SCALEX,s2,p1,p2);
         strcpy(var_name[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 */
         extract_str(s1,s,0,','); x = atoi(s1);	/* get x position */
         extract_str(s1,s,1,','); y = atoi(s1);	/* get y position */
         extract_str(s2,s,2,','); 		/* get name */
         extract_str(s1,s,3,','); p1 = atoi(s1); /* get minimum */
         extract_str(s1,s,4,','); p2 = atoi(s1); /* get maximum */
         add_item(x,y,SCALEY,s2,p1,p2);
         strcpy(var_name[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 */
         extract_str(s1,s,0,','); x = atoi(s1);	/* get x position */
         extract_str(s1,s,1,','); y = atoi(s1);	/* get y position */
         extract_str(s2,s,2,','); 		/* get name */
         extract_str(s1,s,3,','); p1 = atoi(s1); /* get minimum */
         extract_str(s1,s,4,','); p2 = atoi(s1); /* get maximum */
         add_item(x,y,SCALEX11,s2,p1,p2);
         strcpy(var_name[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 */
         extract_str(s1,s,0,','); x = atoi(s1);	/* get x position */
         extract_str(s1,s,1,','); y = atoi(s1);	/* get y position */
         extract_str(s2,s,2,','); 		/* get name */
         extract_str(s1,s,3,','); p1 = atoi(s1); /* get minimum */
         extract_str(s1,s,4,','); p2 = atoi(s1); /* get maximum */
         add_item(x,y,SCALEY11,s2,p1,p2);
         strcpy(var_name[fn_number],cmd);
         fn_number++;
         continue;
      }
      if(strcmp(s,"SELECTION") == 0) {		/* selection box */
         fgetpar(stream,s,' ');			/* get name and position */
         extract_str(s1,s,0,10); x = atoi(s1);	/* get x position */
         extract_str(s1,s,1,','); y = atoi(s1);	/* get y position */
         n = 2; i = 0; s1[0] = 0;
         while(i != -1) {
            i = extract_str(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);
         fgetpar(stream,s2,' ');		/* get variable name */
         fgetpar(stream,cmd,10);		/* get command string */
         fn_command[fn_number] = (char *) malloc(strlen(cmd)+1);
         strcpy(fn_command[fn_number],cmd);
         strcpy(var_name[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 */
         extract_str(s1,s,0,','); x = atoi(s1);	/* get x position */
         extract_str(s1,s,1,','); y = atoi(s1);	/* get y position */
         extract_str(s1,s,2,','); 		/* get name */
         add_item(x,y,FILE_SELECT,s1,0,0);
         fn_command[fn_number] = (char *) malloc(strlen(cmd)+1);
         strcpy(fn_command[fn_number],cmd);
         strcpy(var_name[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)) return(0);
         c = fgetc(stream);
      }
   }
}

/* -------------------------------------------------------------
   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,strptr,l;
int cnt = 0;
int flg;
char c,s[80],str[8192],str2[8192];
char resultfile[80],execfile[80];
char bra,ket;

   tmpnam(resultfile); tmpnam(execfile);

   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(strcmp(s,var_name[m]) == 0 ) {	/* variable name found ! */
               flg = 1;
               strcpy(s,var_value[m]);		/* get replacement value */
               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) 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 */
/* +++++++++++++++
   	freopen(execfile,"w",stdout); printf("%s\n",str);
   +++++++++++++++ */
   freopen(resultfile,"w",stdout);
/* +++++++++++++++
   	sprintf(str,"ksh %s",execfile); system(str);
   	unlink(execfile);
   +++++++++++++++ */
 system(str);
   freopen(resultfile,"r",stdout);
   n=fread(str,1,8190,stdout); str[n]=0;
   freopen("/dev/syscon","w",stdout);
   unlink(resultfile);
   if(strcmp(str,"EXIT\n") == 0) exit(0);
   if(n>0) Help(str);
}

