Subject: Re: bin/10116: vi somewhat easily confused by suspension
To: None <gnats-bugs@gnats.netbsd.org, tech-userlevel@netbsd.org>
From: Julian Coleman <J.D.Coleman@newcastle.ac.uk>
List: tech-userlevel
Date: 05/18/2000 15:50:38
> I tested on Solaris 5.5.1 and see tty keypad will never be disabled
> during a curses session.

Apologies.  I should have noted this.  It does, however, not send the sequence
until keypad() is called.

> Since the keypad flag belongs to the window (not to the terminal) and
> may be set differently between windows, I think the "enable/disable keypad"
> string should not be sent by switching the flag --- it may cause unwanted
> result in switching such windows (especially for pre-typed keys).
> 
> Thoughts?
> 
> By the way, Solaris curses doesn't send "enable" string before a keypad
> flag is set to true, but it is OK and even better to send the string
> in initscr(), in my opinion.
> 
> Solaris manual curs_inopts(3x) says:
> 	If disabled (bf is FALSE), curses does not treat function
> 	keys specially and the program has to interpret the escape
> 	sequences itself.
> 
> and if curses hasn't sent "enable" string, the sequence sent by a keypad
> key is uncertain and user program cannot "interpret" the unknown sequence.

Yes, Solaris' handling of keypad() is broken.  The code I added yesterday only
sends the sequence if it thinks it is necessary.  For example, if you call
keypad() with TRUE or FALSE multiple times, you will only see one instance of
the escape sequence being sent [#1].  Also, the relevant sequence is sent if
you call wgetch() in a window where the keypad state differs from the previous
time you called wgetch() [#2].

We previously always sent the enable sequences when the program started - in
__startwin(), but the documentation states that the initial state is FALSE -

  http://www.opengroup.org/onlinepubs/007908799/xcurses/keypad.html

- so I also changed that.  Agreed, this means that a program may get an
unknown key if it calls wgetch() before it calls keypad().

I'm also not sure that the sequence should be sent when keypad() is called.
[#2] demonstrates an undesirable feature that three sequences will be sent -
on/off/on.  Solutions to that are not to send the sequences from keypad(), or
to only send them when (win == stdscr).  In either case, we're not compatible,
but meet the specification; in the latter we don't need to patch nvi.  Of
course, if you don't bother with the

	keypad(win, FALSE);

line (which is unnecessary), everything is OK.  Not sure if we should worry
about this or not.  My inclination was not.  There are a few corner cases
where it is possible to cause curses to send unnecessary (but not harmful)
sequences.  However, adding code to avoid sending the unnecessary sequences
in these instances may also prevent the correct thing happening at other
times.

J

-- 
                    My other computer also runs NetBSD
                          http://www.netbsd.org/

 ---8<---------------------------- Cut here ---------------------------->8---

[#1]

#include <curses.h>
main()
{
	initscr();
	refresh();

	keypad(stdscr, TRUE);
	keypad(stdscr, TRUE);
	printw(" %d", getch());
	refresh();

	keypad(stdscr, FALSE);
	keypad(stdscr, FALSE);
	printw(" %d", getch());
	refresh();

	endwin();
	return 0;
}

 ---8<---------------------------- Cut here ---------------------------->8---

[#2]

#include <curses.h>
main()
{
	WINDOW	*win;

	initscr();
	refresh();

	win = newwin (1, 2, 3, 4);

	keypad(stdscr, TRUE);
	keypad(win, FALSE);
	printw(" %d", getch());
	refresh();

	printw(" %d", wgetch(win));
	refresh();

	endwin();
	return 0;
}