/* meta-class.c: -*- C++ -*-  C code which calls a C++ library. */

/*  Copyright (c) 1998 Brian J. Fox
    Author: Brian J. Fox (bfox@ai.mit.edu) Tue May 12 14:01:16 1998.

    This file is part of <Meta-HTML>(tm), a system for the rapid
    deployment of Internet and Intranet applications via the use of
    the Meta-HTML language.

    Copyright (c) 1995, 1996, Brian J. Fox (bfox@ai.mit.edu).
    Copyright (c) 1996, Universal Access Inc. (http://www.ua.com).

    Meta-HTML is free software; you can redistribute it and/or modify
    it under the terms of the UAI Free Software License as published
    by Universal Access Inc.; either version 1, or (at your option) 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
    UAI Free Software License for more details.

    You should have received a copy of the UAI Free Software License
    along with this program; if you have not, you may obtain one by
    writing to:

    Universal Access Inc.
    129 El Paseo Court
    Santa Barbara, CA
    93101  */

#if defined (HAVE_CONFIG_H)
#include <config.h>
#endif

#include "language.h"

static void pf_cc_new (PFunArgs);
static void pf_cc_get (PFunArgs);
static void pf_cc_set (PFunArgs);
static void pf_cc_destroy (PFunArgs);

extern void *cc_create (void);
extern char *cc_get (void *obj);
extern void cc_set (void *obj, char *val);
extern void cc_delete (void *obj);

static PFunDesc ftab[] =
{
  /*   tag	     complex? debug_level	   code    */
  { "CC::NEW",		0,	 0,		pf_cc_new },
  { "CC::GET",		0,	 0,		pf_cc_get },
  { "CC::SET",		0,	 0,		pf_cc_set },
  { "CC::DESTROY",	0,	 0,		pf_cc_destroy },
  { (char *)NULL,	0,	 0,		(PFunHandler *)NULL }
};

void
module_initialize (void)
{
  register int i;
  Symbol *sym, *funcnames;

  funcnames = symbol_intern ("modules::syms-of-c++example");

  /* Install the names and pointers. */
  for (i = 0; ftab[i].tag != (char *)NULL; i++)
    {
      sym = symbol_intern_in_package (mhtml_function_package, ftab[i].tag);
      symbol_add_value (funcnames, ftab[i].tag);
      sym->type = symtype_FUNCTION;
      sym->values = (char **)(&ftab[i]);
    }
}

/* void _init (void) { module_initialize (); } */

/* Called like this: <cc::new obj> (obj is now "0x4958fd89") */
static void
pf_cc_new (PFunArgs)
{
  char *varname = mhtml_evaluate_string (get_positional_arg (vars, 0));

  if (!empty_string_p (varname))
    {
      void *obj = cc_create ();
      char address[40];
      sprintf (address, "0X%010lX", (unsigned long) obj);
      pagefunc_set_variable (varname, address);
    }
  xfree (varname);
}

/* A helper function, which gathers the address of the object from
   the passed variable name. */
static void *
get_cc_object (Package *vars)
{
  char *varnam = mhtml_evaluate_string (get_positional_arg (vars, 0));
  char *varval = varnam? pagefunc_get_variable (varnam) : (char *)NULL;
  void *object_address = (void *)0;

  if (!empty_string_p (varval))
    {
      sscanf (varval, "%0lX", &object_address);

      if (object_address == (void *)0)
	page_syserr ("%s Didn't contain a CC_Class!", varnam ? varnam : "");
    }
  else
    page_syserr ("%s Didn't contain a CC_Class!", varnam ? varnam : "");

  xfree (varnam);
  return (object_address);
}
    
/* Called like this: <cc::set myobj "This is a list of things."> */
static void
pf_cc_set (PFunArgs)
{
  void *object_address = get_cc_object (vars);

  if (object_address != (void *)0)
    {
      char *setval = mhtml_evaluate_string (get_positional_arg (vars, 1));
      cc_set (object_address, setval);
      xfree (setval);
    }
}
   
/* Called like this: <cc::get myobj> --> "This is a list of things." */
static void
pf_cc_get (PFunArgs)
{
  void *object_address = get_cc_object (vars);

  if (object_address != (void *)0)
    {
      char *result = cc_get (object_address);

      if (result != (char *)NULL)
	{
	  bprintf_insert (page, start, "%s", result);
	  *newstart += strlen (result);
	}
    }
}

/* Called like this: <cc::destroy myobj> --> myobj is no longer valid. */
static void
pf_cc_destroy (PFunArgs)
{
  void *object_address = get_cc_object (vars);

  if (object_address != (void *)0)
    {
      char *varnam = mhtml_evaluate_string (get_positional_arg (vars, 0));
      cc_delete (object_address);
      pagefunc_set_variable (varnam, "");
      free (varnam);
    }
}
