% --------------------------------------------------------------------------
%   FILE:       RUNOFF.PL
%   AUTHOR:     Tim Duncan
%   UPDATED:    Wed Sep  2 18:01:56 BST 1987
%   PURPOSE:    Runoff text, handling meta text instructions described below.
% --------------------------------------------------------------------------


:- op(100,fx,*).
:- op(100,xfy,:).



/* runoff/1
This predicate takes responsibility for interpreting Miller's
meta text functions, and outputting the text. The meta functions
are:
        *comma    = ","
        *period   = "."  and *cap next word.
        *para     = a blank line and indent.
        *apost_s  = "'s"
        *cap      = capitalise initial of next word.
        *allcaps  = capitalise the whole of the next word.
*/

runoff(X) :- runoff(X,0,_).


/* runoff/3 keeps count of column in line. */

runoff([],X,X) :- !.
runoff([*nl|T],P,N) :- !, nl, runoff(T,0,N).
runoff([H,*comma|T],P,N) :-
    L is P+2,
    com(H,L,I), write(', '), !,
    runoff(T,I,N).
runoff([H,*period|T],P,N) :-
    L is P+2,
    com(H,L,I), write('. '),
    next_word(cap,T,T2), !,
    runoff(T2,I,N).
runoff([*para|T],P,N) :-
    nl, nl, tab(5),
    next_word(cap,T,T2), !,
    runoff(T2,5,N).
runoff([H,*para|T],P,N) :-
    L is P+1,
    com(H,L,_), com('.'),
    nl, nl, tab(5),
    next_word(cap,T,T2), !,
    runoff(T2,5,N).
runoff([H,*apost_s|T],P,N) :-
    L is P+2,
    com(H,L,I), put(39), write(s), tab(1), !,
    runoff(T,I,N).
runoff([*cap|T],P,N) :-
    next_word(cap,T,T2), !,
    runoff(T2,P,N).
runoff([*allcaps|T],P,N) :-
    next_word(allcaps,T,T2), !,
    runoff(T2,P,N).
runoff([H|T],P,N) :-
    L is P+1, com(H,L,I), tab(1), !, runoff(T,I,N).
runoff(Atom,P,N) :- com(Atom,P,N).



/* test the length of a string before printing it,
then update the counter.
*/

com(X,S,F) :-
    length_of(X,N),
    P is S+N,
    ( P < 65,
      write(X),
      F = P
    ; nl, write(X),
      F = N ), !.


length_of([],0) :- !.
length_of([H|T],N) :-
    length_of(H,L1),
    length_of(T,L2),
    N is L1+L2+1, !.
length_of(X,N) :-
    atomic(X),
    name(X,L),
    length(L,N), !.
length_of(S,N) :-
    S =.. [F|A],
    length_of(F,L1),
    length_of(A,L2),
    N is L1+L2+1, !.
length_of(_,1).


/* Do something to the next word (ie. *cap or *allcaps */

next_word(_,[],[]).
next_word(_,[*H|T],[*H|T]).
next_word(cap,[H|T],[C|T]) :-
    name(H,[F|Ft]),
    capitalise(F,F2),
    name(C,[F2|Ft]).
next_word(allcaps,[H|T],[C|T]) :-
    name(H,L),
    allcaps(L,U),
    name(C,U).



allcaps([],[]).
allcaps([H|T],[X|Y]) :-
    capitalise(H,X),
    allcaps(T,Y).

capitalise(L,H) :-
    L > 96,
    L < 123, !,
    H is L-32.
capitalise(X,X).
