Logo Search packages:      
Sourcecode: aime version File versions  Download package

inp_handler.cpp

/**********************************************************************
 ** inp_handler class: handles input assuming a single process design, so
 **                    that the game doesn't hang waiting on a response from
 **                    a player.
 **
 **   
 ** Last reviewed:
 **
 **
 ** Copyright (C) 2000 George Noel (Slate)
 **
 **   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 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 (in the docs dir); if not, write to the Free
 **   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 **    
 **********************************************************************/

#ifndef INP_HANDLER_C
#define INP_HANDLER_C

#include "config.h"
#include "sysdep.h"
#include "inp_handler.h"
#include "inp_funct.h"
#include "mudtypes.h"
#include "strings.h"
#include "newfuncts.h"
#include "bulletin.h"
#include "utils.h"

   char echo_off[] =
    {
      (char) IAC,
      (char) WILL,
      (char) TELOPT_ECHO,
      (char) 0
   };

   char echo_on[] =
    {
      (char) IAC,
      (char) WONT,
      (char) TELOPT_ECHO,
      (char) TELOPT_NAOFFD,
      (char) TELOPT_NAOCRD,
      (char) 0
   };

/***********************************************************************
 ** Inp_Handler (constructor) - creates the input handler
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/
   
Inp_Handler::Inp_Handler()
{
   input_stack = NULL;
   pop_handler = NULL;
   last_invis = 0;
}


/***********************************************************************
 ** Inp_Handler (destructor) - destroys this input handler
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/
   
Inp_Handler::~Inp_Handler()
{
   handler_struct *tmp_handler;

   tmp_handler = input_stack;
   while (input_stack != NULL)
   {
      input_stack = input_stack->next_handler;
      if ((tmp_handler->delete_prompt) && (tmp_handler->the_prompt != NULL))
         delete tmp_handler->the_prompt;

      if (tmp_handler->del_data)
         switch(tmp_handler->data_type)
         {
            case HANDLER_DATA_INT:
               if (tmp_handler->the_data.the_int != NULL)
                  delete_int(tmp_handler->the_data.the_int);
               break;

            case HANDLER_DATA_PAGER:
               if (tmp_handler->the_data.the_pager != NULL)
                  delete_Pager(tmp_handler->the_data.the_pager);
               break;

            case HANDLER_DATA_EDITOR:
             if (tmp_handler->the_data.the_editor != NULL)
                  delete tmp_handler->the_data.the_editor;
               break;

            case HANDLER_DATA_MAILER:
             if (tmp_handler->the_data.the_mailer != NULL)
                  delete_Mailer(tmp_handler->the_data.the_mailer);
               break;

            case HANDLER_DATA_BULLETIN:
             if (tmp_handler->the_data.the_board != NULL)
                  delete_Bulletin(tmp_handler->the_data.the_board);
               break;

            case HANDLER_DATA_BULLENTRY:
             if (tmp_handler->the_data.the_entry != NULL)
                  delete_BullEntry(tmp_handler->the_data.the_entry);
               break;

            default:
               break;
         }

      delete_handler_struct(tmp_handler);
      tmp_handler = input_stack;
   }
}


/***********************************************************************
 ** push_input_handler - Pushes an input handler onto the input handler
 **                      stack 
 **
 ** Parameters: funct_name - the name of the function we are pushing onto
 **                          the stack
 **             prompt - the prompt for this input handler
 **             del_prompt - if we should delete the prompt when we delete
 **                          the input handler, 1 for yes, 0 for no
 **             data_type - the type of data this will hold.
 **                         Current values:
 **                            0 for None
 **                            1 for Integer
 **                            2 for Pager
 **             del_data - delete the data on pop?
 **
 ** Returns: 1 if success, -1 if failed
 **
 ***********************************************************************/
   
int Inp_Handler::push_input_handler(Inp_Func funct_name, Strings *prompt, 
                             int del_prompt, int data_type, int del_data)
{
   handler_struct *new_handler;
   handler_struct *temp_handler = NULL;;

   new_handler = new handler_struct;
   new_handler->the_command = funct_name;
   new_handler->pop_command = NULL;
   new_handler->pop_string = NULL;
   new_handler->the_prompt = prompt;
   new_handler->delete_prompt = del_prompt;
   new_handler->data_type = data_type;
   new_handler->del_data = del_data;
   new_handler->lines_per_handle = 1;
   new_handler->input_vis = 1;

   // If the last prompt had echo off markers on it, make sure we turn echo back on
   if (last_invis)
   {
         Strings holder;

         holder = new_handler->the_prompt;
         new_handler->the_prompt->sprintf("%s%s", echo_on, holder.str_show());
         last_invis = 0;
   }
   

   switch(data_type)
   {
      case HANDLER_DATA_INT:
         new_handler->the_data.the_int = NULL;
         break;

      case HANDLER_DATA_PAGER:
         new_handler->the_data.the_pager = NULL;
         break;

      case HANDLER_DATA_EDITOR:
         new_handler->the_data.the_editor = NULL;
         break;

      case HANDLER_DATA_MAILER:
         new_handler->the_data.the_mailer = NULL;
         break;

      case HANDLER_DATA_BULLETIN:
         new_handler->the_data.the_board = NULL;
         break;

      case HANDLER_DATA_BULLENTRY:
         new_handler->the_data.the_entry = NULL;
         break;

      case HANDLER_DATA_NONE:
      default:
         break;
   }
   new_handler->next_handler = NULL;

   temp_handler = input_stack;
   input_stack = new_handler;
   new_handler->next_handler = temp_handler;

   return 1;
}


/***********************************************************************
 ** push_input_handler - Pushes an input handler onto the input handler
 **                      stack 
 **
 ** Parameters: funct_name - the name of the function we are pushing onto
 **                          the stack
 **             prompt - the prompt for this input handler
 **             del_prompt - if we should delete the prompt when we delete
 **                          the input handler, 1 for yes, 0 for no
 **             data_type - the type of data this will hold.
 **                         Current values:
 **                            0 for None
 **                            1 for Integer
 **                            2 for Pager
 **             del_data - delete the data on pop?
 **             lines_per_handle - how many lines of input to pass per 
 **                                execution of the input handler
 **
 ** Returns: 1 if success, -1 if failed
 **
 ***********************************************************************/
   
int Inp_Handler::push_input_handler(Inp_Func funct_name, Strings *prompt, 
         int del_prompt, int data_type, int del_data, int lines_per_handle)
{
   handler_struct *new_handler;
   handler_struct *temp_handler = NULL;;

   new_handler = new handler_struct;
   new_handler->the_command = funct_name;
   new_handler->pop_command = NULL;
   new_handler->pop_string = NULL;
   new_handler->the_prompt = prompt;
   new_handler->delete_prompt = del_prompt;
   new_handler->data_type = data_type;
   new_handler->del_data = del_data;
   new_handler->lines_per_handle = lines_per_handle;
   new_handler->input_vis = 1;

    // If the last prompt had echo off markers on it, make sure we turn echo back on
   if (last_invis)
   {
         Strings holder;

         holder = new_handler->the_prompt;
         new_handler->the_prompt->sprintf("%s%s", echo_on, holder.str_show());
         last_invis = 0;
   }
  
   switch(data_type)
   {
      case HANDLER_DATA_INT:
         new_handler->the_data.the_int = NULL;
         break;

      case HANDLER_DATA_PAGER:
         new_handler->the_data.the_pager = NULL;
         break;

      case HANDLER_DATA_EDITOR:
         new_handler->the_data.the_editor = NULL;
         break;

      case HANDLER_DATA_MAILER:
         new_handler->the_data.the_mailer = NULL;
         break;

      case HANDLER_DATA_BULLETIN:
         new_handler->the_data.the_board = NULL;
         break;

      case HANDLER_DATA_BULLENTRY:
         new_handler->the_data.the_entry = NULL;
         break;

      case HANDLER_DATA_NONE:
      default:
         break;
   }
   new_handler->next_handler = NULL;

   temp_handler = input_stack;
   input_stack = new_handler;
   new_handler->next_handler = temp_handler;

   return 1;
}


/***********************************************************************
 ** push_input_handler - Pushes an input handler onto the input handler
 **                      stack 
 **
 ** Parameters: funct_name - the name of the function we are pushing onto
 **                          the stack
 **             prompt - the prompt for this input handler
 **             data_type - the type of data this will hold.
 **                         Current values:
 **                            0 for None
 **                            1 for Integer
 **                            2 for Pager
 **
 ** Returns: 1 if success, -1 if failed
 **
 ***********************************************************************/
   
int Inp_Handler::push_input_handler(Inp_Func funct_name, char *prompt,
                                                      int data_type)
{
   Strings *new_string;
   int     results;

   new_string = new Strings(prompt);
   results = push_input_handler(funct_name, new_string, 1, data_type, 1);
   if (results <= 0)
      delete new_string;
   return results; 
}


/***********************************************************************
 ** replace_input_handler - Pops from the stack, then pushes an input handler
 **                         onto the stack
 **
 ** Parameters: funct_name - the name of the function we are pushing onto
 **                          the stack
 **             prompt - the prompt for this input handler
 **             data_type - the type of data this will hold.
 **                         Current values:
 **                            0 for None
 **                            1 for Integer
 **                            2 for Pager
 **
 ** Returns: 1 if success, -1 if failed
 **
 ***********************************************************************/
   
int Inp_Handler::replace_input_handler(Inp_Func funct_name, char *prompt, 
                                                             int data_type)
{
   if (pop_input_handler() <= 0)
      return -1;
  
   return push_input_handler(funct_name, prompt, data_type);
}


/***********************************************************************
 ** replace_input_handler - Pops from the stack, then pushes an input handler
 **                         onto the stack
 **
 ** Parameters: funct_name - the name of the function we are pushing onto
 **                          the stack
 **             prompt - the prompt for this input handler
 **             del_prompt - if we should delete the prompt when we delete
 **                          the input handler, 1 for yes, 0 for no
 **             data_type - the type of data this will hold.
 **                         Current values:
 **                            0 for None
 **                            1 for Integer
 **                            2 for Pager
 **             del_data - should we delete the data on pop
 **
 ** Returns: 1 if success, -1 if failed
 **
 ***********************************************************************/
   
int Inp_Handler::replace_input_handler(Inp_Func funct_name, Strings *prompt, 
                        int del_prompt, int data_type, int del_data)
{
   if (pop_input_handler() <= 0)
      return -1;
  
   return push_input_handler(funct_name, prompt, del_prompt, 
                                                    data_type, del_data);
}


/***********************************************************************
 ** replace_input_handler - Pops from the stack, then pushes an input handler
 **                         onto the stack
 **
 ** Parameters: funct_name - the name of the function we are pushing onto
 **                          the stack
 **             prompt - the prompt for this input handler
 **             del_prompt - if we should delete the prompt when we delete
 **                          the input handler, 1 for yes, 0 for no
 **             data_type - the type of data this will hold.
 **                         Current values:
 **                            0 for None
 **                            1 for Integer
 **                            2 for Pager
 **             del_data - should we delete the data on pop
 **             lines_per_handle - how many lines we get when executing
 **                                the input handler
 **
 ** Returns: 1 if success, -1 if failed
 **
 ***********************************************************************/
   
int Inp_Handler::replace_input_handler(Inp_Func funct_name, Strings *prompt, 
          int del_prompt, int data_type, int del_data, int lines_per_handle)
{
   if (pop_input_handler() <= 0)
      return -1;
  
   return push_input_handler(funct_name, prompt, del_prompt, 
                               data_type, del_data, lines_per_handle);
}


/***********************************************************************
 ** pop_input_handler - Removes an input handler from the stack 
 **
 ** Parameters: None
 **
 ** Returns: 1 if success, -1 if failed
 **
 ***********************************************************************/
   
int Inp_Handler::pop_input_handler(void)
{
   Pop_Func temp_command;

   handler_struct *temp_handler = NULL;

   if (input_stack == NULL)
      return -1;

   temp_handler = input_stack->next_handler;
   if ((input_stack->delete_prompt) && (input_stack->the_prompt != NULL))
      delete input_stack->the_prompt;

   if (input_stack->del_data)
      switch(input_stack->data_type)
      {
         case HANDLER_DATA_INT:
            if (input_stack->the_data.the_int != NULL)
               delete_int(input_stack->the_data.the_int);
            break;

         case HANDLER_DATA_PAGER:
            if (input_stack->the_data.the_pager != NULL)
               delete_Pager(input_stack->the_data.the_pager);
            break;

         case HANDLER_DATA_EDITOR:
            if (input_stack->the_data.the_editor != NULL)
               delete input_stack->the_data.the_editor;
            break;

         case HANDLER_DATA_MAILER:
            if (input_stack->the_data.the_mailer != NULL)
               delete_Mailer(input_stack->the_data.the_mailer);
            break;

         case HANDLER_DATA_BULLETIN:
            if (input_stack->the_data.the_board != NULL)
               delete_Bulletin(input_stack->the_data.the_board);
            break;

         case HANDLER_DATA_BULLENTRY:
            if (input_stack->the_data.the_entry != NULL)
               delete_BullEntry(input_stack->the_data.the_entry);
            break;

         default:
            break;
      }

   pop_handler = input_stack;
   input_stack = temp_handler;

   if ((pop_handler != NULL) && (pop_handler->pop_command != NULL))
   {
      temp_command = pop_handler->pop_command;
      temp_command(this, pop_handler->pop_identifier1.str_show(), 
           pop_handler->pop_identifier2.str_show(), 
           pop_handler->pop_identifier3.str_show(), pop_handler->pop_string);
      if (pop_handler != NULL)
      {
         if (pop_handler->pop_string != NULL)
       {
            delete pop_handler->pop_string;
            pop_handler->pop_string = NULL;
       }
      }
   }

   delete_handler_struct(pop_handler);
   pop_handler = NULL;

   if (input_stack == NULL)
   {
      printf("eep!!! popped last input handler!!\n");   
      RAISE(11);
   }
   return 1;
}


/***********************************************************************
 ** exec_input_handler - executes the function assigned to the top input 
 **                      handler in the stack
 **
 ** Parameters: the_user - the player or builder who is executing this
 **             the_input - the input string to be passed into
 **
 ** Returns: value of the function if successful, -1 if failed
 **
 ***********************************************************************/
   
int Inp_Handler::exec_input_handler(MudObject *the_user, char *the_input)
{
   Inp_Func temp_command;
   Strings  holder;
   char     *tmp_str;

   if (input_stack == NULL)
   {
      fault("Player with empty input stack!  Possibly fatal!\n");
      return -1;
   }

   // If the input is null, treat it like a carriage return
/*   if (the_input == NULL)
      return 0; */

   /* if this is not the repeat order, then save it */
   holder = the_input;

   // A little tweak for empty strings so it doesn't have a NULL string sent in
   if (holder.str_show() != NULL)
   {
     tmp_str = holder.str_show();
     while ((*tmp_str) && (*tmp_str != ' ') && (*tmp_str != '\r') && 
          (*tmp_str != '\n'))
       tmp_str++;
     *tmp_str = '\0';
     if ((STRNCASECMP(holder.str_show(), "repeat", holder.str_len())) &&
       ((*(holder.str_show()) != '!')))
     {
       input_stack->last_command = the_input;
     }
   }
   temp_command = input_stack->the_command;

   return temp_command(the_user, the_input);
}


/***********************************************************************
 ** repeat_last_command - executes the last command entered with the current
 **                       input handler
 **
 ** Parameters: the_user - the player or builder who is executing this
 **
 ** Returns: value of the function if successful, -1 if failed
 **
 ***********************************************************************/
   
int Inp_Handler::repeat_last_command(MudObject *the_user)
{
   Inp_Func temp_command;

   if (input_stack == NULL)
      return -1;

   if ((input_stack->last_command.str_show() == NULL) ||
       (input_stack->last_command.str_len() == 0))
      return 0;

   temp_command = input_stack->the_command;
   return temp_command(the_user, input_stack->last_command.str_show());
}


/***********************************************************************
 ** get_prompt - gets the prompt of the current input handler
 **
 ** Parameters: None
 **
 ** Returns: a pointer to the prompt of the first input handler
 **
 ***********************************************************************/
   
char *Inp_Handler::get_prompt(void)
{
   if (input_stack == NULL)
      return NULL;
 
   if (input_stack->the_prompt == NULL)
      return "";

   return (input_stack->the_prompt)->str_show();
}


/***********************************************************************
 ** get_data - gets the data value for this input handler
 **
 ** Parameters: None
 **
 ** Returns: the counter number
 **
 ***********************************************************************/
   
void *Inp_Handler::get_data(void)
{
   switch(input_stack->data_type)
   {
      case HANDLER_DATA_INT:
         return (void *) (input_stack->the_data.the_int);

      case HANDLER_DATA_PAGER:
         return (void *) (input_stack->the_data.the_pager);

      case HANDLER_DATA_EDITOR:
         return (void *) (input_stack->the_data.the_editor);

      case HANDLER_DATA_MAILER:
         return (void *) (input_stack->the_data.the_mailer);

      case HANDLER_DATA_BULLETIN:
         return (void *) (input_stack->the_data.the_board);

      case HANDLER_DATA_BULLENTRY:
         return (void *) (input_stack->the_data.the_entry);

      case HANDLER_DATA_NONE:
      default:
         return NULL;
   }
}

/***********************************************************************
 ** get_pop_data - gets the data value for the input handler in the pop
 **                portion of the input handler (i.e. it is being popped)
 **
 ** Parameters: None
 **
 ** Returns: the counter number
 **
 ***********************************************************************/
   
void *Inp_Handler::get_pop_data(void)
{
   if (pop_handler == NULL)
      return NULL;

   switch(pop_handler->data_type)
   {
      case HANDLER_DATA_INT:
         return (void *) (pop_handler->the_data.the_int);

      case HANDLER_DATA_PAGER:
         return (void *) (pop_handler->the_data.the_pager);

      case HANDLER_DATA_EDITOR:
         return (void *) (pop_handler->the_data.the_editor);

      case HANDLER_DATA_MAILER:
         return (void *) (pop_handler->the_data.the_mailer);

      case HANDLER_DATA_BULLETIN:
         return (void *) (pop_handler->the_data.the_board);

      case HANDLER_DATA_BULLENTRY:
         return (void *) (pop_handler->the_data.the_entry);

      case HANDLER_DATA_NONE:
      default:
         return NULL;
   }
}

/***********************************************************************
 ** set_data - sets the data to a specified data structure.  The data
 **            structure it expects was predefined when the input handler
 **            was pushed on the stack and it can't be changed
 **
 ** Parameters: the_data - the data to set this to
 **
 ** Returns: Nothing
 **
 ***********************************************************************/
   
void Inp_Handler::set_data(void *the_data)
{
   switch(input_stack->data_type)
   {
      case HANDLER_DATA_INT:
         input_stack->the_data.the_int = (int *) the_data;

      case HANDLER_DATA_PAGER:
         input_stack->the_data.the_pager = (Pager *) the_data;

      case HANDLER_DATA_EDITOR:
         input_stack->the_data.the_editor = (Editor *)the_data;

      case HANDLER_DATA_MAILER:
         input_stack->the_data.the_mailer = (Mailer *)the_data;

      case HANDLER_DATA_BULLETIN:
         input_stack->the_data.the_board = (Bulletin *)the_data;

      case HANDLER_DATA_BULLENTRY:
         input_stack->the_data.the_entry = (BullEntry *)the_data;

      case HANDLER_DATA_NONE:
      default:
         break;
   }
}


/***********************************************************************
 ** get_lines_per_handle - gets the max lines that should be passed per
 **                        execution of the handler
 **
 ** Parameters: None
 **
 ** Returns: the number of lines
 **
 ***********************************************************************/
   
int Inp_Handler::get_lines_per_handle()
{
   return input_stack->lines_per_handle;
}


/***********************************************************************
 ** add_pop_function - adds a function to be executed when the input
 **                    handler is popped.  Will delete the string when
 **                    the function is completed
 **
 ** Parameters: the_function - the function to run
 **             the_id - an identifier to pass to the function, up to the
 **                      function to use it how it sees fit
 **             the_string - a string object to pass to the function
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Inp_Handler::add_pop_function(Pop_Func the_function, char *id1, char *id2,
                                               char *id3, Strings *the_string)
{
   if (input_stack == NULL)
      return -1;

   input_stack->pop_command = the_function;
   input_stack->pop_identifier1 = id1;
   input_stack->pop_identifier2 = id2;
   input_stack->pop_identifier3 = id3;
   input_stack->pop_string = the_string;
   return 1;
}


/***********************************************************************
 ** swap_prompt - swaps the current prompt with a new prompt
 **
 ** Parameters: new_prompt - the new prompt to put in its place
 **
 **
 ***********************************************************************/
   
void Inp_Handler::swap_prompt(Strings *new_prompt)
{
   Strings holder;

   if ((new_prompt == NULL) || (input_stack == NULL))
      return;


   holder = new_prompt->str_show();
   input_stack->the_prompt = new_prompt;

   if (input_stack->input_vis)
   {
      input_stack->the_prompt->sprintf("%s%s", holder.str_show(), echo_off);
   }
}


/***********************************************************************
 ** has_handler - does this input handler stack have the input handler
 **               with the function specified?
 **
 ** returns:  1 for has it, 0 for not
 **
 ***********************************************************************/
int Inp_Handler::has_handler(Inp_Func funct_name) 
{
   handler_struct *tmp_handler;

   tmp_handler = input_stack;
   while (tmp_handler != NULL)
   {
      if (funct_name == tmp_handler->the_command)
         return 1;

      tmp_handler = tmp_handler->next_handler;
   }
   return 0;
}


/***********************************************************************
 ** has_handler - does this input handler stack have the input handler
 **               with the function specified?
 **
 ** returns:  1 for has it, 0 for not
 **
 ***********************************************************************/
Inp_Func Inp_Handler::get_command() 
{
   return input_stack->the_command;
}


/***********************************************************************
 ** remove_pop_function - removes the pop function from the handler so 
 **                       when the handler is popped, it won't run it
 **
 ***********************************************************************/
void Inp_Handler::remove_pop_function() 
{
   input_stack->pop_command = NULL;
   delete input_stack->pop_string;
   input_stack->pop_string = NULL;
}

/***********************************************************************
 ** set_delete_data - sets it so the data will be deleted on pop
 **
 ***********************************************************************/
void Inp_Handler::set_delete_data() 
{
   input_stack->del_data = 1;
}


/***********************************************************************
 ** set_input_invis - makes it so what the user types does not appear on
 **                   their screen
 ***********************************************************************/

void Inp_Handler::set_input_invis()
{
   Strings holder;

   input_stack->input_vis = 0;

   holder = input_stack->the_prompt;
   input_stack->the_prompt->sprintf("%s%s", holder.str_show(), echo_off);
   last_invis = 1;
}

/***********************************************************************
 ** set_last_invis - tricks the input handler into putting a turn echo on
 **                  command in the prompt
 ***********************************************************************/

void Inp_Handler::set_last_invis()
{
  last_invis = 1;
}

#endif


Generated by  Doxygen 1.6.0   Back to index