[[ Definition to push a pager on the output. For now we cheat. ]] :runpager "sh" "sh" "-c" "exec $PAGER" 3 @filter ; [[ Accumulate lines, keeping track of an approximate count of screen lines. If screen lines reaches @height-1, punt and run it all through $PAGER. If we reach end of message first, just dump it to stdout. ]] [[ Process message lines, according to TOS values: f i cp f is code pointer, holding function to return next line, or integer if no more lines; may mutate itself i is integer, number of lines remaining before we punt cp is code pointer, code to run for each line; this will be run with line on TOS above b i cp, is expected to pop the line and leave f i cp undisturbed, may mess with deeper values. On return, f i cp are undisturbed, above them is boolean, true if we ran out of height, false if we ran out of header lines. ]] ::screenlines :msgproc L( 3 sg Cc t?i ?? s- 0 Lb ?. sr so \screenlines - sR so Cc so 1 < ?? 1 Lb ?. L) ; [[ Helper - takes string, returnes number of lines it occupies on screen ]] :screenlines "\n" $*- 0 L( so Lw sx 1 - sx sr $l @width + 1 - @width / s+ 1 < ?? s- 1 ?. + L) sx s- ; [[ Just like msgproc, except ignores integer on stack, no return value, and never runs out of screen room, always continuing until no more lines. ]] :msgdump L( 3 sg Cc t?i ?? s- Lb ?. so Cc L) ; [[ If we have more than five lines, try just saving lines, see if it all fits into @height-1 lines; otherwise act as though we did that but we ran out of height immediately. ]] 0 [[ count of saved lines ]] [[ f for msgproc - line generator ]] { sr s- { L( "" @hdrget t?i ?? s- sr s- { @bodyline } sR "" ?| \hdrignore ?? s- s- Lc ?. ": " sx $+ $+ ?. Lb L) } sR "(Message " mf ":" mn $ ?? [[ Okay, call msgproc, then throw away the code pointer ]] { _5 ss 4 ss 1 + _4 ss } \msgproc sx s- ?| 1 ?. [[ Stack now: ...saved-lines... savecount msgproc-linegen linecount bool-rv ]] [[ The code block is code to dump the saved lines; it gets used in both branches of the conditional. ]] sx s- { sx L( s+ Lw s+ 2 + ss @outstring "\n" @outstring 1 - L) s- } sx ?? [[ Ran out of height. Run a pager, dump the saved lines, and carry on. ]] \runpager Cc ?| [[ End of message came first. Dump the saved lines and we're done. ]] Cc s- Cr ?. [[ Do the rest of the message, dumping to stdout (which must be the pager, if we got to this point). ]] 0 { @outstring "\n" @outstring } \msgdump [[ Clean up the stack. ]] s- s- s-