/*
   "state_stack.c" - part of "RAGMAAN, een anagrammengenerator"

   Copyright (C) 1999 Raymond Zandbergen

   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
   (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
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   The maintainer of this program is Raymond Zandbergen (ray@wirehub.nl)
 */

#include <stdio.h>
#include <string.h>
#include <tcl.h>
#include "ragmaan.h"
#include "glue.h"

#define	tcl_var_stack_depth "stack_depth"	/* variable name in TCL */

/*
 *  TCL state variables that are pushed and popped
 */

static char *state_vars[] =
{"target", "selection", "selection_idx",
 "use_filter", "filter", 0};

#define NOF_STATE_VARS ((sizeof(state_vars)/sizeof(state_vars[0]))-1)

void rm_stack_init (Tcl_Interp * interp);

RM_CMD (rm_push_state);
RM_CMD (rm_pop_state);
RM_CMD (rm_dump_stack);

int
RmStack_Init (Tcl_Interp * interp)
{

  CREATE_CMD (rm_push_state);
  CREATE_CMD (rm_pop_state);
  CREATE_CMD (rm_dump_stack);
  rm_stack_init (interp);
  return TCL_OK;
}

void
rm_stack_init (Tcl_Interp * interp)
{
  int i;

  for (i = 0; i < NOF_STATE_VARS; i++)
    {
      char *v = state_vars[i];
      Tcl_SetVar2 (interp, v, 0, "\0", TCL_GLOBAL_ONLY |
		   TCL_LEAVE_ERR_MSG);
    }
  Tcl_SetVar2 (interp, tcl_var_stack_depth, 0, "0", TCL_GLOBAL_ONLY |
	       TCL_LEAVE_ERR_MSG);
}

int
rm_push_state (ClientData clientData,
	       Tcl_Interp * interp,
	       int argc, char *argv[])
{
  int i, stack_depth;
  char *idx;
  char stack_name[MAX_WORD_LENGTH];

  if (argc > 1)
    interp->result = "arguments ignored";

  idx = Tcl_GetVar2 (interp, tcl_var_stack_depth, 0,
		     TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
  if (!idx)
    idx = "0";

  for (i = 0; i < NOF_STATE_VARS; i++)
    {

      char *v = state_vars[i];
      char *r;

      r = Tcl_GetVar2 (interp, v, 0, TCL_GLOBAL_ONLY |
		       TCL_LEAVE_ERR_MSG);
      if (!r)
	r = "\0";

      strcpy (stack_name, "stack_");
      strcat (stack_name, v);
      strcat (stack_name, "_stack");
      Tcl_SetVar2 (interp, stack_name, idx, r, TCL_GLOBAL_ONLY |
		   TCL_LEAVE_ERR_MSG);
    }
  sscanf (idx, "%d", &stack_depth);
  stack_depth++;
  sprintf (stack_name, "%d", stack_depth);
  Tcl_SetVar2 (interp, tcl_var_stack_depth, 0, stack_name,
	       TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
  return TCL_OK;
}

int
rm_pop_state (ClientData clientData,
	      Tcl_Interp * interp,
	      int argc, char *argv[])
{
  int i, stack_depth;
  char *idx;
  char stack_name[MAX_WORD_LENGTH];

  if (argc > 1)
    interp->result = "arguments ignored";

  idx = Tcl_GetVar2 (interp, tcl_var_stack_depth, 0,
		     TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
  if (!idx)
    idx = "0";

  sscanf (idx, "%d", &stack_depth);
  if (stack_depth == 0)
    {
      interp->result = "stack underflow";
      return TCL_ERROR;
    }
  stack_depth--;
  sprintf (stack_name, "%d", stack_depth);
  Tcl_SetVar2 (interp, tcl_var_stack_depth, 0, stack_name,
	       TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
  idx = Tcl_GetVar2 (interp, tcl_var_stack_depth, 0,
		     TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);

  for (i = 0; i < NOF_STATE_VARS; i++)
    {

      char *v = state_vars[i];
      char *r;

      strcpy (stack_name, "stack_");
      strcat (stack_name, v);
      strcat (stack_name, "_stack");

      r = Tcl_GetVar2 (interp, stack_name, idx, TCL_GLOBAL_ONLY |
		       TCL_LEAVE_ERR_MSG);
      if (!r)
	r = "\0";

      Tcl_SetVar2 (interp, v, 0, r, TCL_GLOBAL_ONLY |
		   TCL_LEAVE_ERR_MSG);
    }
  return TCL_OK;
}

int
rm_dump_stack (ClientData clientData,
	       Tcl_Interp * interp,
	       int argc, char *argv[])

{
  char stack_name[MAX_WORD_LENGTH];
  char idx_ascii[MAX_WORD_LENGTH];
  char *idx, *r;
  int i, stack_depth;

  if (argc != 2)
    {

      interp->result = "need state var";
      return TCL_ERROR;
    }

  strcpy (stack_name, "stack_");
  strcat (stack_name, argv[1]);
  strcat (stack_name, "_stack");
  idx = Tcl_GetVar2 (interp, tcl_var_stack_depth, 0,
		     TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
  if (!idx)
    idx = "0";
  sscanf (idx, "%d", &stack_depth);

  Tcl_ResetResult (interp);
  for (i = 0; i < stack_depth; i++)
    {
      sprintf (idx_ascii, "%d", i);
      r = Tcl_GetVar2 (interp, stack_name, idx_ascii, TCL_GLOBAL_ONLY |
		       TCL_LEAVE_ERR_MSG);
      if (!r)
	r = "\0";
      Tcl_AppendElement (interp, r);
    }
  return TCL_OK;
}
