/* tools.c
 * Copyright (C) 2004, 2005 Sylvain Cresto <scresto@gmail.com>
 *
 * This file is part of graveman!
 *
 * graveman! 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.
 * 
 * graveman! 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 program; see the file COPYING. If not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA. 
 * 
 * URL: http://www.nongnu.org/graveman/
 *
 */

#include "graveman.h"

char *ltrim(char *Abuf)
{
  char *s = Abuf;

  while (*s==' ' || *s==9) s++;	

  return s;
}

gchar *belleHeure(gchar *Abuf, gchar *Adst)
{
  gchar *s = Abuf;
  gchar *d = Adst; 
  gint len = 0;
  while (*s && len++<10) {
    if (isdigit(*s) || *s==':') {
      *(d++)=*(s++);
    } else {
      if (*s=='.') break;
      s++;
    }
  }
  *d=0;

  return Adst;
}

gchar *sc_chomp(gchar *Astr)
{
  gchar *s;
  
  if ((s=strrchr(Astr, 13))) *s=0;
  if ((s=strrchr(Astr, 10))) *s=0;

  return Astr;
}

gint sc_strcountv(gchar **Aarray)
{
  gint i = 0;
  
  while (Aarray[i]) i++;
    
  return i;
}

void sc_strstripv(gchar **Aarray)
{
  gint i = 0;
  while (Aarray[i]) g_strstrip(Aarray[i++]);
}

gchar *sc_realloc_cat(gchar *Asep, gchar *Asrc, gchar *Aplus)
{
  gint Llensrc = Asrc ? strlen(Asrc) : 0;
  gint Llenplus = Aplus ? strlen(Aplus) : 0;
  gint Llensep = Aplus && Asep ? strlen(Asep) : 0;

  Asrc = g_realloc(Asrc, (Llensep + Llensrc + Llenplus + 1) * sizeof(gchar));

  if (Llensep)
    strcpy(Asrc + Llensrc, Asep);

  if (Llenplus)
    strcpy(Asrc + Llensrc + Llensep, Aplus);

  return Asrc;
}

/* retourne la valeur d'un combo */
gpointer get_combo_value(GtkWidget *Acombo)
{
  GtkTreeModel *Lmodel = gtk_combo_box_get_model(GTK_COMBO_BOX(Acombo));
  GtkTreeIter Liter;
  gpointer *Lvalue = NULL;
  if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(Acombo), &Liter)) return NULL;

  gtk_tree_model_get(Lmodel, &Liter, 0, &Lvalue, -1);

  return Lvalue;
}

/* retourne la valeur d'un combo sous forme numerique */
gint get_combo_intvalue(GtkWidget *Acombo)
{
  GtkTreeModel *Lmodel = gtk_combo_box_get_model(GTK_COMBO_BOX(Acombo));
  GtkTreeIter Liter;
  gint Lvalue = -1;
  if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(Acombo), &Liter)) return -1;

  gtk_tree_model_get(Lmodel, &Liter, 0, &Lvalue, -1);

  return Lvalue;
}

/* retourne la valeur d'un combo */
gchar *get_combo_value_pos(GtkWidget *Acombo, gint Apos)
{
  GtkTreeModel *Lmodel = gtk_combo_box_get_model(GTK_COMBO_BOX(Acombo));
  GtkTreeIter Liter;
  gchar *Lvalue = NULL;
  if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(Acombo), &Liter)) return g_strdup("");

  gtk_tree_model_get(Lmodel, &Liter, Apos, &Lvalue, -1);

  return Lvalue;
}


gint make_int(gchar *Abuf)
{
  return *Abuf + (Abuf[1] << 8) + (Abuf[2] << 16) + (Abuf[3] << 24);
}

gshort make_short(gchar *Abuf)
{
  return *Abuf + (Abuf[1] << 8);
}

/* format un nombre en chaine de la forme MM:SS */
gchar *format_length(guint64 Alennbr)
{
   guint Lmin = 0, Lsec = 0;

   Lmin = Alennbr / 60;
   if (Lmin>0) Lsec = Alennbr - (Lmin * 60);

   return g_strdup_printf("%02d:%02d", Lmin, Lsec);
}

/* format un nombre en taille de la forme XX Mo ou XX Ko oo XX octets */
gchar *format_size(guint64 Asize)
{
  guint64 Lko = Asize / 1024;
  gdouble Lreste;
  guint64 Lmo;

  if (Lko < 1) return g_strdup_printf("%lld %s", (unsigned long long) Asize, Asize > 1 ? _("octets") : _("MB"));
  Lmo = Lko / 1024;

  if (Lmo < 1) {
    if (Asize - (Lko * 1024) > 511) Lko++;
    return g_strdup_printf(_("%lld K"), (unsigned long long) Lko);
  }

  Lreste = (Lko - (Lmo * 1024));
  Lreste = Lreste / 1024;
  if (Lreste > 0 && Lreste < 1) {
    return g_strdup_printf(_("%lld.%.0f MB"), (unsigned long long) Lmo, Lreste * 10);
  } else {
    return g_strdup_printf(_("%lld MB"), (unsigned long long) Lmo);
  }
}

gboolean sc_str_has_casesuffix(gchar *Astr, gchar *Asuffix)
{
  gchar *Lpos;
  gchar *Lupsuffix = Asuffix;

  if (!*Astr || !*Asuffix || strlen(Asuffix)>strlen(Astr)) return FALSE;

  Lpos = Astr + (strlen(Astr) - strlen(Asuffix));

  while (*Lpos) {
    if (g_ascii_toupper(*(Lpos)++) != g_ascii_toupper(*(Lupsuffix)++)) return FALSE;
  } 
  
  return TRUE;
}

GtkWidget *sc_glade_xml_get_widgetv(GladeXML *Axml, const gchar *Akeyformat, ...) 
{
  va_list Largs;
  gchar *Lkey;
  GtkWidget *Lreturn;

  va_start(Largs, Akeyformat);
  Lkey = g_strdup_vprintf(Akeyformat, Largs);
  va_end(Largs);
  Lreturn = glade_xml_get_widget(Axml, Lkey);
  g_free(Lkey);

  return Lreturn;
}

void sc_line_data_copy(GtkTreeModel *Amodel, GtkTreeIter *Aiterde, GtkTreeIter *Aitervers);
void sc_line_data_copy(GtkTreeModel *Amodel, GtkTreeIter *Aiterde, GtkTreeIter *Aitervers)
{
  gint Ltype;
  GdkPixbuf *Limg;
  gchar *Lstr1, *Lstr2, *Lstr3;
  guint Lsize;
  GtkTreeIter Lcuriter;
  
  gtk_tree_model_get(Amodel, Aiterde, 0, &Ltype, 1, &Limg, 2, &Lstr1, 3, &Lstr2, 4, &Lstr3, 5, &Lsize, -1);
  gtk_tree_store_set(GTK_TREE_STORE(Amodel), Aitervers, 0, Ltype, 1, Limg, 2, Lstr1, 3, Lstr2, 4, Lstr3, 5, Lsize, -1);

  g_free(Lstr1); g_free(Lstr2); g_free(Lstr3);
  g_object_unref(Limg);

  if (Ltype != TYPE_DIR) return;
  if (gtk_tree_model_iter_children(Amodel, &Lcuriter, Aiterde)) {
    GtkTreeIter Lnewiter;
    do {
      gtk_tree_store_append(GTK_TREE_STORE(Amodel), &Lnewiter, Aitervers); 
      sc_line_data_copy(Amodel, &Lcuriter, &Lnewiter);
    } while (gtk_tree_model_iter_next(Amodel, &Lcuriter));
  }
}

/* comparer une chaine avec gestion des caracteres jokers * et ? */

gboolean sc_str_match(gchar *Lpattern, gchar *Lstr);
gboolean sc_str_match(gchar *Lpattern, gchar *Lstr)
{
	gchar c;
	gchar *s;
  if (!Lpattern || !*Lpattern || !Lstr || !*Lstr) return FALSE;

	while (1) {
		switch (c = *Lpattern++) {
			case 0:
				if (!*Lstr) return TRUE;
				return FALSE;
			case '?':
				if (!*Lstr) return FALSE;
				Lstr++;
        break;
			case '*':
				if (!*Lpattern) return TRUE;
				s = Lstr;
        while (*s) {
					if ((*s == *Lpattern) && sc_str_match(Lpattern, s)) return TRUE;
			  	s++;
				}
        break;
      default:
        if (*Lstr++ != c) return FALSE;
        break;
    }
	}
}

/* copie de g_strescape present dans le fichier gstrfuncs.c
 * sans escape des caracteres < 32 et > 128 */
gchar * sc_strescape (const gchar *source)
{
  const guchar *p;
  gchar *dest;
  gchar *q;
  
  g_return_val_if_fail (source != NULL, NULL);

  p = (guchar *) source;
  /* Each source byte needs maximally four destination chars (\777) */
  q = dest = g_malloc (strlen (source) * 4 + 1);


  while (*p)
  {
    switch (*p)
    {
      case '\b':
        *q++ = '\\';
        *q++ = 'b';
        break;
      case '\f':
        *q++ = '\\';
        *q++ = 'f';
        break;
      case '\n':
        *q++ = '\\';
        *q++ = 'n';
        break;
      case '\r':
        *q++ = '\\';
        *q++ = 'r';
        break;
      case '\t':
        *q++ = '\\';
        *q++ = 't';
        break;
      case '\\':
        *q++ = '\\';
        *q++ = '\\';
        break;
      case '"':
        *q++ = '\\';
        *q++ = '"';
        break;
      default:
        *q++ = *p;
        break;
      }
    p++;
  }
  *q = 0;
  return dest;
}

/* fin d'un programme externe, on defini une erreur si il ne s'est pas terminé correctement */
void exit_prog(gint Apid, gboolean Aabort, GError **Aerror, gchar *Adefmsg)
{
  gint Lcmdstatus = 0;

  if (Aabort) {
    kill(Apid, SIGTERM);
    sleep(1);
    kill(Apid, SIGTERM);
  }
  waitpid(Apid, &Lcmdstatus, 0);
  if ((WIFEXITED(Lcmdstatus) && WEXITSTATUS(Lcmdstatus)!=0) || (!(WIFEXITED(Lcmdstatus)))) {
    _DEB("oui une erreur [%d]\n", Lcmdstatus);
    if (Aerror && !*Aerror) {
      g_set_error(Aerror, GRAVEMAN_ERROR, _ERR_UNKNOWN_ERROR, Adefmsg ? Adefmsg : _("Operation failed"));
    }
  }
}

/* creation de tous les repertoires necessaires */
gint sc_mkdir(const gchar *Aname, mode_t Amode) {
  gchar **Llist = g_strsplit(Aname, G_DIR_SEPARATOR_S, 0);
  gchar *Ldir = NULL, *Ltmp = NULL;
  gint Lstatus = TRUE;
  gint i;

  for (i=0; Llist[i]; i++) {
    if (!*Llist[i]) continue;

    if (Ldir) {
      Ltmp = g_strconcat(Ldir, "/", Llist[i], NULL);
      g_free(Ldir);
    } else {
      Ltmp = g_strconcat("/", Llist[i], NULL);
    }
    Ldir = Ltmp;
  
    if (g_file_test(Ldir, G_FILE_TEST_IS_DIR)) continue;

    if (g_file_test(Ldir, G_FILE_TEST_EXISTS)) {
      Lstatus = FALSE;
      break;
    }

    if (mkdir(Ldir, Amode)!=0) {
      Lstatus = FALSE;
      break;
    }
  }
  
  g_free(Ldir);
  g_strfreev(Llist);

  return Lstatus;
}

/* ne retourne que les numeriques d'une chaine */
gboolean get_only_numerics(gchar *Abuffer, gint Abufsize, gchar *Asource, gchar Aend)
{
  gchar *s = Asource;
  gchar *d = Abuffer;
  gint Lnum = 0;

  if (Abufsize<2) return FALSE;
 
  *d=0;
  while (*s && *s != Aend) {
    if (isdigit(*s)) {
      if (++Lnum == Abufsize-1) {
        *Abuffer = 0;
        return FALSE;
      }
      *(d++)=*s;
    }
    s++;
  }
  *d=0;
  
  return TRUE;
}

/* retourne une chaine MM:SS en secondes */
glong get_2time(gchar *Asource)
{
  gchar *s = Asource;
  gchar *e;
  glong Lret = 0;

  while (*s && !isdigit(*s)) s++;
  if (!*s) return -1;
  e=s;

  /* min */
  while (isdigit(*s)) s++;
  *(s++)=0;
  Lret = atol(e) * 60;

  /* sec */
  while (*s && !isdigit(*s)) s++;
  if (!*s) return -1;
  e=s;
  while (isdigit(*s)) s++;
  *(s++)=0;
  Lret += atol(e);
  
  return Lret;
}

gdouble get_pourcent(gchar *Atotal, gchar *Aactu)
{
  glong Lnumtotal = atol(Atotal);
  glong Lnumactu = atol(Aactu);

  if (Lnumtotal == 0) return -1;

  return (1.0/Lnumtotal) * Lnumactu;
}

gchar *tools_next_no_numeric(gchar *Ade)
{
  gchar *Lret = Ade;

  while (*Lret && isdigit(*Lret)) Lret++;

  return *Lret ? Lret : NULL;
}

gchar *tools_next_no_char(gchar *Ade, gchar Acar)
{
  gchar *Lret = Ade;

  while (*Lret == Acar) Lret++;

  return *Lret ? Lret : NULL;
}

gchar *tools_next_putzero(gchar *Asource, gchar Asrc)
{
  gchar *s;
  if ((s=strchr(Asource, Asrc))) {
    *(s++)=0;
    return s;
  }

  return NULL;
}

gboolean read_all_output_callback(GIOChannel *Astd, GIOCondition Acond, gpointer Adata)
{
  GIOStatus Lstatus;
  gchar *Lbuffer = NULL;
  Tgrave *Lg = (Tgrave *) Adata;
  GString *Lstrbuf = (GString *) sc_grave_get_data(Lg, "buffer");
  gint *Lloccont = (gint *) sc_grave_get_data(Lg, "loccont");

  if (Acond == G_IO_HUP || Acond == G_IO_ERR) {
    *Lloccont = 0;
    return FALSE;
  }

  Lstatus = g_io_channel_read_line(Astd, &Lbuffer, NULL, NULL, NULL);  
  if (!Lbuffer) {
    return TRUE;
  }

  Lstrbuf = g_string_append(Lstrbuf, Lbuffer);

  g_free(Lbuffer);

  return TRUE;
}

/* escape each of 'Aescape' characters who are present in Abuf */
gchar *sc_escape(gchar *Abuf, gint Asizemax, gchar *Aescape)
{
  gchar *Adbl = g_strdup(Abuf);
  gint i, j;

  for (i=0, j=0; i < Asizemax && j < Asizemax-1 && Adbl[i]; i++) {
    if (strchr(Aescape, Adbl[i])) {
      Abuf[j++]='\\';
    }
    Abuf[j++]=Adbl[i];
  }
  g_free(Adbl);
  Abuf[j]=0;
 
  return Abuf; 
}

/*
 * vim:et:ts=8:sts=2:sw=2
 */
