#include <stdio.h>
#include "../lint.h"
#include "../interface.h"
#include "../object.h"
/* Define variables */
extern struct object *previous_ob;


/* Define functions */

static void
efun_cat_file(struct svalue *fp)
{
    extern int read_file_len;
    char *str;
    
    if (fp[0].type != T_STRING || fp[1].type != T_NUMBER
	|| fp[2].type != T_NUMBER)
    {
	push_number(0);
	return;
    }
    str = read_file(fp[0].u.string, fp[1].u.number, fp[2].u.number);
    if (str)
    {
	push_string(str, STRING_MALLOC);
	apply("catch_tell", command_giver, 1, 0);
	push_number(read_file_len);
    }
    else
	push_number(0);
    return;
}

static func func_cat_file = 
{
    "cat_file",
    efun_cat_file,
};

static void
efun_tell_room(struct svalue *fp)
{
    struct object *room = 0, *ob, *tp;
    struct svalue *oblist, *vv;
    int i, print, size;
    
    push_number(0);

    if (fp[3].type == T_OBJECT)
        tp = fp[3].u.ob; 
    else if (command_giver && !(command_giver->flags & O_DESTRUCTED))
	tp = command_giver;
    else
	tp = 0;
    
    if (fp[0].type == T_STRING)
	room = find_object2(fp[0].u.string);
    else if (fp[0].type == T_OBJECT)
	room = fp[0].u.ob;
    if (!room)
       return;
    switch (fp[2].type)
    {
    case T_OBJECT:
	size = 1;
	oblist = &fp[2];
	break;
    case T_POINTER:
	size = fp[2].u.vec->size;
	oblist = fp[2].u.vec->item;
	break;
    default:
	size = 0;
	break;
    }

    /* tell folx in room */
    for(ob = room->contains; ob; ob = ob->next_inv)
    {
	print = 1;
	for (i = 0; i < size; i++)
	    if (oblist[i].u.ob == ob)
	    {
		print = 0;
		break;
	    }
	/* before we push, check if it's a living */
	if ((ob->flags & O_ENABLE_COMMANDS) && print)
	{
	   push_svalue(&fp[1]);
	   push_object(tp); 
	   apply("catch_msg", ob, 2, 0); 
	}
    }
    
    /* tell room */
    print = 1; ob = room;
    for (i = 0; i < size; i++)
	if (oblist[i].u.ob == ob)
	{
	    print = 0;
	    break;
	}
    if ((ob->flags & O_ENABLE_COMMANDS) && print)
    {
	push_svalue(&fp[1]);
	push_object(tp); 
	apply("catch_msg", ob, 2, 0); 
    }
}


static func func_tell_room = 
{
    "tell_room",
    efun_tell_room,
};

static void
efun_write(struct svalue *fp)
{
    push_number(0);

    if (!command_giver)
    {
	if (fp[0].type == T_STRING)
	printf("%s", fp[0].u.string);
	return;
    }
    push_svalue(fp);
    apply("catch_tell", command_giver, 1, 0);
}
static func func_write = 
{
    "write",
    efun_write,
 };


static void
efun_say(struct svalue *fp)
{
    struct object *tp, *ob;
    struct svalue *oblist,
           tp_svalue;      /* new */

    int size, i;
    int print;

    push_number(0);
    
    if (command_giver && !(command_giver->flags & O_DESTRUCTED))
	tp = command_giver;
    else
	tp = previous_ob;

    tp_svalue.type=T_OBJECT; 
    tp_svalue.u.ob=tp;    
    
    switch (fp[1].type)
    {
    case T_OBJECT:
	size = 1;
	oblist = &fp[1];
	break;
    case T_POINTER:
	size = fp[1].u.vec->size;
	oblist = fp[1].u.vec->item;
	break;
    default:
	if (tp)
	{
	   size = 1;
	   oblist = &tp_svalue;
	}
	else size = 0;
	break;
    }

    /* tell folx in room */
    if (tp && tp->super)
    {
	for (ob = tp->super->contains; ob; ob = ob->next_inv)
	{
	    print = 1;
	    for (i = 0; i < size; i++)
		if (oblist[i].u.ob == ob)
		    print = 0;
	    /* before we push, check if it's a living */
	    if ((ob->flags & O_ENABLE_COMMANDS) && print)
	    {
		push_svalue(fp);
		push_svalue(&tp_svalue); 
		apply("catch_msg", ob, 2, 0); 
	    }
	}

	/* tell room */
	print = 1; ob = tp->super;
	for (i = 0; i < size; i++)
	    if (oblist[i].u.ob == ob)
		print = 0;
	if ((ob->flags & O_ENABLE_COMMANDS) && print)
	{
	    push_svalue(fp);
	    push_svalue(&tp_svalue); 
	    apply("catch_msg", ob, 2, 0); 
	}
    }
    
    /* tell folx in player */
    for (ob = tp->contains; ob; ob = ob->next_inv)
    {
	print = 1;
	for (i = 0; i < size; i++)
	    if (oblist[i].u.ob == ob)
		print = 0;
	/* before we push, check if it's a living */
	if ((ob->flags & O_ENABLE_COMMANDS) && print)
	{
	   push_svalue(fp);
	   push_svalue(&tp_svalue);
	   apply("catch_msg", ob, 2, 0);
	}
    }

    /* tell this_player */
    print = 1; ob = tp;
    for (i = 0; i < size; i++)
       if (oblist[i].u.ob == ob)
	  print = 0;
    if (ob && (ob->flags & O_ENABLE_COMMANDS) && print)
    {
       push_svalue(fp);
       push_svalue(&tp_svalue); 
       apply("catch_msg", ob, 2, 0); 
    }   
}

static func func_say = 
{
    "say",
    efun_say,
};

static void
efun_atoi(struct svalue *fp)
{
    if (fp->type == T_STRING)
	push_number(atoi(fp->u.string));
    else
	push_number(0);
}
static func func_atoi =
{
    "atoi",
    efun_atoi,
};

/* Define the interface */

static var *(vars[]) =
{
   0,
};

static func *(funcs[]) =
{
    &func_cat_file,
    &func_say,
    &func_write,
    &func_tell_room,
    &func_atoi,
    0,
};


struct interface efun = 
{
    "secure/simul_efun.c",
    vars,
    funcs,
};