[net.bugs.4bsd] Using "am" or "xn" in programs considered harmful

gnu@hoptoad.uucp (John Gilmore) (07/31/86)

In article <3864@utah-cs.UUCP>, donn@utah-cs.UUCP (Donn Seeley) writes:
> Subject: 'more' doesn't understand 'xn' type terminals (such as 'xterm')

I propose that the termcap fields "am" and "xn" be deprecated and
that programs be written to ignore these fields.  I've been discussing
this with Ken Arnold (for Curses) but I don't know if he's convinced yet.

The problem is that "am" is particularly hard to get right in a termcap
entry.  Often (eg VT100) it depends on physical switch settings which
cannot be changed by escape codes and cannot be read by the program.
Many terminal emulators also have this ("Line Wrap") as a settable option.
I have seen more termcap entries that were "almost right" except for "am",
than any other termcap entry problem.

The reason I think it's a good idea to blow them away is that they
don't buy much.  They only come into play when a character is written
into the last column of the screen.  That's a very infrequent
condition.  Even when it happens, what is saved is a cursor positioning
command.  (Trusting "am" lets the program assume where the cursor will
be; not trusting it means you have to actually move the cursor to where
it should go next.)  If your program (e.g. "more") is outputting lines
of text, in the infrequent case that a line hits the 80th column, it
will have to print 80 chars and then a cursor positioning escape code,
rather than 80 chars, CR, and LF; or 80 chars and nothing.  Even if
the escape code is 8 bytes (some are), this is less than 10% overhead
in an infrequent case.

What you get back for your occasional <10% slower long line is that
your termcap entry is likely to be right, so that the long line will
actually appear in the right place and not mess up the screen display.

(While I recommend that programs not use "am" and "xn", I realize
that until the programs are all fixed, we will have to keep trying
to build termcap entries that get them right, when possible.)
-- 
John Gilmore  {sun,ptsfa,lll-crg,ihnp4}!hoptoad!gnu   jgilmore@lll-crg.arpa
		     May the Source be with you!

gwyn@brl-smoke.ARPA (Doug Gwyn ) (07/31/86)

The DEC VT100 doesn't have the "am" capability no matter how you
set it up, regardless of appearances.  "am" requires that after
a character is displayed in the last column, the cursor move to
the first column of the next row.  The VT100 defers this and in
some cases produces a different display result than if it had a
true "am" capability.

"am" is useful for terminals that have it, but no VT100 termcap
should include "am".  This doesn't preclude enabling auto-wrap
on your VT100, since without "am" no assumption about the right-
margin behavior of the terminal is allowed.  If one's code lets
a character be displayed in the rightmost column, then it has to
consider the cursor position "unknown" unless "am" holds.  This
is no worse than Gilmore's suggestion.  Why handicap terminals
with a true "am" capability?

#
# DEC VT100
# The "vt100" entry supports the Advanced Video Option if present;
# however, AVO is not required for correct operation of the "vt100" entry.
# The following SET-UP modes are assumed for normal operation:
#	ANSI_MODE	AUTO_XON/XOFF_ON	NEWLINE_OFF	80_COLUMNS
# Other SET-UP modes may be set for operator convenience or communication
# requirements; I recommend
#	SMOOTH_SCROLL	AUTOREPEAT_ON	BLOCK_CURSOR	MARGIN_BELL_OFF
#	SHIFTED_3_#	WRAP_AROUND_ON
# Unless you have a graphics add-on such as Digital Engineering's VT640
# (and even then, whenever it can be arranged!) you should set
#	INTERLACE_OFF
# Hardware tabs are assumed to be set every 8 columns; they can be set up
# by the "reset" or "tabs" utility (use vt100-x, 132 columns, for this).
# I have included some compatible code in "rs" for the VT640 if you have one.
# No delays are specified; use "stty ixon -ixany" to enable DC3/DC1 flow control!
d0|vt100|DEC VT100:\
	:ae=^O:as=^N:bl=^G:cd=\E[J:ce=\E[K:cm=\E[%i%d;%dH:co#80:cr=^M:\
	:cs=\E[%i%d;%dr:ct=\E[3g:DO=\E[%dB:do=^J:ho=\E[H:is=\E<\E)0:it#8:\
	:k0=\EOP:k1=\EOQ:k2=\EOR:k3=\EOS:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
	:kr=\EOC:ks=\E[?1h\E=:ku=\EOA:l0=PF1:l1=PF2:l2=PF3:l3=PF4:LE=\E[%dD:\
	:le=^H:li#24:ll=\E[24H:mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:ms:nd=\E[C:\
	:nw=\EE:rc=\E8:RI=\E[%dC:\
	:rs=^X\E<\E2\E[?9h^]\E^L^X\E[20l\E[?3;6;9l\E[r\E[m\E[q\E(B^O\E)0\E>:\
	:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:UP=\E[%dA:\
	:up=\EM:us=\E[4m:vt#3:xo:\
	:ch=\r\E[%dC:cl=\E[H\E[J:\
	:bs:kn#4:pt:
d8|vt100-w|DEC VT100 with AVO in 132-column mode:\
	:co#132:\
	:rs=^X\E<\E2\E[?9h^]\E^L^X\E[20l\E[?6;9l\E[?3h\
\E[r\E[m\E[q\E(B^O\E)0\E>:\
	:tc=vt100:
d9|vt100-x|DEC VT100 without AVO in 132-column mode:\
	:li#14:ll=\E[14H:\
	:tc=vt100-w:

barmar@mit-eddie.MIT.EDU (Barry Margolin) (08/01/86)

In article <925@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
>I propose that the termcap fields "am" and "xn" be deprecated and
>that programs be written to ignore these fields.  I've been discussing
>this with Ken Arnold (for Curses) but I don't know if he's convinced yet.
>
>...  They only come into play when a character is written
>into the last column of the screen.  That's a very infrequent
>condition.  Even when it happens, what is saved is a cursor positioning
>command.  (Trusting "am" lets the program assume where the cursor will
>be; not trusting it means you have to actually move the cursor to where
>it should go next.)  If your program (e.g. "more") is outputting lines
>of text, in the infrequent case that a line hits the 80th column, it
>will have to print 80 chars and then a cursor positioning escape code,
>rather than 80 chars, CR, and LF; or 80 chars and nothing.  Even if
>the escape code is 8 bytes (some are), this is less than 10% overhead
>in an infrequent case.

Unfortunately, this is not completely correct.  I don't recall if
termcap has a separate field for this, but most terminals that have
auto-wrap will also scroll the screen if a character is written into the
rightmost column of the last line.  Applications need to know whether
they can safely output to that cell without causing the screen to
scroll.

On Multics we have a simple solution for this: our video support
software never puts characters in the last column.  The only thing it
ever uses the rightmost column for is to position the cursor there after
if the user has typed exactly N-1 characters on the line.  If the user
then types another character the cursor will first be positioned to the
beginning of the next line before the character is echoed.

Even among terminals that do not have auto-wrap, there are
incompatibilities in the way the rightmost column works.  Most
significantly, what is the effect of a backspace following the output of
a character in column 80?  Some terminals have an imaginary "column 81",
and a backspace from there moves the cursor back to 80.  The VT100,
however, will move the cursor to column 79.  Thus, column 80 must be
special-cased, because <char><bs> doesn't have the same effect there as
in other columns.
-- 
    Barry Margolin
    ARPA: barmar@MIT-Multics
    UUCP: ..!genrad!mit-eddie!barmar

gnu@hoptoad.uucp (John Gilmore) (08/08/86)

Aha!  The problem is coming out!

Some people (Doug Gwyn for example) think "am" means this:

	am:xn@	terminal moves to next line after col 80
	am:xn:	terminal moves to next line after col 80 but ignores next NL
	am@	Can't depend on what terminal does in col 80

On the other hand, Barry Margolin points out that "Applications need to
know whether they can safely output to [column 80 of the last line]
without causing the screen to scroll."  The above definitions provide
no guidance about this; so some software appears to be assuming:

	am@	terminal stays in col 80 after printing char there

This is the problem I've been facing.

So, let me modify my suggestion.  If "am" is set, you can assume that
the cursor will move to the next line.  If "am" is not set, **you must
not assume anything**.  In either case, you can't safely write to column
80 of the last line.

This would mean that removing "am" from a termcap entry would never
cause it to fail.  That is what I am after.
-- 
John Gilmore  {sun,ptsfa,lll-crg,ihnp4}!hoptoad!gnu   jgilmore@lll-crg.arpa
		     May the Source be with you!

mark@cbosgd.UUCP (Mark Horton) (08/11/86)

An interesting idea, but there are a number of problems.

First, some vt100-like terminals (including the vt100) set a flag
when you type something in column 80 and auto-wrap is set.  The
only way to clear this flag is to output some printing char
or to send it CRLF.  Sending an explicit CUP won't clear it.

Second, what do you about a character sent in column 80 of the
last line?  Terminals without am and terminals with am and xn
can use this position, terminals with only am must avoid that
space completely (to avoid scrolling) which isn't transparent
to the user and requires some ugly code.  (You have to delay
the updating of that column until it's been scrolled up a line,
which may never occur.)  You really do need to know when a
terminal can be depended to hammer on the right margin.

Third, what about terminals that don't have a CUP command, and
only have relative motions?  These are becoming more and more
rare, but there are still plenty of them out there.  (The TEK
4025 series, for example.)

Sure, it's a pain to get the terminal set right.  It is, for
reasons I've never understood, traditional to default wrapping
to OFF.  Emulators of terminals with switches (such as the Microterm
emulation of the adm3a, or the CrossTalk emulation of the vt100)
don't give you a choice, they default to off.  How anyone is supposed
to make good use of a terminal that hammers on the right margin is
beyond me - you have to have a screen package involved to program
around the braindamage.

The MIT solution of not using the last column is a nonsolution, in
my opinion.  It's easy to implement, but the user loses.  It makes it
impossible to emulate an 80 column terminal.  If you daisy chain,
you lose one column per emulation.  Your number of columns is no
longer divisible by 8, so your tabs stops can be off.

	Mark

hansen@pegasus.UUCP (Tony L. Hansen) (08/23/86)

< Aha!  The problem is coming out!
< 
< Some people (Doug Gwyn for example) think "am" means this:
< 
< ...
< 
< On the other hand, Barry Margolin points out that "Applications need to
< know whether they can safely output to [column 80 of the last line]
< without causing the screen to scroll."  The above definitions provide
< no guidance about this; so some software appears to be assuming:
< 
< 	am@	terminal stays in col 80 after printing char there
< 
< This is the problem I've been facing.
< 
< So, let me modify my suggestion.  If "am" is set, you can assume that
< the cursor will move to the next line.  If "am" is not set, **you must
< not assume anything**.  In either case, you can't safely write to column
< 80 of the last line.
< 
< This would mean that removing "am" from a termcap entry would never
< cause it to fail.  That is what I am after.

I think it would be instructive to look at how the curses library assumes
that the am/xn interaction is supposed to work.  Taking a 24x80 terminal as
an example, after writing a character into the 80th column:

System Vr2 curses library:

am@, xn@	it assumes that the cursor has remained in the 80th column.
am, xn@		it assumes that the cursor has wrapped to the beginning
am, xn		it assumes that one of two things has happened:
		(vt100 like)
		the cursor is still in column 80 (or a mythical column 81)
		and would go to the beginning of the next one on the next
		character output
	or
		(concept like)
		if the next characters output are <CR> or <NL>, they will
		be ignored

		To handle both of these cases, it outputs <CR><NL> to force
		the cursor to go to the beginning of the next line.

The 4.2BSD curses library doesn't check xn at all, even though it does pull
in the flag from the termcap entry. If am@, it outputs <CR><NL> to force the
cursor to the beginning of the next line; otherwise it seems to assume that
the cursor has gone to the beginning of the next line on its own. (I can't
really check this out on a real 4.2 system because all of the 4.2 systems
that I have access to have converted to the System Vr2 terminfo-based
curses.

By the way, regarding placing a character into the last column (call it the
80th column) of the last line, the way that the System Vr3 curses library
handles this problem is to place the character that belongs in the 80th
column into the 79th column. It then moves back to the 79th column and
INSERTS the character that belongs in the 79th column, forcing the correct
character into the 80th column without causing the screen to scroll. If the
terminal can't do insert, it leaves the 80th column blank.

					Tony Hansen
					ihnp4!pegasus!hansen