/*
   "glue.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 <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <tcl.h>
#include <tk.h>
#include "ragmaan.h"
#include "ipc.h"
#include "glue.h"
#include "server_frontend.h"
#include "state_stack.h"

/* Hard-coded links to GUI - yuck!  */

#define	GUI_PROGRESS_CANVAS ".p_gauge";
#define	GUI_SEARCH_LIST_BOX ".f_searchlist.lb"
#define	GUI_SEARCH_LIST_BOX_SCROLLBAR ".f_searchlist.sb"

/* # of rectangles in progress bar */

#define	NOF_PROGRESS_STEPS (20)

/* ---------------------------------------------------------------------

   declarations of all commands

   --------------------------------------------------------------------- */

RM_CMD (rm_expand_and_show);
RM_CMD (rm_fill_listbox);
RM_CMD (rm_issubset);
RM_CMD (rm_progress);
RM_CMD (rm_subset_subtract);
RM_CMD (rm_trim);

/* ---------------------------------------------------------------------

   registration procedure

   --------------------------------------------------------------------- */

int
Rm_Init (Tcl_Interp * interp)
{
  CREATE_CMD (rm_expand_and_show);
  CREATE_CMD (rm_fill_listbox);
  CREATE_CMD (rm_issubset);
  CREATE_CMD (rm_progress);
  CREATE_CMD (rm_subset_subtract);
  CREATE_CMD (rm_trim);
  RmStack_Init (interp);
  return Rms_Init (interp);
}

/* ---------------------------------------------------------------------

   implementation of the actual commands

   --------------------------------------------------------------------- */

int
rm_fill_listbox (ClientData clientData,
		 Tcl_Interp * interp,
		 int argc, char *argv[])
{
  Tcl_CmdInfo info;
  char *command1[] =
  {GUI_SEARCH_LIST_BOX, "delete", "0", "end"};
  char *command2[] =
  {GUI_SEARCH_LIST_BOX, "insert", "end", "? xxx"};
  int n;
  int (*listbox_proc) (ClientData, Tcl_Interp *, int, char *[]);
  int i;

  if (argc != 2)
    {
      interp->result = "need 1 arg";
      return TCL_ERROR;
    }

  if (Tcl_GetInt (interp, argv[1], &n) != TCL_OK)
    {
      return TCL_ERROR;
    }

  if (Tcl_GetCommandInfo (interp, command1[0], &info) == 0)
    {
      interp->result = "listbox does not exist";
      return TCL_ERROR;
    }
  listbox_proc = info.proc;
  listbox_proc (info.clientData, interp, 4, command1);

  for (i = 0; i < n; i++)
    listbox_proc (info.clientData, interp, 4, command2);
  return TCL_OK;
}

int
rm_subset_subtract (ClientData clientData,
		    Tcl_Interp * interp,
		    int argc, char *argv[])
{
  char *the_result;

  if (argc != 3)
    {
      interp->result = "need 2 args";
      return TCL_ERROR;
    }

  if (!is_sub3 (argv[1], argv[2]))
    {
      Tcl_AppendResult (interp, "\"", argv[2],
			"\" is not a subset of \"", argv[1], "\"", 0);
      return TCL_ERROR;
    }

  the_result = Tcl_Alloc (strlen (argv[1]) + 1);
  strcpy (the_result, argv[1]);
  subtract (the_result, argv[2]);
  Tcl_SetResult (interp, the_result, TCL_DYNAMIC);
  return TCL_OK;
}

int
rm_issubset (ClientData clientData, Tcl_Interp * interp,
	     int argc, char *argv[])
{
  if (argc != 3)
    {
      interp->result = "need 2 args";
      return TCL_ERROR;
    }

  if (is_sub3 (argv[1], argv[2]))
    {
      interp->result = "1";
    }
  else
    {
      interp->result = "0";
    }
  return TCL_OK;
}

int
rm_trim (ClientData clientData, Tcl_Interp * interp,
	 int argc, char *argv[])
{
  char *trim_string;
  char temp_string[] = " ";
  char c;
  int n, i;

  if (argc != 2)
    {
      interp->result = "need 1 arg";
      return TCL_ERROR;
    }

  trim_string = argv[1];
  n = strlen (trim_string);

  for (i = 0; i < n; i++)
    {
      c = tolower (trim_string[i]);
      if (c >= 'a' && c <= 'z')
	{

	  temp_string[0] = trim_string[i];

	  Tcl_AppendResult (interp, temp_string, 0);
	}
    }
  return TCL_OK;
}

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

  static int defined[NOF_PROGRESS_STEPS];
  static char tag[NOF_PROGRESS_STEPS][20];
  double f;
  int f_int;
  int i;
  int width, height;
  int x1, x2;
  double delta;
  char temp_string[MAX_WORD_LENGTH];

  Tk_Window progress_canvas_w;

  if (argc != 3)
    {
      interp->result = "need 2 args";
      return TCL_ERROR;
    }

  progress_canvas_w = Tk_NameToWindow (interp, argv[1], Tk_MainWindow (interp));
  if (!progress_canvas_w)
    return TCL_ERROR;
  width = Tk_Width (progress_canvas_w) - 2;
  height = Tk_Height (progress_canvas_w) - 2;

  if (TCL_ERROR == Tcl_GetDouble (interp, argv[2], &f))
    return TCL_ERROR;

  if (f < 0.0)
    f = 0.0;
  if (f > 1.0)
    f = 1.0;

  delta = ((double) width) / NOF_PROGRESS_STEPS;
  f_int = ((int) (0.5 + f * NOF_PROGRESS_STEPS));
  for (i = 0; i < NOF_PROGRESS_STEPS; i++)
    {

      if (i < f_int)
	{

	  if (!defined[i])
	    {
	      x1 = i * delta + 1;
	      x2 = (i + 1) * delta;
	      sprintf (temp_string,
		       "%s create rectangle %d %d %d %d -fill yellow",
		       argv[1], x1, 1, x2 - 1, height);
	      Tcl_Eval (interp, temp_string);
	      strncpy (tag[i], interp->result, 10);
	      defined[i] = 1;
	    }
	}
      else
	{
	  if (defined[i])
	    {
	      sprintf (temp_string,
		       "%s delete %s", argv[1], tag[i]);
	      Tcl_Eval (interp, temp_string);
	      defined[i] = 0;
	    }
	}
    }
  Tcl_Eval (interp, "update");
  return TCL_OK;
}

void
rm_progress2 (void *interp, double fraction)
{
  /* UNSAFE since the interpreter is saved locally!!! */

  static Tcl_Interp *saved_interp;
  char *argv[3];
  char temp_string[MAX_WORD_LENGTH];

  if (interp)
    {
      saved_interp = interp;
    }
  else
    {
      argv[0] = "rm_progress";
      argv[1] = GUI_PROGRESS_CANVAS;
      argv[2] = temp_string;
      sprintf (temp_string, "%f", fraction);
      rm_progress (0, saved_interp, 3, argv);
    }
}

void
rm_progress3 (Tcl_Interp * interp, double fraction)
{
  char *argv[3];
  char temp_string[MAX_WORD_LENGTH];

  argv[0] = "rm_progress";
  argv[1] = GUI_PROGRESS_CANVAS;
  argv[2] = temp_string;
  sprintf (temp_string, "%f", fraction);
  rm_progress (0, interp, 3, argv);
}

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

  char *command1[] =
  {GUI_SEARCH_LIST_BOX, "size"};
  char *command2[] =
  {GUI_SEARCH_LIST_BOX, "insert", 0, 0};
  char *command3[] =
  {GUI_SEARCH_LIST_BOX, "delete", 0};
  char *command4[] =
  {GUI_SEARCH_LIST_BOX_SCROLLBAR, "set", 0, 0};
  Tcl_CmdInfo info;
  int (*listbox_proc) (ClientData, Tcl_Interp *, int, char *[]);
  int (*scrollbar_proc) (ClientData, Tcl_Interp *, int, char *[]);
  int i, start, end, n;
  double a, b;
  char i_ascii[20];
  char a_ascii[20];
  char b_ascii[20];

  command2[2] = i_ascii;
  command3[2] = i_ascii;
  command2[3] = server_reply->string_reply;
  command4[2] = a_ascii;
  command4[3] = b_ascii;

  if (!server_cmd)
    {
      interp->result = "no server";
      return TCL_ERROR;
    }
  if (argc != 3)
    {
      interp->result = "need 2 fractions";
      return TCL_ERROR;
    }

  if (Tcl_GetCommandInfo (interp, command1[0], &info) == 0)
    {
      interp->result = "listbox does not exist";
      return TCL_ERROR;
    }
  listbox_proc = info.proc;
  listbox_proc (info.clientData, interp, 2, command1);

  if (Tcl_GetInt (interp, interp->result, &n) != TCL_OK)
    {
      return TCL_ERROR;
    }

  if (TCL_OK != Tcl_GetDouble (interp, argv[1], &a))
    {
      return TCL_ERROR;
    }
  if (TCL_OK != Tcl_GetDouble (interp, argv[2], &b))
    {
      return TCL_ERROR;
    }
  start = a * n + 0.5;
  end = b * n + 0.5 - 1;
  if (end == n - 1 && start > 0)
    start--;

  sprintf (i_ascii, "%d", start);
  for (i = start; i <= end; i++)
    {

      server_cmd->cmd = CMD_EXPAND;
      server_cmd->int_arg1 = i;
      server_command (0);

      if (server_reply->error)
	{
/*
   strcpy(interp->result, server_reply->string_reply);
   return TCL_ERROR;
 */
	  break;
	}

      listbox_proc (info.clientData, interp, 4, command2);
      sprintf (i_ascii, "%d", i + 1);
      listbox_proc (info.clientData, interp, 3, command3);
    }

  if (Tcl_GetCommandInfo (interp, command4[0], &info) == 0)
    {
      interp->result = "scrollbar does not exist";
      return TCL_ERROR;
    }
  scrollbar_proc = info.proc;
  Tcl_PrintDouble (interp, a, a_ascii);
  Tcl_PrintDouble (interp, b, b_ascii);
  return scrollbar_proc (info.clientData, interp, 4, command4);
}
