> As to changing fonts while underlining, it's hard to imagine > a situation in which it's likely to happen. Underlining > should at best be an occasional effect, IMHO. Still, > one likes to have solutions that cover every possibility.
Well, for editorial purposes it's sometimes useful to mark up changes to a document, for example by underlining newly inserted text and striking through deleted text, and these have to be available *in addition* to all other markup. Here's my second attempt, which works a bit better but still has problems once in a while because grops's output is "too optimized" (e.g., it sometimes uses "ashow" to produce a space and can thus occasionally step (invisibly) beyond the end of the line, but the simple underline algorithm doesn't realize what grops is doing). Ultimately I think the only sensible solution is to make grops itself underline-aware and make .cu do underlining in troff if not in compatibility mode. .\" .\" ---------------------------------------------------------------- .de XX ps: def grops begin /decornone { grops begin /X { } def /Y { } def /y2 -1 def end } def /decorline { grops begin u neg /uld exch def u /ulw exch def /X { currentpoint /y0 exch def /x0 exch def } def /Y { currentpoint /y1 exch def /x1 exch def drawline /x2 x1 def /y2 y1 def } def end } def /drawline { gsave ulw setlinewidth 0 setlinecap x1 y1 uld sub moveto y2 y0 eq { x2 y2 } { x0 y0 } ifelse uld sub lineto stroke grestore } def decornone /uld 0 def /ulw 0 def /A { X show Y } def /B { 0 SC 3 -1 roll X widthshow Y } def /C { 0 exch X ashow Y } def /D { 0 exch 0 SC 5 2 roll X awidthshow Y } def /E { 0 rmoveto X show Y } def /F { 0 rmoveto 0 SC 3 -1 roll X widthshow Y } def /G { 0 rmoveto 0 exch X ashow Y } def /H { 0 rmoveto 0 exch 0 SC 5 2 roll X awidthshow Y } def /I { 0 exch rmoveto X show Y } def /J { 0 exch rmoveto 0 SC 3 -1 roll X widthshow Y } def /K { 0 exch rmoveto 0 exch X ashow Y } def /L { 0 exch rmoveto 0 exch 0 SC 5 2 roll X awidthshow Y } def /M { rmoveto X show Y } def /N { rmoveto 0 SC 3 -1 roll X widthshow Y } def /O { rmoveto 0 exch X ashow Y } def /P { rmoveto 0 exch 0 SC 5 2 roll X awidthshow Y } def /Q { moveto X show Y } def /R { moveto 0 SC 3 -1 roll X widthshow Y } def /S { moveto 0 exch X ashow Y } def /T { moveto 0 exch 0 SC 5 2 roll X awidthshow Y } def end .. .de normal \X'ps: exec decornone'\c .. .de underline .ie '\\$1'' .nr _w \\n[.ps]/20 .el .nr _w \\$1 .ie '\\$2'' .nr _d \\n[.ps]/16 .el .nr _d \\$2 \X'ps: exec \\n[_w] \\n[_d] decorline'\c .. .de strikethrough .ie '\\$1'' .nr _w \\n[.ps]/20 .el .nr _w \\$1 .ie '\\$2'' .nr _d -\\n[.ps]/4 .el .nr _d \\$2 \X'ps: exec \\n[_w] \\n[_d] decorline'\c .. .\" ---------------------------------------------------------------- .sp 3c .ll 4c .\" .ps 24 .\" .vs 26 \Y[XX]\c .strikethrough The general syntax for writing \fBgroff\fP documents is relatively easy, but writing extensions to the roff language can be a bit harder. .normal The roff language is line-oriented. .underline There are only two kinds of lines, \fIcontrol lines\fP and \fItext lines\fP. .normal The control lines start with a \fIcontrol character\fP, by default a period \(lq.\(rq or a single quote \(lq\^'\^\(rq; all other lines are text lines.