/* Zweck: Stelle Baumterme mit dem Programm /bin/dot graphisch dar.
   Autor: H.Leiss,                   28.7.2002, angepaßt an CL-2: 21.11.2005

   Siehe das Handbuch dazu unter Unix: man dot  ...

   Man bekommt dot von AT&T als Teil des Graphikpakets graphviz unter
      http://www.research.att.com/sw/tools/graphviz/download.html

   Ein Baumterm ist eine Liste [Cat|SubTrees], worin
   - Cat eine Kategorie der Grammatik ist
     (atomar: Kategoriename als Funktionszeichen, Merkmale als Argumente,
   - SubTrees die Liste Baumterm der direkten Teilbäume.

   Der Baum ordnet die Blätter auf einer Grundlinie entsprechend den Wörtern
   des Eingabeausdrucks an.

*/

:- module(display_tree,[displayTrees/1,displayTree/1]).
                        
/* Schreibe eine Liste <Terme> von Prolog-Termen als Bäume im .dot-Format auf die
   Datei <Datei>.tmp.dot : */

showTrees(Terme,Datei) :-
        concat(Datei,'.tmp.dot',File),
        tell(File),
        dot(Terme),
        told.

dot([Term|Terme]) :-
        nl,
        (ground(Term) ->
            write('digraph syntaxbaum {'),
            write('\ncenter=true; size=\"7.5,14\";\
                   \nratio=compress; ordering=out;\
                   \nedge[dir=none]; node[shape=plaintext];\n'),
            drawTree(Term),
            write('}')
        ; write(user,'Fehler: der darzustellende Term \"'),
            writeq(user,Term),
            write(user, '\" enthält freie Variable!\n')
        ),
        dot(Terme).
dot([]).
drawTree(Term) :-
    drawTree(Term,0,_,[],[],BlattfolgeR,[]),
    reverse(BlattfolgeR,Blattfolge),
    order(Blattfolge).

order(Blattfolge) :-
    write('{ rank=same ; '),
    write_list(Blattfolge,' ; '),
    write('};\n'),
    write('subgraph {edge[style=invis]; '), % Blaetter
    write_list(Blattfolge,' -> '),          % auf einer Linie
    write(' }\n').                          % anordnen

write_list([A,B|Bs],Atom) :-
    write(A),write(Atom),write_list([B|Bs],Atom).
write_list([A],_) :-
    write(A).
write_list([],_).

/* drawTree(+Term,+Wurzelnummer,-naechste nicht verbrauchte Knotennummer)  */

drawTree([Term],N,K,AkkL,AkkR,[N|AkkL],AkkR) :-
        atom(Term),
        !,
        write(N),
        write(' [fontcolor = blue, label = "'),write(Term),write('"];'),
        write('\n'),
        K is N+1.

drawTree([Kategorie,(Arg1,Arg2)],N,K,AkkL,_,NAkkL,NAkkR) :-
        !,
        write(N),
        write(' [label = "'),write(Kategorie),write('"];\n'),
        M is N+1,
        drawTrees([Arg1],N,M,L,AkkL,[],NAkkL,[]),
        drawTrees([Arg2],N,L,K,[],[],NAkkR,[]).

drawTree([Kategorie|Args],N,K,AkkL,AkkR,AkkLN,AkkRN) :-
        !,
        write(N),write(' [label = \"'),write(Kategorie),write('\"];\n'),
        M is N+1,
        drawTrees(Args,N,M,K,AkkL,AkkR,AkkLN,AkkRN).

list([]).
list([_|L]) :- list(L).

/* Nachfolger von Baum N, ab Nummer M bis Nummer K fuer deren Knoten */

drawTrees([Arg|Args],N,M,K,AkkL,AkkR,NAkkL,NAkkR) :-
        write(N), write(' -> '), write(M), write(' ;\n'),        
        drawTree(Arg,M,K1,AkkL,AkkR,NAkkL1,NAkkR1),
        drawTrees(Args,N,K1,K,NAkkL1,NAkkR1,NAkkL,NAkkR).

drawTrees([],_,M,M,AkkL,AkkR,AkkL,AkkR).

/* Anzeigen der Bäume am Bildschirm: */

displayTree(Term) :-
        displayTrees([Term]).

displayTrees(Terme) :-
        showTrees(Terme,testbaum),
        viewgraph(testbaum).

viewgraph(Datei) :-
       concat_atom(['dot -Tps ',Datei,'.tmp.dot ',' -o',Datei,'.tmp.ps '],Command1),
       % Kleiner: concat_atom(['gv -magstep -2 ',Datei,'.tmp.ps &\n'],Command2),
       concat_atom(['gv ',Datei,'.tmp.ps &\n'],Command2),
       shell(Command1),
       shell(Command2).

/* Beispiel: Baumkodierung wie in CL-2, nicht wie in Satzgrammatik

displayTree([np([def, 3, mask], [sg, nom]),
               [det([def], [mask, sg, nom]), [der]],
               [rn([mask], [sg, nom]), ['Planet']],
               [np([def, 3, fem], [sg, gen]),
                  [det([def], [fem, sg, gen]), [der]],
                  [en([fem], [sg, nom]), ['Venus']]]]).

*/


