/*===========================================================================
  Copyright (C) 1995-2005 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*+++++++++++++++   MIDAS monitor routines PREPA1  +++++++++++++++++++++++++
.LANGUAGE      C
.IDENTIFICATION  Module PREPA1
.AUTHOR  K. Banse                  	ESO - Garching
.KEYWORDS  MIDAS monitor
.ENVIRONMENT  VMS and UNIX
.PURPOSE
synchronize fore- and background processes; 
get the MIDAS command string + take action accordingly
.ALGORITHM
loop on command input (from terminal or procedure file),
test for background activity and synchronize
system commands are executed directly,
all others are executed as command procedures

holds NUMBIZ, REDOBIZ, MYREAD, COM_WINDOW

.VERSION  [1.00] 930125: pulled out from "old" prepa.c + prepb.c

 051021		last modif

------------------------------------------------------------------------*/
 
#include <osyparms.h>
#include <fileexts.h>
#include <monitdef.h>
#include <midfront.h>
#include <stdlib.h>
#include <string.h>


static int  ord[MAX_COMWIN][2];
static int  comwinmax;
static int  lwa;

static char  *comwinadr;

static float  rwa;

static double dwa;



/*

*/
 
int NUMBIZ(curcom)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  handle the command recalling business (via number or pattern)
.ALGORITHM
  cumbersome but straight forward
.RETURNS
  status = 1, 2, 3      according to nbra for redobiz
         = 0            just continue in calling module
         = -1           go + get new input
------------------------------------------------------------------*/

int   *curcom;   /* IN/OUT: current command no. */

{
char   *cpntr, *ccpntr;

int  iwa, nbra, m;




nbra = 1;
cpntr = ccpntr = TOKEN[0].STR;

if ( (*cpntr == ':') ||
     ((*cpntr == '.') && (*(cpntr+1) == ':')) )
   {
   cpntr++;                                  /* point to 2. character */
   if (*cpntr == '.')                                /* is it ":." ?  */
      nbra = 3;
   else if ((*ccpntr == '.') && (*cpntr == ':'))   /* is it ".:" ?  */
      nbra = 2;

   COM_WINDOW("FST",&m);          /* search for com.string in buffer  */
   if (m >= 0)
      {
      comwincur = comwinp + m;
      *curcom = comwincur->COMNO;            /* update current command  */
      return nbra;
      }

   (void) printf("Command string not in buffer\n");
   }


/*  It's a number. Test, if simple repeat or edit or lock/unlock  */

else
   {
   if (*cpntr == '.')                                /* is it ".no" ?  */
      {
      nbra = 2;
      cpntr ++;
      }
   else if (*(cpntr+TOKEN[0].LEN-1) == '.')          /* is it "no." ?  */
      {
      nbra = 3;
      *(cpntr+TOKEN[0].LEN-1) = '\0';        /* replace '.' by NULL  */
      }
   else
      {
      m = CGN_INDEXC(cpntr,'/');        /* look for xxx/LOCK,UNLOCK  */
      if (m > 0)
         {
         (void)strncpy(LINE.STR,cpntr,m);
         LINE.STR[m] = '\0';
         COM_WINDOW(cpntr+m,&iwa);      /* lock or unlock command xxx */
         return (-1);			/* get new command */
         }
      }

   if (CGN_CNVT(cpntr,1,1,&lwa,&rwa,&dwa) < 1)	/* convert to binary */
      {
      (void) printf("Invalid syntax (not a number) ...\n");
      goto error_1;
      }

   if (lwa <= 0) lwa = *curcom;		/* 0 means last used command  */
   m = lwa;				/* save that command no. */
   COM_WINDOW("FNO",&m);		/*  find command with given no.  */
   if (m >= 0)
      {
      comwincur = comwinp + m;
      *curcom = lwa;			/* update current command  */
      return (nbra);                    /* indicate that we need to redo it */
      }

   (void) printf("Command no. %d not in buffer \n",lwa);
   }


error_1:
FRONT.COMCNT --;			/* don't increment command counter */
return(-1);				/* look for next command   */
}

/*

*/
 
int REDOBIZ(nbra)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  handle the command recalling business (via number or pattern)
.ALGORITHM
  cumbersome but straight forward
.RETURNS
  status = 1            we have to go back to main start loop
                        if psw = 1, we have to go back to parsing only
         = 0            just continue in calling module
------------------------------------------------------------------*/

int  nbra;              /* IN: switch (coming from numbiz */

{
int  iwa;


if (nbra == 1)
   {
   comwincur->LREF = FRONT.COMCNT;                  /* set last_used entry */
   FRONT.COMCNT--;                  /* no increment comm_count for numbers */
   (void) printf("%s\n\r",LINE.STR);
   }
else
   {                                         /* nbra = 2 or 3  */
   TTEDIT(LINE.STR,160);                     /* edit this command  */
   LINE.LEN = (int)strlen(LINE.STR);

   if (nbra != 2)
      {
      if (LINE.LEN == 0)             /* may happen in edit mode ... */
         {
         COM_WINDOW("SH",&iwa);
         return (0);                       /* get new command */
         }
      if (LINE.LEN > MAX_WINLEN)
         {
         (void)strncpy(comwincur->STR,LINE.STR,MAX_WINLEN);
         comwincur->STR[MAX_WINLEN] = '\0';
         }
      else
         (void)strcpy(comwincur->STR,LINE.STR);

      comwincur->LREF = FRONT.COMCNT;           /* set last_used entry  */
      FRONT.COMCNT--;                           /* don't increment com_count */
      }
   }

return(1);                         /* parse that command again */
}

/*

*/
 
int MYREAD()
	
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  display a prompt string on the terminal + read the user input
.ALGORITHM
  use QIOW system service to display prompt string with time out option
  and get user input as character string
  convert this string to relevant data via GEN_CNVT
.RETURNS
   = 0				normally
   = 1				if end of playback file reached
------------------------------------------------------------------*/
 
{
int   amount, off, reclen, start;
int   kk, nn, partial, promend5;

char	atom1[16], atom2[16];
char	*rec, *cpntrc;
static char   intrpt[80];
 
 

promend5 = FRONT.PEND + 5;
rec = KAUX.STR;
off = 0;			/* offset within command buffer  */
LINE.LEN = 0;
amount = MAX_LINE;
 
	
/*  test playback switch, = 0 for terminal input, 
                          > 0 for input from playback file        */
 
sect_100:
cpntrc = &LINE.STR[off];		/* point to begin of command line */

if (FRONT.PLAYBACK == 0)
   {
 
   /* read a line from terminal and wait for `timeout' seconds  */
 
   TERM.INTENA = 1;
   if (off == 0)
      TTPRO(FRONT.PROMPT,cpntrc,amount);
   else
      {
      memset((void *)KAUX.STR,32,(size_t)promend5);
      KAUX.STR[promend5] = '\0';
      TTPRO(KAUX.STR,cpntrc,amount);
      }
   TERM.INTENA = 0;
   if (TERM.TIMEOUT != 0) return (0);		/* special treatment ... */

   partial = (int)strlen(cpntrc);
   if (partial <= 0)
      {
      LINE.LEN = 0;
      return (0);		/* nothing came in...  */
      }
   }
 
else 
   {
   start = 0;	
 
read_play:				/* read a line from playback file  */
   reclen = osaread(FRONT.PP,rec,96);
   if (reclen == -1) 
      {					/*  end of playback file reached   */
      FRONT.PLAYBACK = 0;
      (void) printf("--- end of playback reached ---\n");
      osaclose(FRONT.PP);
      return (-1);			/* indicate it to caller */
      }	
 
   if (reclen == 0) goto read_play;
   if (rec[reclen-1] == 13) reclen --;		/* get rid of RETURN char.  */
 
   if (off > 0) goto sect_200;

 
   /* for logfiles check, if it was a MIDAS command */
 
   if (FRONT.PLAYBACK == 11)  			
      {					/* test for Midas prompt  */
      nn = 0;
      (void) CGN_EXTRSS(FRONT.PROMPT,20,' ',&nn,atom1,14);
      (void) CGN_EXTRSS(rec,reclen,' ',&start,atom2,14);
      if (strcmp(atom1,atom2) == 0) 
         {
         kk = CGN_EXTRSS(rec,reclen,' ',&start,atom2,12);
         goto sect_200;			/* start -> begin of command line */
         }

      start = 0;
      goto read_play;
      }
	
sect_200:
   partial = reclen - start;
   (void)strcpy(cpntrc,&rec[start]);			/* build up LINE.STR */
   if (off == 0)
      (void)strcpy(rec,FRONT.PROMPT);
   else
      memset((void *)rec,32,(size_t)promend5);

   (void)strcpy(rec+promend5,cpntrc);		/* old line with new prompt */
   (void)printf("%s\n\r",rec);
   }
 
	
/*  for all options update counters + pointers   */
 
off += partial;
LINE.LEN = off ;
nn = LINE.LEN - 1;

	
/*  test for continuation   */
 
if (LINE.STR[nn] != '-')  			/* no. we are done ...  */
   {
   if (LINE.STR[nn] == '\\')   /*  but don't forget the interrupt. business  */
      {
      if (LINE.LEN == 1)  		/* recall interrupted command line  */
         {
         (void)strncpy(KAUX.STR,FRONT.PROMPT,promend5);
         (void)strcpy(&KAUX.STR[promend5],intrpt); /* get saved string back */
         (void)printf("%s\n\r",KAUX.STR);
         LINE.LEN = CGN_COPY(LINE.STR,intrpt);
         goto sect_2000;		/* handle like continuation line  */
         }
      else				/* save interrupted command line   */
         {
	 (void)strcpy(intrpt,LINE.STR);       /* simulate continuation...   */
         intrpt[partial-1] = ' ';	/* change '\' to ' ' */
         LINE.LEN = -1;			/* indicate interruption to PREPA  */
         return (0);
         }
      }
   }
 
else
   {
sect_2000:			   /*  yes...delete continuation char.   */
 
   off = LINE.LEN -1;
   amount = MAX_LINE - off;
   if (amount >= 0)
      goto sect_100;			/* get max. MAX_LINE  chars...  */
   }
 

/*  normal return here  */
 
LINE.STR[LINE.LEN] = '\0';

return (0);
}

/*

*/
 
int COM_WINDOW(action,curcom)
 
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  handle the interactions with the command buffer
.ALGORITHM
  straight forward
.RETURNS
  0 if o.k., else we have problems
-----------------------------------------------------------------*/
 
char	*action; /* IN: = ADD, for adding an entry */
		 /*	= SHOW, for showing the command window */
		 /*	= READ, for reading from procedure into window */
		 /*	= WRITE, for writing the window to procedure */
		 /*	= CLEAR, for initializing window */
		 /*	= /LOCK,UNLOCK for locking,unlocking an entry  */
		 /*	= EXtend (Init) to (re)create command buffer  */
 
int   *curcom  /* IO: current command no. in command window  */;
 
 
 
{	
int   kk, kret, n, nn, m, mm;
register int  nr;
	
static char   title[78];
 
 
	
/*   ADD  =>  store command in command window   */
 
 
if (*action == 'A')
   {
   m = comwinp->LREF + comwinp->FIX;
   mm = 0;					      /* start with 1. entry */
   comwincur = comwinp + 1;
   for (nr=1; nr<comwinmax; nr++)		/* search for "oldest" entry */
      {
      if ( (comwincur->LREF + comwincur->FIX)  <  m )
         {
         m = comwincur->LREF + comwincur->FIX;		/* m = oldest entry  */
         mm = nr;
         }
      comwincur ++;
      }
 
   comwincur = comwinp + mm;
   if (LINE.LEN > MAX_WINLEN) 
      {
      (void) strncpy(comwincur->STR,LINE.STR,MAX_WINLEN);   /* store command */
      comwincur->STR[MAX_WINLEN] = '\0';
      }
   else
      (void)strcpy(comwincur->STR,LINE.STR);
 
   comwincur->COMNO = FRONT.COMCNT;	  /* and set comno + last_used entry */
   comwincur->LREF = FRONT.COMCNT;
   *curcom = FRONT.COMCNT;
   }
 
	
/*   FNO and FST  =>  find matching commands  */
 
else if (*action == 'F')
   {
   kret = -1;			/* indicate that no match */
   if (*(++action) == 'S')
      {
      if ((TOKEN[0].STR[1] == '.') || (TOKEN[0].STR[1] == ':'))
         m = 2;
      else
         m = 1;
      kk = sort_it();			/* sort according to comand no. */
      for (nr=kk; nr>=0; nr--)		/* to begin with most recent command */
         {
         n = ord[nr][1];
         comwincur = comwinp + n;
         if (CGN_INDEXS(comwincur->STR,&TOKEN[0].STR[m]) >= 0)
            {
            kret = n;
            break;
            }
         }
      }
   else
      {
      mm = *curcom;			/* save parameter */
      comwincur = comwinp;
      for (nr=0; nr<comwinmax; nr++)      /* search for com.no in buffer  */
         {
         if (comwincur->COMNO == mm)
            {
            kret = nr;
            break;
            }
         comwincur ++;
         }
      }
   
   *curcom = kret;
   if (kret != -1)			/* copy string if if found */
      LINE.LEN = CGN_COPY(LINE.STR,comwincur->STR);
   }
 
	
/*   SHOW  =>  display command buffer  */
 
else if (*action == 'S')
   {
   kk = sort_it();			/* sort according to comand no. */

   (void) printf("%s\n\r",title);
	
   for (nr=0; nr<=kk; nr++)
      {
      comwincur = comwinp + ord[nr][1];
      (void) sprintf(KAUX.STR,"%4d %s",comwincur->COMNO,comwincur->STR);
      (void) printf("%s\n\r",KAUX.STR);
      }
 
   FRONT.COMCNT --;			/* keep counter at same value  */
   }
 
	
/*  READ  =>  store commands from a procedure into command buffer  */
 
else if (*action == 'R') 
   {
   if (cmw_read(curcom) < 0) return (-22);
   }
	
	
/*   WRITE  =>  save commands from command buffer in procedure   */
	
else if (*action == 'W')
   {
   kk = cmw_write(moncnt,*curcom);
   if (kk < 0)
      return (-22);
   }
 
	
/*   CLEAR  =>  reset FRONT.COMCNT + clear command buffer   */
 
else if (*action == 'C')
   {
   cmw_clear();
   }
 
	
/*  /LOCK, /UNLOCK => lock or unlock an entry  */
 
else if (*action == '/')
   {
   FRONT.COMCNT --;			/* keep counter at same value  */
	
   nn = CGN_CNVT(LINE.STR,1,1,&lwa,&rwa,&dwa);	/* get command no.  */
   if ( (lwa <= 0) || (nn < 1) )
      return (-1);				/* invalid command no.  */
	
   comwincur = comwinp;
   mm = lwa;
   for (nr=0; nr<comwinmax;nr++)		/* search for given command  */
      {
      if (comwincur->COMNO == mm)
         {
         if ( (action[1] == 'L') || (action[1] == 'l') )
            comwincur->FIX = 1000;		/* set lock flag  */
         else
	    comwincur->FIX = 0;			/* clear lock flag  */
         break;
         }
      comwincur ++;
      }
   }

	
/*  Extend (or Init) command buffer  */
 
else 
   {
   if (*action == 'I')
      {
      comwinmax = 15;					/* initial value */
      if (FRONT.TITLE[0] == 'F')		/* FrontEnd version */
         (void)strcpy(title,"no.  command:");
      else 
         {
         (void)strcpy(title,
         "no.  command:              (Midas unit   , version 12345pl");
         title[39] = FRONT.DAZUNIT[0];
         title[40] = FRONT.DAZUNIT[1];
         (void)strcpy(&title[51],&FRONT.TITLE[1]);
         if (FRONT.TITLE[0] == 'P')
            (void)strcat(title,", parallel)");
         else
            (void)strcat(title,", noparallel)");
         }
      nn = 1;
      }

   else
      {
      if (TOKEN[1].STR[0] == '?')
         lwa = 15;				/* default, if no params */
      else
         {
         nn = CGN_CNVT(TOKEN[1].STR,1,1,&lwa,&rwa,&dwa);
         if ( (lwa <= 0) || (nn < 1) )
            return (-1);			/* invalid command no.  */
         if (lwa > MAX_COMWIN)			/* keep in [2,MAX_COMWIN] */
            lwa = MAX_COMWIN;
         else if (lwa < 2)
            lwa = 2;
         }
      
      nn = cmw_write(0,*curcom);	/* save contents of current buffer  */
      if (nn < 0) return (-22);

      free(comwinadr);			/* free allocated memory */
      comwinmax = lwa;		 /* only now update comwinmax ... */

      }

   kk = (sizeof(struct COMWIN_STRUCT)) * comwinmax;
   if ((comwinadr = malloc((size_t) kk)) == NULL) return (-99);
   comwinp = (struct COMWIN_STRUCT *) comwinadr;

   cmw_clear();
 
   if (nn == 0)				/* only if we saved something before */
      {
      TOKEN[1].STR[0] = '?';		/* force to default frame name */
      cmw_read(curcom);
      }
   }

return (0); 

}

/*

*/
 
int cmw_read(curcom)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
.PURPOSE
 store commands from a procedure into command buffer  
.ALGORITHM
 open file + read records
.RETURNS
 no. of lines in procedure file, -1 if problems
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
	
int  *curcom;

{

int  lcount, lrec, kk, idum, mm, m, cur;
int  fp;

register int  nr;

char frame[200];
char frname[80];


if (TOKEN[1].STR[0] == '?')
   {
   idum = 1;				/* use as 1. time flag */
   mm = CGN_COPY(frame,FRONT.STARTUP);
   (void)strcpy(&frame[mm],"midtemp  .prg");		/* default procedure */
   frame[mm+7] = FRONT.DAZUNIT[0];
   frame[mm+8] = FRONT.DAZUNIT[1];
   }
else
   {
   idum = 0;				/* use as 1. time flag */
   CGN_CLEANF(TOKEN[1].STR,6,frame,70,&kk,&kk);
   }
 
cur = 0;				/* start with 1. entry  */
lcount = 0;				/* init record count */

open_file:
fp = osaopen(frame,0);		/* open for read  */
if (fp == -1) 
   {
   if (TOKEN[1].STR[0] == '*')
      {
      *curcom = cur;
      return (0);
      }
   else
      {
      if (idum == 0)
         {
         idum = -1;
         mm = CGN_COPY(frame,FRONT.STARTUP);
         CGN_CLEANF(TOKEN[1].STR,6,&frame[mm],20,&kk,&kk);
         goto open_file;
         }
      else
         {
         (void)strcpy(frname,"READ/COMM ");
         (void)strcat(frname,frame);
         return (-1);
         }
      }
   }
	
read_loop:
 
lrec = osaread(fp,KAUX.STR,MAX_WINLEN);	/* read in procedure file  */
if (lrec == 0) goto read_loop;
 
if (lrec < 0)
   {
   osaclose(fp);
   *curcom = cur;
   return (lcount);
   }
else
   {
   if ( KAUX.STR[0] == '!') goto read_loop;	/* omit comment lines */
  	
   lcount ++ ;
   m = comwinp->LREF;
   cur = 0;
   for (nr=1; nr<comwinmax; nr++)		/* search for "oldest" entry */
      {
      comwincur = comwinp + nr;
      if (comwincur->LREF < m)
         {
         m = comwincur->LREF;			/* m = oldest entry  */
         cur = nr;
         }
      }
 
   FRONT.COMCNT ++;				/* increment command counter */
   comwincur = comwinp + cur;			/* pointer to current entry */
   (void)strcpy(comwincur->STR,KAUX.STR);		/* store command */
   comwincur->COMNO = FRONT.COMCNT;	  /* and set comno + last_used entry */
   comwincur->LREF = FRONT.COMCNT;
   goto read_loop;				/* read next line  */
   }
}

/*

*/
 
int cmw_write(parflag,curcom)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
.PURPOSE
 save commands from command buffer in procedure 
.ALGORITHM
 create file + write records
.RETURNS
 0 if o.k., else we have problems
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
	
int  parflag;
int  curcom;

{

int  kk, jj, nn, mm, m;

int  fp;

register int  nr;

char  frame[200], frname[80];

static char   parms[8] = {'1','2','3','4','5','6','7','8'};


 
jj = sort_it();			/* sort currently stored commands */
if (jj < 0) return(1);			/* nothing to do! */

if ((parflag > 1) && (TOKEN[1].STR[0] != '?'))
   CGN_CLEANF(TOKEN[1].STR,6,frame,70,&kk,&kk);	/* append type .prg  */
else
   {
   mm = CGN_COPY(frame,FRONT.STARTUP);
   (void)strcpy(&frame[mm],"midtemp  .prg");		/* default procedure */
   frame[mm+7] = FRONT.DAZUNIT[0];
   frame[mm+8] = FRONT.DAZUNIT[1];
   }

fp = osaopen(frame,1);			/*   open for write  */
if (fp == -1)
   {
   (void)strcpy(frname,"WRITE/COMM ");
   (void)strcat(frname,frame);
   return (-1);
   }

for (m=0; m<=jj; m++)		/*  loop through sorted command no.s */
   {
   comwincur = comwinp + ord[m][1];		/* get sorted command no.  */
   if (comwincur->COMNO != curcom)	   /* omit WRITE/COMM command itself */
      {	
      (void)strcpy(LINE.STR,comwincur->STR);

      for (nr=2; nr<parflag; nr++) 		/* now search for parameters */
         {
         kk = CGN_INDEXS(LINE.STR,TOKEN[nr].STR);

         if (kk >= 0)
            {
            nn = kk + TOKEN[nr].LEN;
            (void)strcpy(KAUX.STR,&LINE.STR[nn]);
 
            LINE.STR[kk++] = '{';
            LINE.STR[kk++] = 'P';
            LINE.STR[kk++] = parms[nr-2];
            LINE.STR[kk++] = '}';
            (void)strcpy(&LINE.STR[kk],KAUX.STR);
            }
         }

      osawrite(fp,LINE.STR,(int)strlen(LINE.STR));
      }
   }
osaclose(fp);			/* close procedure file midtemp.prg  */

return (0);
}

/*

*/
 
void cmw_clear()

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
.PURPOSE
 clear command buffer + reset FRONT.COMCNT
.ALGORITHM
 straight forward
.RETURNS
 nothing
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
	
{
register int  nr;

FRONT.COMCNT = 0;			/* reset counter  */
comwincur = comwinp;

for (nr=0; nr<comwinmax; nr++)
   {
   comwincur->COMNO = -1;		/* clear command numbers  */
   comwincur->LREF = 0;
   comwincur->FIX = 0;
   comwincur ++;
   }
}

/*

*/
 
int sort_it()
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  sort the command buffer + return no. of commands in buffer
.ALGORITHM
  straight forward
.RETURNS
  highest index of commands in buffer
------------------------------------------------------------*/

{
int   ordr[2];
int   nn, jj, m;
register int  nr;


jj = -1;
comwincur = comwinp;
for (nr=0; nr<comwinmax; nr++)
   {
   if (comwincur->COMNO > -1)
      {
      jj ++;
      ord[nr][0] = comwincur->COMNO;
      ord[nr][1] = nr;
      }
   comwincur ++;
   } 
	
if (jj < 0) return (jj);


/* if more than one command, sort them  */

for (nr=jj; nr>0; nr--)
   {
   for (nn=1,m=0; nn<=nr; nn++,m++)
      {
      if (ord[m][0] > ord[nn][0])
         {
         ordr[0] = ord[nn][0];
         ordr[1] = ord[nn][1];
         ord[nn][0] = ord[m][0];
         ord[nn][1] = ord[m][1];
         ord[m][0] = ordr[0];
         ord[m][1] = ordr[1];
         }
      }
   }

return (jj);
}

