rem: operation = gtk_object_get_data ( GTK_OBJECT ( formulaire ),
add: transaction = gtk_object_get_data ( GTK_OBJECT ( formulaire ),
context: gboolean fin_edition ( void ){    struct structure_operation *operation;    gint modification;    GSList *liste_no_tiers;    GSList *liste_tmp;    /* récupération de l'opération : soit l'adr de la struct, soit NULL si nouvelle */    operation = gtk_object_get_data ( GTK_OBJECT ( formulaire ),				      "adr_struct_ope" );    if ( operation )	modification = 1;    else	modification = 0;    /*     on donne le focus à la liste, pour que le widget en cours perde le focus */    /* 	et applique les modifs nécessaires */    gtk_widget_grab_focus ( gsb_account_get_tree_view (compte_courant) );       /* on commence par vérifier que les données entrées sont correctes */    /* si la fonction renvoie false, c'est qu'on doit arrêter là */    if ( !verification_validation_operation ( operation ))	return FALSE;    /* si le tiers est un état, on va faire autant d'opérations qu'il y a de tiers       dans l'état concerné. On va créer une liste avec les nos de tiers       ( ou -1, le tiers n'est pas un état), puis on fera une boucle sur cette liste       pour ajouter autant d'opérations que de tiers */    liste_no_tiers = NULL;    /*     on vérifie que le champ tiers existe... */    if ( verifie_element_formulaire_existe ( TRANSACTION_FORM_PARTY ))    {	if ( strncmp ( g_strstrip ( gtk_combofix_get_text ( GTK_COMBOFIX ( widget_formulaire_par_element (TRANSACTION_FORM_PARTY) ))),		       COLON(_("Report")),		       7 ))	    /*     ce n'est pas un état, on met -1 comme no de tiers */	    liste_no_tiers = g_slist_append (liste_no_tiers,					     GINT_TO_POINTER ( -1 ));	else	{	    /* c'est bien un état */	    /* on commence par retrouver le nom de l'état */	    /* toutes les vérifications ont été faites précédemment */	    gchar **tableau_char;	    struct struct_etat *etat;	    GSList *liste_opes_selectionnees;	    tableau_char = g_strsplit ( g_strstrip ( gtk_combofix_get_text ( GTK_COMBOFIX ( widget_formulaire_par_element (TRANSACTION_FORM_PARTY) ))),					":",					2 );	    if ( tableau_char[1] )	    {		tableau_char[1] = g_strstrip ( tableau_char[1] );		liste_tmp = liste_struct_etats;		etat = NULL;		while ( liste_tmp )		{		    etat = liste_tmp -> data;		    if ( !strcmp ( etat -> nom_etat,				   tableau_char[1] ))			liste_tmp = NULL;		    else			liste_tmp = liste_tmp -> next;		}		g_strfreev ( tableau_char );		/* à ce niveau, etat contient l'adr le la struct de l'état choisi */		liste_opes_selectionnees = recupere_opes_etat ( etat );		liste_tmp = liste_opes_selectionnees;		while ( liste_tmp )		{		    struct structure_operation *operation;		    operation = liste_tmp -> data;		    if ( !g_slist_find ( liste_no_tiers,					 GINT_TO_POINTER ( operation -> tiers )))			liste_no_tiers = g_slist_append ( liste_no_tiers,							  GINT_TO_POINTER ( operation -> tiers ));		    liste_tmp = liste_tmp -> next;		}		g_slist_free ( liste_opes_selectionnees );	    }	}    }    else	/* 	il n'y a pas de tiers, donc ce n'est pas un état */	liste_no_tiers = g_slist_append (liste_no_tiers,					 GINT_TO_POINTER ( -1 ));    /* à ce niveau, liste_no_tiers contient la liste des no de tiers pour chacun desquels on */    /* fera une opé, ou -1 si on utilise que le tiers dans l'entrée du formulaire */    /* on fait donc le tour de cette liste en ajoutant l'opé à chaque fois */    liste_tmp = liste_no_tiers;    while ( liste_tmp )    {	/* soit on va chercher le tiers dans la liste des no de tiers et on le met dans le formulaire, */	/* soit on laisse tel quel et on met liste_tmp à NULL */	if ( liste_tmp -> data == GINT_TO_POINTER ( -1 ) )	    liste_tmp = NULL;	else	{	    if ( !liste_tmp -> data )	    {		dialogue_error ( _("No third party selected for this report."));		return FALSE;	    }	    else	    {		gtk_combofix_set_text ( GTK_COMBOFIX ( widget_formulaire_par_element (TRANSACTION_FORM_PARTY) ),					tiers_name_by_no ( GPOINTER_TO_INT (liste_tmp -> data), TRUE ));		/* si le moyen de paiement est à incrémentation automatique, à partir de la 2ème opé, */		/* on incrémente le contenu (no de chèque en général) */		/* comme c'est une liste de tiers, c'est forcemment une nouvelle opé */		/* donc si operation n'est pas nul, c'est qu'on n'est pas sur la 1ère */		/* donc on peut incrémenter si nécessaire le contenu */		/* et on peut récupérer le no_type de l'ancienne opé */		if ( operation )		{		    struct struct_type_ope *type;		    type = type_ope_par_no ( operation -> type_ope,					     compte_courant );		    if ( type			 &&			 type -> affiche_entree			 &&			 type -> numerotation_auto			 &&			 verifie_element_formulaire_existe ( TRANSACTION_FORM_CHEQUE ))			gtk_entry_set_text ( GTK_ENTRY ( widget_formulaire_par_element (TRANSACTION_FORM_CHEQUE) ),					     automatic_numbering_get_new_number ( type ));		}		liste_tmp = liste_tmp -> next;	    }	}	/* si c'est une nouvelle opé, on la crée en mettant tout à 0 sauf le no de compte et la devise */	if ( !modification )	{	    operation = calloc ( 1,				 sizeof ( struct structure_operation ) );	    if ( !operation )	    {		dialogue_error ( _("Cannot allocate memory, bad things will happen soon") );		return FALSE;	    }	    operation -> no_compte = compte_courant;	    /* 	    la devise par défaut est celle du compte, elle sera modifiée si nécessaire plus tard */	    operation -> devise = gsb_account_get_currency (compte_courant);	}	/* on récupère les données du formulaire sauf la categ qui est traitée plus tard */	recuperation_donnees_generales_formulaire ( operation );	/* il faut ajouter l'opération à la liste à ce niveau pour lui attribuer un numéro */	/* celui ci sera utilisé si c'est un virement ou si c'est une ventil qui contient des */	/* virements */	if ( modification )	    modifie_operation ( operation );	else	    ajout_operation ( operation );	/*   récupération des catégories / sous-catég, s'ils n'existent pas, on les crée */	/* à mettre en dernier car si c'est une opé ventilée, chaque opé de ventil va récupérer les données du dessus */	recuperation_categorie_formulaire ( operation,					    modification );    }    /* on libère la liste des no tiers */    g_slist_free ( liste_no_tiers );    /* si on est en train d'équilibrer => recalcule le total pointé */    if ( etat.equilibrage )	calcule_total_pointe_compte ( compte_courant );    /* si c'était une nouvelle opération, on efface le formulaire,       on remet la date pour la suivante,       si c'était une modification, on redonne le focus à la liste */    formulaire_a_zero ();    if ( modification )    {	if ( !etat.formulaire_toujours_affiche )	    gtk_widget_hide ( frame_droite_bas );    }    else    {	/* 	c'est une nouvelle opé, on sauvegarde la dernière date */	GtkWidget *entree_date;	entree_date = widget_formulaire_par_element (TRANSACTION_FORM_DATE);	derniere_date = g_strdup ( gtk_entry_get_text ( GTK_ENTRY ( entree_date )));	clique_champ_formulaire ( entree_date,				  NULL,				  GINT_TO_POINTER ( TRANSACTION_FORM_DATE ) );	gtk_entry_select_region ( GTK_ENTRY ( entree_date ), 0, -1);	gtk_widget_grab_focus ( GTK_WIDGET ( entree_date ) );    }    /* met à jour les listes ( nouvelle opération associée au tiers et à la catégorie ) */    if ( mise_a_jour_combofix_tiers_necessaire )	mise_a_jour_combofix_tiers ();    if ( mise_a_jour_combofix_categ_necessaire )	mise_a_jour_combofix_categ ();    if ( mise_a_jour_combofix_imputation_necessaire )	mise_a_jour_combofix_imputation ();    /*     on affiche un avertissement si nécessaire */    affiche_dialogue_soldes_minimaux ();    update_transaction_in_trees ( operation );    modification_fichier ( TRUE );    return FALSE;}