/* Autoconf patching by David Hedbor, neotron@lysator.liu.se */
/*********************************************************************/
/* file: parse.c - some utility-functions                            */
/*                             TINTIN III                            */
/*          (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t             */
/*                     coded by peter unold 1992                     */
/*********************************************************************/
#include "stdafx.h"
#include "tintin.h"


void parse_tintin_command(char *command, char *arg);
void do_speedwalk(char *cp) ;
char *get_arg_with_spaces(char * s, char* arg);

void all_command();
void read_command();
void session_command();
void write_command();
void writesession_command();
void zap_command();
extern char *space_out();
void write_com_arg_mud(char* command, char* argument);
char *get_arg_all(char *s, char *arg);

char *get_arg_stop_spaces(char *s, char *arg);
extern char *cryptkey;
extern void tstphandler();

/*static ALIAS_INDEX FindAlias(char* command)
{
    ALIAS_INDEX ind = AliasList.begin();

    while ( ind != AliasList.end() ) {

    }

}
*/

/**************************************************************************/
/* parse input, check for TINTIN commands and aliases and send to session */
/**************************************************************************/
void parse_input(char *input)
{
    char command[BUFFER_SIZE], arg[BUFFER_SIZE], result[BUFFER_SIZE];
    char *input2;

    bPasswordEcho = TRUE;

    if(*input=='\0') {
        write_line_mud("");
        return ; 
    }

    if ( verbatim  && *input == cCommandChar && *(input+1) == 'v' ) {// check verbatim command
        char command[BUFFER_SIZE];
        char* input2=get_arg_stop_spaces(input+1, command);
        if(command[0] == 'v' && is_abrev(command, "verbatim")){
            char arg[BUFFER_SIZE];
            get_arg_all(input2, arg);
            verbatim_command(arg);
            return;
        }
    }
    
    if (verbatim ) {
        write_line_mud(input);
        return ;
    }
  
    if (*input==verbatim_char) {
        input++;
        write_line_mud(input);
        return ;
    }
    substitute_myvars(input, result);
    input2=result;
    while(*input2) {
        // if(*input2==';')
        if(*input2==cCommandDelimiter)
            input2++;
        input2=get_arg_stop_spaces(input2, command);
        input2=get_arg_all(input2, arg);

        ALIAS_INDEX ind;
        if(*command==cCommandChar) 
            parse_tintin_command(command+1, arg);
        else if( (ind=AliasList.find(command)) != AliasList.end() && 
            ind->second->m_pGroup->m_bEnabled ) {
            
            int i;
            char *cpsource, *cpsource2, newcommand[BUFFER_SIZE], end;

            strcpy(vars[0], arg);

            for(i=1, cpsource=arg; i<10; i++) {
                /* Next lines CHANGED to allow argument grouping with aliases */
                while (*cpsource == ' ')
                    cpsource++;
                end = (*cpsource == '{') ? '}' : ' ';
                cpsource = (*cpsource == '{') ? cpsource+1 : cpsource;
                for(cpsource2=cpsource; *cpsource2 && *cpsource2!=end; cpsource2++);
                strncpy(vars[i], cpsource, cpsource2-cpsource);
                *(vars[i]+(cpsource2-cpsource))='\0';
                cpsource=(*cpsource2) ? cpsource2+1 : cpsource2;
            }
            ALIAS* pal = ind->second;
            prepare_actionalias((char*)pal->m_strRight.data(), newcommand); 
            if(!strcmp(pal->m_strRight.data(), newcommand) && *arg) {
                strcat(newcommand, " "); 
                strcat(newcommand, arg);
            }

            parse_input(newcommand);
         }
         else if(speedwalk && !*arg && is_speedwalk_dirs(command))
            do_speedwalk(command);
            else {
                get_arg_with_spaces(arg,arg);
                write_com_arg_mud(command, arg);
            }
    }
    return;
}

/**********************************************************************/
/* return TRUE if commands only consists of capital letters N,S,E ... */
/**********************************************************************/
int is_speedwalk_dirs(char *cp)
{
  char command[2];
  int flag;
  flag=FALSE;

  while(*cp) {
      command[0] = *cp;
      command[1] = 0;
    if(*cp!='n' && *cp!='e' && *cp!='s' && *cp!='w' && *cp!='u' && *cp!='d' &&
    !isdigit(*cp) && !searchnode_list(common_pathdirs, cp) )
      return FALSE;
    if(!isdigit(*cp))
      flag=TRUE;
    cp++;
  }
  return flag;
}

/**************************/
/* do the speedwalk thing */
/**************************/
void do_speedwalk(char *cp)
{
  char sc[2];
  char *loc; 
  int multflag,loopcnt,i;
  strcpy(sc, "x");
  while(*cp) {
    loc=cp;
    multflag=FALSE;
    while(isdigit(*cp)) {
      cp++;
      multflag=TRUE;
    }
    if(multflag && *cp) {
      sscanf(loc,"%d%c",&loopcnt,sc);
      i=0;
      while(i++<loopcnt)
    	write_com_arg_mud(sc, "");
    }
    else if (*cp) {
      sc[0]=*cp;
      write_com_arg_mud(sc, "");
    }
    /* Added the if to make sure we didn't move the pointer outside the 
       bounds of the origional pointer.  Corrects the bug with speedwalking
       where if you typed "u7" tintin would go apeshit. (JE)
    */
    if (*cp)
       cp++;
  }
}


/*************************************/
/* parse most of the tintin-commands */
/*************************************/
void parse_tintin_command(char *command, char *arg)
{
  
  if(isdigit(*command)) {
    int i=atoi(command);
    if(i>0) {
     get_arg_in_braces(arg, arg, 1);
     while(i-->0)
       parse_input(arg);
    }
    else {
      tintin_puts2(rs::rs(1144));
    }
    return;
  }

  else if(command[0] == 'v' && is_abrev(command, "variable"))
    var_command(arg);

  else if(command[0] == 'a' && is_abrev(command, "action"))
    action_command(arg);
   
  else if(command[0] == 'a' && is_abrev(command, "alias"))
    alias_command(arg);
   
  else if(command[0] == 'r' && is_abrev(command, "read"))
    read_command(arg);

  else if(command[0] == 'i' && is_abrev(command, "if")) 
    if_command(arg);

  else if(command[0] == 'l' && is_abrev(command, "loop"))
    loop_command(arg);

  else if (command[0] == 't' && is_abrev(command, "tolower"))
    tolower_command(arg);

  else if (command[0] == 't' && is_abrev(command, "toupper"))
    toupper_command(arg);

  else if(command[0] == 'a' && is_abrev(command, "antisubstitute"))
    parse_antisub(arg);
    
  else if(command[0] == 'd' && is_abrev(command, "drop"))
    drop_command();


  else if(command[0] == 'c' && is_abrev(command, "cr"))
     cr_command(); 

  else if(command[0] == 'e' && is_abrev(command, "echo"))
    echo_command(arg);

  else if(command[0] == 'h' && is_abrev(command, "highlight"))
    parse_high(arg);
    
  else if(command[0] == 'i' && is_abrev(command, "ignore"))
    ignore_command(arg);
  
  else if(command[0] == 'i' && is_abrev(command, "info"))
    display_info();
  
  else if(command[0] == 'k' && is_abrev(command, "killall"))
    KillAll( CLEAN, "1");

  else if(command[0] == 'l' && is_abrev(command, "log")) 
    log_command(arg);

  else if(command[0] == 'm' && is_abrev(command, "map"))
    map_command(arg);
  
  else if(command[0] == 'm' && is_abrev(command, "math")) 
    math_command(arg);

  else if(command[0] == 'm' && is_abrev(command, "mark")) 
    mark_command(arg);

  else if(command[0] == 'm' && is_abrev(command, "message"))
    message_command(arg);

  else if(command[0] == 'o' && is_abrev(command, "output"))
    output_command(arg);
  
  else if(command[0] == 'p' && is_abrev(command, "path")) 
    path_command();
  
  else if(command[0] == 'p' && is_abrev(command, "pathdir")) 
     pathdir_command(arg); 

  else if(command[0] == 'p' && is_abrev(command, "presub"))
    presub_command(arg);
  
  else if(command[0] == 'r' && is_abrev(command, "return"))
    return_command();

  else if(command[0] == 's' && is_abrev(command, "script"))
    script_command(arg);

  else if(command[0] == 's' && is_abrev(command, "savepath"))
    savepath_command(arg);

  else if(command[0] == 's' && is_abrev(command, "showme"))
    showme_command(arg);
    
  else if(command[0] == 's' && is_abrev(command, "speedwalk"))
    speedwalk_command(arg);

  else if(command[0] == 't' && is_abrev(command, "textin"))
    read_file(arg);  

  else if(command[0] == 's' && is_abrev(command, "substitute"))
    parse_sub(arg);

  else if(command[0] == 'g' && is_abrev(command, "gag")) {
    if (*arg!='{') {
      strcpy(command,arg);
      strcpy(arg,"{");
      strcat(arg,command);
      strcat(arg,"} ");
    }
    strcat(arg, " .");
    parse_sub(arg);
  }
  
  else if(command[0] == 't' && is_abrev(command, "tick")) 
    tick_command();

  else if(command[0] == 't' && is_abrev(command, "tickoff")) 
    tickoff_command();

  else if(command[0] == 'g' && is_abrev(command, "group")) 
    group_command(arg);

  else if(command[0] == 't' && is_abrev(command, "tickon")) 
    tickon_command();

  else if(command[0] == 't' && is_abrev(command, "tickset"))
    tickset_command();

  else if(command[0] == 't' && is_abrev(command, "ticksize")) 
    ticksize_command(arg);

  else if(command[0] == 't' && is_abrev(command, "togglesubs"))
    togglesubs_command(arg);

  else if(command[0] == 'u' && is_abrev(command, "unaction"))
    unaction_command(arg);

  else if(command[0] == 'u' && is_abrev(command, "unalias"))
    unalias_command(arg);

  else if(command[0] == 'u' && is_abrev(command, "unantisubstitute"))
    unantisubstitute_command(arg);
    
  else if(command[0] == 'u' && is_abrev(command, "unhighlight"))
    unhighlight_command(arg);
  
  else if(command[0] == 'u' && is_abrev(command, "unsubstitute"))
    unsubstitute_command(arg);

  else if(command[0] == 'u' && is_abrev(command, "ungag"))
    unsubstitute_command(arg);

  else if(command[0] == 'u' && is_abrev(command, "unpath")) 
    unpath_command();

  else if(command[0] == 'u' && is_abrev(command, "unvariable"))
    unvar_command(arg);

  else if(command[0] == 'w' && is_abrev(command, "write"))
    write_command(arg);

  else if(command[0] == 'z' && is_abrev(command, "zap"))
    zap_command();

  else if(command[0] == 'h' && is_abrev(command, "hotkey"))
    SetHotKey(arg);

  else if(command[0] == 'u' && is_abrev(command, "unhotkey"))
    Unhotkey(arg);

  else if(command[0] == 'c' && is_abrev(command, "connect"))
    connect_command(arg);

  else if(command[0] == 'b' && is_abrev(command, "bell"))
    bell_command();

  else if(command[0] == 'c' && is_abrev(command, "char"))
    char_command(arg);

  else if(command[0] == 's' && is_abrev(command, "status"))
    status_command(arg);

  else if(command[0] == 't' && is_abrev(command, "tabadd"))
    tabadd_command(arg);

  else if(command[0] == 't' && is_abrev(command, "tabdel"))
    tabdel_command(arg);

  else if( command[0] == 'm' && is_abrev(command, "multiaction"))
    MultiactionCommand(arg);

  else if( command[0] == 'm' && is_abrev(command, "multihighlight"))
    MultiHlightCommand(arg);

  else if( command[0] == 'v' && is_abrev(command, "verbatim"))
    verbatim_command(arg);

  else if(command[0] == 'n' && is_abrev(command, "nop")); 

  else {
    tintin_puts2(rs::rs(1145));
  }
  return;
}


/**********************************************/
/* get all arguments - don't remove "s and \s */
/**********************************************/
char *get_arg_all(char *s, char *arg)
{
  /* int inside=FALSE; */
  int nest=0;
  s=space_out(s);
  while(*s) {

    if(*s=='\\') {
      *arg++=*s++;
      if(*s)
	*arg++=*s++;
    }


    // else if(*s==';' && nest<1) {
	else if(*s==cCommandDelimiter && nest<1) {
	break;
    }

    else if(*s==DEFAULT_OPEN) {
      nest++;
      *arg++=*s++;
    }

    else if(*s==DEFAULT_CLOSE) {
      nest--;
      *arg++=*s++;
    }

    else
      *arg++=*s++;
  }

  *arg='\0';
  return s;
}

/**************************************/
/* get all arguments - remove "s etc. */
/* Example:                           */
/* In: "this is it" way way hmmm;     */
/* Out: this is it way way hmmm       */ 
/**************************************/
char *get_arg_with_spaces(char * s, char* arg)
{
  int nest=0;
  /* int inside=FALSE; */

  s=space_out(s);
  while(*s) {

    if(*s=='\\') {
      if(*++s)
	*arg++=*s++;
    }


    // else if(*s==';' && nest==0) {
	else if(*s==cCommandDelimiter && nest==0) {
	break;
    }
    else if(*s==DEFAULT_OPEN) {
      nest++;
      *arg++=*s++;
    }
    else if(*s==DEFAULT_CLOSE) {
      *arg++=*s++;
      nest--;
    }
    else
      *arg++=*s++;
  }
*arg='\0'; 
return s;
}
/********************/
/* my own routine   */
/********************/
char *get_arg_in_braces(char *s, char *arg, int flag)
{
   int nest=0;
   char *ptr;
   s=space_out(s);
   ptr=s;
   if (*s!=DEFAULT_OPEN) {
     if (flag==0) 
       s=get_arg_stop_spaces(ptr,arg);
     else
       s=get_arg_with_spaces(ptr,arg);
     return s;
   }
   s++;
     while(*s!='\0' && !(*s==DEFAULT_CLOSE && nest==0)) {
       if(*s==DEFAULT_OPEN) {
         nest++;
       }
     
       else if(*s==DEFAULT_CLOSE) {
         nest--;
       }                                    
       *arg++=*s++;
     }
   if (!*s)
     tintin_puts2(rs::rs(1146));
   else
     s++;
   *arg='\0';
   return s;
   
}
/**********************************************/
/* get one arg, stop at spaces                */
/* remove quotes                              */
/**********************************************/
char *get_arg_stop_spaces(char *s, char *arg)
{
  int inside=FALSE;
  s=space_out(s);
  
  while(*s) {
    if(*s=='\\') {
      if(*++s)
	*arg++=*s++;
    }
    else if(*s=='"') {
      s++;
      inside=!inside;
    }

    // else if(*s==';') {
	else if(*s==cCommandDelimiter) {
      if(inside)
	*arg++=*s++;
      else
	break;
    }

    else if(!inside && *s==' ')
      break;
    else
      *arg++=*s++;
  }

  *arg='\0';
  return s;
}

/*********************************************/
/* spaceout - advance ptr to next none-space */
/* return: ptr to the first none-space       */
/*********************************************/ 
char *space_out(char *s)
{
  while(isspace(*s))
    s++;
  return s;
}

/************************************/
/* send command+argument to the mud */
/************************************/
void write_com_arg_mud(char* command, char* argument)
{
    char outtext[BUFFER_SIZE];
    int i;

    check_insert_path(command);
    strncpy(outtext, command, BUFFER_SIZE);
    if(*argument) {
      strncat(outtext, " ", BUFFER_SIZE-strlen(command)-1); 
      strncat(outtext, argument, BUFFER_SIZE-strlen(command)-2);
    }
    write_line_mud(outtext);
    i=strlen(outtext);
    outtext[i++]='\r';
    outtext[i++]='\n';
/*    if(hLogFile)
        WriteToLog2(outtext, i); 
*/
}
