next up previous contents
Next: Programme principal Up: Implémentation du simulateur de Previous: Outils de trace

Multifenétrage textuel


/*****************************************************************************/
/*                                                                           */
/* Fenetres en mode texte                                                    */
/*                                                                           */
/*****************************************************************************/

:-module(windows,
    [
        win_init/2,
        win_open/6,
        win_close/1,
        win_write/2,
        win_write/3,
        win_nl/1,
        win_clear/1,
        win_pos/3,
        draw_windows/0,
        win_link/1
    ]
).

:-use_module(tools).

test:-
    win_init(80,25),
    win_open(my_window,10,10,50,20,"Hello world"),
    for(I,1,10,win_write(my_window,"I=%t\n",[I])),
    win_write(my_window,"Hallo Welt\n"),
    draw_windows,
    win_write(my_window,"Salut monde\n"),
    draw_windows,
    win_clear(my_window),
    win_write(my_window,"That's all folks...........\n..."),
    draw_windows,
    win_close(my_window).

/*  win_descr(W,X1,Y1,X2,Y2,TITLE)
 *  W : handle
 *  W est le nom du module contenant les caracteres
 */

/*  W:char(X,Y,CH)
 */

win_init(MAXX,MAXY):-
    retractall(maxXY(_,_)),
    asserta(maxXY(MAXX,MAXY)),
    retractall(real_char(_,_,_)),
    forall(win_descr(W,_,_,_,_,_),retractall(W:char(_,_,_))),
    retractall(win_descr(_,_,_,_,_,_)),
    forall(recorded(win_pos,_,K),erase(K)),
    retractall(link(_,_)),
    !.

:-dynamic
    win_descr/6,
    real_char/3.

:-index(win_descr(1,0,0,0,0,0)).
:-index(real_char(1,1,0)).

win_open(W,X1,Y1,X2,Y2,TITLE):-
    (   var(W)
    ->  gen_sym(win_,W)
    ;   true
    ),
    (   win_descr(W,_,_,_,_,_)
    ->  error("Fenetre deja definie : %t\n",[W])
    ;   true
    ),
    (   is_list(TITLE)
    ->  THE_TITLE=TITLE
    ;   name(TITLE,THE_TITLE)
    ),
    assertz(win_descr(W,X1,Y1,X2,Y2,THE_TITLE)),
    dynamic(W:char/3),
    index(W:char(1,1,0)),
    win_clear(W),
    !.

win_close(W):-
    (   clause(win_descr(W,_,_,_,_,_),_,REF)
    ->  win_clear(W),
        erase(REF),
        W:retractall(char(_,_,_))
    ;   error("Fenetre non ouverte : %t\n",[W])
    ),
    retractall(link(W,_)),
    retractall(link(_,W)),
    !.

win_clear(W):-
    W:retractall(char(_,_,_)),
    (   recorded(win_pos,W=(_,_),REF)
    ->  erase(REF)
    ;   true
    ),
    recordz(win_pos,W=(1,1)),
    !.

win_pos(W,X,Y):-
    recorded(win_pos,W=(X,Y)),
    !.

win_put(W,CH):-
    recorded(win_pos,W=(X,Y),REF),
    erase(REF),
    W:retractall(char(X,Y,_)),
    (   (   CH=10
        ;   CH=13
        )
    ->  X1=1,
        (   win_descr(W,_,Ym,_,YM,_),
            Y is YM-Ym-1
        ->  win_scroll(W,fail),
            Y1=Y
        ;   Y1 is Y+1
        )
    ;   X1 is X+1,
        Y1=Y,
        W:assertz(char(X,Y,CH))
    ),
    recordz(win_pos,W=(X1,Y1)),
    !.

win_scroll(W,LINK):-
    findall(char(X,Y,CH),W:char(X,Y,CH),CHARS),
    retractall(W:char(_,_,_)),
    forall(member(char(X,Y,CH),CHARS),
        (   (   Y>1
            ->  Y1 is Y-1,
                W:assertz(char(X,Y1,CH))
            ;   true
            )
        )
    ),
    (   LINK
    ->  recorded(win_pos,W=(X,Y),REF),
        erase(REF),
        (   Y>1
        ->  Y1 is Y-1
        ;   Y1 is 1
        ),
        recordz(win_pos,W=(X,Y1))
    ;   forall(
            link(W,WL),
            win_scroll(WL,true)
        )
    ),
    !.

win_write(W,FORMAT):-
    win_write(W,FORMAT,[]),
    !.
    
win_write(W,FORMAT,ARGS):-
    swritef(ST,FORMAT,ARGS),
    string_to_list(ST,LST),
    win_put_all(W,LST),
    !.

win_nl(W):-
    win_write(W,"\n"),
    !.

win_put_all(_,[]):-!.
win_put_all(W,[CH|ST]):-
    win_put(W,CH),
    win_put_all(W,ST),
    !.

:-dynamic used/2.

:-index(used(1,1)).

draw_windows:-
    retractall(real_char(_,_,_)),
    forall(win_descr(W,X1,Y1,X2,Y2,TITLE),
        (   retractall(win_adjust(_,_,_,_)),
            asserta(
                (   win_adjust(XA,YA,XB,YB):-
                        XB is XA+X1,
                        X1 < XB, XB < X2,
                        YB is YA+Y1+1,
                        Y1+1 < YB, YB < Y2
                )
            ),
            length(TITLE,L),
            XT is (X1+X2-L)>>1,
            YT is Y1+1,
            draw_title(XT,YT,TITLE),
            forall(W:char(X,Y,CH),draw_char(X,Y,CH)),
            box(X1,Y1,X2,Y2)
        )
    ),
    maxXY(MAXX,MAXY),
    nl,
    (   feature(unix,true)
    ->  tty_clear,
        retractall(used(_,_)),
        forall(
            (   real_char(X,Y,CH),
                \+ used(X,Y)
            ),
            (   tty_goto(X,Y),
                format('~c',[CH]),
                asserta(used(X,Y))
            )
        ),
        retractall(used(_,_)),
        tty_goto(1,MAXY),
        nl
    ;   for(Y,1,MAXY,
            (   for(X,1,MAXX,
                    (   (   real_char(X,Y,CH)
                        ->  format('~c',[CH])
                        ;   format(' ')
                        )
                    )
                ),
                nl
            )
        )
    ),
    retractall(real_char(_,_,_)),
    !.

draw_title(_,_,[]):-!.
draw_title(X,Y,[CH|ST]):-
    assertz(real_char(X,Y,CH)),
    X1 is X+1,
    draw_title(X1,Y,ST),
    !.

draw_char(X,Y,CH):-
    (   win_adjust(X,Y,XD,YD)
    ->  assertz(real_char(XD,YD,CH))
    ;   true
    ),
    !.

box(X1,Y1,X2,Y2):-
    YT is Y1+1,
    for(X,X1,X2,
        (   asserta(real_char(X,Y1,0'-)),
            asserta(real_char(X,Y2,0'-)),
            assertz(real_char(X,YT,0'_))
        )
    ),
    for(Y,Y1+1,Y2-1,
        (   asserta(real_char(X1,Y,0'|)),
            asserta(real_char(X2,Y,0'|))
        )
    ),
    !.

:-dynamic link/2.

win_link([]):-!.
win_link([_]):-!.
win_link([WIN|LINKED_WIN_LIST]):-
    (   member(LINKED_WIN,LINKED_WIN_LIST),
            assertz(link(WIN,LINKED_WIN)),
            assertz(link(LINKED_WIN,WIN)),
            fail
    ;   win_link(LINKED_WIN_LIST)
    ).
win_link(_).



Christophe Delord
1998-09-02