/**CFile*******************************************************************
  PackageName [gui]
  Synopsis    [Package 'gui' is used to redirect output to GUI.]

  FileName    [guiTcl.c]
  Revision    [$Revision: 76 $]
  Date        [$Date: 2013-04-26 14:26:09 +0200 (pet, 26 apr 2013) $]
  Authors     [Robert Meolic (meolic@uni-mb.si)]
  Description [File guiTcl.c contains definitions of Tcl commands, which
               can be used from Tcl interpreter (e.g. tclsh or wish).]
  SeeAlso     [gui.h, guiInt.h]

  Copyright   [This file is part of EST (Efficient Symbolic Tools).
               Copyright (C) 2003, 2013
               UM-FERI, Smetanova ulica 17, SI-2000 Maribor, Slovenia

               EST 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.

               EST 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., 51 Franklin Street, Fifth Floor,
               Boston, MA 02110-1301 USA.]
  ************************************************************************/

#include "guiInt.h"
#include "guiDecls.h"

#include <tcl.h>

extern GuiStubs guiStubs;

/* on tcl 8.3 use #define USECONST */
/* on tcl 8.4 use #define USECONST const*/
/* this is defined in Makefile */

/*-----------------------------------------------------------------------*/
/* Constant declarations                                                 */
/*-----------------------------------------------------------------------*/

/*-----------------------------------------------------------------------*/
/* Variable declarations                                                 */
/*-----------------------------------------------------------------------*/

Tcl_Interp *gui_interp = NULL;

/**AutomaticStart*********************************************************/

/*-----------------------------------------------------------------------*/
/* Static function prototypes                                            */
/*-----------------------------------------------------------------------*/

static int GuiInitPkgCmd(ClientData clientData, Tcl_Interp *interp,
                          int argc, USECONST char **argv);

static int GuiExitPkgCmd(ClientData clientData, Tcl_Interp *interp,
                          int argc, USECONST char **argv);

static int GuiAboutPkgCmd(ClientData clientData, Tcl_Interp *interp,
                          int argc, USECONST char **argv);


/**AutomaticEnd***********************************************************/

/*-----------------------------------------------------------------------*/
/* Definition of exported functions                                      */
/*-----------------------------------------------------------------------*/

/**Function****************************************************************
  Synopsis    []
  Description []
  SideEffects []
  SeeAlso     []
  ************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

int
Gui_Init(Tcl_Interp *interp)
{

#ifdef USE_TCL_STUBS
  if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
    return TCL_ERROR;
  }
#endif

  gui_interp = interp;

  Tcl_CreateCommand(interp, "gui_initPkg", GuiInitPkgCmd,
                     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateCommand(interp, "gui_exitPkg", GuiExitPkgCmd,
                     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateCommand(interp, "gui_aboutPkg", GuiAboutPkgCmd,
                     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  return Tcl_PkgProvideEx(interp, "est2ed-gui", "1.0", &guiStubs);
}

#ifdef __cplusplus
}
#endif

/**Function****************************************************************
  Synopsis    [Function Gui_Printf.]
  Description [This function redirect printf to GUI.]
  SideEffects [To write text to stdout please use fprintf(stdout,...)]
  SeeAlso     []
  ************************************************************************/

int
Gui_Printf(char *format, ...)
{
  int result;
  va_list args;
  static char cmd[1024]; /* ONLY 1024 BYTES ARE ALLOCATED !!! */
  static char cmdnew[1024]; /* ONLY 1024 BYTES ARE ALLOCATED !!! */
  int i,j,len;

  /*
  fprintf(stdout,"%s\n",format);
  return 0;
  */

  /* cmd AND cmdnew ARE STATIC */
  /* Gui_Printf CANNOT RUN CONCURENTLY */

#ifdef USETHREADS
  pthread_mutex_lock(&gui_mutex);
#endif

  cmd[0] = 'o';
  cmd[1] = 'u';
  cmd[2] = 't';
  cmd[3] = ' ';
  cmd[4] = '\"';

  va_start(args, format);
  len = vsnprintf(&cmd[5], 1000, format, args);
  va_end(args);

  if ((len == -1) || (len >= 1000)) len = 1000;

  cmd[len+5] = '\"';
  cmd[len+6] = 0;
  len = len+6;

  i = 0;
  j = 0;
  while ( (i <= len) && (j < 1000) ) {
    if ((cmd[i] != '[') && (cmd[i] != ']') && (cmd[i] != '\\')) {
      cmdnew[j++] = cmd[i++];
    } else {
      cmdnew[j++] = '\\';
      cmdnew[j++] = cmd[i++];
    }
  }

  if (i == len) {
    cmdnew[j++] = 0;
  }

  if (i < len) {
    cmdnew[j++] = '.';
    cmdnew[j++] = '.';
    cmdnew[j++] = '.';
    cmdnew[j++] = '\"';
    cmdnew[j++] = 0;
  }

  result = Tcl_EvalEx(gui_interp,cmdnew,j-1,TCL_EVAL_GLOBAL);

#ifdef USETHREADS
  pthread_mutex_unlock(&gui_mutex);
#endif

  return result;
}

/*-----------------------------------------------------------------------*/
/* Definition of internal functions                                      */
/*-----------------------------------------------------------------------*/

/*-----------------------------------------------------------------------*/
/* Definition of static functions                                        */
/*-----------------------------------------------------------------------*/

/**Function****************************************************************
  Synopsis    [Function GuiInitPkgCmd.]
  Description []
  SideEffects []
  SeeAlso     []
  ************************************************************************/

static int
GuiInitPkgCmd(ClientData clientData, Tcl_Interp *interp, int argc,
                  USECONST char **argv)
{
  if (argc != 1) {
    interp->result = "wrong # args";
    return TCL_ERROR;
  }

  printf("Initialization of GUI package... ");
  Gui_InitPkg();
  printf("OK");

  printf("\n");
  Tcl_SetResult(interp, "", TCL_STATIC);
  return TCL_OK;
}

/**Function****************************************************************
  Synopsis    [Function GuiExitPkgCmd.]
  Description []
  SideEffects []
  SeeAlso     []
  ************************************************************************/

static int
GuiExitPkgCmd(ClientData clientData, Tcl_Interp *interp, int argc,
                   USECONST char **argv)
{
  if (argc != 1) {
    interp->result = "wrong # args";
    return TCL_ERROR;
  }

  printf("Exit GUI package... ");
  Gui_ExitPkg();
  printf("OK");

  printf("\n");
  Tcl_SetResult(interp, "", TCL_STATIC);
  return TCL_OK;
}

/**Function****************************************************************
  Synopsis    [Function GuiAboutPkgCmd.]
  Description []
  SideEffects []
  SeeAlso     []
  ************************************************************************/

static int
GuiAboutPkgCmd(ClientData clientData, Tcl_Interp *interp, int argc,
              USECONST char **argv)
{
  if (argc != 1) {
    interp->result = "wrong # args";
    return TCL_ERROR;
  }

  Gui_AboutPkg();

  Tcl_SetResult(interp, "", TCL_STATIC);
  return TCL_OK;
}
