(* This PASCAL Program was written by : Francis J. Monaco Major, US ARMY Systems Manager, Computer Graphics Laboratory Department of Geography and Computer Science The United States Military Academy West Point, New York 10996 914-938-2063 The author acknowledges the PASCAL Book PASCAL, An Introduction to Methodical Programming by W Findlay and DA Watt as well as the folks at Georgia Institute of Technology for the hyphenation algorithms. Also, this entire program was originally developed for the LSI-11 under UCSD PASCAL Version 2.0. Contact the author for Further information. *) PROGRAM FMT (INPUT, OUTPUT, FIN, FOUT, FNEW); CONST BLANK = ' '; STRINGMAX = 100; MAXWORDLENGTH = 35; MAXLINEWIDTH = 131; TOF = '1'; NOLF = '+'; TYPE CHARS = PACKED ARRAY [ 1 .. MAXLINEWIDTH ] OF CHAR; STRING = RECORD LEN : 0 .. STRINGMAX; CH : PACKED ARRAY [ 1 .. STRINGMAX ] OF CHAR END; WORDREC = RECORD SPELLING : PACKED ARRAY [ 1 .. MAXWORDLENGTH ] OF CHAR; LENGTH : 0 .. MAXWORDLENGTH; ISUL, ISBO : BOOLEAN; END; STRING11 = PACKED ARRAY [ 1 .. 11 ] OF CHAR; VAR WORD, WORDR : WORDREC; LINE, ULLINE, BOLINE : CHARS; POSITION : 0 .. MAXLINEWIDTH; LINEWIDTH, LEFTMARGIN : INTEGER; FIN, FOUT, FNEW : TEXT; THETITLE, THEHEADER, THEFOOTER : STRING; CARRIAGECONTROL, HYNATE, HAVEATITLE, DIDHYPHENATE, HAVEAHEADER, HAVEAFOOTER, ULFLAG, NOADJ, BOFLAG, DIDUL, DIDBO, NEWFILE : BOOLEAN; CURRLINE, CURRPAGE, LINESPACING, PAGESIZE, M1, M2, M3, M4, I, PDENT, TDENT, LINES: INTEGER; BITMAP : PACKED ARRAY ['a'..'z','a'..'z'] OF BOOLEAN; THEDATE : STRING; STARTNEWPARAGRAPH, CENTERALINE, BREAKCURRENTLINE, DONOTFILLTEXT, SKIPLINE, TAKEINPUTFROMNEWFILE, SETLEFTMARGIN, SETRIGHTMARGIN, ONHYPHEN, OFFHYPHEN, LINEPRINTER, CRT, TITLE, HEADER, FOOTER, SETM1, SETM2, SETM3, SETM4, SETPAGENUM, STARTPAGE, BOLDFACE, UNDERLINE, SETLINESPACING, SETPAGESIZE, PROMPT, NEED, SKIPPLUS, COMMENT, PINDENTATION, TINDENTATION, DONOTADJUST ,ATSYM,ULSYM,TION,ING,DATESY,PAGY,DELIM,NFSYM : STRING; (******************************************************************) FUNCTION LOWER ( CH : CHAR ) : CHAR; BEGIN IF CH IN ['A'..'Z'] THEN LOWER := CHR ( ORD ( CH ) + 32 ) ELSE LOWER := CH; END; PROCEDURE FILLC ( VAR S : CHARS ); VAR I : INTEGER; BEGIN FOR I := 1 TO MAXLINEWIDTH DO S [I] := BLANK; END; (*******************************************************************) FUNCTION LENGTH (S: STRING): INTEGER; BEGIN LENGTH := S.LEN; END; (********************************************************************) PROCEDURE FILLCHAR ( VAR S: STRING; CHARACTER: CHAR); VAR I : INTEGER; BEGIN S . LEN := 0; FOR I := 1 TO STRINGMAX DO S . CH [ I ] := CHARACTER; END; (*********************************************************************) PROCEDURE CONCAT ( VAR S : STRING; T : STRING ); VAR I, J : INTEGER; BEGIN IF S . LEN + T . LEN > STRINGMAX THEN J := STRINGMAX - S . LEN ELSE J := T . LEN; FOR I := 1 TO J DO S . CH [ S . LEN + I ] := T . CH [ I ]; S . LEN := S . LEN + J; END; (**********************************************************************) FUNCTION POS ( S, T : STRING ): INTEGER; VAR I, J : INTEGER; UNEQ : BOOLEAN; BEGIN IF ( ( 1 + T . LEN) > (S . LEN + 1) ) OR (T . LEN = 0) THEN POS := 0 ELSE BEGIN I := 0; REPEAT I := SUCC ( I ); J := 0; REPEAT J := SUCC ( J ); UNEQ := T . CH [ J ] <> S . CH [ I + J - 1 ]; UNTIL UNEQ OR ( J = T . LEN ); UNTIL (NOT UNEQ) OR (I = S . LEN - T . LEN + 1); IF UNEQ THEN POS := 0 ELSE POS := I; END; END; (******************************************************************) PROCEDURE READS ( VAR F: TEXT; VAR S: STRING ); VAR CH1 : CHAR; BEGIN FILLCHAR ( S, BLANK ); WITH S DO WHILE ( (NOT EOLN(F)) AND (LEN <=STRINGMAX)) DO BEGIN LEN := SUCC (LEN); READ (F, CH1); CH [ LEN ] := CH1; END; READLN(F); END; (********************************************************************) PROCEDURE WRITES(VAR F: TEXT; S: STRING); VAR I : INTEGER; BEGIN FOR I := 1 TO S . LEN DO WRITE ( F, S . CH [ I ] ); END; (********************************************************************) PROCEDURE COPY (VAR T: STRING; S: STRING; START, SPAN: INTEGER); VAR I: INTEGER; BEGIN IF SPAN < 0 THEN BEGIN SPAN := - SPAN; START := START - SPAN; END; IF START < 1 THEN BEGIN SPAN := SPAN + START - 1; START := 1; END; IF START + SPAN > S . LEN + 1 THEN SPAN := S . LEN - START + 1; IF SPAN <= 0 THEN FILLCHAR ( T, BLANK ) ELSE BEGIN FOR I := 1 TO SPAN DO T . CH [ I ] := S . CH [ START + I - 1 ]; FOR I := SPAN + 1 TO STRINGMAX DO T . CH [ I ] := ' '; T . LEN := SPAN; END; END; (*******************************************************************) PROCEDURE DELETE (VAR S: STRING; START, SPAN: INTEGER); VAR I, LIMIT : INTEGER; BEGIN IF SPAN < 0 THEN BEGIN SPAN := - SPAN; START := START - SPAN; END; LIMIT := START + SPAN; IF START < 1 THEN START := 1; IF LIMIT > S . LEN + 1 THEN LIMIT := S . LEN + 1; SPAN := LIMIT - START; IF SPAN > 0 THEN BEGIN FOR I := 0 TO S . LEN - LIMIT DO S . CH [ START + I ] := S . CH [ LIMIT + I ]; FOR I := s . len - span + 1 TO S . LEN DO S . CH [ I ] := ' '; S . LEN := S . LEN - SPAN; END; END; (*****************************************************************) PROCEDURE INSERT (VAR S: STRING; T : STRING; P: INTEGER); VAR I, J: INTEGER; BEGIN IF T . LEN > 0 THEN IF (P > 0) AND (P <= S . LEN + 1) THEN BEGIN IF S . LEN + T . LEN <= STRINGMAX THEN S . LEN := S . LEN + T . LEN ELSE S . LEN := STRINGMAX; FOR I := S . LEN DOWNTO P + T . LEN DO S . CH [ I ] := S . CH [ I - T . LEN ]; IF S . LEN < P + T . LEN THEN J := S . LEN ELSE J := P + T . LEN - 1; FOR I := P TO J DO S . CH [ I ] := T . CH [ I - P + 1 ]; END END; (****************************************************************) PROCEDURE INITCMDS; VAR TODAY: STRING11; BEGIN DATE(TODAY); TODAY [ 3 ] := BLANK; TODAY [ 7 ] := BLANK; TODAY [ 5 ] := LOWER ( TODAY [ 5 ] ); TODAY [ 6 ] := LOWER ( TODAY [ 6 ] ); REWRITE(FNEW); WRITELN(FNEW,'.pp'); WRITELN(FNEW,'.ce'); WRITELN(FNEW,'.br'); WRITELN(FNEW,'.nf'); WRITELN(FNEW,'.sp'); WRITELN(FNEW,'.so'); WRITELN(FNEW,'.lm'); WRITELN(FNEW,'.rm'); WRITELN(FNEW,'.hy+'); WRITELN(FNEW,'.hy-'); WRITELN(FNEW,'.lpt'); WRITELN(FNEW,'.crt'); WRITELN(FNEW,'.tl'); WRITELN(FNEW,'.he'); WRITELN(FNEW,'.fo'); WRITELN(FNEW,'.m1'); WRITELN(FNEW,'.m2'); WRITELN(FNEW,'.m3'); WRITELN(FNEW,'.m4'); WRITELN(FNEW,'.pn'); WRITELN(FNEW,'.pg'); WRITELN(FNEW,'.bo'); WRITELN(FNEW,'.ul'); WRITELN(FNEW,'.ls'); WRITELN(FNEW,'.ps'); WRITELN(FNEW,'.pr'); WRITELN(FNEW,'.ne'); WRITELN(FNEW,'.sp+'); WRITELN(FNEW,'.#'); WRITELN(FNEW,'.pi'); WRITELN(FNEW,'.ti'); WRITELN(FNEW,'.noadj'); WRITELN(FNEW,'@'); WRITELN(FNEW,'_'); WRITELN(FNEW,TODAY:11); WRITELN(FNEW,'tion'); WRITELN(FNEW,'ing'); WRITELN(FNEW,'^'); WRITELN(FNEW,'#'); WRITELN(FNEW,''''); WRITELN(FNEW,'.nf'); RESET(FNEW); READS(FNEW,STARTNEWPARAGRAPH); READS(FNEW,CENTERALINE); READS(FNEW,BREAKCURRENTLINE); READS(FNEW,DONOTFILLTEXT); READS(FNEW,SKIPLINE); READS(FNEW,TAKEINPUTFROMNEWFILE); READS(FNEW,SETLEFTMARGIN); READS(FNEW,SETRIGHTMARGIN); READS(FNEW,ONHYPHEN); READS(FNEW,OFFHYPHEN); READS(FNEW,LINEPRINTER); READS(FNEW,CRT); READS(FNEW,TITLE); READS(FNEW,HEADER); READS(FNEW,FOOTER); READS(FNEW,SETM1); READS(FNEW,SETM2); READS(FNEW,SETM3); READS(FNEW,SETM4); READS(FNEW,SETPAGENUM); READS(FNEW,STARTPAGE); READS(FNEW,BOLDFACE); READS(FNEW,UNDERLINE); READS(FNEW,SETLINESPACING); READS(FNEW,SETPAGESIZE); READS(FNEW,PROMPT); READS(FNEW,NEED); READS(FNEW,SKIPPLUS); READS(FNEW,COMMENT); READS(FNEW,PINDENTATION); READS(FNEW,TINDENTATION); READS(FNEW,DONOTADJUST); READS(FNEW,ATSYM); READS(FNEW,ULSYM); READS(FNEW,THEDATE); READS(FNEW,TION); READS(FNEW,ING); READS(FNEW,DATESY); READS(FNEW,PAGY); READS(FNEW,DELIM); READS(FNEW,NFSYM); CLOSE(FNEW); END; (*****************************************************************) PROCEDURE INITBITMAP; CONST (* MAKE IT EASIER TO DEFINE THE BITMAP FOR HYPHENATION *) A = 'a'; B = 'b'; C = 'c'; D = 'd'; E = 'e'; F = 'f'; G = 'g'; H = 'h'; I = 'i'; J = 'j'; K = 'k'; L = 'l'; M = 'm'; N = 'n'; O = 'o'; P = 'p'; Q = 'q'; R = 'r'; S = 's'; T = 't'; U = 'u'; V = 'v'; W = 'w'; X = 'x'; Y = 'y'; Z = 'z'; (* NOTE THAT HYPHENATION WORKS ONLY ON LOWER CASE LETTERS!!! *) VAR CH1, CH2, CH : 'A'..'Z'; BEGIN FOR CH1 := A TO Z DO FOR CH2 := A TO Z DO BITMAP [ CH1, CH2 ] := TRUE; (* SET ALL OK AT FIRST *) FOR CH := A TO Z DO BEGIN (* CAN'T HYPHENATE AT TWO VOWELS *) BITMAP [ CH, A ] := FALSE; BITMAP [ CH, E ] := FALSE; BITMAP [ CH, I ] := FALSE; BITMAP [ CH, O ] := FALSE; BITMAP [ CH, U ] := FALSE; BITMAP [ CH, Y ] := FALSE; BITMAP [ A, CH ] := FALSE; BITMAP [ E, CH ] := FALSE; BITMAP [ I, CH ] := FALSE; BITMAP [ O, CH ] := FALSE; BITMAP [ U, CH ] := FALSE; BITMAP [ Y, CH ] := FALSE END; (* THESE ARE SPECIAL CASES WHERE ENGLISH GRAMMER AND EXPERIENCE DICTATE THAT HYPHENATION ISN'T USUALLY DONE .... NOTE THAT YOU CAN'T ADD TO THIS PROCEDURE BECAUSE OF SYMBOL TABLE OVERFLOW (YOU'LL HAVE TO CREATE ANOTHER PROCEDURE AND CALL IT WITH VAR PARAMETERS) IF YOU WANT TO ADD OK TO HYPHENATE LEFT AND RIGHT LETTER PAIRS *) BITMAP[N,C] := FALSE; BITMAP[S,C] := FALSE; BITMAP[T,C] := FALSE; BITMAP[D,G] := FALSE; BITMAP[N,G] := FALSE; BITMAP[C,H] := FALSE; BITMAP[G,H] := FALSE; BITMAP[P,H] := FALSE; BITMAP[S,H] := FALSE; BITMAP[T,H] := FALSE; BITMAP[W,H] := FALSE; BITMAP[R,K] := FALSE; BITMAP[S,K] := FALSE; BITMAP[B,L] := FALSE; BITMAP[C,L] := FALSE; BITMAP[F,L] := FALSE; BITMAP[P,L] := FALSE; BITMAP[S,L] := FALSE; BITMAP[W,L] := FALSE; BITMAP[N,M] := FALSE; BITMAP[R,M] := FALSE; BITMAP[D,N] := FALSE; BITMAP[R,P] := FALSE; BITMAP[S,P] := FALSE; BITMAP[B,R] := FALSE; BITMAP[C,R] := FALSE; BITMAP[D,R] := FALSE; BITMAP[S,T] := FALSE; BITMAP[F,R] := FALSE; BITMAP[G,R] := FALSE; BITMAP[P,R] := FALSE; BITMAP[R,R] := FALSE; BITMAP[T,R] := FALSE; BITMAP[W,R] := FALSE; BITMAP[N,R] := FALSE; BITMAP[N,S] := FALSE; BITMAP[T,S] := FALSE; BITMAP[T,W] := FALSE; END; PROCEDURE INIT; (* SET THE DEFAULT PARAMETERS......*) BEGIN INITCMDS; INITBITMAP; DIDHYPHENATE := FALSE; HYNATE := TRUE; CARRIAGECONTROL := FALSE; (* CRT OUTPUT ON *) CURRLINE := 0; CURRPAGE := 1; M1 := 1; M2 := 2; M3 := 2; M4 := 1; (* DEFAULT FOR M MARGINS *) PAGESIZE := 60; (* GOOD FOR STANDARD 11 INCH PAPER *) PDENT := 5; (* PARAGRAPH INDENT *) TDENT := 5; ULFLAG := FALSE; BOFLAG := FALSE; LINESPACING := 1; (* SINGLE SPACE THE OUTPUT *) HAVEAHEADER := FALSE; HAVEAFOOTER := FALSE; HAVEATITLE := FALSE; LEFTMARGIN := 9; (* GOOD FOR 8 IN PAPER WIDTH *) LINEWIDTH := 69; (* " *) DIDBO := FALSE; DIDUL := FALSE; NEWFILE := FALSE; NOADJ := FALSE; (* WE'LL START WITH RIGHT ADJUSTING *) LINES := 0; (* USED TO COUNT OUTPUT LINES FOR STATISTICS *) RESET(FIN); OPEN(FOUT,CARRIAGE); REWRITE(FOUT); LINELIMIT(FOUT,MAXINT); END; PROCEDURE INSERTDATE ( VAR THESTRING : STRING ); (* PUTS THEDATE INTO THE HEADER OR FOOTER WHEN A "^" IS ENCOUNTERED BETWEEN THE " ' ' " *) VAR DATEPOS : 1..MAXLINEWIDTH; HASDATE: BOOLEAN; BEGIN HASDATE := FALSE; I := 0; REPEAT I := SUCC ( I ); IF (THESTRING . CH [ I ] = '^') THEN BEGIN HASDATE := TRUE; DATEPOS := I END UNTIL (I>= LENGTH(THESTRING)); IF HASDATE THEN BEGIN DELETE(THESTRING,DATEPOS,1); INSERT(THESTRING,THEDATE,DATEPOS) END END; PROCEDURE WRITEHEADER; (* GENERATE UPTO THREE PART HEADER WITH KNOWLEDGE OF THEDATE, CUURPAGE *) VAR SPACEPERPART, S1, S2, S3, NUMPARTS, I, J : INTEGER; HASDELIM : BOOLEAN; FIRSTDELIM : INTEGER; BEGIN IF HAVEAHEADER (* CAN'T HAVEAHEADER ON PAGE 1 *) THEN BEGIN NUMPARTS := 0; INSERTDATE ( THEHEADER ); WRITE ( FOUT, BLANK: (LEFTMARGIN)); I := 0; REPEAT I := SUCC ( I ) UNTIL ( (I>= LENGTH(THEHEADER) ) OR (THEHEADER . CH [ I ] = DELIM . CH [ 1]) ); HASDELIM := THEHEADER . CH [ I ] = DELIM . CH [ 1 ]; FIRSTDELIM := I; IF HASDELIM THEN FOR I := FIRSTDELIM + 1 TO LENGTH ( THEHEADER ) DO IF THEHEADER . CH [ I ] = DELIM .CH [1 ] THEN BEGIN NUMPARTS := SUCC ( NUMPARTS ); (* COUNT NUMBER OF PARTS*) CASE NUMPARTS OF 1: S1 := I; 2: S2 := I; 3: S3 := I END END; IF NUMPARTS <> 0 THEN SPACEPERPART := LINEWIDTH DIV NUMPARTS; (* CALCULATE SPREAD *) CASE NUMPARTS OF 0: ; 1: FOR I := 2 TO S1 - 1 DO (* WE HAVE A ONE PART HEADER *) IF THEHEADER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE (FOUT, THEHEADER . CH [ I ]) ELSE WRITE (FOUT, CURRPAGE : 1 ); 2: BEGIN (* WE HAVE A TWO PART HEADER *) FOR I := 2 TO S1 - 1 DO IF THEHEADER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE(FOUT, THEHEADER . CH [ I ]) ELSE WRITE(FOUT, CURRPAGE : 1); WRITE(FOUT, BLANK: (SPACEPERPART - S1 + 2)); FOR I := S1 + 1 TO S2 - 1 DO IF THEHEADER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE ( FOUT, THEHEADER . CH [ I ] ) ELSE WRITE ( FOUT, CURRPAGE : 1 ); END; 3: BEGIN (* WE HAVE A THREE PART HEADER *) FOR I := 2 TO S1 - 1 DO IF THEHEADER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE(FOUT, THEHEADER . CH [ I ]) ELSE WRITE (FOUT, CURRPAGE : 1); WRITE(FOUT, BLANK: (SPACEPERPART - S1 + 2), BLANK: ((SPACEPERPART - ( S2 - S1 )) DIV 2)); FOR I := S1 + 1 TO S2 - 1 DO IF THEHEADER .CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE ( FOUT, THEHEADER . CH [ I ]) ELSE WRITE ( FOUT, CURRPAGE : 1); WRITE ( FOUT, BLANK: ((SPACEPERPART - ( S2 - S1 ) ) DIV 2), BLANK : (SPACEPERPART - ( S3 - S2) + 4) ); FOR I := S2 + 1 TO S3 - 1 DO IF THEHEADER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE ( FOUT, THEHEADER . CH [ I ]) ELSE WRITE ( FOUT, CURRPAGE: 1); END; END; WRITELN( FOUT ); END ELSE WRITELN(FOUT); END; PROCEDURE WRITEFOOTER; (* SEE ABOVE FOR WRITEHEADER; SUGGESTED IMPROVEMENT IS TO ELIMINATE THIS CODE AND CHANGE ALL CALLS TO WRITEFOOTER TO CALLS TO WRITEHEADER WITH A PARAMETER DENOTING WHICH TO WRITE !! *) VAR SPACEPERPART, S1, S2, S3, NUMPARTS, I, J : INTEGER; HASDELIM : BOOLEAN; FIRSTDELIM : INTEGER; BEGIN IF HAVEAFOOTER THEN BEGIN NUMPARTS := 0; INSERTDATE ( THEFOOTER ); WRITE ( FOUT, BLANK: (LEFTMARGIN)); I := 0; REPEAT I := SUCC ( I ) UNTIL ( (I>= LENGTH(THEFOOTER) ) OR (THEFOOTER . CH [ I ] = DELIM . CH [ 1] ) ); HASDELIM := THEFOOTER . CH [ I ] = DELIM . CH [ 1 ]; FIRSTDELIM := I; IF HASDELIM THEN FOR I := FIRSTDELIM + 1 TO LENGTH ( THEFOOTER ) DO IF THEFOOTER . CH [ I ] = DELIM . CH [ 1 ] THEN BEGIN NUMPARTS := SUCC ( NUMPARTS ); CASE NUMPARTS OF 1: S1 := I; 2: S2 := I; 3: S3 := I END END; IF NUMPARTS <> 0 THEN SPACEPERPART := LINEWIDTH DIV NUMPARTS; CASE NUMPARTS OF 0: ; 1: FOR I := 2 TO S1 - 1 DO IF THEFOOTER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE (FOUT, THEFOOTER . CH [ I ]) ELSE WRITE ( FOUT, CURRPAGE: 1); 2: BEGIN FOR I := 2 TO S1 - 1 DO IF THEFOOTER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE(FOUT, THEFOOTER . CH [ I ]) ELSE WRITE ( FOUT, CURRPAGE: 1); WRITE(FOUT, BLANK: (SPACEPERPART - S1 + 2)); FOR I := S1 + 1 TO S2 - 1 DO IF THEFOOTER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE ( FOUT, THEFOOTER . CH [ I ] ) ELSE WRITE ( FOUT, CURRPAGE: 1); END; 3: BEGIN FOR I := 2 TO S1 - 1 DO IF THEFOOTER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE(FOUT, THEFOOTER . CH [ I ]) ELSE WRITE ( FOUT, CURRPAGE: 1); WRITE(FOUT, BLANK: (SPACEPERPART - S1 + 2), BLANK: ((SPACEPERPART - ( S2 - S1)) DIV 2)); FOR I := S1 + 1 TO S2 - 1 DO IF THEFOOTER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE ( FOUT, THEFOOTER . CH [ I ]) ELSE WRITE ( FOUT, CURRPAGE : 1); WRITE ( FOUT, BLANK: ((SPACEPERPART - ( S2 - S1 ) ) DIV 2), BLANK: (SPACEPERPART - (S3 - S2) + 4) ); FOR I := S2 + 1 TO S3 - 1 DO IF THEFOOTER . CH [ I ] <> PAGY . CH [ 1 ] THEN WRITE(FOUT, THEFOOTER . CH [ I ] ) ELSE WRITE ( FOUT, CURRPAGE : 1 ); END; END; WRITELN( FOUT ); END ELSE WRITELN(FOUT); END; PROCEDURE INCURRLINE; (* USED PRIMARILY BY PUTLINE *) BEGIN CURRLINE := SUCC ( CURRLINE ); LINES := SUCC ( LINES ); IF (LINES MOD 60) = 0 THEN WRITELN ( (LINES DIV 60):2,' pages processed '); END; PROCEDURE PUTLINE ( VAR FOUT: TEXT ); (* ALMOST ALL "WRITELNS" TO THE OUTPUT FILE COME HERE FIRST TO FILTER OUT PAGINATION, HEADERS, BOLDFACING, UNDERLINING ETC.... *) (* THIS ROUTINE IS CRITICAL; IT BUILDS THE OUTPUT FILE FROM NUMEROUS CALLS IN FMT; NOTE THAT BY INCREMENTING THE VALUE OF CURRLINE, PUTLINE KNOWS EXACTLY WHAT MUST BE DONE TO THE OUTPUT FILE *) VAR I, J : INTEGER; BEGIN (* PUTLINE *) IF ( ( (NOT DIDUL) AND (NOT DIDBO) ) OR ( NOT CARRIAGECONTROL ) ) THEN BEGIN WRITELN ( FOUT ); INCURRLINE END; IF CURRLINE <= M1 THEN BEGIN IF CURRLINE < M1 THEN REPEAT WRITELN ( FOUT ); INCURRLINE UNTIL CURRLINE = M1 ELSE WRITEHEADER; IF CURRLINE < (M1 + M2 + 1) THEN REPEAT WRITELN ( FOUT ); INCURRLINE UNTIL CURRLINE = (M1 + M2 + 1) END ELSE IF ((CURRLINE >= (M1 + M2 + 1)) AND (CURRLINE < (PAGESIZE - M3 - M4 - 1))) THEN BEGIN IF (DIDUL AND CARRIAGECONTROL) THEN BEGIN WRITELN(FOUT); INCURRLINE; DIDUL := ULFLAG; FOR J := 1 TO 3 DO BEGIN WRITE ( FOUT, NOLF); WRITE ( FOUT, BLANK: (LEFTMARGIN - 1)); FOR I := 1 TO LINEWIDTH DO WRITE ( FOUT, ULLINE [ I ] ); WRITELN(FOUT); END; END; IF (DIDBO AND CARRIAGECONTROL) THEN BEGIN WRITELN(FOUT); INCURRLINE; DIDBO := BOFLAG; FOR J := 1 TO 3 DO BEGIN WRITE(FOUT, NOLF); WRITE(FOUT, BLANK: (LEFTMARGIN - 1)); FOR I := 1 TO LINEWIDTH DO WRITE ( FOUT, BOLINE [ I ]); WRITELN ( FOUT ); END; END; CASE LINESPACING OF 1: ; 2: BEGIN INCURRLINE; WRITELN(FOUT); END; 3: BEGIN INCURRLINE; INCURRLINE; WRITELN(FOUT); WRITELN(FOUT) END; END (*CASE*) END ELSE IF (CURRLINE >= (PAGESIZE - M3 - M4 - 1)) THEN BEGIN REPEAT WRITELN(FOUT); INCURRLINE UNTIL CURRLINE = (PAGESIZE - M4 - 1); WRITEFOOTER; IF CARRIAGECONTROL THEN WRITELN(FOUT, TOF) ELSE PAGE ( OUTPUT ); CURRPAGE := SUCC ( CURRPAGE ); CURRLINE := 0; REPEAT WRITELN(FOUT); INCURRLINE UNTIL CURRLINE = M1; WRITEHEADER; REPEAT WRITELN(FOUT); INCURRLINE UNTIL CURRLINE = (M1 + M2 + 1); END; FILLC ( BOLINE ); FILLC ( ULLINE ); END; (* PROCEDURE PUTLINE *) (* NOTE: THE BASIC FLOW OF FMT COMES STRAIGHT FROM PASCAL, AN INTRODUCTION TO METHODICAL PROGRAMMING BY WYATT AND FINDLAY (INCLUDING ROOMFOR, ADJUSTLINE, READWORD, STARTLINE, STARTPARAGRAPH *) FUNCTION ROOMFOR (NMROFCHARS : INTEGER) : BOOLEAN; (* FROM METHODICAL PROGRAMMI NG *) BEGIN ROOMFOR := POSITION + NMROFCHARS <= LINEWIDTH; END; FUNCTION SUFFIX ( CHARPOS : INTEGER ) : BOOLEAN; (* RETURNS TRUE IF A SUFFIX EXISTS AT CHARPOS *) VAR BUF : STRING; J : INTEGER; BEGIN SUFFIX := FALSE; FOR J := 1 TO WORD.LENGTH DO BUF . CH [ J ] := WORD.SPELLING [ J ]; IF POS (BUF,TION) = CHARPOS THEN SUFFIX := TRUE; IF POS (BUF,ING ) = CHARPOS THEN SUFFIX := TRUE; END; FUNCTION CANHYPHENATEAT ( LEFTCH, RIGHTCH : CHAR; I : INTEGER ) : BOOLEAN; (* AFTER SATISFING SOME RULES FOR THE NUMBER OF CHARACTERS ON EITHER SIDE OF A PROPOSED HYPHENATION POINT, THIS FUNCTIONS MERELY CHECKS BITMAP AND RETURNS TRUE IF IT IS OK TO HYPHENATE AT LEFTCH, RIGHTCH *) LABEL 13; VAR COUNT1, COUNT2, J : INTEGER; BEGIN CANHYPHENATEAT := FALSE; COUNT1 := 0; LEFTCH := LOWER ( LEFTCH ); RIGHTCH := LOWER ( RIGHTCH ); FOR J := 1 TO I - 1 DO BEGIN IF WORD.SPELLING [ J ] IN [ '-', '/', '_', '<', '>' ] (* DON'T HYPHENATE IF WORD HAS ANY OF THESE *) THEN GOTO 13; IF WORD.SPELLING [ J ] IN [ 'a' .. 'z'] (* COUNT LOWER CASE ONLY *) THEN COUNT1 := SUCC ( COUNT1 ); END; COUNT2 := 0; FOR J := I TO WORD.LENGTH DO BEGIN IF WORD.SPELLING [ J ] IN ['-', '/', '_', '<', '>' ] THEN GOTO 13; IF WORD.SPELLING [ J ] IN [ 'a' .. 'z' ] THEN COUNT2 := SUCC ( COUNT2); END; IF ((COUNT1 <= 2) AND (COUNT2 <= 2)) THEN GOTO 13; IF ((COUNT1 < 2) OR (COUNT2 < 2)) THEN GOTO 13; IF (( SUFFIX ( I ) ) AND (WORD.SPELLING [I-2] <> WORD.SPELLING [I-1])) THEN BEGIN CANHYPHENATEAT := TRUE; GOTO 13 END; IF (( LEFTCH IN [ 'a' .. 'z' ] ) AND ( RIGHTCH IN ['a' .. 'z'])) THEN IF BITMAP [ LEFTCH, RIGHTCH ] THEN BEGIN CANHYPHENATEAT := TRUE; END; 13: END; PROCEDURE CHECKHYPHENATE; (* PRELIMINARY DECISIONS ON WHETHER THE CURRENT WORD CAN BE SUCCESSFULLY HYPHENATED; USES FUNCTION CANHYPHENATEAT AS A FINAL CHECK *) CONST HYPHEN = '-'; VAR WORDL : WORDREC; (* THE LEFT PART OF PROPOSED HYPHENATED WORD *) CHLEFT, CHRIGHT : CHAR; C1, C2, C3, I : INTEGER; BEGIN DIDHYPHENATE := FALSE; FOR C1 := 1 TO MAXWORDLENGTH DO BEGIN WORDL.SPELLING [ C1 ] := BLANK; WORDR.SPELLING [ C1 ] := BLANK END; WORDL.ISUL := FALSE; WORDL.ISBO := FALSE; WORDL.LENGTH := 0; WORDR.LENGTH := 0; C1 := PRED ( WORD.LENGTH); (* THE FOLLOWING CODE MERELY CHECKS THE NUMBER OF CHARACTERS LEFT AND RIGHT OF POSSIBLE HYPHEN POINTS TO SEE IF THEY WILL FIT *) WHILE ((NOT DIDHYPHENATE) AND (C1 >= 2)) DO BEGIN CHLEFT := WORD.SPELLING [ C1 - 1 ]; CHRIGHT := WORD.SPELLING [ C1 ]; IF ( (CANHYPHENATEAT(CHLEFT, CHRIGHT, C1)) AND ((WORD.LENGTH - C1) > 2) AND ( NOT ( (WORD.SPELLING [ WORD.LENGTH ] IN ['.', ',', ';']))) ) THEN (* NOT A GOOD IDEA TO HYPHENATE IF LAST CHARACTER IN A WORD IS IN '. .. ;' *) BEGIN FOR C2 := 1 TO C1 - 1 DO WORDL.SPELLING [ C2 ] := WORD.SPELLING [ C2 ]; WORDL.SPELLING [ C1 ] := HYPHEN; WORDL.ISUL := WORD.ISUL; WORDL.ISBO := WORD.ISBO; FOR I := C1 + 1 TO MAXWORDLENGTH DO WORDL.SPELLING [ I ] := BLANK; WORDL.LENGTH := C1; IF ROOMFOR ( WORDL.LENGTH ) THEN BEGIN FOR C3 := 1 TO ( WORD.LENGTH - PRED (C1) ) DO WORDR.SPELLING [ C3 ] := WORD.SPELLING [C1 + C3 - 1]; FOR I := C3 + 1 TO MAXWORDLENGTH DO WORDR.SPELLING [ I ] := BLANK; WORDR.LENGTH := C3; WORDR.ISUL := WORD.ISUL; WORDR.ISBO := WORD.ISBO; DIDHYPHENATE := TRUE; END ELSE BEGIN FOR I := 1 TO MAXWORDLENGTH DO BEGIN WORDR.SPELLING [ I ] := BLANK; WORDL.SPELLING [ I ] := BLANK; END; WORDR.LENGTH := 0; WORDL.LENGTH := 0; WORDR.ISUL := FALSE; WORDR.ISBO := FALSE; WORDL.ISUL := FALSE; WORDL.ISBO := FALSE END END ELSE IF WORD.SPELLING [ C1 ] = HYPHEN (* WORD IS ALREADY HYPHENATED *) THEN IF WORD.LENGTH - C1 > 2 THEN BEGIN FOR C2 := 1 TO C1 DO WORDL.SPELLING [ C2 ] := WORD.SPELLING [ C2 ]; WORDL.LENGTH := C2; WORDL.ISUL := WORD.ISUL; WORDL.ISBO := WORD.ISBO; IF ROOMFOR (WORDL.LENGTH) THEN BEGIN FOR C3 := 1 TO (WORD.LENGTH - C1 ) DO WORDR.SPELLING [ C3] := WORD.SPELLING [ C3 + C1 ]; WORDR.ISUL := WORD.ISUL; WORDR.ISBO := WORD.ISBO; FOR I := C3 + 1 TO MAXWORDLENGTH DO WORDR.SPELLING [ I ] := BLANK; WORDR.LENGTH := WORD.LENGTH - C1; DIDHYPHENATE := TRUE; END ELSE BEGIN FOR I := 1 TO MAXWORDLENGTH DO BEGIN WORDR.SPELLING [ I ] := BLANK; WORDL.SPELLING [ I ] := BLANK; END; WORDL.LENGTH := 0; WORDR.LENGTH := 0; WORDR.ISUL := FALSE; WORDR.ISBO := FALSE; WORDL.ISUL := FALSE; WORDL.ISBO := FALSE; END; END; C1 := PRED ( C1 ); END (* WHILE *); IF DIDHYPHENATE THEN BEGIN FOR I := 1 TO MAXWORDLENGTH DO WORD.SPELLING [ I ] := WORDL.SPELLING[ I ]; WORD.LENGTH := WORDL.LENGTH; WORD.ISUL := WORDL.ISUL; WORD.ISBO := WORDL.ISBO END; END; PROCEDURE READWORD( VAR FIN : TEXT ); (* GET NEXT WORD BETWEEN BLANKS *) VAR CH : CHAR; BEGIN CH := BLANK; WHILE NOT EOF(FIN) AND (CH = BLANK) DO READ(FIN, CH); WITH WORD DO (* BUILD UP THE WORD RECORD *) BEGIN LENGTH := 0; FOR I := 1 TO MAXWORDLENGTH DO SPELLING [ I ] := BLANK; ISUL := ULFLAG; ISBO := BOFLAG; WHILE NOT EOF(FIN) AND (CH <> BLANK) DO BEGIN IF LENGTH < MAXWORDLENGTH THEN BEGIN LENGTH := SUCC ( LENGTH ); SPELLING [ LENGTH ] := CH END; READ(FIN,CH) END END END (* READWORD *); PROCEDURE APPENDWORD; (* PUT NEXT WORD IN OUTPUT BUFFER *) VAR POS : 1 .. MAXWORDLENGTH; BEGIN FOR POS := 1 TO WORD.LENGTH DO BEGIN POSITION := SUCC ( POSITION ); LINE [ POSITION ] := WORD.SPELLING[POS]; IF WORD.ISUL THEN ULLINE [ POSITION ] := '_'; IF WORD.ISBO THEN BOLINE [ POSITION ] := LINE [ POSITION ]; END END (* APPENDWORD *); PROCEDURE APPENDBLANK; (* BLANKS BETWEEN WORDS *) BEGIN POSITION := SUCC ( POSITION ); LINE [ POSITION ] := BLANK; IF ULFLAG THEN ULLINE [ POSITION ] := BLANK; IF BOFLAG THEN BOLINE [ POSITION ] := BLANK; END (* APPENDBLANK *); PROCEDURE STARTLINE ; (* INDENT AND INITIALIZE A NEW LINE *) VAR I : INTEGER; BEGIN WRITE(FOUT,' ':LEFTMARGIN ); IF ((DIDHYPHENATE) AND (WORD.LENGTH > 1)) THEN BEGIN FOR I := 1 TO WORD.LENGTH DO BEGIN LINE [ I ] := WORD.SPELLING [ I ]; IF WORD.ISUL THEN ULLINE [ I ] := '_'; IF WORD.ISBO THEN BOLINE [ I ] := WORD.SPELLING [ I ] END; POSITION := WORD.LENGTH; END ELSE POSITION := 0; END (* STARTLINE *); PROCEDURE BREAKLINE; (* DUMP CURRENT UNFILLED LINE TO OUTPUT BUFFER *) VAR POS : 1 .. MAXLINEWIDTH; BEGIN IF POSITION > 1 THEN FOR POS := 1 TO POSITION DO BEGIN WRITE ( FOUT, LINE [ POS ] ); END; IF POSITION > 1 THEN PUTLINE( FOUT ); FOR POS := 1 TO MAXLINEWIDTH DO LINE [ POS ] := ' '; END (* BREAKLINE *); PROCEDURE CENTERLINE ( THISSTRING : STRING ); (* UTILITY ROUTINE TO CENTER ANY STRING BETWEEN CURRENT LEFT AND RIGHT MARGINS; UNDERSTANDS "@" TO MEAN BOLDFACE THE STRING, "_" TO MEAN UNDERLINE THE STRING (MUST BE THE FIRST CHARACTER *) VAR BO, UL : BOOLEAN; LEFT, I, J : INTEGER; BEGIN BO := POS (THISSTRING, ATSYM ) <> 0; UL := POS (THISSTRING, ULSYM ) <> 0; LEFT := (LINEWIDTH - LENGTH (THISSTRING ) ) DIV 2; WRITE (FOUT, BLANK : LEFT + LEFTMARGIN ); IF ( BO OR UL) AND CARRIAGECONTROL THEN FOR I := 2 TO LENGTH (THISSTRING ) DO WRITE ( FOUT, THISSTRING . CH [ I ]) ELSE FOR I := 1 TO LENGTH (THISSTRING ) DO WRITE (FOUT, THISSTRING . CH [ I ]); IF ( BO OR UL ) AND CARRIAGECONTROL THEN WRITELN( FOUT ) ELSE PUTLINE ( FOUT ); IF ( BO AND CARRIAGECONTROL ) THEN FOR J := 1 TO 3 DO BEGIN WRITE ( FOUT, NOLF); WRITE (FOUT, BLANK: LEFT + LEFTMARGIN - 1); FOR I := 2 TO LENGTH ( THISSTRING ) DO WRITE ( FOUT, THISSTRING . CH [ I ] ); WRITELN ( FOUT ); END; IF ( UL AND CARRIAGECONTROL ) THEN FOR J := 1 TO 3 DO BEGIN WRITE(FOUT, NOLF); WRITE(FOUT, BLANK: LEFT + LEFTMARGIN - 1); FOR I := 2 TO LENGTH ( THISSTRING ) DO WRITE ( FOUT, '_'); WRITELN ( FOUT ); END; IF (BO OR UL ) AND CARRIAGECONTROL THEN BEGIN CURRLINE := SUCC(CURRLINE); IF LINESPACING > 1 THEN BEGIN FOR I := 1 TO LINESPACING - 1 DO BEGIN CURRLINE := SUCC ( CURRLINE ); WRITELN(FOUT) END; END; END; END; PROCEDURE ADJUSTLINE ; (* SPREAD ALGORITHM FROM METHODICAL PROGRAMMING EXTENSIVELY MODIFIED TO HANDLE UNDERLINES AND BOLDFACES *) VAR EXTRABLANKS, NMROFGAPS,WIDENING, SEXTRA, THISPOS : 0 .. MAXLINEWIDTH; LEFTMOST, RIGHTMOST, POS : 1 .. MAXLINEWIDTH; BBOLINE, UULLINE : CHARS; BEGIN FILLC(BBOLINE); FILLC(UULLINE); LEFTMOST := 1; WHILE LINE [ LEFTMOST ] = BLANK DO LEFTMOST := SUCC ( LEFTMOST ); RIGHTMOST := POSITION; WHILE LINE [ RIGHTMOST ] = BLANK DO RIGHTMOST := PRED ( RIGHTMOST ); NMROFGAPS := 0; FOR POS := LEFTMOST TO RIGHTMOST DO IF LINE[POS] = BLANK THEN NMROFGAPS := SUCC(NMROFGAPS); EXTRABLANKS := LINEWIDTH - RIGHTMOST; SEXTRA := EXTRABLANKS; THISPOS := 0; FOR POS := 1 TO RIGHTMOST DO IF (POS > LEFTMOST) AND (LINE[POS]=BLANK) THEN BEGIN WIDENING := EXTRABLANKS DIV NMROFGAPS; WRITE(FOUT,BLANK:(WIDENING + 1 ) ); THISPOS := THISPOS + WIDENING; EXTRABLANKS := EXTRABLANKS - WIDENING; NMROFGAPS := PRED ( NMROFGAPS ); END ELSE BEGIN WRITE(FOUT,LINE [ POS ]); IF (DIDBO AND CARRIAGECONTROL) THEN BBOLINE [ POS + THISPOS ] := BOLINE [ POS ]; IF (DIDUL AND CARRIAGECONTROL) THEN UULLINE [POS + THISPOS ] := ULLINE [ POS ]; END; IF (DIDBO AND CARRIAGECONTROL) THEN FOR I := 1 TO POSITION + SEXTRA DO BOLINE [ I ] := BBOLINE [ I ]; IF (DIDUL AND CARRIAGECONTROL) THEN FOR I := 1 TO POSITION + SEXTRA DO ULLINE [ I ] := UULLINE [ I ]; PUTLINE ( FOUT ); IF DIDHYPHENATE THEN BEGIN FOR I := 1 TO MAXWORDLENGTH DO WORD . SPELLING [ I ] := WORDR . SPELLING [ I ]; WORD . LENGTH := WORDR . LENGTH; WORD . ISUL := WORDR . ISUL; WORD . ISBO := WORDR . ISBO; END; END; (*****************************************************************) PROCEDURE NOFILL (VAR FIN: TEXT); VAR LINEBUF : STRING; BEGIN REPEAT READS(FIN,LINEBUF); IF (POS (LINEBUF,NFSYM) = 0) THEN BEGIN WRITE(FOUT,BLANK: LEFTMARGIN); WRITES(FOUT,LINEBUF); PUTLINE(FOUT); END UNTIL ( (POS(LINEBUF,NFSYM)<>0) OR (EOF(FIN))); END; (*******************************************************************) PROCEDURE STARTPARAGRAPH; BEGIN BREAKLINE; PUTLINE(FOUT); WRITE(FOUT,BLANK:LEFTMARGIN); FOR POSITION := 1 TO PDENT DO LINE [ POSITION] := BLANK; POSITION := PDENT; END; (********************************************************************) PROCEDURE CHECKOPTIONS ( VAR FIN: TEXT); VAR ASTRING, CMD: STRING; OLDDENT, THESKIP : INTEGER; (*******************************************************************) FUNCTION COMMAND ( FMTCMD: STRING): BOOLEAN; BEGIN COMMAND := FALSE; IF (FMTCMD.LEN = CMD.LEN) THEN IF (LOWER ( FMTCMD . CH [ 2 ] ) = CMD . CH [ 2 ]) THEN IF (LOWER ( FMTCMD . CH [ 3 ] ) = CMD . CH [ 3 ] ) THEN IF (LOWER ( FMTCMD . CH [ FMTCMD . LEN ] ) = CMD . CH [ CMD . LEN ]) THEN COMMAND := TRUE; END; (******************************************************************) BEGIN (*Checkoptions*) I := 1; WHILE ( (WORD.SPELLING[I]<>BLANK) AND (I<=MAXWORDLENGTH) ) DO BEGIN CMD . CH [ I ] := WORD . SPELLING [ I ]; I := SUCC ( I ); END; CMD . LEN := PRED ( I ); IF COMMAND(STARTNEWPARAGRAPH) THEN STARTPARAGRAPH ELSE IF COMMAND (CENTERALINE ) THEN BEGIN READS(FIN,ASTRING); BREAKLINE; CENTERLINE ( ASTRING ); END ELSE IF COMMAND (BREAKCURRENTLINE) THEN BREAKLINE ELSE IF COMMAND (DONOTFILLTEXT) THEN BEGIN BREAKLINE; NOFILL ( FIN ) END ELSE IF COMMAND (SKIPLINE) THEN BEGIN BREAKLINE; PUTLINE ( FOUT ); POSITION := 0; END ELSE IF COMMAND (TAKEINPUTFROMNEWFILE) THEN BEGIN NEWFILE := TRUE; BREAKLINE; END ELSE IF COMMAND (SETLEFTMARGIN) THEN BEGIN READLN(FIN,LEFTMARGIN); LEFTMARGIN := PRED ( LEFTMARGIN ); END ELSE IF COMMAND ( SETRIGHTMARGIN) THEN BEGIN READLN(FIN, LINEWIDTH); LINEWIDTH := PRED ( LINEWIDTH ) - LEFTMARGIN; END ELSE IF COMMAND (ONHYPHEN ) THEN HYNATE := TRUE ELSE IF COMMAND ( OFFHYPHEN) THEN HYNATE := FALSE ELSE IF COMMAND (LINEPRINTER) THEN CARRIAGECONTROL := TRUE ELSE IF COMMAND (TITLE) THEN BEGIN READS(FIN,THETITLE); BREAKLINE; CENTERLINE ( THETITLE ); BREAKLINE; POSITION := 0; END ELSE IF COMMAND (SKIPPLUS) THEN BEGIN READLN(FIN,THESKIP); BREAKLINE; THESKIP := THESKIP * LINESPACING; REPEAT IF CURRLINE < (PAGESIZE - (M1 + M2 + M3 + M4 ) ) THEN PUTLINE ( FOUT ); THESKIP := PRED ( THESKIP ); UNTIL THESKIP <= 1; PUTLINE ( FOUT ); END ELSE IF COMMAND (NEED) THEN BEGIN READLN(FIN, I); IF (I > (PAGESIZE - CURRLINE - M3 + M4) ) THEN BEGIN BREAKLINE; REPEAT PUTLINE ( FOUT ) UNTIL CURRLINE = (M1 + M2 + 1); END; END ELSE IF COMMAND (COMMENT) THEN BEGIN READS(FIN,THETITLE); BREAKLINE END ELSE IF COMMAND (PROMPT) THEN BEGIN READS(FIN,THETITLE); END ELSE IF COMMAND (UNDERLINE) THEN IF ULFLAG THEN ULFLAG := FALSE ELSE BEGIN ULFLAG := TRUE; DIDUL := TRUE; FILLC (ULLINE ); END ELSE IF COMMAND (BOLDFACE) THEN IF BOFLAG THEN BOFLAG := FALSE ELSE BEGIN BOFLAG := TRUE; DIDBO := TRUE; FILLC ( BOLINE ); END ELSE IF COMMAND (SETLINESPACING) THEN BEGIN READLN(FIN,LINESPACING); IF ( (LINESPACING > 3) OR (LINESPACING < 1) ) THEN LINESPACING := 1; END ELSE IF COMMAND (SETPAGENUM) THEN READLN(FIN,CURRPAGE) ELSE IF COMMAND(PINDENTATION) THEN READLN(FIN,PDENT) ELSE IF COMMAND (TINDENTATION) THEN BEGIN READLN(FIN,TDENT ); OLDDENT := PDENT; PDENT := TDENT; STARTPARAGRAPH; PDENT := OLDDENT END ELSE IF COMMAND (STARTPAGE) THEN BEGIN BREAKLINE; REPEAT PUTLINE ( FOUT ) UNTIL CURRLINE = (M1 + M2 + 1); END ELSE IF COMMAND (DONOTADJUST) THEN NOADJ := NOT NOADJ ELSE IF COMMAND (CRT) THEN CARRIAGECONTROL := FALSE ELSE IF COMMAND ( HEADER ) THEN BEGIN HAVEAHEADER := TRUE; READS(FIN,THEHEADER); END ELSE IF COMMAND (FOOTER) THEN BEGIN HAVEAFOOTER := TRUE; READS(FIN,THEFOOTER) END ELSE IF COMMAND(SETPAGESIZE) THEN READLN(FIN,PAGESIZE) ELSE IF COMMAND (SETM1) THEN READLN(FIN,M1) ELSE IF COMMAND (SETM2) THEN READLN(FIN,M2) ELSE IF COMMAND (SETM3) THEN READLN(FIN,M3) ELSE IF COMMAND (SETM4) THEN READLN(FIN,M4) END; (**************************************************************) BEGIN LINELIMIT ( OUTPUT, MAXINT ); PAGE ( OUTPUT ); WRITELN (' Welcome to VAX/FMT Version 2.1'); WRITELN('A Developing Text Formatter by Cpt(P) F. J. Monaco'); WRITELN('Your document is being prepared...'); INIT; LINEWIDTH := LINEWIDTH - LEFTMARGIN; PAGE(FOUT); PUTLINE (FOUT); STARTLINE; READWORD(FIN); WHILE WORD . LENGTH <> 0 DO BEGIN IF WORD . SPELLING [ 1 ] = '.' THEN IF NOT NEWFILE THEN CHECKOPTIONS (FIN) ELSE CHECKOPTIONS(INPUT) ELSE BEGIN IF NOT ROOMFOR( WORD . LENGTH ) THEN BEGIN IF NOADJ THEN BEGIN BREAKLINE; STARTLINE; END ELSE BEGIN IF HYNATE THEN CHECKHYPHENATE; IF DIDHYPHENATE THEN APPENDWORD; ADJUSTLINE; STARTLINE END; END; IF NOT DIDHYPHENATE THEN APPENDWORD; DIDHYPHENATE := FALSE; IF ROOMFOR ( 1 ) THEN APPENDBLANK END; IF NOT NEWFILE THEN READWORD ( FIN ) ELSE READWORD ( INPUT ); IF ( (NEWFILE) AND (WORD . SPELLING [ 4 ] = '-') ) THEN BEGIN NEWFILE := FALSE; READWORD ( FIN ) END; END; BREAKLINE; PAGE(OUTPUT); END.