/* prompter.c
                              COPYRIGHT (c) 1990
                        Kapteyn Astronomical Institute
         University of Groningen  -  9700 AV Groningen, The Netherlands

*/


#include "hercom.h"
#include "errno.h"
#include "parse.h"
#include "ctype.h"
#include "string.h"
#include "stdlib.h"

#define UCLEN 80
#define SLEN  20
#define ESC   27

int     read( int , char* ,int );

/*
#>        prompter.dc3
Name:     prompter

Purpose:  Private to Hermes. Prompt user and process command.

File:     prompter.c

Author:   J.P. Terlouw

Use:      int prompter(char* prompt, int context);

             The routine returns the number of characters typed.
             Arguments:
                        prompt     - the prompt string
                        context    - either FREE or KEYPROMPT
                                     In the case of KEYPROMPT the prompt is
                                     assumed to be part of the command e.g.
                                     Userinp keywords.

Updates:  25-Feb-90  --  original document
#<
*/

static void log_inp(TaskStatus,char*);

int prompter(char *prompt, int context)
{
   int     n, pl;
   fint    type, subtype, q1, q2, q3, l1=NAMLEN, l2=SLEN, l3=SLEN, l4=SLEN;
   fint    cmdlen;
   char    s2[SLEN], s3[SLEN], s4[SLEN];
   
   char    taskname[NAMLEN+1];
   char    usercommand[UCLEN+1];
   char    first;
   char    key[KEYLEN];
   TaskStatus curstat;
   
   static bool    initialized=0;

   
   curstat = namstatus("");
   strcpy(usercommand,prompt);
   do {
      put_uca(usercommand);
      if (context==KEYPROMPT) {
         pl = strlen(usercommand);
      } else {
         strcpy(usercommand,curstat->name);
         strcat(usercommand," ");
         pl = strlen(usercommand);
      }
      while ((n = read(0,&usercommand[pl],UCLEN-pl)-1) == -2 && errno == EINTR);
      first = usercommand[pl];
      switch(first) {
         case '!' : use_par(curstat); initialized=1;
                    log_inp(curstat,"!");
                    (void)strcpy(usercommand,">"); break;
         case '?' : if (curstat->state == WAITINP) {
                       put_psa(curstat,curstat->userinp.message,PLUSINP);
                       (void)strcpy(usercommand,curstat->name);
                       (void)strcat(usercommand,",");
                       (void)strcat(usercommand,curstat->userinp.key);
                       context = KEYPROMPT;
                     } else if (curstat->state == PAUSING) {
                       (void)strcpy(usercommand,"(PAUSING)>");
                       context = FREE;
                     } else (void)strcpy(usercommand,">");
                     break;
         case ESC : (void)strcpy(usercommand,">"); context = FREE; break;
      }
   } while(first=='!' || first=='?' || first==ESC);
   if (!initialized) {
     init_par(curstat);
     initialized=1;
   }
   cmdlen = n+pl;
   if (cmdlen==0 || n==0 && context==FREE) return 0;  /* allow empty input */
   usercommand[cmdlen] = 0;
   { int i; for(i=0; i<cmdlen; i++) usercommand[i]=toupper(usercommand[i]);}
#if 0
   parse_c((fint*)usercommand,&cmdlen,&type,&subtype,&q1,&q2,&q3,
           (fint*)taskname,&l1,(fint*)s2,&l2,(fint*)s3,&l3,(fint*)s4,&l4);
#endif
   {
      fchar S1, S2, S3, S4;
      S1.a = taskname; S1.l = l1; S2.a = s2; S2.l = l2; S3.a = s3; S3.l = l3; S4.a = s4; S4.l = l4;
      parse_c( tofchar(usercommand), &type, &subtype, &q1, &q2, &q3, S1, S2, S3, S4 );
   }
   switch (type) {
      case 3:
             /* !!! Currently store only 1 (one) keyword */
             if (q1) {
               int i;
               for (i=0; (q1+i-1)<cmdlen && i<KEYLEN; i++) {
                  key[i] = usercommand[q1+i-1];
                  if (key[i]=='=') {
                     i++; key[i]=0; 
                     break;
                  }
               }
               if (key[i]==0) {
                  insert_par(curstat,key,&usercommand[q1+i-1]);
                  log_inp(curstat,usercommand);
                  if (curstat->state == WAITINP) {
                     (void)satisfy(curstat,&curstat->userinp,context);
                  }
               } else {
                  err_uca("BAD KEYWORD");
               }
             } else {
               err_uca("Cannot start task -- wait until Hermes is implemented");
             } break;
      case 4: switch (subtype) {
                case  1:   /* /INP     */ break;
                case  2:   /* /WAIT    */ break;
                case  3:   if (curstat->state==PAUSING) {
                              reply_send(curstat,0);
                              put_psa(curstat,"RUNNING",PLUSPAUSE);
                              curstat->state = RUNNING;
                           }
                           break;
                case  4:   put_psa(curstat,"USER ABORT\n",PLUSTERM); 
                                    /*!!! evt.\n weg */
                           exit(0);
                           break;
                case  5:   err_uca("No hardcopies impimented"); break;
                case  6:   curstat->status_level = q1;
                           log_inp(curstat,usercommand); break;
                case  7:   err_uca("The whole session? You must be kidding!");
                           break;
                case  8:   curstat->devmask |= q1; 
                           log_inp(curstat,usercommand); break;
                case  9:   curstat->devmask ^= q1; 
                           log_inp(curstat,usercommand); break;
                case 10:   curstat->errlev = q1; 
                           log_inp(curstat,usercommand); break;
                case 11:   curstat->meslev = q1; 
                           log_inp(curstat,usercommand); break;
                case 12:   curstat->output_mode = q1;
                           log_inp(curstat,usercommand); break;
                default:   err_uca("BAD SYNTAX");
               }
               break;
      case 1: err_uca("Cannot page in log file -- not implemented"); 
              break;
      case 2: err_uca("Cannot search text in log file -- not implemented");
              break;
      case 5: err_uca("DCL commands not avaliable");
              break;
      case 6: err_uca("Interactive DCL commands not implemented");
              break;
      default: err_uca("BAD SYNTAX");
   }
   return n;
}

static void log_inp(TaskStatus status, char *command)
{
   char logline[LINLEN];
   
   strcpy(logline,"<USER  > ");
   strcat(logline,command);
   put_log(status,logline);
}

