/**
 * getxml-extract:
 * @title: getxml-extract
 * @subtitle: getxml-extract
 * @project: getxml
 * @lang: fr,en
 * @authors: Philippe Roy <ph_roy@toutdoux.org>
 * @copyright: Copyright (c) 2001 Philippe Roy
 * @license: GNU GPL
 *
 * fr: Extraction
 *
 * en: Extrac
 **/

/*
 * Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier
 * sous les termes de la licence publique générale GNU telle qu'elle est publiée par
 * la Free Software Foundation ; soit la version 2 de la licence, ou
 * (comme vous voulez) toute version ultérieure.
 *
 * Ce programme est distribué dans l'espoir qu'il sera utile,
 * mais SANS AUCUNE GARANTIE ; même sans la garantie de
 * COMMERCIALITÉ ou d'ADÉQUATION A UN BUT PARTICULIER. Voir la
 * licence publique générale GNU pour plus de détails.
 *
 * Vous devriez avoir reçu une copie de la licence publique générale GNU
 * avec ce programme ; si ce n'est pas le cas, écrivez à la Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <parser.h>
/*  #include <libxml/parser.h> */

#include "getxml-extract.h"

/*****************************************************************************/
/*** Standardisation du vocabulaire - Vocabulary standardization */
/*****************************************************************************/

#define XmlDoc xmlDoc
#define XmlNs xmlNs
#define XmlNode xmlNode
#define XmlAttribute xmlAttribute
#define XmlAttr xmlAttr
#define XmlChar xmlChar

/*****************************************************************************/
/*** Variables globales - Global variables */
/*****************************************************************************/

GList *DICO;
gchar *PACKAGE_COMMAND;
TdPopt popts[3];

/*****************************************************************************/
/*** Arguments de la ligne de commande - Command line arguments */
/*****************************************************************************/

/**
 * popt_def:
 * @key: char key
 * @long key: string key
 * @argument: argument
 * @description: description
 *
 * fr: Créé une option de ligne de commande
 *
 * en: Creates an option of command line
 *
 * Return value: popt structure
 **/

TdPopt popt_def (gchar *key, gchar *longkey, gchar *argument, gchar *description)
{
  TdPopt ret = NULL;
  ret = g_malloc0 (sizeof (TdPopt_tmp));
  ret->key = g_strdup (key);
  ret->longkey = g_strdup (longkey);
  ret->argument = g_strdup (argument);
  ret->description = description;
  ret->flag = FALSE;
  ret->value = NULL;
  ret->nbpredef = 0;
  return ret;
}

/**
 * popts_help:
 * @nbpopts: counter of options of commande line
 * @popts[]: arraw of options of commande line options
 *
 * fr: Affiche l'usage
 *
 * en: Displays the usage
 **/

void popts_help (gint nbpopts, TdPopt popts[])
{
  gint i, j, k, key, longkey, argument;
  gint length = 0;

  /*** Alignement - Aligment */
  g_print ("%s [option ...]\n", PACKAGE_COMMAND);
  for (i=0; i<nbpopts; i++)
    {
      key = 0;
      longkey = 0;
      argument = 0;
      if (popts[i]->key)
	key = 3;
      if (popts[i]->longkey)
	longkey = strlen (popts[i]->longkey);
      if (popts[i]->argument)
	argument = strlen (popts[i]->argument);
      if (length < (9+key+longkey+argument))
	length = 9+key+longkey+argument;
    }


  /*** Texte - Text */
  for (i=0; i<nbpopts; i++)
    {
      g_print ("  ");
      key = 0;
      longkey = 0;
      argument = 0;
      if (popts[i]->key)
	{
	  g_print ("-%s, ", popts[i]->key);
	  key = 4;
	}
      if (popts[i]->longkey)
	{
	  g_print ("--%s ", popts[i]->longkey);
	  longkey = strlen (popts[i]->longkey);
	}
      if (popts[i]->argument)
	{
	  g_print ("%s", popts[i]->argument);
	  argument = strlen (popts[i]->argument);
	}
      for (j=7+key+longkey+argument; j<length; j++)
	g_print (" ");
      g_print ("%s\n", popts[i]->description);
      for (j=0; j<popts[i]->nbpredef; j++)
	{
	  for (k=0; k<length; k++)
	    g_print (" ");
	  g_print ("%s\n", popts[i]->predef[j]);
	}
    }
  exit (0);
}

/**
 * popts_parse:
 * @argc: counter of options used of command line
 * @argv[]: arraw of options used of command line
 * @nbpopts: counter of options of command line
 * @popts[]: arraw of options of command line
 *
 * fr: Analyse de la ligne de commande
 *
 * en: Parses the command line
 **/

void popts_parse (gint argc, char *argv[], gint nbpopts, TdPopt popts[])
{
  gint i, j;
  GList *option = NULL;
  GList *argument = NULL;
  gchar *txt_tmp = NULL;
  gchar *txt_tmp1 = NULL;
  gchar *txt_tmp2 = NULL;
  gboolean bool_tmp;

  /*** Découpage - Cutting */
  for (i=1; i<argc; i++)
    if (argv[i][0] == '-')
      {
	if (argv[i][1] == '-')
	  option = g_list_append (option, g_strdup (argv[i]+2));
	else
	  option = g_list_append (option, g_strdup (argv[i]+1));
	if (i!=1)
	  {
	    argument = g_list_append (argument, g_strdup (txt_tmp));
	    txt_tmp = "(null)";
	  }
      }
    else
      txt_tmp = g_strdup (argv[i]);
  if (i!=1)
    argument = g_list_append (argument, g_strdup (txt_tmp));

  /*** Affectation - Allocation */
  for (i=0; i<g_list_length (option); i++)
    {

      /*** Aide - Help */
      if ((!strcmp ("h", g_list_nth_data (option, i))) || (!strcmp ("help", g_list_nth_data (option, i))))
	{
	  popts_help (nbpopts, popts);
	  break;
	}
      if (!strcmp ("about", g_list_nth_data (option, i)))
	{
	  popts_about();
	  break;
	}
      if ((!strcmp ("v", g_list_nth_data (option, i))) || (!strcmp ("version", g_list_nth_data (option, i))))
	{
	  popts_version();
	  break;
	}

      /*** Application */
      bool_tmp = FALSE;
      for (j=0; j<nbpopts; j++)
	if (((popts[j]->key) && (!strcmp (popts[j]->key, g_list_nth_data (option, i)))) || 
	    ((popts[j]->longkey) && (!strcmp (popts[j]->longkey, g_list_nth_data (option, i)))))
	  {
	    popts[j]->flag = TRUE;
	    bool_tmp = TRUE;
	    if (g_list_nth_data (argument, i))
	      popts[j]->value = g_strdup (g_list_nth_data (argument, i));
	    else
	      if (popts[j]->argument)
		g_error ("getxml-extract: option '%s' needs argument '%s'", (gchar*) g_list_nth_data (option, i), popts[j]->argument);
	  }
      if (!bool_tmp)
	g_error ("getxml-extract: option '%s' unknow", (gchar*) g_list_nth_data (option, i));
    }
}

/**
 * popts_version:
 *
 * fr: Affiche la version du programme
 *
 * en: Display the version of the program
 **/

void popts_version (void)
{
  g_print ("%s %s\n", PACKAGE_COMMAND, GETXML_VERSION);
  exit (0);
}

/*****************************************************************************/
/*** Element */
/*****************************************************************************/

/**
 * extract:
 * @file_in: input file location
 *
 * fr: Extraction des mots
 *
 * en: Words extraction
 **/

void extract (gchar *file)
{
  gint i;
  XmlDoc *doc;
  XmlNs *ns;
  XmlNode *cur;
  XmlNode *cur_parent = NULL;
  gboolean stop_doc;
  gboolean stop_node;
  gchar *txt_tmp;
  XmlAttr *property;
  gboolean bool_tmp;

  /*** En-tête - Head */
  doc = xmlParseFile (file);
  if (!doc)
    g_error ("getxml-extract: parsing XML file : doc == NULL");
  cur = xmlDocGetRootElement (doc);
  if (!cur)
    {
      xmlFreeDoc (doc);
      g_error ("getxml-extract: parsing XML file : cur == NULL");
    }

  /*** Valeurs - Values */
  stop_doc = FALSE;
  while (!stop_doc)
    {

      /*** Attributs - Attributes */
      property = (XmlAttr*) (cur->properties);
      if (property)
	{
	  stop_node = FALSE;
	  if ((!property->name) || (!strlen (g_strstrip ((gchar*) property->name))))
	    stop_node = TRUE;
	  while (!stop_node)
	    {
	      if (*property->name == '_')
		{
		  bool_tmp = FALSE;
		  for (i=0; i<g_list_length (DICO); i++)
		    if (!strcmp ((gchar*) (g_list_nth_data (DICO, i)), xmlGetProp (cur, property->name)))
		      {
			bool_tmp = TRUE;
			break;
		      }
		  if (!bool_tmp)
		    DICO = g_list_append (DICO, xmlGetProp (cur, property->name));
		}
	      if (!property->next)
		stop_node = TRUE;
	      else
		property = property->next;
	    }
	}

      /*** Suivant - Next */
      if (cur->xmlChildrenNode)
	{
	  cur = cur->xmlChildrenNode;
	  continue;
	}
      else
	{
	  if (cur->next)
	    {
	      cur = cur->next;
	      continue;
	    }
	  else 
	    {
	      do
		{
		  if (cur == xmlDocGetRootElement (doc))
		    stop_doc = TRUE;
		  else
		    {
		      cur_parent = cur->parent;
		      if (cur_parent->next == NULL)
			cur = cur_parent;
		      else
			cur = cur_parent->next;
		    }
		}
	      while ((cur == cur_parent) && (!stop_doc));
	    }
	}
    }
  xmlFreeDoc (doc);
}

/**
 * sax_start_element:
 * @ctx: not used
 * @name: name of element
 * @attrs: attributes of element
 *
 * fr: Evènement SAX de début d'élément
 *
 * en: SAX event of begin of element
 **/

void sax_start_element (void *ctx, const xmlChar *name, const xmlChar **attrs)
{
  gint i, j;
  gchar *carac;
  gboolean bool_tmp;
  /* xmlSwitchEncoding(ctx, 0); */
  if (attrs == NULL)
    return;
  for (i=0; (attrs[i]!=NULL); i++)
    {
      carac = (guchar*) attrs[i];
      if (*carac == '_')
	{
	  i++;
	  bool_tmp = FALSE;
	  for (j=0; j<g_list_length (DICO); j++)
	    if (!strcmp ((gchar*) (g_list_nth_data (DICO, j)), attrs[i]))
	      {
		bool_tmp = TRUE;
		break;
	      }
	  if (!bool_tmp)
	    DICO = g_list_append (DICO, (gchar*) g_strdup (attrs[i]));
	}
    }
}

static xmlSAXHandler xmlSAXParser = 
{
  0, /*** internalSubset */
  0, /*** isStandalone */
  0, /*** hasInternalSubset */
  0, /*** hasExternalSubset */
  0, /*** resolveEntity */
  0, /*** getEntity */
  0, /*** entityDecl */
  0, /*** notationDecl */
  0, /*** attributeDecl */
  0, /*** elementDecl */
  0, /*** unparsedEntityDecl */
  0, /*** setDocumentLocator */
  0, /*** startDocument */
  0, /*** endDocument */
  (startElementSAXFunc)sax_start_element, /*** startElement */
  0, /*** endElement */
  0, /*** reference */
  0, /*** characters */
  0, /*** ignorableWhitespace */
  0, /*** processingInstruction */
  0, /*** comment */
  0, /*** warning */
  0, /*** error */
  0, /*** fatalError */
};

/*****************************************************************************/
/*** Principale - Main */
/*****************************************************************************/

/**
 * popts_about:
 *
 * fr: Affiche le à propos du programme
 *
 * en: Display the about of the program
 **/

void popts_about (void)
{
  g_print ("%s %s : Traducteur XML - XML translator\n", PACKAGE_COMMAND, GETXML_VERSION);
  g_print ("Copyright (c) 2001 Philippe Roy\n");
  g_print ("Author : Philippe Roy <ph_roy@toutdoux.org>\n");
  g_print ("getxml-extract is a free software, covered by the GNU General Public License. (http://www.gnu.org)\n");
  g_print ("getxml-extract is a tool developped for the ToutDoux project. (http://www.toutdoux.org)\n");
  exit (0);
}

/**
 * popts_def:
 *
 * fr: Definition des options de la ligne de commande
 *
 * en: Definition of the options of command line
 **/

void popts_def (void)
{
  PACKAGE_COMMAND = "getxml-extract";
  popts[0] = popt_def (NULL, "about", NULL, "About");
  popts[1] = popt_def ("v", "version", NULL, "Version");
  popts[2] = popt_def ("i", "input", "<xml file>", "Specify the XML input file (obligatory)");
};

/**
 * main:
 * @argc: counter of command line options used
 * @argv[]: arraw of command line options used
 *
 * fr: Procédure principale
 *
 * en: Main procedure
 *
 * Return value: -1 on error
 **/

int main (gint argc, char *argv[])
{
  FILE *file;
  void *ctx;
  gint i;

  /*** Popts */
  popts_def();
  popts_parse (argc, argv, 3, popts);

  /*** Vérification du fichier - File checking */
  file = fopen (popts[2]->value, "r");
  if (file == NULL)
    g_error ("getxml-extract: reading XML input file : error in opening");
  fclose (file);

  /*** Extraction - Extract */
  if (xmlSAXUserParseFile (&xmlSAXParser, &ctx, popts[2]->value) < 0)
    g_error ("getxml-extract: reading XML input file : document not well formed");
  /* FIXME: SAX + encoding + libxml2 = rien capté - SAX + encoding + libxml2 = ununderstood */
  /* extract (popts[2]->value); */
  for (i=0; i<g_list_length (DICO); i++)
    g_print ("char *s = N_(\"%s\");\n", (gchar*) (g_list_nth_data (DICO, i)));
  return 0;
}











syntax highlighted by Code2HTML, v. 0.9.1