%           -------------------------------------------------------
%           Ein einfacher klauselorientierter Editor fr TOY Prolog
%
%                 (c) 1983 Kluzniak/Szpakowicz, IIUW Warszawa
%            nderungen fr TOY Prolog ST V4  (c) 1987 Jens Kilian
%           -------------------------------------------------------

edit(Name/Arity) :- not (atom(Name), integer(Arity)), !,
      write('Bad parameters : '),
      write(edit(Name/Arity)), nl, fail.
edit(Name/Arity) :- predefined(Name, Arity), !,
      write('Can''t edit system routine : '),
      write(Name/Arity), nl, fail.
edit(NameArity) :- tag(ed(NameArity, 0)).

ed(NameArity, Cursor) :- show(NameArity, Cursor), !,
      docmd(NameArity, Cursor, NewCursor),
      ed(NameArity, NewCursor).
ed(NameArity, Cursor) :- write('Cursor out of range : '),
      write(Cursor), nl, ed(NameArity, 0).

docmd(NameArity, Cursor, NewCursor) :-
      repeat,
         getline(Line), cmd(Line, NameArity, Cursor, NewCursor),
      !.

getline([]) :- rch, lastch(C), iseoln(C), !.
getline([C | L]) :- lastch(C), getline(L).

cmd([],  NmAr, Cur, NCur) :- next_cursor(NmAr, Cur, NCur).
cmd("+", NmAr, Cur, NCur) :- next_cursor(NmAr, Cur, NCur).
cmd("-", _,    Cur, NCur) :- prev_cursor(Cur, NCur).
cmd("t", NmAr, _,   0).
cmd("b", NmAr, Cur, NCur) :- bottom_cursor(NmAr, Cur, NCur).
cmd("l", NmAr, Cur, Cur ) :- listing(NmAr).
cmd("d", NmAr, Cur, NCur) :- delete(NmAr, Cur, NCur).
cmd("i", NmAr, Cur, NCur) :- insert(NmAr, Cur, NCur).
cmd([f, ' ' | NameString], NmAr, Cur, NCur) :-
      file_insert(NameString, NmAr, Cur, NCur).
cmd("s", NmAr, Cur, Cur)  :- screen_edit(NmAr, Cur).
cmd([e, ' ' | Args], NmAr, Cur, NCur) :-
      append(NameString, ['/' | ArityString], Args),
      call_edit(NameString, ArityString).
cmd("x", _, _, _)        :- tagexit(ed(_, _)).
cmd("p", NmAr, Cur, Cur) :- invoke_Prolog.
cmd(String, _, _, _)     :- write('--- incorrect command : '),
      writetext(String), nl, fail.

next_cursor(Name/Arity, Cursor, Next) :-
      Next is Cursor + 1, check(clause(Name, Arity, Next, _, _)), !.
next_cursor(_, Cursor, Cursor).

prev_cursor(0, 0).
prev_cursor(Cursor, Prev) :- Cursor > 0, Prev is Cursor - 1.

bottom_cursor(Name/Arity, Cursor, Bottom) :-
      Next is Cursor + 1, check(clause(Name, Arity, Next, _, _)), !,
      bottom_cursor(Name/Arity, Next, Bottom).
bottom_cursor(_, Cursor, Cursor).

delete(_, 0, 0) :- !, write('Can''t delete clause 0 !'), nl.
delete(Name/Arity, Cursor, NewCursor) :-
      retract(Name, Arity, Cursor),
      cursor_in_range(Name, Arity, Cursor, NewCursor).

cursor_in_range(Nm, Ar, Cur, Cur) :- check(clause(Nm, Ar, Cur, _, _)), !.
cursor_in_range(_, _, Cur, Prev)  :- Prev is Cur - 1.

insert(NameArity, Cursor, NewCursor) :-
      read(Clause), accept(NameArity, Clause, Head, Body), !,
      proceed(Head, Body, NameArity, Cursor, NewCursor).
insert(_, Cursor, Cursor).

proceed(Head, Body, NameArity, Cursor, NewCursor) :-
      Next is Cursor + 1, assert(Head, Body, Cursor),
      insert(NameArity, Next, NewCursor).

accept(Name/Arity, Clause, Head, Body) :- convert(Clause, Head, Body),
   functor(Head, Name, Arity), !.
accept(NameArity, Clause, Head, Body) :-
      write('--- clause not in edited procedure - ignored.'), nl,
      write(Clause), nl,
      read(NextClause), accept(NameArity, NextClause, Head, Body).

file_insert(FNameString, NameArity, Cursor, NewCursor) :-
      pname(FileName, FNameString),
      see(FileName), insert(NameArity, Cursor, NewCursor),
      seen, see(user).

screen_edit(_, 0) :- !, write('Can''t edit clause 0 !'), nl.
screen_edit(Name/Arity, Cursor) :- edit(Name, Arity, Cursor).
screen_edit(_, _) :- write('--- clause not changed.'), nl.

call_edit(NameString, ArityString) :-
      pname(Name, NameString), pnamei(Arity, ArityString),
      edit(Name/Arity).

invoke_Prolog :- tag(loop).
invoke_Prolog.

show(NameArity, 0) :- !, write('[0] ('), write(NameArity),
      write(')'), nl.
show(Name/Arity, Cursor) :-
      side_effects((clause(Name, Arity, Cursor, Head, Body),
                     wch('['), write(Cursor), write('] '),
                     prettyprint((Head :- Body))
                  )).

