/*
 *   This file is part of VBA Express.
 *
 *   Copyright (c) 2005-2006 Achraf cherti <achrafcherti@gmail.com>
 * 
 *   VBA Express 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.
 *
 *   VBA Express 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 VBA Express; if not, write to the Free Software
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

/**************************************
 * chargement et sauvegarde des
 * fichiers ini
 *
 * Auteur: Achraf cherti
 * Email:  achrafcherti@gmail.com
 *************************************/

#ifndef _LCFG_H
#define _LCFG_H

#ifdef __cplusplus
   extern "C" {
#endif

#define LCFG_OK        0
#define LCFG_E_FOPEN   1 // load ou save: err
#define LCFG_E_OUTMEM  2
#define LCFG_E_FCLOSE  3
#define LCFG_E_FWRITE  4 // n'a pas pu tout écrire
#define LCFG_E_FREAD   5 // n'a pas pu tout lire...

#define LCFG_E_FFORMAT 6 // quand il charge un fichier binaire 
	                     // qui a un header incorrect ou
						 // qu'une donnée de type est incorrecte...
#define LCFG_E_NEXIST   7
#define LCFG_E_SECTION  8   //section sélectionnée invalide (debut>fin)

#define LCFG_T_LINE    1
#define LCFG_T_VAR     2
#define LCFG_T_SECTION 3
#define LCFG_T_COMMENT_VAR 4

typedef struct {
	char type; // LCFG_T_*
	
	char *var; // contient soit la section, var ou line.
	char *value; // si var=var alors contient la valeur de la var, sinon 0.
	
	char *comment; // contient comment qu'il y a après une var=var # comment
	
	char *extra;   //utilisé pour mettre quelque chose de plus (dans LCFG_T_COMMENT, ça sert à réinitialiser la ligne comme elle était)
	char guillemet; // nonz si guillemets
} LCFG_ELEMENT;

typedef struct {
	LCFG_ELEMENT *el;
	int s_el; //nombre d'éléments...

	// Pour le fichier
	const char *password; // LE mot de passe de cryptage!
	char binary; // si fichier binaire

	// personnalisation
	char default_comment; //par défaut '#'
	char default_equal;   // par défaut '='
	char autoindent;      // 0 si non, 1,nonz (défaut) pour oui!

	char uncomment_var;   // quand il y a une variable commentée, la décommenter pour y mettre la valeur... par exemple: #var=salut devint var=contenunouvau

	// bouding
	int begin, end;       // début et fin de recherche
	                      // sert surtout pour les sections!
						  // par défaut: begin,end=0,-1
} LCFG;

/************************************
 * création de lcfg
 ***********************************/
void lcfg_new(LCFG *lcfg, char binary);

//-------------------------------------------------
// Ajout d'un élément dans un lcfg...
// si pas assez de mémoire retourne LCFG_E_OUTMEM
//-------------------------------------------------

// Changer variable, si elle existe
// si elle n'existe pas elle est ajoutée au début (dans begin,
// ou si on veut dans le début de la section).
int lcfg_var_value_ex(LCFG *lcfg, const char *var, const char *value, const char *comment);
int lcfg_var_value(LCFG *lcfg, const char *var, const char *value);
int lcfg_var_comment(LCFG *lcfg, const char *var, const char *comment);

// ajoute: n = n # comment
int lcfg_a_var(LCFG *lcfg, const char *var, const char *value);
int lcfg_a_var_ex(LCFG *lcfg, const char *var, const char *value, const char *comment);

// ajoute: [ section ]
int lcfg_a_section(LCFG *lcfg, const char *section);
int lcfg_a_section_ex(LCFG *lcfg, const char *section, const char *comment);

// ajoute: # commentaire 
int lcfg_a_comment(LCFG *lcfg, const char *comment);

// Ajoute: une ligne vide...
int lcfg_a_void(LCFG *lcfg);

/*************************************
 * personnalisation
 ************************************/

// cette fonction doit être mise avant load ou save.
// quand elle est déclarée une fois tout les load 
// et save qui suivent utiliserons password
// Attention: le pointeur password est copié dans un
// pointeur statique (*default_password) donc si vous
// modifiez le contenu de la place mémoire pointée par
// *password le password se modifiera. Evitez cela!
void lcfg_set_password(const char *password); // REVISEE

//donne l'ordre de décommenter les variables lors de l'ouverture d'un fichier
void lcfg_set_uncomment_var(char enabled);

// ces trois fonctions doivent êtres mises avant 
// *load* ou *_init
void lcfg_set_equal(char equal);        // change par exemple = par :
void lcfg_set_comment(char comment);    // change par exemple # par '

void lcfg_set_guillemet(int enabled);   // les guillemets (par défaut 1):
void lcfg_set_autoindent(int enabled);  // Indentation automatique lors
                                        // de la sauvegarde en texte

// Lecture numérique
// retournent 0 si pas trouvé...
int lcfg_get_double(LCFG *lcfg, const char *var, double *out); // REVISEE
int lcfg_get_long(LCFG *lcfg, const char *var, long *out);     // REVISEE
int lcfg_get_int(LCFG *lcfg, const char *var, int *out);       // REVISEE

// spécifie que toutes les lectures se ferons dans section
// retourne nonz si section n'existe pas.
int lcfg_set_section(LCFG *lcfg, const char *section);  //REVISEE

// retourne un pointeur vers la chaine qui contient la valeur
// de var.
// cette chaine est malloquée. Et ne dois pas être modifiée.
char *lcfg_get_value(LCFG *lcfg, const char *var); //REVISEE

// désallocation
// (l'appeler après avoir fini avec un lcfg chargé)
// Attention: ne jamais appeler cette fonction avant la
// sauvegarde.
void lcfg_free(LCFG *lcfg); // REVISEE

/****************************************
 * chargement/save
 ****************************************/
// chargement/save automatique:
// détete si texte ou binaire, puis le charge...
int lcfg_load(LCFG *lcfg, const char *filename); // REVISEE

// sauver sous
//
// Quand on sauve sous un autre nom ou un autre format,
// le format binary et filename interne ne change pas.
// Il faut les changer manuellement si on le souhaite
// lcfg->filename="newname.cfg"
// lcfg->binary=1
//
// par ex.
int lcfg_save(LCFG *lcfg, const char *filename); // REVISEE
int lcfg_save_ex(LCFG *lcfg, const char *filename, char binary); //REVISEE

// forcer un chargement... Par exemple si binary=1 forcer
// un chargement binaire et si c'est pas un binaire alors
// erreur!
int lcfg_load_ex(LCFG *lcfg, const char *filename, char binary); // REVISEE

#ifdef __cplusplus
}
#endif

#endif

