{$T+} program ShoH (file1, file2, input, output); { ShoH - a program to display two text files simultaneously on the user's terminal in a horizontal format. For the purposes of this program, "page" is defined to mean one-half of the space available on the user's terminal screen. ShoH shows a page of text from filea on the top half of the screen, and a page from fileb on the bottom half. The size of the pages is defined by "maxlinesize" and "nroflines". Lines are truncated on the right to maxlinesize. ShoH uses some of the nonstandard features of NBS Pascal. It is designed for use with DEC VT52 or VT100 crt terminals, but could be adopted for use with other terminals. User commands: A - Advance filea (file1); B - Advance fileb (file2); C or - Advance both files; L - set line number mode (initial default); N - turn off line number mode; E or Q - exit program. RSX-11 usage: MCR>SHH filea.ext fileb.ext written by: Bill Heidebrecht TRW DSSG R2 / 1170 One Space Park Redondo Beach, CA 90278 7 December 1979 } const maxlinesize = 80; { chars per line, if no line numbers } shortlinesize = 75; { chars per line, if line numbers } nroflines = 10; { lines per page } pagesize = maxlinesize * nroflines; ht = chr(9); nl = chr(10); ff = chr(12); esc = chr(27); Debug = false; type textpage = array [1..pagesize] of char; var eof1, eof2, filesok, linenumbermode: Boolean; firstline1, firstline2: integer; page1, page2: textpage; file1, file2: text; procedure CursorPosition (column, line: integer); begin {CursorPosition} write (output, esc, 'Y', chr (31 + line), chr (31 + column)) end {CursorPosition}; procedure ClearScreen; begin {ClearScreen} write (output, esc, 'H', esc, 'J', esc, 'H') end {ClearScreen}; procedure EraseToEndOfScreen; begin {EraseToEndOfScreen} write (output, esc, 'J') end {EraseToEndOfScreen}; procedure DisplayFiles; type usercommand = (unknown, show1, show2, showboth, reshowboth, exitprog); var command: usercommand; Finished: Boolean; procedure GetCommand (var cmd: usercommand); { get the next user command in the form of a single character. } var ch: char; begin {GetCommand} cmd := unknown; repeat CursorPosition (1, 23); write(output, '?'); break(output); read(input, ch); if eoln(input) then cmd := showboth else begin if (ch>='a') and (ch<='z') then ch := chr(ord(ch) - 32); if ch = 'A' then cmd := show1 else if ch = 'B' then cmd := show2 else if ch = 'C' then cmd := showboth else if ch = 'L' then begin linenumbermode := true; cmd := reshowboth end else if ch = 'N' then begin linenumbermode := false; cmd := reshowboth end else if (ch = 'E') or (ch = 'Q') then cmd := exitprog end until cmd <> unknown end {GetCommand}; procedure ClearPage (var pagex: textpage); { clear page to spaces. } var i: integer; begin {ClearPage} for i := 1 to pagesize do pagex[i] := ' ' end {ClearPage}; procedure Advance (var filex: text; var eofx: Boolean; var firstline: integer; var pagex: textpage); { Advance the file to the next page. } var i, c, nrch, nlines: integer; ch: char; begin {Advance} if not eofx then begin ClearPage(pagex); firstline := firstline + nroflines; c := 0; nlines := 0; while (not eof(filex)) and (nlines < nroflines) do begin { read a page: } nlines := nlines + 1; nrch := 0; repeat { read a line: } read(filex, ch); if Debug then write(output, ch); if nrch < maxlinesize then begin if ch = ht then repeat { replace ht with spaces: } nrch := nrch+1; c := c+1; pagex[c] := ' ' until ((nrch mod 8)=0) or (nrch>=maxlinesize) else if ch = ff then begin { replace ff with '': } if nrch >= maxlinesize - 6 then begin c := c - 6; nrch := nrch - 6 end; pagex[c+1] := '<'; pagex[c+2] := 'F'; pagex[c+3] := 'F'; pagex[c+4] := '>'; c := c + 4; nrch := nrch + 4 end {ch = ff} else if ch <> nl then begin nrch := nrch+1; c := c+1; pagex[c] := ch end; end {nrch < maxlinesize} until (ch = nl) or eof(filex); c := c + maxlinesize - nrch end {while}; eofx := eof(filex) end {not eofx} end {Advance}; procedure DisplayText (which_page: integer); { display the current pages from file1 and file2 on the user's terminal. which_page tells which page has been updated, and therefore which page must be redisplayed. which_page action 1 page1 2 page2 3 both pages } procedure DisplayHpage (var pagex: textpage; linepos, firstline: integer); { display a page. } var lineno, linpsn, c, i, increndofline, linewidth: integer; begin {DisplayHpage} c := 0; if linenumbermode then begin linewidth := shortlinesize; increndofline := maxlinesize - shortlinesize end else begin { no line numbers: } linewidth := maxlinesize; increndofline := 0 end; linpsn := linepos; for lineno := 0 to nroflines - 1 do begin CursorPosition (1, linpsn); if linenumbermode then write(output, (firstline + lineno): 4, ' '); for i := 1 to linewidth do begin c := c + 1; write(output, pagex[c]) end; c := c + increndofline; linpsn := linpsn + 1 end {for}; break(output) end {DisplayHpage}; begin {DisplayText} if which_page = 1 then DisplayHpage(page1, 1, firstline1) else if which_page = 2 then DisplayHpage(page2, 13, firstline2) else begin { display both: } clearscreen; DisplayHpage(page1, 1, firstline1); writeln(output, '--------------------------------------------------'); DisplayHpage(page2, 13, firstline2) end end {DisplayText}; begin {DisplayFiles} firstline1 := 1 - nroflines; firstline2 := 1 - nroflines; Finished := false; ClearPage(page1); ClearPage(page2); command := showboth; { show both pages at first. } repeat case command of show1: begin Advance(file1, eof1, firstline1, page1); DisplayText (1) end; show2: begin Advance(file2, eof2, firstline2, page2); DisplayText (2) end; showboth: begin Advance(file1, eof1, firstline1, page1); Advance(file2, eof2, firstline2, page2); DisplayText (3) end; reshowboth: DisplayText (3); exitprog: Finished := true end {case}; if eof1 and eof2 then Finished := true; if not Finished then GetCommand(command) until Finished; CursorPosition (1, 23) end {DisplayFiles}; procedure OpenFiles; { This procedure uses nonstandard Pascal features. } begin {OpenFiles} filesok := true; linenumbermode := true; if argc = 3 then begin reset (file1, argv[1]@); reset (file2, argv[2]@) end else begin writeln(output); writeln(output, ' Arg error: SHH f1.ext f2.ext'); filesok := false end; eof1 := false; eof2 := false end {OpenFiles}; begin {ShoH} OpenFiles; if filesok then DisplayFiles end.