lima-1.0b5/
lima-1.0b5/driver/
lima-1.0b5/driver/ChangeLog.old/
lima-1.0b5/driver/Win32/
lima-1.0b5/driver/compat/
lima-1.0b5/driver/include/
lima-1.0b5/driver/testsuite/
lima-1.0b5/driver/testsuite/clone/
lima-1.0b5/driver/testsuite/command/
lima-1.0b5/driver/testsuite/data/
lima-1.0b5/driver/testsuite/etc/
lima-1.0b5/driver/testsuite/include/
lima-1.0b5/driver/testsuite/inherit/
lima-1.0b5/driver/testsuite/inherit/master/
lima-1.0b5/driver/testsuite/log/
lima-1.0b5/driver/testsuite/single/
lima-1.0b5/driver/testsuite/single/tests/compiler/
lima-1.0b5/driver/testsuite/single/tests/efuns/
lima-1.0b5/driver/testsuite/single/tests/operators/
lima-1.0b5/driver/testsuite/u/
lima-1.0b5/driver/tmp/
lima-1.0b5/etc/
lima-1.0b5/lib/WWW/help/
lima-1.0b5/lib/cmds/
lima-1.0b5/lib/cmds/create/
lima-1.0b5/lib/cmds/player/attic/
lima-1.0b5/lib/contrib/bboard/
lima-1.0b5/lib/contrib/boards/
lima-1.0b5/lib/contrib/marriage/
lima-1.0b5/lib/contrib/roommaker/
lima-1.0b5/lib/contrib/transient_effect/
lima-1.0b5/lib/daemons/channel/
lima-1.0b5/lib/daemons/imud/
lima-1.0b5/lib/data/
lima-1.0b5/lib/data/config/
lima-1.0b5/lib/data/links/
lima-1.0b5/lib/data/news/
lima-1.0b5/lib/data/players/
lima-1.0b5/lib/data/secure/
lima-1.0b5/lib/domains/
lima-1.0b5/lib/domains/std/2.4.5/maze1/
lima-1.0b5/lib/domains/std/2.4.5/npc/
lima-1.0b5/lib/domains/std/2.4.5/post_dir/
lima-1.0b5/lib/domains/std/2.4.5/sub/
lima-1.0b5/lib/domains/std/camera/
lima-1.0b5/lib/domains/std/config/
lima-1.0b5/lib/domains/std/cult/
lima-1.0b5/lib/domains/std/effects/
lima-1.0b5/lib/domains/std/misc/
lima-1.0b5/lib/domains/std/monsters/
lima-1.0b5/lib/domains/std/recorder/
lima-1.0b5/lib/domains/std/rooms/
lima-1.0b5/lib/domains/std/rooms/beach/
lima-1.0b5/lib/domains/std/rooms/labyrinth/
lima-1.0b5/lib/domains/std/school/
lima-1.0b5/lib/domains/std/school/O/
lima-1.0b5/lib/domains/std/spells/
lima-1.0b5/lib/domains/std/spells/stock-mage/
lima-1.0b5/lib/domains/std/spells/stock-priest/
lima-1.0b5/lib/help/
lima-1.0b5/lib/help/admin/
lima-1.0b5/lib/help/hints/General_Questions/
lima-1.0b5/lib/help/hints/Pirate_Quest/
lima-1.0b5/lib/help/player/
lima-1.0b5/lib/help/player/bin/
lima-1.0b5/lib/help/player/quests/
lima-1.0b5/lib/help/wizard/
lima-1.0b5/lib/help/wizard/coding/guilds/
lima-1.0b5/lib/help/wizard/coding/rooms/
lima-1.0b5/lib/help/wizard/lib/daemons/
lima-1.0b5/lib/help/wizard/lib/lfun/
lima-1.0b5/lib/help/wizard/lib/std/
lima-1.0b5/lib/help/wizard/mudos_doc/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/interactive/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/concepts/
lima-1.0b5/lib/help/wizard/mudos_doc/driver/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/arrays/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/buffers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/compile/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/filesystem/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/floats/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/functions/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/general/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mappings/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mixed/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/numbers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/constructs/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/types/
lima-1.0b5/lib/include/driver/
lima-1.0b5/lib/log/
lima-1.0b5/lib/obj/admtool/
lima-1.0b5/lib/obj/admtool/internal/
lima-1.0b5/lib/obj/admtool/mudinfo/
lima-1.0b5/lib/obj/admtool/secure/
lima-1.0b5/lib/obj/secure/
lima-1.0b5/lib/obj/secure/cmd/
lima-1.0b5/lib/obj/secure/mailers/
lima-1.0b5/lib/obj/secure/shell/
lima-1.0b5/lib/obj/secure/shell/classes/
lima-1.0b5/lib/obj/tasktool/
lima-1.0b5/lib/obj/tasktool/internal/
lima-1.0b5/lib/open/
lima-1.0b5/lib/secure/
lima-1.0b5/lib/secure/cgi/
lima-1.0b5/lib/secure/modules/
lima-1.0b5/lib/secure/simul_efun/
lima-1.0b5/lib/std/adversary/
lima-1.0b5/lib/std/adversary/advancement/
lima-1.0b5/lib/std/adversary/armor/
lima-1.0b5/lib/std/adversary/blows/
lima-1.0b5/lib/std/adversary/death/
lima-1.0b5/lib/std/adversary/formula/
lima-1.0b5/lib/std/adversary/health/
lima-1.0b5/lib/std/adversary/pulse/
lima-1.0b5/lib/std/adversary/wield/
lima-1.0b5/lib/std/classes/event_info/
lima-1.0b5/lib/std/container/
lima-1.0b5/lib/std/living/
lima-1.0b5/lib/std/modules/contrib/
lima-1.0b5/lib/std/patterns/
lima-1.0b5/lib/std/race/
lima-1.0b5/lib/std/race/restricted/
lima-1.0b5/lib/std/room/
lima-1.0b5/lib/tmp/
lima-1.0b5/lib/trans/
lima-1.0b5/lib/trans/admincmds/
lima-1.0b5/lib/trans/obj/
lima-1.0b5/lib/wiz/
/* Do not remove the headers from this file! see /USAGE for more info. */

/*
** inputsys.c
**
** Handles the input system processing for the player.
**
** 94-Aug-11.  Deathblade.  Created.
** 95-Apr-29.  Deathblade.  Converted to function ptrs.
** 95-May-20.  Rust.        Added char mode support.
** 95-Jul-20.  Rust. 	Added clear_input_stack for sw_user.c 's benefit.
** 95-Jul-20.  Beek.    Modified clear_input_stack to be more robust and
			to allow objects to clean up
** 95-Jul-20.  Beek.    Prompts can be strings as well as functions
*/

#include <driver/function.h>

string query_userid();
void start_shell();
mixed query_privilege();


#define INPUT_NORMAL	0
#define INPUT_AUTO_POP	1
#define INPUT_CHAR_MODE	2

class input_info
{
    function	input_func;
    mixed	prompt;
    int		secure;
    function	return_to_func;
    int		input_type;
    int         lock;
}
private nosave class input_info *	modal_stack = ({ });

private nosave int	dispatching_to;

private nomask void dispatch_modal_input(string str);


private nomask int create_handler()
{
    /*
    ** Attempt to create a handler (the user has none!)
    */
    start_shell();

    if ( !sizeof(modal_stack) )
    {
	write("Sorry, but I can't process your typing for some reason.\n"
	  "Please log in and try again or send mail to " ADMIN_EMAIL "\n"
	  "if you continue to have problems.\n");
	destruct(this_object());
	return 1;
    }

    return 0;
}

private nomask class input_info get_top_handler(int require_handler)
{
    int some_popped = 0;

    while ( sizeof(modal_stack) )
    {
	class input_info info;

	/*
	** Get the top of the stack and make sure the func is valid
	*/
	info = modal_stack[<1];
	if ( !(functionp(info->input_func) & FP_OWNER_DESTED) )
	{
	    if ( some_popped && info->return_to_func )
		evaluate(info->return_to_func);
	    return info;
	}

	modal_stack = modal_stack[0..<2];
	some_popped = 1;
    }

    if ( !require_handler || create_handler() )
	return 0;

    return modal_stack[<1];
}

private nomask class input_info get_bottom_handler()
{
    while ( sizeof(modal_stack) )
    {
	class input_info info;

	/*
	** Get the bottom of the stack and make sure the func is valid
	*/
	info = modal_stack[0];
	if ( !(functionp(info->input_func) & FP_OWNER_DESTED) )
	    return info;

	modal_stack = modal_stack[1..];
    }

    if ( create_handler() )
	return 0;

    return modal_stack[0];
}


/*
** push_handler()
**
** Push a handler onto the modal stack.  The stack is grown as
** necessary to accomodate the new element.
*/
private nomask void push_handler(function input_func,
				 mixed prompt,
				 int secure,
				 function return_to_func,
				 int input_type,
				 int lock
				 )
{
    class input_info info;

    info = new(class input_info);
    info->input_func		= input_func;
    info->prompt		= prompt;
    info->secure		= secure;
    info->return_to_func	= return_to_func;
    info->input_type		= input_type;
    info->lock                  = lock;

    modal_stack += ({ info });

    if ( info->input_type == INPUT_CHAR_MODE )
    {
	efun::get_char((: dispatch_modal_input :), info->secure | 2);
    }
    else	
    {
	efun::input_to((: dispatch_modal_input :), info->secure | 2);
    }
}

/*
** modal_push()
** modal_pop()
** modal_func()
**
** Handle the pushing, popping, and altering of the input handlers
** on the stack.
*/
varargs nomask void modal_push(function input_func,
			       mixed prompt,
			       int secure,
			       function return_to_func,
			       int lock
  
)
{
  push_handler(input_func, prompt, secure, return_to_func,
	       INPUT_NORMAL,lock);
}

nomask void modal_pop()
{
    class input_info info;

    /*
    ** Erase/pop the handler at the top level
    */
    //### work around driver bug with [0..<2] on alphas. it doesn't
    //### work for the last element
    if (sizeof(modal_stack)==1) modal_stack=({ }); else
	modal_stack = modal_stack[0..<2];

    /*
    ** If there is something in the stack, then execute its return_to_func
    ** now that we have returned to this input handler.
    **
    ** Note: during login, we will sometimes empty the input stack, so
    ** we need to use get_top_handler() carefully -- tell it not to require
    ** a handler.  We want it for validating any TOS that may be there.
    */
    if ( (info = get_top_handler(0)) && info->return_to_func )
	evaluate(info->return_to_func);
}

varargs nomask void modal_func(function input_func,
			       mixed prompt,
			       int secure,
			       int lock)
{
    modal_stack[<1]->input_func = input_func;
    if ( prompt )
	modal_stack[<1]->prompt = prompt;
    modal_stack[<1]->secure = secure;
    modal_stack[<1]->lock=lock;
}

protected nomask void modal_recapture()
{
    class input_info info;
    string prompt;

    if ( !(info = get_top_handler(1)) )
	return;

    /* char handlers don't have prompts */
    if ( info->input_type != INPUT_CHAR_MODE && info->prompt )
    {
	prompt = evaluate(info->prompt);
	if ( prompt )
	    write(prompt);
    }
    if ( info->input_type == INPUT_CHAR_MODE )
    {
	efun::get_char((: dispatch_modal_input :), info->secure | 2);
    }
    else
    {
	efun::input_to((: dispatch_modal_input :), info->secure | 2);
    }
}

/*
** modal_simple()
**
** This function is used for very simple input handling (such as
** retrieving a single line of input).  It is much like modal_push()
** but the handler with automatically be popped after the first line
** of input is dispatched.
**
** This can be used as a direct replacement for input_to().
**
** NOTE: for multiple inputs, the standard push/pop is encouraged
** for efficiency reasons.
*/
varargs nomask void modal_simple(function input_func, 
				 mixed prompt,
				 int secure,
				 int lock)
{
  push_handler(input_func, prompt, secure, 0, INPUT_AUTO_POP,lock);
}

/*
** modal_pass()
**
** Pass a string of input to the next input handler.  This is used
** by a handler when it cannot process input and would like it to
** return to the next handler down while still retaining control.
*/
nomask void modal_pass(string str)
{
    class input_info info;

    if ( !dispatching_to )
	error("no handlers to bubble to");

    info = modal_stack[--dispatching_to - 1];
    //### how to indicate passed?
    evaluate(info->input_func, str);
}

/*
** Send a command to the 'shell'.  (The bottom handler)
*/
private nomask void dispatch_to_bottom(mixed str) {
    class input_info info;

    if (!(info = get_bottom_handler()))
	return;

    dispatching_to = 0;

    evaluate(info->input_func, str);
}

/*
** dispatch_modal_input()
**
** Dispatch the command as appropriate.
*/
private nomask void dispatch_modal_input(mixed str)
{
    class input_info info;
    if( str[0] == '!'&& ! modal_stack[<1]->lock)
    {
	/* Dispatch ! escapes */
	dispatch_to_bottom(str[1..]);
    } else {
	/*
	 ** Get the top handler, or fail if none are present/can be created.
	 */
	if ( !(info = get_top_handler(1)) )
	    return;

	/* auto-pop _before_ dispatching, so we pop the correct handler */
	if ( info->input_type == INPUT_AUTO_POP )
	    modal_pop();

	dispatching_to = sizeof(modal_stack);

	evaluate(info->input_func, str);
    }

    if ( this_object() )
	modal_recapture();
}

nomask void modal_push_char(function input_func)
{
    push_handler(input_func, 0, 1, 0, INPUT_CHAR_MODE,0);
}


/*
** process_input()
**
** In the absence of an input_to() (happens when an uncaught error occurs),
** then the driver will call this apply with the input.  
**
** Note that we retain the use of input_to() so that we can use its
** "secure" setting.
**
** maybe we should only use input_to if we need it now.  -Beek
*/
private nomask string process_input(string str)
{
    dispatch_modal_input(str);
}

/*
** force_me()
**
** Force a line of input to the user's bottom level input handler.
*/
nomask void force_me(string str)
{
    object save_this_user = this_user();

    /*
    ** If this user has a privilege, then allow forces only from self or
    ** an admin.
    */
    if (SECURE_D->valid_privilege(query_userid() + ":"))
	if ( query_privilege() && !check_privilege(query_userid() + ":") )
	    error("Illegal force attempt.\n");
	//### prevents an admin from forcing themselves. need to think...
	//    if ( adminp(this_object()) )
	//        error("illegal force attempt.\n");

    set_this_player(this_object());
    dispatch_to_bottom(str);
    set_this_player(save_this_user);
}


string stat_me()
{
  //    if ( check_previous_privilege(1) )
  //    {
	return sprintf("INPUT STACK:\n%O\n", modal_stack);
	//   }
    return "";
}

protected nomask void clear_input_stack()
{
    class input_info top;

    while (sizeof(modal_stack))
    {
	if (catch {
	      top = get_top_handler(1);
	      modal_pop();
	      evaluate(top->input_func, -1);
	}) {
	  write_file("/tmp/bad_handler",
	  sprintf("Error in input_func(-1):\n\tinput_func: %O\n\tprompt: %O\n", top->input_func, top->prompt));
	}
    }
}

nomask int modal_stack_size()
{
  return sizeof(modal_stack);
}