          
/* ========================================================================== */
/*                        PREDICATES UTILITIES TO DISPLAY                     */
/* ========================================================================== */

:- module(
          formated_writing,
          [
             write_nvars/1,
             my_numbervars/1,
             display_clause/1,
                                                   		/* display */
             clear/0,
             println/1,
             display_term/1,
             display_ln/1,
             display_list/1,
             writeln_tab/1,  
             writeln_point/1,
             writeln_tab_point/1,
             writeln_list/1,
             write_list_of_lists/1,
             write_list/1,        
             write_elements_list/1,
                                                    /* write to a file */
            fdisplay_clause/2,
            fwrite_term/2,
            fwriteln/2,
            fwrite_tab/2,
            fwriteln_tab/2, 
            fwrite_point2/2,
            fwriteln_point/2,
            fwriteln_tab_point/2,
            fwriteln_list/2,
            fwrite_listf/2,        
            fwrite_elements_list/2,
            fwrite_spaces/2,
            
                                           /* handle internal tabulation */
            reset_tab/0,
            reset_tab/1,
            increment_tab/0,
            increment_tab/1,
            decrement_tab/0,
            decrement_tab/1,
            get_tab/1,
            set_tab/1,
            get_increment_tab/1,
            set_increment_tab/1
          ]
         ). 

/* ========================================================================= */
/*                       FORMATED WRITINGS TO THE SCREEN                     */
/* ========================================================================= */   
        
        /* clear the screen */
clear :-
   shell('clear').      
   
                        /* pass to the next line */
newline :-
        nl.
        
println(T) :-
        print(T),
        nl.
        
                /* affiche Terme avec renommage des variables */
display_term(Term) :-
        copy_term(Term, T),
        numbervars(T, 0, _),            
        write_nvars(T).
        
display_ln(Term) :-
        display_term(Term),
        nl.
        
                        /* affiche une liste, chaque element a la ligne */
display_list([]) :-
        !.
        
display_list([X]) :-
   !,
   display_term(X).
        
display_list([X|L]) :-
        display_term(X),
        write(','),
        display_list(L).   


        /* display a clause in a specific format */               
display_clause((Head, [])) :-
    !,
    display_term(Head),
    write('.'),
    nl.
        
display_clause(C_in) :-
    copy_term(C_in, C),
    my_numbervars(C),
    C = (Head,Body),
    write_nvars(Head),
    write(' :- '),
    display_body(Head, Body).
   
display_body(_Head, [X]) :-
   !,
   write_nvars(X),
   write('.'),
   nl.
  
display_body(Head, [X|Body]) :-
   write_nvars(X),
   write(', '),
   display_body(Head, Body).
                
/* =============================== WRITE TERMS ============================== */

        /* specific numbervars */
my_numbervars(X) :-
   numbervars(X, 0, _).

        /* write term according to numbervars convention */
write_nvars(X) :-
   write_term(X, [numbervars(true)]).
   
writeln_nvars(X) :-
   write_nvars(X),
   nl.

        /* writeln a term (without point) */
write_tab(Term) :-
   get_tab(Tab),
   tab(Tab),
   write(Term).
   
        /* writeln a term (without point) */
writeln_tab(Term) :-
   write_tab(Term),
   nl.
      
        /* write a line containing Term */
writeln_point(Term) :-
   write(Term),
   write('.'),
   nl.
   
        /* write a line containing Term with Tab spaces */
writeln_tab_point(Term) :-
   get_tab(Tab),
   tab(Tab),
   write(Term),
   write('.'),
   nl.      


        /* write a line containing Term with Tab spaces */
writeln_tab_point(Term) :-
   get_tab(Tab),
   tab(Tab),
   write(Term),
   write('.'),
   nl.           
     
/* ==========================  WRITE A LIST ================================ */
          
           /* write each element of the list L */  
writeln_list([]) :-
   !.
   
writeln_list([X|L]) :-
   writeln(X),
   writeln_list(L).     

        /* write a list of lists */   
write_list_of_lists([]) :-
   !.
   
write_list_of_lists([L|LL]) :-
   write_list(L),
   write_list_of_lists(LL).
   
/* ========================== WRITE FORMATED LISTS ========================== */   
   
           /* write into each the elements of the list L */        
write_list([]) :-
   !,
   writeln([]).
           
write_list(L) :-
   writeln_tab('['),
   increment_tab,
   write_elements_listf(L),
   decrement_tab,
   write_tab(']'). 
   
        /* write into elements of the list L 
           with one element per line */
write_elements_list([]) :-
   !.

write_elements_list([X]) :- 
   !,
   write_element(X),
   nl.
   
write_elements_list([X|L]) :-
   write_element(X),
   writeln(','),
   write_elements_list(L).   
   
        /* display the current element of a list on the screen */   
write_element(X) :-
   is_list(X),
   !,
   write_list(X).
   
write_element(X) :-
   write_tab(X).
   
                  
/* ========================================================================= */
/*                       FORMATED WRITINGS INTO A FILE                       */
/* ========================================================================= */

/* ==========================  write a single element ====================== */
			
        /* writeln a term (without point) */
fwriteln(Out, Term) :-
   write(Out, Term),
   nl(Out).
 
        /* writeln a term (without point) */
fwrite_tab(Out, Term) :-
   get_tab(Tab),
   fwrite_spaces(Out, Tab),
   write(Out, Term).
 
        /* writeln a term (without point) */
fwriteln_tab(Out, Term) :-
   fwrite_tab(Out, Term),
   nl(Out).
           
        /* write a line containing Term in a prolog file */
fwrite_point2(Out, Term) :-
   write(Out, Term),
   write(Out,'.').  
  
        /* write a line containing Term in a prolog file */
fwriteln_point(Out, Term) :-
   fwrite_point2(Out, Term),
   nl(Out).
   
        /* write a line containing Term in a prolog file with Tab spaces */
fwriteln_tab_point(Out, Term) :-
   get_tab(Tab),
   write_spaces(Out, Tab),
   write(Out, Term),
   write(Out,'.'),
   nl(Out).   
   
 /* ================================= write any term ========================= */ 
  
	/* write a term in a file */  	
fwrite_term(Out, Term) :-
   is_list(Term),
   !,
   fwrite_listf(Out, Term).
   
fwrite_term(Out, Term) :-
   compound(Term),
   !,
   fwrite_compound_term(Out, Term).
    
fwrite_term(Out, Term) :-
 fwrite_tab(Out, Term).
 

fwrite_compound_term(Out, Term) :-
   Term =..[Functor|LArgs],
   fwrite_tab(Out, Functor),
   fwriteln(Out, '('),
   atom_length(Functor, N),
   T1 is N+1,                % espace pour functeur
   T2 is T1 + 2,             % espace apres parentheses
   increment_tab(T2),
   fwrite_arguments(Out, LArgs),
   decrement_tab(2),
   fwrite_tab(Out,')'),
   decrement_tab(T1).


   		% dernier argument
fwrite_arguments(Out, [X]) :-
   !,
   fwrite_term(Out, X),
   nl(Out).
   		
   		% reste plusieurs arguments
fwrite_arguments(Out, [X|L]) :-
   fwrite_term(Out, X),
   fwriteln(Out, ','),
   fwrite_arguments(Out, L).
 
 
/* ================================ write a list ============================== */   
 
            /* write into the file Out each element of the list L with Tab spaces */  
fwriteln_list(_Out, []) :-
   !.
   
fwriteln_list(Out, [X|L]) :-
   fwriteln_point(Out, X),
   fwriteln_list(Out, L).       
       

           /* write into the file Out each the elements of the list L */    
fwrite_listff(Out, []) :-
   !,
   fwriteln(Out, []).
           
fwrite_listf(Out, L) :-
   fwriteln_tab(Out, '['),
   increment_tab,
   fwrite_elements_list(Out, L),
   decrement_tab,
   fwrite_tab(Out, ']'). 
   
   
        /* write into the file Out elements of the list L 
           with one element per line */
fwrite_elements_list(_Out, []) :-
   !.

fwrite_elements_list(Out, [X]) :- 
   !,
   fwrite_element(Out, X),
   nl(Out).
   
fwrite_elements_list(Out, [X|L]) :-
   fwrite_element(Out, X),
   fwriteln(Out, ','),
   fwrite_elements_list(Out, L).
   
        /* write the current element X of a list */
fwrite_element(Out, X) :-
   is_list(X),
   !,
   fwrite_listf(Out, X).
   
fwrite_element(Out, X) :-
   fwrite_tab(Out, X).
   

       /* write spaces */   
fwrite_spaces(_Out, 0) :-
   !.
   
fwrite_spaces(Out, N) :-
   write(Out, ' '),
   N1 is N-1,
   fwrite_spaces(Out, N1).

/* ===================== DISPLAY A CLAUSE (in a file) ======================= */     
      
  /* display a clause in a specific format */               
fdisplay_clause(Clause, Stream) :-
   current_output(Output),
   set_output(Stream),
   display_clause(Clause),
   set_output(Output).
  
/* ========================================================================== */
/*                       HANDLE A TABULATION COUNTER                          */
/* ========================================================================== */        
   
:- dynamic current_tabulation/1. 
:- dynamic current_increment_tabulation/1.     
   
/*  ------------------------ Internal values ------------------------------- */

        /* default value of the tabulation */
default_tabulation(0).


    /* current value of the internal tabulation */
current_tabulation(0).    
 
        /* default value of increment of the tabulation */
default_increment_tabulation(3).        


        /* current value of the increment of the tabulation */  
current_increment_tabulation(3).


reset_all_tab :-
   retractall(current_tabulation(_)),
   default_tabulation(T1),
   assert(current_tabulation(T1)),
   retractall(current_increment_tabulation(_)),
   default_increment_tabulation(T2),
   assert(current_increment_tabulation(T2)).
   

/* ------------------------- public predicates ---------------------------- */

    /* increment the internal tabulation */
increment_tab :-
   get_tab(T),
   get_increment_tab(Inc),
   T1 is T + Inc,
   set_tab(T1).

increment_tab(Inc) :-
   get_tab(T),
   T1 is T + Inc,
   set_tab(T1).
   
    /* decrement the internal tabulation */
decrement_tab :-
   get_tab(T),
   get_increment_tab(Inc),
   T1 is T - Inc,
   T2 is max(0, T1), 
   set_tab(T2).
   
decrement_tab(Inc) :-
   get_tab(T),
   T1 is T - Inc,
   T2 is max(0, T1), 
   set_tab(T2).   
  
    /* change the value of the internal increment tabulation */
get_increment_tab(T) :-   
   current_increment_tabulation(T).
   
   /* change the value of the internal increment tabulation */
set_increment_tab(T) :-  
   integer(T),
   T >= 0,
   !,
   retract(current_increment_tabulation(_)),
   assert(current_increment_tabulation(T)).
   
set_increment_tab(_).   
   
   /* put the increment of the tabulation to its initial value */
reset_increment_tab :-
   retract(current_increment_tabulation(_)),
   default_increment_tabulation(T),
   assert(current_increment_tabulation(T)).
   
reset_increment_tab(T) :-
   retract(current_increment_tabulation(_)),
   assert(current_increment_tabulation(T)).   
   
   
   /* get the current value of the internal tabulation */
get_tab(T) :-
   current_tabulation(T).
   
   /* put the tabulation to its initia value */
reset_tab :-
   default_tabulation(T),
   set_tab(T).
   
reset_tab(T) :-
   set_tab(T).   
        
   /* change the value of the internation tabulation */
set_tab(T) :-  
   integer(T),
   T >= 0,
   !,
   retract(current_tabulation(_)),
   assert(current_tabulation(T)).

set_tab(_).
  
     
/* ============================= END OF LISTING ====================================== */
   
