home *** CD-ROM | disk | FTP | other *** search
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- {+ +}
- {+ PROGRAM TITLE: RUNOFF ROUTINE +}
- {+ +}
- {+ +}
- {+ SUMMARY: +}
- {+ Complete instructions are found in file RUNOFF.DOC +}
- {+ +}
- {+ VERSION RECORD +}
- {+ 04/22/82 - added single sheet, continuous sheet, pause, +}
- {+ and message commands. R.E. Penley +}
- {+ 04/21/82 - added .OUT command. R.E. Penley +}
- {+ 04/17/82 - first complete run under Pascal/Z with no +}
- {+ errors. R.E. Penley +}
- {+ 02/19/82 - First attempt at modification for operation +}
- {+ under CP/M operating system. R.E. Penley +}
- {+ 01/01/79 - TRW KERNAL OPERATING SYSTEM VERS 1A +}
- {+ MULTIPLE MINICOMPUTER ARCHITECTURE +}
- {+ IR&D PROJECT. Michelle Feraud +}
- {+ +}
- {+ PROGRAMMERS NOTES: +}
- {+ -Pascal/Z compiler v 4.0 by Ithaca Intersystems. +}
- {+ -The program tries to use as much in line code as possible. +}
- {+ This makes the program much faster since we cut down on +}
- {+ calls to procedures/functions and the extra code associated +}
- {+ with procedure calls. +}
- {+ -Under Pascal/Z the following was observed: +}
- {+ case 1 - conversion of a chr() takes 6 bytes of code. +}
- {+ const +}
- {+ nl = 10; +}
- {+ begin +}
- {+ c := chr(nl); +}
- {+ case 2 - conversion of a variable takes 7 bytes of code. +}
- {+ var newline: char; +}
- {+ begin +}
- {+ newline := chr(10); +}
- {+ c := newline; +}
- {+ +}
- {+ -If any changes are made to the source program the +}
- {+ following steps will recompile RUNOFF.PAS (assume dr A:). +}
- {+ pascal runoff +}
- {+ asmbl main,runoff.aa/rel +}
- {+ era runoff.src +}
- {+ link /n:runoff runoff/v asl/s /e +}
- {+ era runoff.rel +}
- {+ +}
- {+ required files are: +}
- {+ asl.rel, runoff.pas, runinit.p, +}
- {+ runcomm.p, stdopen.p, open.p +}
- {+ +}
- {+ NICE TO HAVE: +}
- {+ 1. chaining to other text files +}
- {+ 2. ability to read text/data from another file. +}
- {+ 3. read/get inputs from console/disk files. +}
- {+ 4. top and bottom margin settings. +}
- {+ 5. Indent command. +}
- {+ +}
- {+ BUGS: +}
- {+ 1. Program does not seem to like blank lines in text files. +}
- {+ +}
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- PROGRAM RUNOFF;
-
- CONST
- DfltLeftMrgn = 0; { default left margin }
- DfltRightMrgn = 60; { " right margin }
- DfltLineSpacing = 1; { " line spacing }
- DfltIndent = 5; { " indent }
- DftlTestPage = 0; { " test page }
- DfltPageSize = 60; { " page size }
-
- ZR = 0; { ASCII NULL }
- NL = 10; { ASCII Line feed CODE / New line }
- FF = 12; { ASCII FORM feed CODE }
- CR = 13; { ASCII carriage return CODE }
- SPACE = ' ';
- NmbrArgs = 8; { MAX # OF NUMERICAL ARGUMENTS << 04/21/82 >>}
-
- LineLength = 132; { Max length of a single "line" }
- MaxBuffer = 128 * 8; { use 1K buffers. } {<<< 04.26.82 >>>}
-
- IDLENGTH = 12;
- CmdSize = 4;
- anull = -maxint;
-
- TYPE
- ARGARRAY = ARRAY [0..NmbrArgs] OF INTEGER;
- cstring = PACKED ARRAY [1..4] OF CHAR;
- IDENTIFIER = PACKED ARRAY [1..IDLENGTH] OF CHAR;
- Line = PACKED ARRAY [1..MaxBuffer] OF CHAR; {<<< 04.26.82 >>>}
- LISTRECORD = RECORD
- NUMBER,
- SPACING,
- OFFSET : INTEGER
- END;
-
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- {+ NOTE: commands MUST be inserted here in order of most frequent +}
- {+ usage. Only by trial and error can the correct/most +}
- {+ correct sequence be found. +}
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
-
- CmdType = ( FIRST,
- CmdJustify, { MOST USED COMMAND FIRST }
- CmdNoFill,
- CmdParaGraph,
- CmdFill,
- CmdRem, {Remarks lines added <<< 04.16.82 >>>}
- CmdLeftMrgn,
- CmdHeadLevel,
- CmdNoJustify,
- CmdBreak,
- CmdSkip,
- CmdBlank,
- CmdPage,
- CmdCenter,
- CmdSpacing,
- CmdTitle,
- CmdNumber,
- CmdHeader,
- CmdNoHeader,
- CmdMessage, {Show message on console device < 04.22.82 >}
- CmdLeftJustify, {Left Justify CMD added <<< 04.18.82 >>>}
- CmdSingle, {Single sheet paper <<< 04.22.82 >>>}
- CmdCont, {Continuous sheet paper <<< 04.22.82 >>>}
- CmdPause, {Pause await console input <<< 04.22.82 >>>}
- CmdPageSize,
- CmdTestPage,
- CmdOut, {Output direct commands to printer }
- CmdRightMrgn,
- CmdTempIndent, { Temporary indent command }
- CmdPeriod,
- CmdNoPeriod,
- CmdNoNumber,
- CmdList,
- CmdListEntry,
- CmdEndList,
- Invalid, {Sentinal in CommandTable <<< 04.16.82 >>>}
- Cmdp1c,
- Cmdp2c,
- Cmdp3c,
- Cmdpgs1c,
- Cmdpgs2c );
-
- VAR
- Cmdchar : CHAR; { character defining the start of a command }
- CCmd : CmdType;
-
- INBUF : Line; { input line buffer }
- ipos : integer; { position of cursor in input line }
-
- OUTBUF : Line; { output line buffer }
- opos : integer; { position of cursor in output line }
-
- CommandTable : ARRAY [FIRST..Invalid] OF cstring;
-
- Line_count,
- PAGE_count,
- Line_SPACING,
- PARA_SPACING,
- PARA_INDENT,
- PARA_TESTPAGE,
- PAGE_SIZE,
- PAGE_CENTER,
- LEFT_MARGIN,
- RIGHT_MARGIN : INTEGER;
-
- { FORMATTING FLAGS }
- Headerflag,
- Numberflag,
- Periodflag,
- Single_sheet, {<<< 04.22.82 >>>}
- Fillflag,
- Justifyflag : BOOLEAN;
-
- { PARAMETER INITIALIZATION PHASE }
- Setup : BOOLEAN;
- INITPARAMCommandS : SET OF CmdType;
-
- { HEAD LEVEL DECLARATONS }
- OLDHeadLevel : integer;
- Level : ARRAY [1..5] OF INTEGER;
-
- { LIST AND BULLET DECLARATIONS }
- LISTLevel : integer;
- LISTPARAM : ARRAY [1..5] OF LISTRECORD;
-
- { FILL AND JUSTIFY DECLARATIONS }
- wrdbuffull,
- STARTOFLine,
- EndOfFile,
- EndOfSENTENCE : BOOLEAN;
- inval, { indent value }
- tival, { temp indent value }
- ceval, { # of lines to center <<< 04.22.82 >>>}
- SPACES,
- WORDLENGTH,
- outwds,
- DIRECTION : integer;
-
- CURRENT_TITLE : Line;
-
- SENTENCE_ENDERS,
- DIGITS : SET OF CHAR;
-
- STDIN, { standard input file }
- STDOUT : TEXT; { standard output file }
-
-
- {++++++++++++++++++++++++++++++++++++++++++}
- {+ COMPILER OPTIONS FOR PASCAL/Z COMPILER +}
- {++++++++++++++++++++++++++++++++++++++++++}
-
- {$C-}{ control-c checking OFF }
- {$F-}{ floating point error checking OFF }
- {$M-}{ integer mult & divd error checking OFF }
-
-
- {************************************}
- {* GENERAL UTILITY ROUTINES *}
- {************************************}
-
- function toupper ( ch: char ): char;
- external;
-
- function max ( x,y: integer ): integer;
- begin
- if x>y then max := x
- else max := y
- end;
-
- function min ( x,y: integer ): integer;
- begin
- if x<y then min := x
- else min := y
- end;
-
- {*****************************************}
- {* PROGRAM SPECIFIC UTILITY ROUTINES *}
- {*****************************************}
-
- function EndOfLine ( var buf: line ): boolean;
- begin
- EndOfLine := (buf[ipos]=chr(nl));
- end;
-
-
- PROCEDURE print ( var TEXT: Line );
- { Prints the string TEXT to the console device }
- { last modified 04/14/82 rep }
- VAR I: integer;
- ch : char;
- BEGIN
- i := 1;
- ch := text[i];
- while not ( (ch=chr(nl)) OR (ch=CHR(ZR)) )
- do begin
- write ( ch );
- i := i + 1;
- ch := text[i];
- end;
- writeln;
- END{print};
-
-
- PROCEDURE HELP;
- BEGIN
- writeln;
- writeln('TRY AGAIN:');
- writeln(' RUNOFF INPUTFILE OUTPUTFILE <output to disk file>' );
- writeln(' RUNOFF INPUTFILE <output to list device>');
- writeln(' RUNOFF INPUTFILE LST:' );
- writeln(' RUNOFF INPUTFILE CON: <output to console>' );
- writeln;
- end{help};
-
-
-
-
- {***************************************}
- {* I/O BUFFER ROUTINES *}
- {***************************************}
-
- PROCEDURE getc ( VAR ch: char );{$R-}(*** RANGE CHECKING OFF ***)
- var xeoln: boolean;
- begin
- xeoln := eoln(stdin);
- EndOfFile := eof(stdin);
- if not EndOfFile then Read(stdin,ch);
- if xeoln or EndOfFile then
- ch := CHR(NL);
- end{ getc }; {$R+}(*** RANGE CHECKING ON ***)
-
-
- PROCEDURE getline;
- (************************************************)
- (* GET ONE LINE FROM SOURCE FILE INTO INBUF *)
- (* GLOBAL: *)
- (* NL, EndOfFile, MaxBuffer *)
- (************************************************)
- var ch: char;
- ix: integer;
- BEGIN {$R-}
- ix := 0;
- repeat
- ix := ix + 1;
- getc(ch);
- if ORD(ch) > 127 then ch := CHR( ORD(ch)-128 );
- INBUF[ix] := ch;
- until (ch=CHR(NL)) or (EndOfFile) or (ix=MaxBuffer);
- { set cursor position to beginning of input buffer less one }
- ipos := 0;
- end{ getline }; {$R+}
-
-
- PROCEDURE putc ( C: CHAR );
- { WRITE ONE CHAR TO OUTPUT FILE }
- begin
- if ( c = CHR(NL) ) then
- writeln(stdout)
- else
- write(stdout,c); {output the character}
- end{ putc };
-
-
- PROCEDURE putline { var outbuf: line };
- {
- Put current output line to output file. Line is
- expected to have appropriate end-of-line character
- when received. Also, keeps track of line count
- AND StartOfLine flag (for fill routines).
- }
- VAR I: integer;
- BEGIN
- IF ( opos > LEFT_MARGIN ) THEN BEGIN
- FOR I:=1 TO opos
- DO putc ( OUTBUF[I] );
- opos := LEFT_MARGIN;
- FOR I:=1 TO opos
- DO OUTBUF[I] := SPACE;
- STARTOFLine := TRUE;
- Line_count := Line_count + 1;
- END;
- END{putline};
-
-
- function value { var INBUF: line; var ipos: integer }: INTEGER;
- { RETURNS }
- { Integer value of source string 'INBUF' }
- { starting at position "ipos" }
- const zero = 48; { ordinal value of '0' }
- VAR sign : -1..1;
- NUM : INTEGER;
- BEGIN
- IF INBUF[ipos] = '-' THEN BEGIN
- sign := -1;
- ipos := ipos + 1
- END
- ELSE BEGIN
- sign := 1;
- IF INBUF[ipos] = '+' THEN ipos := ipos + 1
- END;
- NUM := 0;
- REPEAT
- NUM := 10 * NUM + ord(INBUF[ipos]) - zero;
- ipos := ipos + 1
- UNTIL NOT ( INBUF[ipos] IN DIGITS );
- VALUE := NUM * SIGN
- END{VALUE};
-
-
- {++++++++++++++++++++++++++++++++++++++++++++++++}
- {+ CHECK BOUNDS AND/OR SET PARAMETERS +}
- {++++++++++++++++++++++++++++++++++++++++++++++++}
-
- PROCEDURE Check_Set ( argtype: CmdType; { command argument }
- var val: INTEGER ); { value to check/set }
- VAR I: INTEGER;
- BEGIN {$R-}
- CASE argtype OF
-
- CmdSkip, CmdBlank: { CHECK SKIP & BLANK ARGUMENT }
- val := max ( val,1 ); { always space at least 1 line }
-
- CmdTempIndent : { CHECK INDENT ARGUMENT }
- IF ( (LEFT_MARGIN+val) < 0 ) THEN
- val := LEFT_MARGIN
- ELSE IF ( (LEFT_MARGIN+val) > (RIGHT_MARGIN-1) ) THEN
- val := 0;
-
- Cmdp1c : { IF NOT NULL RESET PARAGRAPH INDENT }
- IF ( val <> anull ) THEN
- IF ( (LEFT_MARGIN+val) < 0 ) OR
- ( (LEFT_MARGIN+val) > (RIGHT_MARGIN-1) ) THEN
- PARA_INDENT := DfltIndent
- ELSE
- PARA_INDENT := val;
-
- Cmdp2c : { IF NOT NULL RESET PARAGRAPH VERTICAL SPACING }
- IF ( val <> anull ) THEN
- IF ( val < 0 ) THEN
- PARA_SPACING := (Line_SPACING+1) DIV 2
- ELSE
- PARA_SPACING := val;
-
- Cmdp3c : { IF NOT NULL RESET PARAGRAPH TEST PAGE ARGUMENT }
- IF ( val <> anull ) THEN
- IF ( val < 0 ) THEN
- PARA_TESTPAGE := DftlTestPage
- ELSE
- PARA_TESTPAGE := val;
-
- CmdCenter : { Compute value for page center }
- begin
- ceval := max ( val,1 ); { always center 1 line }
- page_center := ( ( right_margin-left_margin ) DIV 2 ) + left_margin;
- end;
-
- CmdTestPage : { CHECK TESTPAGE ARGUMENT }
- IF NOT ( (val <> anull) AND (val >= 0) ) THEN val := 0;
-
- CmdHeadLevel : { CHECK HeadLevel ARGUMENT }
- begin
- val := max ( val,1 ); { set floor to larger of val or 1 }
- val := min ( val,5 ); { set ceiling to smaller of val or 5 }
- end;
-
- CmdList : { CHECK LIST ARGUMENTS }
- IF ( val < 0 ) THEN val := DfltLineSpacing
-
- CmdLeftMrgn : { RESET LEFT MARGIN & BLANK OUTBUF UP TO LEFT MARGIN }
- BEGIN
- IF ( val < 0 ) OR ( val >= RIGHT_MARGIN ) THEN
- LEFT_MARGIN := DfltLeftMrgn
- ELSE
- LEFT_MARGIN := val;
- FOR I:=1 TO LEFT_MARGIN
- DO OUTBUF[I] := SPACE;
- opos := LEFT_MARGIN;
- END;
-
- CmdRightMrgn : { RESET RIGHT MARGIN. No further than LineLength }
- IF ( val > (LineLength-1) ) OR ( val < LEFT_MARGIN ) THEN
- RIGHT_MARGIN := DfltRightMrgn
- ELSE
- RIGHT_MARGIN := val;
-
- CmdSpacing : { RESET Line SPACING AND PARAGRAPH SPACING }
- begin
- IF ( val < 1 ) OR ( val > 5 ) THEN
- Line_SPACING := DfltLineSpacing
- ELSE
- Line_SPACING := val;
- PARA_SPACING := (Line_SPACING+1) DIV 2;
- end;
-
- Cmdpgs1c: { RESET PAGE SIZE }
- IF ( val < 11 ) THEN
- PAGE_SIZE := DfltPageSize
- ELSE
- PAGE_SIZE := val;
-
- Cmdpgs2c : { IF NOT NULL RESET RIGHT MARGIN }
- IF ( val <> anull ) THEN
- IF ( val > (LineLength-1) ) OR ( val < LEFT_MARGIN ) THEN
- RIGHT_MARGIN := DfltRightMrgn
- ELSE
- RIGHT_MARGIN := val;
-
- CmdNumber : { IF NOT NULL RESET PAGE count }
- IF ( val <> anull ) THEN
- IF ( val > 0 ) THEN
- PAGE_count := val - 1
- ELSE
- PAGE_count := 0
- END{CASE};
- END{Check_Set}; {R+}
-
-
- PROCEDURE SETTITLE ( argstring : Line );
- { REPLACE CURRENT TITLE WITH Command STRING ARGUMENT }
- VAR CTP, STP: integer;
- BEGIN
- FOR CTP:=1 TO RIGHT_MARGIN
- DO CURRENT_TITLE[CTP] := SPACE;
- CTP := LEFT_MARGIN + 1;
- STP := 1;
- WHILE ( argstring[STP] <> CHR(ZR) ) AND ( CTP<=RIGHT_MARGIN )
- DO BEGIN
- CURRENT_TITLE[CTP] := argstring[STP];
- CTP := CTP + 1;
- STP := STP + 1
- END
- END{SETTITLE};
-
-
- FUNCTION ATTOPOFPAGE: BOOLEAN;
- { IS CURRENT OutPutLine THE FIRST Line OF TEXT AFTER THE PAGE Head? }
- BEGIN
- ATTOPOFPAGE := ( Line_count=5 )
- END;
-
-
- FUNCTION TEST_PAGE ( argc: INTEGER ): BOOLEAN;
- { ARE THERE argc lines LEFT ON THE CURRENT PAGE? }
- BEGIN
- TEST_PAGE := ( (PAGE_SIZE-Line_count) >= argc )
- END;
-
-
- PROCEDURE SKIPLines ( N: INTEGER );
- { INSERT N BLANK Lines INTO OUTPUT FILE }
- VAR I: integer;
- BEGIN {$R-}
- IF ( N>0 ) THEN
- FOR I:=1 TO N DO BEGIN
- putc(CHR(NL));
- Line_count := Line_count + 1
- END
- END{SKIPLines}; {$R+}
-
-
- PROCEDURE PUTPAGEHead;
- { PUT CURRENT TITLE AND PAGE NUMBER INTO OUTPUT Line AND PRINT }
- VAR PAGE_NUMBER: INTEGER;
- BEGIN {$R-}
- OUTBUF := CURRENT_TITLE;
- IF ( NUMBERflag ) THEN BEGIN { TRANSLATE AND OUTPUT PAGE NUMBER }
- opos := RIGHT_MARGIN;
- PAGE_NUMBER := PAGE_count;
- REPEAT
- OUTBUF[opos] := CHR((PAGE_NUMBER MOD 10)+48);
- opos := opos - 1;
- PAGE_NUMBER := PAGE_NUMBER DIV 10
- UNTIL ( PAGE_NUMBER=0 );
- END;
-
- OUTBUF[opos-4] := 'P';
- OUTBUF[opos-3] := 'A';
- OUTBUF[opos-2] := 'G';
- OUTBUF[opos-1] := 'E';
- OUTBUF[opos ] := ' ';
- opos := RIGHT_MARGIN + 1;
- OUTBUF[opos] := CHR(NL);
- putline
- END{PUTPAGEHead}; {$R+}
-
-
- PROCEDURE NEWPAGE;
- { GO TO TOP OF NEW PAGE AND PRINT PAGE Head }
- var dummy: char;
- BEGIN {$R-}
- putc ( CHR(FF) ); {*** assumes printer recognizes formfeed char ***}
- PAGE_count := PAGE_count + 1;
- Line_count := 0;
-
- if single_sheet then begin {pause for operator intervention << 04.22.82 >>}
- writeln;
- write ( 'Insert new page. Press return to continue. ' );
- readln ( dummy );
- end;
-
- IF Headerflag THEN BEGIN { PRINTED PAGE Head }
- SKIPLines(1);
- PUTPAGEHead;
- SKIPLines(3)
- END
- ELSE { BLANK PAGE Head }
- SKIPLines(5)
- END{NEWPAGE}; {$R+}
-
-
- PROCEDURE MOVE_opos ( mvarg: INTEGER );
- { MOVE OUTPUT Line Cursor position FORWARD OR BACKWARD. A }
- { FORWARD MOVE BLANKS THE Line UP TO THE NEW POSITION OF opos. }
- VAR I: integer;
- BEGIN
- IF ( mvarg > 0 ) THEN BEGIN
- opos := opos + 1;
- FOR i:=opos TO (opos+mvarg-1)
- DO OUTBUF[i] := SPACE;
- opos := opos + mvarg - 1
- END
- ELSE IF ( mvarg < 0 ) THEN
- opos := opos + mvarg
- END{MOVE_opos};
-
-
- PROCEDURE PUTHeadLevel ( NEWHeadLevel: INTEGER; HeadSTRING: Line );
- { PUT Head Level NUMBER AND Head Level TITLE INTO OUTPUT Line }
- VAR chars,
- k, I,
- HSP : integer;
- LevelsOut,
- LevelNUM,
- NUMBER : INTEGER;
- BEGIN {$R-}
- IF ( NEWHeadLevel<OLDHeadLevel ) THEN { ZERO UNNEEDED Head Level NUMBERS }
- FOR i:=(NEWHeadLevel+1) TO OLDHeadLevel
- DO Level[i] := 0;
- Level[NEWHeadLevel] := Level[NEWHeadLevel] + 1;
- IF ( NEWHeadLevel=1 ) THEN (* WILL PRINT FIRST 2 Head Level NUMBERS *)
- LevelsOut := 2
- ELSE (* WILL PRINT SPECIFIED Head Level NUMBERS *)
- LevelsOut := NEWHeadLevel;
- FOR LevelNUM:=1 TO LevelsOut
- DO BEGIN { PRINT Head Level NUMBERS }
- IF ( LevelNUM <> 1 ) THEN
- OUTBUF[opos] := '.';
- NUMBER := Level[LevelNUM];
- k := number;
- CHARS := 1;
- WHILE ( k>9 )
- DO BEGIN
- k := k DIV 10;
- CHARS := CHARS + 1
- END;
- FOR I:=(opos+CHARS) DOWNTO (opos+1)
- DO BEGIN
- OUTBUF[I] := CHR( (NUMBER MOD 10)+48 );
- NUMBER := NUMBER DIV 10
- END;
- opos := opos + CHARS + 1
- END;
- OLDHeadLevel := NEWHeadLevel;
- IF ( HeadSTRING[1] <> CHR(ZR) ) THEN BEGIN { PRINT Head Level TITLE }
- OUTBUF[opos] := SPACE;
- OUTBUF[opos+1] := SPACE;
- opos := opos + 2;
- HSP := 1;
- WHILE ( HeadSTRING[HSP] <> CHR(ZR) ) AND ( opos<=RIGHT_MARGIN )
- DO BEGIN
- OUTBUF[opos] := HeadSTRING[HSP];
- opos := opos + 1;
- HSP := HSP + 1
- END;
- END;
- OUTBUF[opos] := CHR(NL);
- putline;
- END{PUTHeadLevel}; {$R+}
-
-
- PROCEDURE STARTLIST ( VAR N: INTEGER );
- { INITIALIZE THIS Level OF LIST }
- VAR NEWLEFTMARGIN: INTEGER;
- BEGIN
- LISTLevel := LISTLevel + 1;
- WITH LISTPARAM[LISTLevel]
- DO BEGIN
- NUMBER := 0;
- SPACING := N;
- NEWLEFTMARGIN := LEFT_MARGIN + OFFSET;
- Check_Set ( CmdLeftMrgn, NEWLEFTMARGIN );
- END
- END{STARTLIST};
-
-
- PROCEDURE PUTLISTNUMBER ( LISTTYPE: CmdType );
- { TRANSLATE LIST ELEMENT NUMBER INTO CHARACTERS }
- VAR NUMBER: INTEGER;
- BEGIN
- OUTBUF[LEFT_MARGIN-2] := '.';
- OUTBUF[LEFT_MARGIN-1] := ' ';
- OUTBUF[LEFT_MARGIN ] := ' ';
- NUMBER := LISTPARAM[LISTLevel].NUMBER;
- opos := LEFT_MARGIN - 3;
- REPEAT
- OUTBUF[opos] := CHR( (NUMBER MOD 10)+48 );
- NUMBER := NUMBER DIV 10;
- opos := opos - 1;
- UNTIL NUMBER=0;
- opos := LEFT_MARGIN;
- END{PUTLISTNUMBER};
-
-
- PROCEDURE LISTMEMBER ( LISTTYPE: CMDTYPE );
- { SPACE DOWN AND NUMBER A LIST ENTRY }
- BEGIN
- WITH LISTPARAM[LISTLevel]
- DO BEGIN
- IF TEST_PAGE ( SPACING+1 ) THEN
- SKIPLINES ( SPACING )
- ELSE
- NEWPAGE;
- NUMBER := NUMBER + 1;
- END;
- PUTLISTNUMBER ( LISTTYPE );
- END{LISTMEMBER};
-
-
- PROCEDURE STOPLIST;
- { TERMINATE THIS Level OF LIST AND RESET TO PRIOR Level }
- VAR NEWLEFTMARGIN: INTEGER;
- BEGIN
- WITH LISTPARAM[LISTLevel] DO BEGIN
- IF TEST_PAGE ( SPACING+1 ) THEN
- SKIPLines ( SPACING )
- ELSE
- NEWPAGE;
- NEWLEFTMARGIN := LEFT_MARGIN - OFFSET;
- Check_Set ( CmdLeftMrgn, NEWLEFTMARGIN )
- END;
- LISTLevel := LISTLevel - 1
- END{STOPLIST};
-
-
- PROCEDURE BREAK;
- BEGIN
- putline;
- IF TEST_PAGE ( Line_SPACING ) THEN
- SKIPLines ( Line_SPACING-1 )
- ELSE
- NEWPAGE
- END{BREAK};
-
-
- {************************************}
- {* TEXT PROCESSING ROUTINES *}
- {************************************}
-
-
- PROCEDURE DoText ( var INBUF: Line );
- { FORMAT TEXT }
- VAR
- wrdbuffer : Line;
-
-
- PROCEDURE PUTCENTERED;
- { CENTER TEXT FROM INPUT LINE }
- VAR i,
- width, { width of input text }
- fudge: integer; { computed center of input text }
- BEGIN
- (*** width := length(INBUF); ***)
- repeat ipos := ipos + 1
- until EndOfLine ( INBUF );
- width := ipos - 1;
-
- (*** Compute center char of line to be centered ***)
- fudge := width DIV 2;
- if odd(width) then { pretty it up }
- fudge := fudge + 1;
-
- (*** Now compute how much to indent to get there ***)
- tival := (page_center - fudge) + 1; { have to add 1 to get off of zero base }
-
- (*** However don't go less than left margin ***)
- tival := max ( tival, (left_margin+1) );
-
- for i:=(left_margin+1) to (tival-1)
- do outbuf[i] := space;
- opos := tival;
- ipos := 1;
- WHILE ( not EndOfLine(INBUF) ) AND ( opos <= RIGHT_MARGIN )
- DO BEGIN { PUT CENTERED TEXT }
- OUTBUF[opos] := INBUF[ipos];
- opos := opos + 1;
- ipos := ipos + 1
- END;
- OUTBUF[opos] := CHR(NL)
- END{PUTCENTERED};
-
-
- PROCEDURE GETWORD;
- { REMOVE A CONTIGUOUS GROUP OF CHARS FROM INPUT Line }
- VAR WBP: integer;
- BEGIN
- REPEAT ipos := ipos + 1
- UNTIL INBUF[ipos] <> SPACE;
- IF NOT EndOfLine(INBUF) THEN BEGIN { GET WORD }
- wrdbuffull := FALSE;
- WBP := 1;
- WHILE NOT wrdbuffull
- DO begin
- IF ( EndOfLine(INBUF) ) OR ( INBUF[ipos]=SPACE ) THEN BEGIN
- (* WORD HAS BEEN GOTTEN *)
- wrdbuffull := TRUE;
- WORDLENGTH := WBP - 1;
- EndOfSENTENCE := (wrdbuffer[WORDLENGTH] IN SENTENCE_ENDERS);
- END{IF}
- ELSE BEGIN
- wrdbuffer[WBP] := INBUF[ipos];
- WBP := WBP + 1;
- ipos := ipos + 1
- END{ELSE}
- end{while}
- END{IF}
- ELSE BEGIN {AT END OF INPUT LINE AND NO WORD HAS BEEN GOTTEN}
- wrdbuffull := FALSE;
- WORDLENGTH := 0;
- END;
- END{GETWORD};
-
-
- FUNCTION SpaceRemaining: BOOLEAN;
- { Is there enough room left in output line for current word? }
- BEGIN
- SpaceRemaining := ( (SPACES+WORDLENGTH+opos-1) <= RIGHT_MARGIN )
- END;
-
-
- procedure justify ( var outbuf: line );
- { JUSTIFY OUTPUT LINE OUT TO RIGHT MARGIN.
- { ALGORITHM FROM "SOFTWARE TOOLS" BY K & F, PG 241. }
- VAR I, nextra,
- nmbrholes,
- LEFTSIDE,
- RIGHTSIDE,
- BLANKS : INTEGER;
- BEGIN {$R-}
- { COMPUTE NUMBER OF BLANKS THAT WILL HAVE TO BE INSERTED }
- nextra := (RIGHT_MARGIN+1) - opos;
- IF (nextra>0) AND (outwds>1) THEN BEGIN
- { REVERSE PREVIOUS DIRECTION FOR INSERTING BLANKS }
- DIRECTION := 1 - DIRECTION;
- { COMPUTE # OF HOLES IN WHICH TO ADD BLANKS }
- nmbrholes := outwds - 1;
- LEFTSIDE := opos;
- RIGHTSIDE := RIGHT_MARGIN + 1;
- opos := RIGHTSIDE;
- WHILE ( LEFTSIDE < RIGHTSIDE )
- DO BEGIN { JUSTIFY TEXT }
- OUTBUF[RIGHTSIDE] := OUTBUF[LEFTSIDE];
- IF ( OUTBUF[LEFTSIDE]=' ' ) THEN BEGIN {END OF WORD}
- IF NOT (PERIODflag AND (OUTBUF[LEFTSIDE-1] IN SENTENCE_ENDERS))
- THEN BEGIN { COMPUTE # OF EXTRA BLANKS TO INSERT }
- IF DIRECTION=0 THEN
- BLANKS := ((nextra-1) DIV nmbrholes) + 1
- ELSE
- BLANKS := nextra DIV nmbrholes;
- nextra := nextra - BLANKS;
- nmbrholes := nmbrholes - 1;
- FOR I:=1 TO BLANKS
- DO BEGIN { INSERT EXTRA BLANKS }
- RIGHTSIDE := RIGHTSIDE - 1;
- OUTBUF[RIGHTSIDE] := ' '
- END;
- END{IF}
- END{IF};
- LEFTSIDE := LEFTSIDE - 1;
- RIGHTSIDE := RIGHTSIDE - 1
- END{WHILE}
- END{IF}
- END{justify}; {$R+}
-
-
- PROCEDURE PUTWORD ( var wrdbuffer : line );
- { PUT CURRENT WORD INTO OUTPUT Line. KEEP }
- { TRACK OF WORD count FOR JUSTIFY ROUTINE. }
- VAR I, WBP: integer;
- BEGIN
- IF NOT STARTOFLine THEN BEGIN { SPACING BETWEEN WORDS }
- FOR I:=1 TO SPACES
- DO BEGIN
- OUTBUF[opos] := SPACE;
- opos := opos + 1
- END{FOR}
- END
- ELSE BEGIN { THIS IS THE FIRST WORD ON THE Line }
- STARTOFLine := FALSE;
- outwds := 0;
- opos := opos + 1
- END;
- FOR WBP:=1 TO WORDLENGTH
- DO BEGIN { COPY WORD INTO OUTPUT Line }
- OUTBUF[opos] := wrdbuffer[WBP];
- opos := opos + 1
- END;
- OUTBUF[opos] := CHR(NL);
- outwds := outwds + 1
- END{PUTWORD};
-
-
- PROCEDURE Fill_Lines;
- { Fill AND JUSTIFY ONE OR MORE OUTPUT Lines FROM CURRENT INPUT Line }
- VAR LineFilled: BOOLEAN;
-
-
- PROCEDURE Fill_ONE_Line;
- { Fill OUTPUT Line FROM CURRENT INPUT Line }
- VAR FINISHED: BOOLEAN;
- BEGIN
- IF NOT wrdbuffull THEN GETWORD;
- LineFilled := FALSE;
- FINISHED := FALSE;
- WHILE NOT FINISHED
- DO BEGIN
- IF ( spaceremaining ) then begin
- if ( WORDLENGTH <> 0 ) then begin
- { CONTINUE FillING Line }
- PUTWORD ( wrdbuffer );
- IF EndOfSENTENCE THEN { SET SPACING BEFORE NEXT WORD }
- SPACES := 2
- ELSE
- SPACES := 1;
- IF NOT EndOfLine(INBUF) THEN
- GETWORD
- ELSE BEGIN { NO MORE WORDS IN THIS INPUT Line }
- FINISHED := TRUE;
- wrdbuffull := FALSE;
- END{else}
- end{if wordlength <> 0}
- END{if spaceremaining}
- ELSE BEGIN { Stop filling line }
- FINISHED := TRUE;
- LineFilled := Not SpaceRemaining;
- END{Stop filling line}
- END
- END{Fill ONE Line};
-
- BEGIN {Fill_Lines}
- Fill_ONE_Line;
- WHILE ( LineFilled )
- DO BEGIN
- IF JUSTIFYflag THEN justify ( OUTBUF );
- BREAK;
- Fill_ONE_Line;
- END
- END{Fill_Lines};
-
-
- PROCEDURE CopyAsIs;
- { COPY INPUT Line LITERALLY AS FOUND IN SOURCE FILE }
- VAR LineCOPIED: BOOLEAN;
- BEGIN
- LineCOPIED := FALSE;
- WHILE NOT LineCOPIED DO BEGIN
- REPEAT
- opos := opos + 1;
- ipos := ipos + 1;
- OUTBUF[opos] := INBUF[ipos];
- UNTIL (opos=RIGHT_MARGIN) OR ( EndOfLine(INBUF) );
- IF EndOfLine(INBUF) THEN { INPUT Line HAS BEEN COPIED }
- LineCOPIED := TRUE
- ELSE BEGIN { INPUT Line MAY BE TOO LONG, REMAINDER GOES TO NEXT Line }
- IF INBUF[ipos+1]=CHR(NL) THEN {Line IS EXACTLY THE RIGHT SIZE}
- LineCOPIED := TRUE;
- opos := opos + 1;
- OUTBUF[opos] := CHR(NL)
- END;
- BREAK;
- END
- END{CopyAsIs};
-
-
- BEGIN {DoText}
- if ceval>0 then begin
- PUTCENTERED;
- ceval := ceval - 1;
- BREAK
- END
- ELSE
- IF Fillflag THEN
- Fill_Lines
- ELSE
- CopyAsIs
- END{DoText};
-
-
- FUNCTION ScanCommand: CmdType;
- { REMOVE Command STRING FROM INPUT Line AND SEARCH
- Command Table FOR MATCHING Command TYPE }
- VAR CommandLine : cstring;
- CmdIndex : CmdType;
- hash,
- j,
- cpos : integer;
- BEGIN {$R-}
- FOR cpos:=1 TO (CmdSize-1)
- DO CommandLine[cpos] := SPACE;
- ipos := 2; { skip CmdChar }
- cpos := 1;
- WHILE ( INBUF[ipos] <> ' ' )
- AND ( not EndOfLine(INBUF) )
- AND ( cpos <= CmdSize )
- DO BEGIN { get Command string }
- CommandLine[cpos] := toupper ( INBUF[ipos] );
- ipos := ipos + 1;
- cpos := cpos + 1
- END{WHILE};
- CommandLine[CmdSize] := CHR(ZR);
-
- { since the table is so short just do a sequential search. <<<04.15.82>>>}
- CmdIndex := FIRST;
- CommandTable[invalid] := CommandLine; { insert the sentinal }
- repeat CmdIndex := SUCC(CmdIndex);
- until CommandTable[CmdIndex]=CommandLine;
- ScanCommand := CmdIndex
- END{ScanCommand}; {$R+}
-
-
- {$iRUNCOMM.P }
-
-
- {$iSTDOPEN.P }
-
-
- {$iRUNINIT.P }
-
-
- BEGIN {* MAIN PROGRAM *}
- for ipos:=1 to 24 do writeln;
- WRITELN ( ' RUNOFF' );
- writeln ( ' CP/M Version 1.0 Created April 30, 1982' );
- OpenFiles;
- INITIALIZE{ all parameters now };
-
- {$C+}{ allow program termination from this section }
- getline;
- Setup := TRUE;
- { PROCESS THOSE Commands THAT AFFECT THE VARIOUS PARAMETER & flag SETTINGS }
- WHILE NOT EndOfFile AND Setup
- DO BEGIN
- IF INBUF[1]=Cmdchar THEN BEGIN
- CCmd := ScanCommand;
- IF CCmd IN INITPARAMCommandS THEN BEGIN
- DoCommand ( INBUF );
- getline
- END
- ELSE { First non-init Command ends setup phase }
- Setup := FALSE;
- END
- ELSE { First text line ends setup phase }
- Setup := FALSE;
- END{WHILE};
-
- NEWPAGE; { TOP OF FIRST PAGE }
- WHILE NOT EndOfFile
- DO BEGIN { PROCEED WITH NORMAL SOURCE FILE PROCESSING }
- IF INBUF[1]=Cmdchar THEN
- DoCommand ( INBUF )
- ELSE
- DoText ( INBUF );
- getline
- {+++ test for break key press here +++}
- END{WHILE};
-
- putline;{ terminate }
- putc ( CHR(FF) );
- writeln ( 'End of job.' );
- writeln;writeln;
- END{ RUNOFF }.
-