(****************************************************************)
(*                                                              *
*  PROGRAM TITLE:      Z - P R I N T   T E X T                 *
*                                                              *
*  WRITTEN BY:         Raymond E. Penley                       *
*  DATE WRITTEN:       17 NOV 1979                             *
*                                                              *
*  PROGRAM SUMMARY:                                            *
*                                                              *
* A very simple text formatter program.                        *
*                                                              *
* Command Directives:                                          *
*      ^P      New Paragraph.                                  *
*      ^$      End of Text.                                    *
*      ^I      Indent/space.                                   *
*      ^N      New Line but not New Paragraph.                 *
*      ^B      Break/Pause. Continue on any console input.     *
*                                                              *
* NOTE - Command directives may be in either upper or          *
*        lower case.                                           *
*                                                              *
* MODIFICATION RECORD:                                         *
*        1.0   19 Nov 79 Original Program 'PWORD.PAS'          *
*              An attempt to extract "WORDS" from text         *
*              and print them.                                 *
*        1.1  25 Nov 79 -Analyze, Bump, ProcessCommand         *
*               Newline, Page                                  *
*        1.2  26 Nov 79 -From the the Program Text Formatter(1)*
*              Adjustline, Appendblank, Appendword,            *
*              Printline, Roomfor, StartParagraph              *
*        1.3  28 Nov 79                                        *
*              -Added File selection from the console          *
*        1.4  19 Aug 80 -Slight mods to program.               *
*              -Rewrote READWORD.                              *
*                                                              *
*      (1)PASCAL, An Introduction to                           *
*         Methodical Programming                               *
*         Authors: W.Findlay & D.A. Watt                       *)
(****************************************************************)
PROGRAM ZPTEX;
CONST
MAXLENGTH      = 255;  (* GROSS MAXIMUM LINE LENGTH *)
MAXWORDLENGTH  = 30;   (* GET THOSE REALLY BIG WORDS *)
MAXLINEWIDTH   = 80;   (* SET TO VIDEO TERMINAL WIDTH  *)
MINLINEWIDTH   = 30;   (* It isn't a co-incidence that Max Word Length *)
                       (* and Min Line Width are equal.                *)
SPACE          = ' ';
TYPE
 BYTE = 0..255;        (* POSITIVE SINGLE BYTE INTEGER *)
 STRING14   = PACKED ARRAY [ 1..14 ] OF CHAR;
 STRINGTYPE = RECORD
                LENGTH : 0..MAXLENGTH;
                IMAGE  : PACKED ARRAY [ 1..MAXLENGTH ] OF CHAR
              END;
VAR
 BLANKINDEX    : 0..MAXWORDLENGTH;
 DIRCH         : CHAR; (* Char to mark a Command *)
 FATALERROR    : BOOLEAN;
 TEXTFILE      : TEXT;
 FILEID        : STRING14;     (* FILE NAME *)
 INDENT        : BYTE;
 LINE          : PACKED ARRAY [ 1..MAXLINEWIDTH ] OF CHAR;
 LINEWIDTH     : BYTE;
 POS           : BYTE; (* GLOBAL INDEXER *)
 POSITION      : 0..MAXLINEWIDTH;
 TAB           : CHAR; (* ASCII TAB character *)
 WORD          : STRINGTYPE;

       (**************************)

PROCEDURE CLEAR(* OUTPUT *);
VAR
 I: BYTE;
BEGIN
 FOR I:=1 TO 24 DO WRITELN;
END; (* CLEAR *)

PROCEDURE SKIP( LINES : BYTE );
VAR
 I: BYTE;
BEGIN
 FOR I := 1 TO LINES DO WRITELN
END;

PROCEDURE PRINTLINE;
BEGIN
 FOR POS:=1 TO POSITION DO WRITE( LINE[ POS ]);
 WRITELN
END;

PROCEDURE STARTLINE;
BEGIN
 POSITION := 0
END;

PROCEDURE READWORD;
VAR     CH: CHAR;

       PROCEDURE GETC(VAR CH: CHAR);
       BEGIN
         IF NOT EOF(TEXTFILE) THEN
            READ(TEXTFILE, CH);
         (* Classify the character just read *)
         IF CH=TAB THEN CH := SPACE;
         IF EOF(TEXTFILE) THEN
            CH := SPACE;
       END;

(*$C- [Control-C OFF]**********************************)

BEGIN
 CH := SPACE;
 WHILE (NOT EOF(TEXTFILE)) AND (CH=SPACE) DO (* skipblanks *)
   GETC(CH);
 WITH WORD DO BEGIN
   LENGTH := 0;
   WHILE (NOT EOF(TEXTFILE)) AND (CH<>SPACE) DO
     BEGIN (* accept only non space *)
       IF LENGTH < MAXWORDLENGTH THEN
         BEGIN (* store the char *)
           LENGTH := LENGTH + 1;
           IMAGE[ LENGTH ] := CH;
         END;
       GETC(CH);
     END; (* WHILE *)
(**
       WE NOW HAVE ONE "WORD" IN WORD.IMAGE
       WORD.LENGTH IS THE LENGTH OF THIS WORD
**)
  IF LENGTH >= BLANKINDEX THEN
    BLANKINDEX := LENGTH
  ELSE
    REPEAT
      IMAGE[ BLANKINDEX ] := SPACE;
      BLANKINDEX := PRED(BLANKINDEX);
    UNTIL BLANKINDEX=LENGTH;
 END; (* WITH *)
END; (* READWORD *)

PROCEDURE ANALYZE;
VAR
 PAUSE: CHAR;

       PROCEDURE APPENDWORD;
       BEGIN
         FOR POS:=1 TO WORD.LENGTH DO
           BEGIN
             POSITION := POSITION +1;
             LINE[ POSITION ] := WORD.IMAGE[ POS ]
           END
       END;

       PROCEDURE APPENDBLANK;
       BEGIN
         POSITION := POSITION +1;
         LINE[ POSITION ] := SPACE
       END;

       FUNCTION ROOMFOR( NMROFCHARS: INTEGER ): BOOLEAN;
       BEGIN
         ROOMFOR := (POSITION + NMROFCHARS) <= LINEWIDTH
       END;

       PROCEDURE ADJUSTLINE;
       VAR
         EXTRABLANKS,
         NMROFGAPS,
         WIDENING,
         LEFTMOST,
         RIGHTMOST: 0..MAXLINEWIDTH;
       BEGIN
         (*    Make LeftMost the POSition of   *
          *    the LeftMost non:blank          *)
         LEFTMOST := 1;
         WHILE LINE[ LEFTMOST ] = SPACE DO
           LEFTMOST := SUCC(LEFTMOST);
         (*    Make RightMost the POSition of  *
          *    the RightMost non-blank         *)
         RIGHTMOST := POSITION;
         WHILE LINE[ RIGHTMOST ] = SPACE DO
           RIGHTMOST := PRED(RIGHTMOST);
         (*    Make NMROFGAPS the number of inter-word gaps *)
         NMROFGAPS := 0;
         FOR POS := LEFTMOST TO RIGHTMOST DO
           IF (LINE[ POS ] = SPACE) THEN NMROFGAPS := NMROFGAPS +1;
         EXTRABLANKS := LINEWIDTH - RIGHTMOST;
         FOR POS := 1 TO RIGHTMOST DO
           IF (POS > LEFTMOST) AND (LINE[ POS ] = SPACE) THEN
             BEGIN (* this Char is an inter-WORD gap *)
               WIDENING := EXTRABLANKS DIV NMROFGAPS;
               WRITE( SPACE:(WIDENING+1) );
               EXTRABLANKS := EXTRABLANKS - WIDENING;
               NMROFGAPS := NMROFGAPS -1
             END(* If *)
           ELSE
             WRITE( LINE[ POS ] );
         WRITELN
       END; (* ADJUSTLINE *)

       PROCEDURE NEWLINE;
       (*
           Print the current LINE without adjustment and
           move to the next line.
       *)
       BEGIN
         PRINTLINE;
         STARTLINE
       END;

       PROCEDURE STARTPARAGRAPH;
       (*
          Write the current LINE without adjustment
        *)
       BEGIN
         PRINTLINE;
         WRITELN;
         FOR POSITION := 1 TO INDENT DO
           LINE[ POSITION ] := SPACE;
         POSITION := INDENT
       END;

       FUNCTION VALIDCOMMAND( THISCHAR : CHAR ) : BOOLEAN;
       BEGIN
         VALIDCOMMAND :=
                (THISCHAR IN [ '$','p','P','i','I','n','N','b','B' ] )
       END;

       PROCEDURE BUMP;
       BEGIN
         IF (POSITION < LINEWIDTH) THEN
           BEGIN
           POS := 0;
           REPEAT
             POS := POS + 1;
             APPENDBLANK
           UNTIL (POS = INDENT) OR (POSITION = LINEWIDTH);
           END(* IF *)
       END; (* BUMP *)

BEGIN (*** ANALYZE ***)
 (* All Command Directives must start a Word *)
 IF WORD.IMAGE[ 1 ] = DIRCH THEN
   BEGIN
     IF VALIDCOMMAND( WORD.IMAGE[ 2 ] ) THEN
       BEGIN
         CASE WORD.IMAGE[ 2 ] OF
             '$':      FATALERROR := TRUE;(* Force termination *)
             'P','p':  STARTPARAGRAPH;
             'I','i':  BUMP;
             'N','n':  NEWLINE;
             'B','b':  BEGIN
                       NEWLINE;
                       READLN( PAUSE )
                       END
         END (* CASE WORD.IMAGE *)
       END(* IF VALIDCOMMAND *)
   END(* IF *)
 ELSE
   (* Output the WORD followed by a blank, right-adjusting
      the old Line and starting a new line if necessary  *)
   BEGIN
     IF NOT ROOMFOR(WORD.LENGTH) THEN
       BEGIN
         ADJUSTLINE;     (* Right-justify the Current Line *)
         STARTLINE
       END;
    APPENDWORD;
    IF ROOMFOR(1) THEN APPENDBLANK
  END (* ELSE *)
END; (* ANALYZE *)

(*$C+ [Control-C ON]*********************************)

PROCEDURE INITIALIZE;
BEGIN
 BLANKINDEX    := MAXWORDLENGTH;(* start at the extreme right *)
 DIRCH         := '^';         (* Default for Command Character *)
 INDENT        := 6;           (* Default for all indents *)
 TAB           := CHR(9);      (* ASCII TAB CHARACTER *)
 FATALERROR    := FALSE;
 REPEAT
   WRITELN;
   WRITE('Line width?');
   READLN( LINEWIDTH );
   IF LINEWIDTH < MINLINEWIDTH THEN
     WRITELN('Minimum line width is', MINLINEWIDTH:3, '. Please reenter');
 UNTIL (LINEWIDTH>=MINLINEWIDTH) AND (LINEWIDTH<=MAXLINEWIDTH);
 WRITE('Enter text file name ');
 READLN( FILEID );
 (* OPEN file "FILEID" for READ assign TEXTFILE *)
         RESET( FILEID, TEXTFILE );
 CLEAR(* OUTPUT *);
END;

BEGIN (*** Z-PRINT TEXT ***)
 INITIALIZE;
 IF EOF(TEXTFILE) THEN
   WRITELN('File ', FILEID, 'not found')
 ELSE
   BEGIN
     STARTLINE;
     READWORD; (*** Attempt to read a word ***)
     WHILE NOT ( EOF(TEXTFILE) OR FATALERROR ) DO
       BEGIN
         ANALYZE;
         READWORD;     (*** Attempt to read another word ***)
       END; (* WHILE *)
     PRINTLINE; (*** Write the current line without adjustment ***)
   END; (* else *)
 SKIP(4);
END. (*** Z-PRINT TEXT ***)