[comp.lang.c] Keyboard support in C

conor@lion.inmos.co.uk (Conor O'Neill) (02/28/91)

In article <15302@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <1991Feb23.170142.538@ux1.cso.uiuc.edu>
>>mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:
>>That is because it SHOULD be possible to do such very common things
>>as non-echo reading or reading single characters without terminating
>>carriage returns. We should be discussing how to put this into the
>>next standardized version of the language. It SHOULD have been in the
>>present version. 
>
>I don't think you would find many (if any) people among those who have
>carefully considered what needed to go into the C standard, who would
>agree with you.  This is clearly a very system-specific notion; there
>are C environments where the notion makes no sense.  The C standard
>addresses (for hosted environments only) just the minimum universally-
>implementable support necessary for useful applications across all
>hosted environments.  There are other standards, such as POSIX.1, that
>address more system-specific features, and that is an appropriate way
>to deal with them.

I agree strongly with Doug McDonald.
There is already a huge quantity of `system-specific' stuff in the hosted
version of ANSI C. Examples such as getenv and system spring to mind.
Since all computers which support files almost certainly have a keyboard,
it would seem sensible to provide for keyboard access within ANSI C.
I agree that some operating systems would not support un-buffered/echoed
input, but there again, some operating systems do not support
environment variables, the system function,
or access to the time of day, or...
The function ("inkey", or whatever it might be called) could simply
return an error code if it could not be supported.

It also seems, because of the frequency with which this question occurs,
that it is exactly the sort of problem which it would have been useful
to standardise, so that it would be possible to write interactive
programs which were at least portable to machines and operating systems
with `normal' keyboards.

(Standard disclaimer that ANSI C existed to standardise existing practice,
and not to introduce new ideas. It is unfortunate that a large proportion of
existing practice was UNIX, which has terrible support for keyboards).
(Sorry - pretend that I didn't say that!)

---
Conor O'Neill, Software Group, INMOS Ltd., UK.
UK: conor@inmos.co.uk		US: conor@inmos.com
"It's state-of-the-art" "But it doesn't work!" "That is the state-of-the-art".

peter@ficc.ferranti.com (Peter da Silva) (03/02/91)

In article <14542@ganymede.inmos.co.uk> conor@inmos.co.uk (Conor O'Neill) writes:
> The function ("inkey", or whatever it might be called) could simply
> return an error code if it could not be supported.

Perhaps a better model would be something like:

	open_keyboard()	/* tell the library you're gonna do something
			 * with the keyboard, return YES/FAILURE */
	set_mode(ECHO|NOECHO|LINE|CHARACTER)	/* Set echo/erase/etc mode */
	check_key()	/* return YES/NO/FAILURE */
	wait_key(t)	/* wait t seconds for a key, return YES/NO/FAILURE */
	get_key()	/* return the key struck or FAILURE */
	close_keyboard()	/* tell the library you're through */

The result of getchar(), etc, between open_keyboard() and close_keyboard()
would be undefined, as would whether pending input was flushed.

This would keep raw I/O from interfering with stdio, and allow for systems
where setting/clearing modes is expensive and/or not transparent.

What does POSIX.1 do about this stuff?
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

gwyn@smoke.brl.mil (Doug Gwyn) (03/02/91)

In article <14542@ganymede.inmos.co.uk> conor@inmos.co.uk (Conor O'Neill) writes:
>Since all computers which support files almost certainly have a keyboard,
>it would seem sensible to provide for keyboard access within ANSI C.

No, this is another example of parochial thinking.  There are computers
with no keyboards as well as computers with lots of them.  Standard C
provides I/O facilities sufficient for many practical applications, but
if you've ever been involved in trying to specify terminal attribute
standards (I have), you would appreciate that no universal specification
for such things would be of acceptable technical quality.

ian@airs.UUCP (Ian Lance Taylor) (03/02/91)

In article <1991Feb23.170142.538@ux1.cso.uiuc.edu>
>mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:
>That is because it SHOULD be possible to do such very common things
>as non-echo reading or reading single characters without terminating
>carriage returns. We should be discussing how to put this into the
>next standardized version of the language. It SHOULD have been in the
>present version. 

In the set of ANSI C libraries I wrote for the Alpha Micro, opening a
terminal in unbuffered mode returns single characters without waiting
for a carriage return.  I don't know whether UNIX libraries work this
way or not, but is there any reason they couldn't or shouldn't?  This
doesn't handle echo suppression, of course.  In any case, these things
seem more appropriate for POSIX than for ANSI C.
-- 
Ian Taylor               airs!ian@uunet.uu.net                uunet!airs!ian
From a courtroom deposition quoted in the Boston Globe of February 18, 1991:
Q: Doctor, how many autopsies have you performed on dead people?
A: All my autopsies have been on dead people.

scs@adam.mit.edu (Steve Summit) (03/02/91)

mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:
>That is because it SHOULD be possible to do such very common things
>as non-echo reading or reading single characters without terminating
>carriage returns. We should be discussing how to put this into the
>next standardized version of the language. It SHOULD have been in the
>present version. 

In article <14542@ganymede.inmos.co.uk> conor@inmos.co.uk (Conor O'Neill) writes:
>I agree strongly with Doug McDonald.
>Since all computers which support files almost certainly have a keyboard,
>it would seem sensible to provide for keyboard access within ANSI C.
>It also seems, because of the frequency with which this question occurs,
>that it is exactly the sort of problem which it would have been useful
>to standardise, so that it would be possible to write interactive
>programs which were at least portable to machines and operating systems
>with `normal' keyboards.

Oh, for heaven's sake.  Have either of you read the frequently-
asked questions list carefully?  I realize that the answer that's
in there isn't the one you like, but there's also a brief
explanation of *why* that has to be the answer.  The frequently-
asked questions list isn't just to answer frequently asked simple
questions, it's also supposed to lay some of these interminable
debates to rest.  (Don't worry; I harbor no illusions about the
likelihood of that ever really happening.)

The point has been made approximately 2,974 times, but if you
want a standard which defines controls over terminal driver
characteristics, GO READ POSIX.  X3J11 didn't just decline to
address this issue because some operating systems wouldn't be
able to support the desired functionality, it also declined to
address it because it had been explicitly yielded to IEEE 1003.1
to handle.

Whenever this issue comes up, someone volunteers to define a
simple interface for controlling the most popular terminal driver
modes, which could be widely implemented using the services which
various operating systems provide.  I've made this suggestion
myself, at least once; now I'm just annoyed enough that I'm going
to spend an hour and cobble one together.  Now, the fact that
this package will have an hour or so of work put into it should
tell you two things:

     1.	it wouldn't be very hard for a program which needs to do
	these things to do them itself, and

     2.	this package isn't going to come close to addressing the
	sorts of complicated functionality that complicated programs
	want.  No specification, short of a full terminal driver
	definition in an operating system specification (such as
	Posix) could do so.  (In fact, terminal driver definitions,
	no matter how overladen with features, are notorious for
	being found inadequate by demanding application programs.)

To use this simple package, a program must #include "ttyio.h",
and call tty_init.  It can then call tty_setmode to control tty
operating modes (only two are defined: character-at-a-time-ness
and echo), and tty_getchar to read single characters.  tty_navail
reports the number of characters immediately available, if known.
tty_reset cleans up the terminal driver before exiting.

A separate posting (in comp.lang.c and/or alt.sources) contains
implementations for V7/bsd Unix, curses, and MS-DOS, as well as a
dubious, untested implementation for Posix.  (The MS-DOS version
has been tested under Microsoft C, but I believe most if not all
PC C RTL's supply getch and kbhit.)  A System V version would
probably be very close to Posix, but I don't have access to a
System V system for testing.  It has been several years since I
worked with VMS, and I have forgotten the details of its terminal
driver, so I won't be able to provide a VMS implementation at the
moment.

It should be obvious, but it probably isn't, so I'll point out
a couple of things:

     1.	This package isn't perfect.  It isn't supposed to be.
	There are _lots_ of ways the names and functionality
	could be changed.  (*Please* don't post, or even send me
	mail, informing me of any of its limitations.  I know of
	them, lots of them, on many levels.)

     2.	This package is not intended to be, and never will be,
	any kind of standard, formal or informal.  If you want to
	use it, put it in with your application's sources. 
	That way, you can modify it to your heart's content; you
	don't have to worry about keeping the interface
	compatible with anyone else's copy.

Think about these two points carefully.  This is the kind of
simple interface package everyone keeps asking for.  But it
probably isn't adequate for anyone's needs, let alone everyone's.
(I just wrote it, and I doubt I'll ever use it.)  You are going
to see things in this package you'll need to change.  Everybody
who looks at it is going to see things they'll need to change.
No one would use it, as is, to write anything more complicated
than the test program that comes with it.  By the time enough
features got added to it to make it generally usable by real
programs, it wouldn't be simple any more, many of its features
wouldn't be implementable under one operating system or another
(its tty_navail already falls into that category), and it still
wouldn't satisfy everyone.  (On the other hand, if I'm wrong, and
this package is just what you need, then by all means use it.)

It isn't really possible to address this issue simply (unless you
do so pedagogically, as this package does).  That's why X3.159
doesn't have any terminal driver stuff in it, and why nothing
short of a full terminal driver definition in an operating system
specification can usefully do so.  If someone wants to try
writing a Posix terminal driver emulator for older versions of
Unix, or for VMS, or for MS-DOS, with some kind of indication to
the calling program of which Posix features are/aren't emulated,
that would be an, er, "interesting" project (to say the least).

                                            Steve Summit
                                            scs@adam.mit.edu

gmt@cs.arizona.edu (Gregg Townsend) (03/03/91)

In article <1213@airs.UUCP> airs!ian@uunet.uu.net (Ian Lance Taylor) writes:
>
> In the set of ANSI C libraries I wrote for the Alpha Micro, opening a
> terminal in unbuffered mode returns single characters without waiting
> for a carriage return.  I don't know whether UNIX libraries work this
> way or not, but is there any reason they couldn't or shouldn't?

Good for you.  That is a valid and very useful interpretation of the
language in the ANSI specification, though I don't know if the ANSI
committee thought of it.  The ANSI spec, of necessity, is loose enough
to allow other interpretations including doing nothing, and as far as
I know that's the easy path that's been chosen by all Unix vendors.
(It's tricky to do "right", by which I mean ensuring that the tty modes
aren't changed permanently.)

    Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
    +1 602 621 4325     gmt@cs.arizona.edu     110 57 16 W / 32 13 45 N / +758m

torek@elf.ee.lbl.gov (Chris Torek) (03/03/91)

In article <568@coatimundi.cs.arizona.edu> gmt@cs.arizona.edu
(Gregg Townsend) writes, in regard to a C library implementation
in which `unbuffered' stdio streams that talk to `terminals'
>>returns single characters without waiting for a carriage return
writes:

>Good ...  The ANSI spec, of necessity, is loose enough to allow other
>interpretations including doing nothing, and as far as I know that's
>the easy path that's been chosen by all Unix vendors.  (It's tricky
>to do "right", by which I mean ensuring that the tty modes aren't
>changed permanently.)

I agree that it is valid, but not that it is necessarily good.  I
contend that it is *impossible* to do `right', at least on some systems
(such as the ones I tend to use), simply because the definition of
`right' changes dramatically from application to application.  No
matter which definition you (or even I) choose as `right', it will
turn out to be wrong for something else.

(This is why the tty interfaces on Unix boxes are so complicated.  Perhaps
not all of the complexity is needed, but as yet, no one has figured out
how to get rid of it.)
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

gwyn@smoke.brl.mil (Doug Gwyn) (03/03/91)

In article <10530@dog.ee.lbl.gov> torek@elf.ee.lbl.gov (Chris Torek) writes:
>(This is why the tty interfaces on Unix boxes are so complicated.  Perhaps
>not all of the complexity is needed, but as yet, no one has figured out
>how to get rid of it.)

Another important point is that, for most applications, users expect
to have their typed input "canonicalized", e.g. to be allowed to
backspace over mistyped characters.  The UNIX terminal handler normally
provides this service in a uniform manner for th evast majority of
applications; only those that attempt their own "fancy" input handling
override this default terminal-handler support.  If the stdio routines
were to defeat input canonicalization when input comes from a terminal
(even if only after a NULL setbuf), most UNIX users would find the
application behavior to be surprising and annoying.

peter@ficc.ferranti.com (Peter da Silva) (03/05/91)

In article <1991Mar2.065232.1637@athena.mit.edu> scs@adam.mit.edu writes:
> The point has been made approximately 2,974 times, but if you
> want a standard which defines controls over terminal driver
> characteristics, GO READ POSIX.

Too prescriptive, too complex. There really is a need for something
less complex.

> I've made this suggestion
> myself, at least once; now I'm just annoyed enough that I'm going
> to spend an hour and cobble one together.

Thanks. Will be eagerly waiting for it.

>      2.	this package isn't going to come close to addressing the
> 	sorts of complicated functionality that complicated programs
> 	want.

If you want screen control, use curses. If that's not enough, code directly
in termlib. Once *this* package is available, termlib is trivial to do
portably. I posted a version to alt.sources late last year.
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"