[comp.windows.x] how does xterm tell vi the window size

rick@zeek.UUCP (Rick Wilhelm) (10/04/89)

Here is our problem, hope that someone can help out.

From an xterm, I logged on to a remote host and tried to vi a file.
vi thinks that the window is 24 lines deep.  It has no idea that I have
extended the window to >30 lines.
vi apparently goes to the termcap entry for xterm and finds out that
the default window size is 24x80.  However, the window is not necessarily
that size.

Without explicitly setting the window variable in vi (after counting the
number of lines in the window), how can vi act correctly?
Normally, when xterm is running locally, my guess is that it uses the
window i.d. to get the window size.  But since the vi session is on a
remote host, it has no idea about the window i.d.

So my question is two-fold.
1)  (this case)  How can we let vi know that the window is _not_ necessarily
    24x80?
2)  (in general) How does vi (or vnews for that matter) find out a window's
    size from xterm?
    
Thanks for your help

Rick Wilhelm
Andersen Consulting
Advanced Systems Center, Chicago
(312)517-5471
uunet!zeek!rick

cpcahil@virtech.UUCP (Conor P. Cahill) (10/04/89)

In article <253@zeek.UUCP>, rick@zeek.UUCP (Rick Wilhelm) writes:
> From an xterm, I logged on to a remote host and tried to vi a file.
> vi thinks that the window is 24 lines deep.  It has no idea that I have
> extended the window to >30 lines.

Depending upon what OS you are running you can set up the environment
to specify the correct size of the window.

For system V.3 you can use:

	LINES=xx
	COLUMNS=xx
	export LINES COLUMNS

For bsd you need to use: (check the man page, I may not have the exact
sequence since I no longer have access to a BSD system)

	stty rows xx columns xx

On the local system this info is available via the resize command.
On remote systems I handle this by a couple of prompts in my .profile.

Since vi is a pre-X program, it has no built in mechanisms for determining
the size of the window from X.  You must specify the information in your
environment.


-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

argv%turnpike@Sun.COM (Dan Heller) (10/05/89)

In article <253@zeek.UUCP> rick@zeek.UUCP (Rick Wilhelm) writes:
> So my question is two-fold.
> 1)  (this case)  How can we let vi know that the window is _not_ necessarily
>     24x80?
> 2)  (in general) How does vi (or vnews for that matter) find out a window's
>     size from xterm?
you need to use the program (distributed with X) called resize.
I have it in my .login and use it like so:

if ($TERM == xterm) eval `resize`

The nice thing about "resize" is that you don't have to have
Xlib to use it.  I frequently login to a machine that doesn't
run X, but I'm logging in from an xterm.  You can copy resize.c
to that other machine and edit it commenting out copyright.h
and Xos.h.  Then compile: cc resize.c -o resize -ltermlib


dan <island!argv@sun.com>
-----
My postings reflect my opinion only -- not the opinion of any company.

rao@enuxha.eas.asu.edu (Arun Rao) (10/05/89)

In article <1227@virtech.UUCP>, cpcahil@virtech.UUCP (Conor P. Cahill) writes:
> In article <253@zeek.UUCP>, rick@zeek.UUCP (Rick Wilhelm) writes:
> > I logged on to a remote host and tried to vi a file.
> > vi thinks that the window is 24 lines deep.

> For bsd you need to use: 
> 
> 	stty rows xx columns xx
> 
> Since vi is a pre-X program, it has no built in mechanisms for determining
>	....

	vi seems to work fine on our BSD system (an HCX-7 running 4.3BSD)
	when I log in from our System V workstations (a bunch of  Ardent
	Titans). I copied the /etc/termcap file from the Ardent to a
	.termcap file in my home dir. on the Harris - this is probably what
	did it.

	-Arun
	
-- 
Arun Rao
ARPANET: rao@enuxha.eas.asu.edu BITNET: agaxr@asuacvax, agazr@asuacad
950 S. Terrace Road, #B324, Tempe, AZ 85281
Phone: (602) 968-1852 (Home) (602) 965-3452 (Office)

stolcke@icsib2.Berkeley.EDU (Andreas Stolcke) (10/05/89)

 
> From an xterm, I logged on to a remote host and tried to vi a file.
> vi thinks that the window is 24 lines deep.  It has no idea that I have
> extended the window to >30 lines.
> vi apparently goes to the termcap entry for xterm and finds out that
> the default window size is 24x80.  However, the window is not necessarily
> that size.

I'm not an expert on this, but from what I know about UNIX here's one way it
could actually be implemented.

vi doesn't rely on termcaps to figure out the window size. Instead, it
looks up the relevant tty parameters (including window
size) via ioctl() calls.  These parameters get set by the process controlling
the pseudo terminal (i.e., xterm). Processes running in the pty can be
notified of a change in window size by way of a dedicated signal (SIGWINCH)
so they know when to reconsult pty parameters and adjust.

Now, rlogin opens a new pty on the remote machine. So on receiving a
SIGWINCH the rlogin process can communicate the new window size to the remote
pty and update parameters there, as well as send out SIGWINCH's to
remote processes.

Something to this effect actually happens since 'stty all' shows
modified 'rows' and 'columns' parameters after a window resize,
both on local and remote machines. A fresh vi process does always
know about the current window size, both local and remote.
Apparently, however, vi doesn't care or know about SIGWINCH since it won't
adjust on a resize after startup. (I'm talking SunOS 4.0.3 here).

From your posting I infer that on your system window size is not correctly
propagated across rlogins as described above. Maybe you're not running a
BSDish UNIX ?

----
Andreas Stolcke
International Computer Science Institute	stolcke@icsi.Berkeley.EDU
1957 Center St., Suite 600, Berkeley, CA 94704	(415) 642-4274 ext. 126

cpcahil@virtech.UUCP (Conor P. Cahill) (10/05/89)

In article <286@enuxha.eas.asu.edu>, rao@enuxha.eas.asu.edu (Arun Rao) writes:
> In article <1227@virtech.UUCP>, cpcahil@virtech.UUCP (Conor P. Cahill) writes:
> > For bsd you need to use: 
> > 	stty rows xx columns xx
> > 
> > Since vi is a pre-X program, it has no built in mechanisms for determining
> >	....
> 
> 	vi seems to work fine on our BSD system (an HCX-7 running 4.3BSD)
> 	when I log in from our System V workstations (a bunch of  Ardent
> 	Titans). I copied the /etc/termcap file from the Ardent to a
> 	.termcap file in my home dir. on the Harris - this is probably what
> 	did it.


But how does this solve the problem when you login with one window that
is 40 rows and another that is 32 rows and a monster that is 75 rows?
Do you have different terminal types for every window?  the stty option
lets you use the same terminal definition for each window.









-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

mink@cfa.HARVARD.EDU (Doug Mink, OIR) (10/05/89)

 In article <253@zeek.UUCP> rick@zeek.UUCP (Rick Wilhelm) writes:
> So my question is two-fold.
> 1)  (this case)  How can we let vi know that the window is _not_ necessarily
>     24x80?
> 2)  (in general) How does vi (or vnews for that matter) find out a window's
>     size from xterm?

1) run eval `resize`

2) The resize program adds a TERMCAP entry to the xterm's environment.  tgetint
   in the libtermcap.a library checks to see whether there is a TERMCAP in the
   environment before reading the terminal's entry in /etc/termcap.  resize
   sets the "co" and "li" entries which can be read with tgetnum.

Doug Mink
Harvard-Smithsonian Center for Astrophysics
Cambridge, Massachusetts

Internet:  mink@cfa.harvard.edu
BITNET:    mink@cfa

john@acorn.co.uk (John Bowler) (10/06/89)

The mechanism used by vi, and most other termcap (and terminfo?) based
programs, to find out how big the window is simply doesn't work
adequately on systems with variable sized windows (eg xterm windows).
On BSD systems (including Sun OS) what vi does goes something along the
lines of:-

	1) Look in the environment (getenv(3)) - is there a TERMCAP?
		Yes - use the values of the ``co'' (columns) and ``li''
			(lines) parameters if they exist.
		No - if there is a TERM variable look that up in the
			termcap (terminfo on Sys V) database and use
			that information.

	2) If the number of columns or lines is still not known, use
		BSD specific ioctl's to attempt to find the column and
		line values from the *new* tty driver.  If the old tty
		driver is being used this fails, if not, and the columns
		and lines values are non-zero use these.  (See tty(4) on
		a BSD system).  Since pre-R4 System V systems only have
		the old (version 7) tty driver this mechanism can't
		be used on System V (until release 4).

	3) If the columns or lines value is still zero, complain about
		the terminal being too dumb (and give up - vi goes into
		ex mode).

If the new tty driver is in use then vi may receive a SIGWINCH while it
is running - in this case it resizes its window (within certain limits -
try using the ``micro'' font and zooming the window to full screen).

The problem is that the standard ``xterm'' termcap (or terminfo) entry
has co#80:li#24 entries (ie 80 columns, 24 lines).  These entries are
picked up at stage (1) above, and vi does not see if the terminal
driver has any opinion.  The ``resize'' program does not really fix the
problem - it allows you (the user) to generate new TERMCAP entries and
put them into your environment, but these still become incorrect
whenever the window size is changed.  Our (Acorn's) approach to this
problem is to distribute the following ``xterm'' /etc/termcap entries
(NOTE - this ONLY works on BSD systems with the new tty line driver, and
read the other comments below the entry before using it...)

X0|xterm-24|vs100s|xterm terminal emulator (small)(X window system):\
        :co#80:li#24:tc=xterm:
X1|xterm-32|vs100|xterm terminal emulator (medium)(X window system):\
        :co#96:li#32:tc=xterm:
X2|xterm-45|vs100-w|xterm terminal emulator (large)(X window system):\
        :co#144:li#45:tc=xterm:

# Following contains a major fixup to make xterm work semi sensibly - the
# ``co'' and ``li'' entries are commented out so that xterm can still see
# them but doesn't actually set anything useful.  It also contains an am
# (auto-margin) flag and has an im/ei/mi sequence instead of the ic one
# (this makes things faster on our system).
#
AX|xterm|xterm terminal emulator (X window system):\
        :.co#80:.li#24:cr=^M:do=^J:nl=^J:bl=^G:le=^H:ho=\E[H:\
        :cl=\E[H\E[2J:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\
        :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
        :md=\E[1m:mr=\E[7m:me=\E[m:\
        :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
        :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:ta=^I:pt:sf=\n:sr=\EM:\
        :al=\E[L:dl=\E[M:im=\E[4h:ei=\E[4l:mi:dc=\E[P:\
        :MT:ks=\E[?1h\E=:ke=\E[?1l\E>:\
        :is=\E[m\E>\E[?7h\E[?1;3;4l\E[2;4;12;20l:\
        :rs=\E[r\E<\E[m\E[2J\E[H\E>\E[?7h\E[?1;3;4;5;6l\E[2;4;12;20l:xn:\
        :AL=\E[%dL:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:\
        :ti=\E7\E[?47h:te=\E[2J\E[?47l\E8:\
        :hs:ts=\E[?E\E[?%i%dT:fs=\E[?F:es:ds=\E[?E:am:

This causes the first step above to fail.  This works for vi (which
understands the new tty driver) but does *NOT* work for some versions
of emacs and some games - such programs skip step (2) above.  This is
the reason for providing xterm-24 and so on.  Notice that the
``resize'' command will not work (correctly) with the xterm entry above
(because it edits .co and .li entries, but does not remove the dots!)

Of course the ``correct'' solution is for all programs to use the new
tty line driver and to get the display size from it - but I cannot see
this happening in the near future.  As if this isn't bad enough one
extra problem arises when using rlogin.  Rlogin trys to transfer the
terminal characteristics to the other end of the pseudo-tty (so that
the device which the remote program talks to sees a terminal with the
same characteristics as that on which its output is displayed).  To do
this both rlogin and the daemon it talks to must agree.  In practice
this works if you rlogin between machines running the same version of
the same operating system, but sometimes fails when working between
different machines with different operating systems.

To make this worse login, in an apparent attempt at security, cleans
the characteristics of the new tty line driver (setting rows and
columns to 0) when it starts up a (Unix) session.  Thus xterm -L used
to result in a pseudo-tty with 0 rows and columns (even though xterm
*did* set them correctly).  It is also one reason for the tset
aberration - the correct tset command (in a .profile or .login)
restores the terminal line characteristics which (in the ideal world)
would be put in place by getty/xdm/xterm/whatever.

John Bowler (jbowler@acorn.co.uk)

thurlow@convex.com (Robert Thurlow) (10/08/89)

john@acorn.co.uk (John Bowler) writes:
>	2) If the number of columns or lines is still not known, use
>		BSD specific ioctl's to attempt to find the column and
>		line values from the *new* tty driver.  If the old tty
>		driver is being used this fails, if not, and the columns
>		and lines values are non-zero use these.  (See tty(4) on
>		a BSD system).  Since pre-R4 System V systems only have
>		the old (version 7) tty driver this mechanism can't
>		be used on System V (until release 4).

Um, just a nit, but I remember a major change to the AT&T 'tty' driver
between System III and System V Release 1.  It made a big difference to
the performance of our Zilog Z8000, and I think I remember the release
notes making some comments.  And the 'termio' structure came along in
there somewhere as well, changing the ioctl()'s completely from 'sgtty'
days.  How much heritage does the Sys V driver have with version 7?

Rob T
--
Rob Thurlow - Expatriate Canadian                      thurlow@convex.com
"From the heart of 'The Friendship State'"

brsmith@umn-cs.CS.UMN.EDU (Brian R. Smith) (10/12/89)

john@acorn.co.uk (John Bowler) writes:
>The mechanism used by vi, and most other termcap (and terminfo?) based
>programs, to find out how big the window is simply doesn't work
>adequately on systems with variable sized windows (eg xterm windows).
>On BSD systems (including Sun OS) what vi does goes something along the
>lines of:-

I beg to differ; I've just tried it, and the checking order is:
 vi on SunOs 3.5:
  1) The environment variable TERMCAP, if it contains the termcap
      entry and not the name of the file it's in.
  2) The new tty driver (on BSD, who uses anything else?)
  3) /etc/termcap (using TERM) (if the tty driver reports (0,0))
 
 vi on SunOS 4.0.3, Dynix 3.0.12:
  1) new tty driver (only tty driver on SunOS 4.0.3)
  2) TERMCAP
  3) /etc/termcap (using TERM)

>The problem is that the standard ``xterm'' termcap (or terminfo) entry
>has co#80:li#24 entries (ie 80 columns, 24 lines).  These entries are
>picked up at stage (1) above, and vi does not see if the terminal
>driver has any opinion.  The ``resize'' program does not really fix the
>problem - it allows you (the user) to generate new TERMCAP entries and
>put them into your environment, but these still become incorrect
>whenever the window size is changed.  Our (Acorn's) approach to this
>problem is to distribute the following ``xterm'' /etc/termcap entries
>(NOTE - this ONLY works on BSD systems with the new tty line driver, and
>read the other comments below the entry before using it...)

Looks like a kludge.  The easiest fix is just to keep TERMCAP unset.
That way, even on a SunOS 3.5 machine, it will work just fine.
This also avoids your having to re-set TERMCAP if you change TERM, etc.

Re-sizes pass just fine through rlogind in all of them, but SunOS 3.5
*and* 4.0.3 vi's ignore SIGWINCH for some reason.  Looks like only
Sequent got it right, and they don't even have a proprietary windowing
system...

Brian
brsmith@umn-cs.cs.umn.edu

john@acorn.co.uk (John Bowler) (10/12/89)

As several people have pointed out my description of the algorithm used
by vi to determine terminal window size was incorrect - vi looks at the
tty line settings (on a BSD/Sun OS system) *FIRST*.  Therefore my
explanation of the original posters problem was also incorrect.  In
fact if the vi in an rlogin session (on a BSD/Sun OS system) assumes
the wrong window size it can only be because the information is not
stored correctly in the tty line (either the wrong driver is in use -
not the new one - or the information has not be stored correctly or has
been altered).

The likely explanation is that the rlogin (on the original machine) or
the rlogind (on the remote machine) have failed to communicate the
window size information at all.  This, at least, is relatively easy to
test (because it should be entirely independant of X) - simply rlogin
to the remote machine from an xterm (or other terminal/terminal
emulator) with the correct tty row/column settings and examine the
settings on the client machine (using ``stty all'').  If the
rows/columns values are 0 they haven't been transmitted for some reason
(some difference of opinion between the remote rlogind and the local
rlogin, or perhaps the remote login does not support the ``-r'' option
which rlogind uses to preserve the rows/columns values?)  If the values
have changed (eg to 80x24, as in the original article) the likely
explanation is that they were set to 0, then a ``tset'' command in the
users ``.login'' reset the values from the termcap information (notice
that tset does not reset the values (in BSD4.3) if they are not zero!)

In <16231@umn-cs.CS.UMN.EDU>, brsmith@umn-cs.CS.UMN.EDU (Brian R. Smith) writes:-
> Re-sizes pass just fine through rlogind in all of [these operating systems], but SunOS 3.5
> *and* 4.0.3 vi's ignore SIGWINCH for some reason.  Looks like only
> Sequent got it right, and they don't even have a proprietary windowing
> system...

Guy Harris (<guy@auspex.com>) provided me with an explanation of this:-

``... try resizing the window when you're in the middle of reading a big
file; you'll discover that the SIGWINCH is handled by "longjmp"ing out
of whatever it's doing and jumping back into the main input loop.  This
is somewhat rude when e.g. reading in a file, since it stops reading in
part of the file and doesn't tell you about it.  That's why the SunOS
"vi" doesn't do this - SIGWINCHes are delivered when a window is raised
in SunView, so it's even more likely to shaft you.''

Personally I prefer vi to respond to SIGWINCH - I resize my windows a
lot (for example, I have window zooming bound to a function key under
twm, and I quite often use this to expand a vi session to full screen
size).

Eirik Fuller (<eirik@elf.labs.tek.com>) also pointed out that the xterm
termcap which I posted contains both IC (insert multiple characters)
and im/ei (enter insert mode/exit insert mode) sequences.  This seems
to be incorrect - we replaced the ``ic'' with the ``im/ei'' pair
because it can speed up character insertion in vi a lot, leaving in the
IC is an error (although one which causes problems with relatively few
applications apparently).

John Bowler (jbowler@acorn.co.uk)