/********************************************************************** 
 Copyright (C) 1998 - Gareth Owen
   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, 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.
***********************************************************************/
#include <string.h>
#include <unistd.h>
#include "glaunch.h"

extern gchar * format_string;
extern option_flags ** opts;
extern gint error_flag;

#ifdef USE_STATUSBAR
extern GtkWidget * message_bar;
#endif

void add_xterm_info (gchar ** args, cmd_line * prog);
void start_process(GtkButton *sender, gpointer data);

void
start_process(GtkButton *sender, gpointer data)
/* data is a command line in execv format */
{
  gint i=1;
  gint j, k;
  gint xterm_flag=0;		/* Set if we are using an implicit xterm */
  gchar ** initial;
  gchar ** final;
  gchar * copy;
  gchar * program_name;

  cmd_line * prog;

  
#ifdef USE_STATUSBAR
  guint status_context;
  status_context = gtk_statusbar_get_context_id
    (GTK_STATUSBAR(message_bar), "errors");
#endif
  
  
  prog = (cmd_line *) data;
  copy = g_malloc((strlen(format_string)+1) * sizeof(gchar));

  strcpy(copy,format_string);

  /* FIX: Dynamic memory */
  initial = g_malloc(sizeof(gchar *) * (OPTNUM + 1));
  final = g_malloc(sizeof(gchar *) * (OPTNUM + 1));

  /*  Strip the first two things from the command */
  strtok(copy,":");
  strtok(NULL,":");

  /* Check whether we need an xterm as a wrapper */
  if(strcmp(strtok(NULL,":"),"y") == 0){
    add_xterm_info(final, prog);
    program_name = g_malloc(sizeof(gchar) * (strlen(XTERM_PATH) + 1));
    strcpy(program_name, XTERM_PATH);
    xterm_flag = 2; /* Adjust for used up space in arg list */
  }

  else{			/* No xterm */
    final[0] = g_malloc(sizeof(gchar) * (strlen(prog->program)+1));
    strcpy(final[0],prog->program);
    program_name = g_malloc(sizeof(gchar) * (strlen(prog->program)+1));
    strcpy(program_name,prog->program);
  }
  
  while(((prog)->data_ptr)[i-1] != NULL){
    /*
#ifdef DEBUG
    fprintf(stderr,"initial[%d] = %p\n",(2*i),
	    initial[(2*i) - 1 + xterm_flag]);
#endif */ /* DEBUG */

    /* Here we need to start using the global option_flags array */
    /* Read in the option */
    /* This case deals with the flag "-foo" */
    switch(opts[i-1]->type){
      case TEXT_FIELD:			/* Text field */
      case FILE_FIELD:			/* File field */
      case COMPULSORY_TEXT_FIELD:	
      case COMPULSORY_FILE_FIELD:
	{
	  initial[(2*i) - 1] = strtok(NULL,":");
	  break;
	}
      case BOOLEAN:			/* Boolean */
	{
	  /* If the button is down copy the flag */
	  if(GTK_TOGGLE_BUTTON((prog->data_ptr)[i-1])->active)
	    initial[(2*i) - 1] = strtok(NULL,":");
	  /* Otherwise stick in a star but move the parser on */
	  else
	    {
	      initial[(2*i) - 1] = g_malloc(2 * sizeof(gchar));
	      strcpy(initial[(2*i) - 1], "*");
	      strtok(NULL,":");
	    }
	  break;
	}

      default:
	{
	  fprintf(stderr,
 "Fatal error: Unknown data type %d in start_process(), process.c\n",
		  opts[i-1]->type);
	  exit(-1);
	  break;
	}
    }

    /* Skip two in format string */
    strtok(NULL,":");
    strtok(NULL,":");

    switch(opts[i - 1]->type){
      case TEXT_FIELD:			/* Text box */
      case FILE_FIELD:			/* Filename text box */
      case COMPULSORY_TEXT_FIELD:	
      case COMPULSORY_FILE_FIELD:
	{
	  initial[2 * i] =
	    (gtk_entry_get_text(GTK_ENTRY((prog->data_ptr)[i-1])));
	  break;
	}
      case BOOLEAN:			/* Boolean */
	{			/* g_malloc() it, but it will be ignored */
	  initial[2 * i] = g_malloc(sizeof(gchar));
	  break;
	}
      default:
	{
	  fprintf(stderr,
 "Fatal error: Unknown data type %d in start_process(), process.c, line 125\n",
		  opts[i-1]->type);
	  exit(-1);
	  break;
	}
    }
    i++;
  } /* End while(opts) */

  /* Terminate the list of arguments so exec knows when to quit */
  initial[2 * i - 1] = NULL;

  /* Construct the final command line */

  /* Loop through the structure containing the arguments, removing the
     meta-characters "*" */
  i=1;				/* Count the args read */
  j=xterm_flag + 1;		/* Count the args written */
  /* Cope with special cases */
  
  while(initial[i] != NULL){
    if(i > 0){		/* Are we dealing with the tricky bits */
      k = copy_cmd_line(i, j, opts[(i - 1)/2]->type, initial, final);
      if(k < -1){
	/* Failed to specify compulsory form. */
#ifdef DEBUG
	fprintf(stderr,"An error flagged\n");
#endif
	return;
      }
      j += k;
    } /* End if(i>0) */
    i++;
  }

  final[j] = NULL;		/* Terminate the arglist. */

  /* Check no errors occured */
  if(error_flag){
    error_flag = 0;
    fprintf(stderr,"Compulsory field omitted, please enter a value.\n");
#ifdef USE_STATUSBAR
    gtk_statusbar_push
      (GTK_STATUSBAR(message_bar),status_context,"Compulsory field omitted.");
#endif
    return;

  }
  
  switch (fork()){
      case 0:
	execv(program_name, final);
#ifdef DEBUG
	fprintf(stderr,"execv() failed!");
	exit(-2);
#endif
	break;			/* Shouldn't get seen */
      
    case -1:			/* An error occured : Bail!*/
      fprintf(stderr,
	      "Fork failed in parse.c.  Fatal error - Exiting\n");
      exit(-1);
      break;
    default:
#ifdef DEBUG
      i=0;
      fprintf(stderr, "program_name: %s\n", program_name);
      while(final[i]!=NULL){
	fprintf(stderr,"%s ",final[i]);
	i++;}
      fprintf(stderr,"\nCalling gtk_main_quit()\n");
#endif
      /* exit(0); */
      gtk_main_quit();
  }
  return;
}

void add_xterm_info (gchar ** dest, cmd_line * prog)
{
  dest[0] = g_malloc (sizeof(gchar) * (strlen(XTERM_NAME) + 1));
  dest[1] = g_malloc (sizeof(gchar) * (strlen(XTERM_EXECUTE_FLAG) + 1));
  dest[2] = g_malloc (sizeof(gchar) * (strlen(prog->program) + 1));
  
  strcpy(dest[0],XTERM_NAME);	/* Copy in the data */
  strcpy(dest[1],XTERM_EXECUTE_FLAG);
  strcpy(dest[2],prog->program); /* We need to copy this, since we are
				    about to spoo all over it */
}

